FAIL (the browser should render some flash content, not this).
  • Главная
  • ИТ-аутсорсинг
  • Сайтостроение
  • Портфолио
  • Контакты
  • Информация



Контролируем буфер обмена из приложения на Delphi

  На самом деле всё сводится к обработке сообщения WM_DRAWCLIPBOARD, но дело в том, что никто просто так нам его не отправит.

  Есть такое понятие, как «Clipboard chain», или «цепочка буфера обмена». Фактически в ней содержится список handle’ов окон, которым посылается сообщение WM_DRAWCLIPBOARD. На самом же деле оно посылается только первому окну в цепочке. И каждое окно в этой цепочке должно (обязано).

  Итак, как же нам попасть в эту цепочку? Для этого есть функция SetClipboardViewer. Создадим новый проект, на событие создания формы (или в любой другой нужный нам момент) напишем:

1
nhwnd := SetClipboardViewer(Handle);

  nhwnd – глобальная переменная типа Cardinal (тот же THandle), в неё мы получили следующий в цепочке handle, она нам пригодится в других процедурах.

  Теперь нужно позаботиться о том, чтобы удалять себя из цепочки в том случае, когда нам уже не нужно перехватывать обновление информации в буфере – например, при закрытии:

1
2
3
4
procedure TForm1.FormDestroy(Sender: TObject);  
begin  
  ChangeClipboardChain(Handle, nwnd);  
end;

  Функция ChangeClipboardChain удаляет нас из цепочки. Функция рассылает сообщение WM_CHANGECBCHAIN окнам цепочки, нам это сообщение также предстоит обработать. Обычно возвращает false, а true только в том случае, если наше окно в цепочке было единственным. Нам результат этой функции в данном случае не важен.

  Обработаем WM_CHANGECBCHAIN. Для тех, кто подзабыл: в раздел private типа TForm1 пишем procedure WMChangeCBChain(var msg: TWMChangeCBChain); message WM_CHANGECBCHAIN; и обрабатываем:

1
2
3
4
5
6
7
procedure TForm1.WMChangeCBChain(var msg: TWMChangeCBChain);
begin
 if msg.Remove = nwnd then
   nwnd := msg.Next
 else
   SendMessage(nwnd, WM_CHANGECBCHAIN, msg.Remove, msg.Next);
end;

  Здесь всё тоже несложно: если удалилось следующее в цепочке окно, берём на заметку – меняем nwnd на теперь действительное следующее окно. Иначе уведомляем следующее окно, как этого требует цепочка. Осталось только обработать событие WM_DRAWCLIPBOARD:

1
2
3
4
5
6
7
8
procedure TForm1.WMDrawClipBoard(var msg: TWMDrawClipboard);
begin
 if ClipBoard.HasFormat(CF_TEXT) then
   ShowMessage(ClipBoard.AsText)
 else
   ShowMessage('Скопирован не текст...');
 SendMessage(nwnd, WM_DRAWCLIPBOARD, 0, 0);
end;

  На самом деле всё очень не сложно. Смотрим, что скопировано, делаем, что нам нужно, и отправляем сообщение по цепочке дальше…