IPB
ЛогинПароль:

 
 Ответить  Открыть новую тему 
> Буфер обмена, FreePascal
сообщение
Сообщение #1


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Как скинуть в буфер обмена(Ctrl+C) текстовую информацию?


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






Ты имеешь в виду программно? Или чтоб скопировать текст программы из окна в ClipBoard? Программно - надо смотреть (опять же, программа оконная или консоль)... Если чтоб скопировать - то Edit -> Copy To Windows
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Надо програмно из консоля. Возможно?


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Я думаю, да... Сейчас гляну...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Гость






Значится, так:

первая часть реализована у Vit-а в DRKB:
Системные функции и WinAPI -> Windows -> Консольные приложения -> Как захватить весь вывод в консоли?
(с незначительными переделками возвращает строку, содержащую все, что было записано в консоль), а вот со второй частью (а именно - сам процесс копирования в ClipBoard) есть проблемы... Нужно передавать в OpenClipboard() Application.Handle, которого, как ты понимаешь, у консольного приложения нет в том виде, как у приложения оконного... Да и юнита ClipBrd нет в FreePascal-е, ибо это часть VCL... sad.gif
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Знаток
****

Группа: Пользователи
Сообщений: 419
Пол: Мужской

Репутация: -  6  +


volvo

а в fcl или lcl аналог есть? В fcl нашел только clipboard в gtk2 и под morphos.


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Гость






Цитата(virt @ 15.09.2006 22:01)
а в fcl или lcl аналог есть?
Я предпочел воспользоваться функциями WinAPI...

uses windows, sysutils;

const
size = 80 * 50;
var
chiBuffer: string;
hStdOut: THandle;

rd: LongWord;
buf: array[0 .. pred(size)] of char;


function GetConsoleWindow: THandle;
var
S: AnsiString;
C: Char;
begin
Result := 0;
Setlength(S, MAX_PATH + 1);
if GetConsoleTitle(PChar(S), MAX_PATH) <> 0 then
begin
C := S[1];
S[1] := '$';
SetConsoleTitle(PChar(S));
Result := FindWindow(nil, PChar(S));
S[1] := C;
SetConsoleTitle(PChar(S));
end;
end;


procedure grabber();
var
Data: THandle;
DataPtr: Pointer;
len: integer;

crd: TCoord;
i: integer;

begin
crd.X := 0;
crd.Y := 0;

hStdout := GetStdHandle(STD_OUTPUT_HANDLE);
ReadConsoleOutputCharacter(hStdout, buf, size, crd, rd);

chiBuffer := '';
for i := 0 to pred(rd) do begin

chiBuffer := chiBuffer + buf[i];
if succ(i) mod 80 = 0 then chiBuffer := chiBuffer + #13#10;

end;

if OpenClipboard(GetConsoleWindow) then
try
{ opening clipboard succeeded... }
len := Length(chiBuffer) + 1;
Data := GlobalAlloc(GMEM_DDESHARE or GMEM_MOVEABLE, len);
try

DataPtr := GlobalLock(Data);
try
Move(pchar(chiBuffer)^, DataPtr^, len);
EmptyClipboard;
SetClipboardData(CF_TEXT, Data);
finally
GlobalUnlock(Data);
end;

except
GlobalFree(Data);
end;

finally
CloseClipboard;
end;

end;

var
i: integer;

begin

{ Заполняем чем-то экран }
for i := 1 to 10 do
writeln('Wow !!! Wow !!! Wow !!! ', i);

{ и забираем его содержимое в буфер }
grabber;

end.


Bokul,
Единственный недостаток программы (кстати, можно попробовать его избежать smile.gif как - догадайся сам) - при копировании ВСЕ строки содержат по 80 символов, и если из них "нужных" - 10, то 70 остальных - пробелы...

Да... Еще кое-что... Надо бы добавить программное определение числа символов в строке, а то мало ли, может у кого-то 40 установлено, будет некорректно работать...

Сообщение отредактировано: volvo -


Прикрепленные файлы
Прикрепленный файл  grabber.pas ( 1.61 килобайт ) Кол-во скачиваний: 203
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Ух, спасибо большое good.gif , сейчас буду разбираться, только не мог бы ты выложить файл с исходником - при копирование форматирования пропадает.


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Компиляция не проходит...
Ide ругается на 66 строчку - Move(pchar(chiBuffer)^, DataPtr^, len);
Цитата

Error: Illegal type conversion: 'ShortString' to '^Char'


Добавил потом: наконец-то разобрался как работает этот код! И всего-то спустя 2 часа, но почему возникает ошибка, я так и не понял. Почему вообще компилятор проверяет тип переменных в этой функции? В справке написано, что не должен...

Сообщение отредактировано: Bokul -


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Гость






А у тебя совместимость с Delphi установлена в настройках? Если нет, то первой строкой программы добавляй
{$mode DELPHI}
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Спаибо Volvo, теперь все работает good.gif . Компилятор и раньше писал что-то про mode, только я поставил вместо {$mode DELPHI} {$mode ObjFpc}.

Осталось несколько моментов, которые я не понял:
Цитата

Setlength(S, MAX_PATH + 1);


Откуда взялась переменная MAX_PATH? Или это константа? Чему она ровна?
Цитата

C := S[1];
S[1] := '$';
---------
S[1] := C;


Для чего сначала первому символу строки присваивать символ '$', а потом возвращать предыдущее значение?
Чтобы снизить вероятность нахождения другого окна с тем же именем?
Цитата

chiBuffer: string;
----------------------
for i := 0 to pred(rd) do begin
chiBuffer := chiBuffer + buf[i];

Сколько символов помещается в string? Я думал 255... а тут получается больше 400 - rd = size = 80 * 50, да плюс еще 50 раз по #13#10. Получается 500 символов. Я не прав?

Сообщение отредактировано: Bokul -


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Гость






Цитата(Bokul @ 16.09.2006 18:04)
Откуда взялась переменная MAX_PATH? Или это константа? Чему она ровна?
Константа... Описана в модуле SysUtils, в свою очередь равна константе MaxPathLen (из модуля System) = 256 (зависит от ОС)
Цитата(Bokul @ 16.09.2006 18:04)
Для чего сначала первому символу строки присваивать символ '$', а потом возвращать предыдущее значение? Чтобы снизить вероятность нахождения другого окна с тем же именем?
Именно так... Вообще Microsoft в этом случае рекомендует заменить заголовок окна на сгенерированный GUID, чтобы вообще исключить возможность присутствия второго такого же заголовка, но я думаю, это лишнее smile.gif

Цитата(Bokul @ 16.09.2006 18:04)
Сколько символов помещается в string? Я думал 255... а тут получается больше 400 - rd = size = 80 * 50, да плюс еще 50 раз по #13#10. Получается 500 символов. Я не прав?
К сожалению, нет smile.gif Или к счастью... В FPC String = AnsiString в режиме совместимости с Дельфи, а

Цитата(ref.pdf)
3.2.4 Ansistrings
Ansistrings are strings that have no length limit. They are reference counted and null terminated.


excl.gif

P.S. Кстати, чтобы убрать лишние пробелы (о чем я говорил выше), достаточно сделать так:
  { Это уже есть в программе ... }
chiBuffer := '';
for i := 0 to pred(rd) do begin

chiBuffer := chiBuffer + buf[i];
if succ(i) mod 80 = 0 then chiBuffer := chiBuffer + #13#10;

end;

{ А вот это надо добавить ... }
while pos(' '#13#10, chiBuffer) > 0 do
chibuffer := stringreplace(chibuffer, ' '#13#10, #13#10, [rfreplaceall]);
...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Цитата
while pos(' '#13#10, chiBuffer) > 0 do
chibuffer := stringreplace(chibuffer, ' '#13#10, #13#10, [rfreplaceall]);

Круто, классный способ! Я знал, что надо делать и где надо исправлять, но как определить, какие пробелы надо удалять еще надо было подумать.

Сообщение отредактировано: Bokul -


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 




- Текстовая версия 20.11.2017 20:18
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"