Как вставить данные буфера обмена нестандартного формата в TMemo? - PullRequest
2 голосов
/ 01 января 2012

Этот вопрос относится к этому вопросу вместе с принятым ответом , размещенным здесь на stackoverflow.

Я не чувствую себя комфортно в Windows API программирование.

Изучение способа EasyGPS от Topografix обрабатывает манипуляции с буфером обмена, я обнаружил, что он использует собственный формат буфера обмена с именем GPX который на самом деле представляет собой простой текст XML (если быть точным, GPX ).Использование буфера обмена. Текст исключен.

На этом этапе я спотыкаюсь:

program ProbeClipboard;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Windows,
  ClipBrd;

var
  CF_GPX: Cardinal;
  ClipboardData: THandle;

begin
  CF_GPX:=RegisterClipboardFormat('GPX');

  if ClipBoard.HasFormat(CF_GPX) then
  begin
    Writeln('GPX format available in clipboard');
    //
    OpenClipboard(0);

    ClipboardData := GetClipboardData(CF_GPX);

    if ClipboardData = 0 then
      raise Exception.Create('Clipboard data Error');

    /// How to use GlobalLock and GlobalUnLock
    /// so that I can paste the Clipboard data
    /// to a TMemo instance for example

    CloseClipboard;
  end;
end.

Пожалуйста, помогите мне исправить эту программу.

1 Ответ

5 голосов
/ 02 января 2012

Я бы написал так:

program ProbeClipboard;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Windows,
  ClipBrd;

var
  CF_GPX: Cardinal;
  ClipboardData: Windows.HGLOBAL;
  Ptr: Pointer;
  Size: DWORD;

begin
  CF_GPX := RegisterClipboardFormat('GPX');

  Clipboard.Open;
  try
    if Clipboard.HasFormat(CF_GPX) then
    begin
      Writeln('GPX format available in clipboard');

      ClipboardData := Clipboard.GetAsHandle(CF_GPX);
      if ClipboardData=0 then
        RaiseLastOSError;

      Ptr := Windows.GlobalLock(ClipboardData);
      if Ptr=nil then
        RaiseLastOSError;

      try
        Size := Windows.GlobalSize(ClipboardData);

        //Ptr now points to a memory block of Size bytes 
        //containing the clipboard data
      finally
        Windows.GlobalUnlock(ClipboardData);
      end;
    end;
  finally
    Clipboard.Close;
  end;
end.

Обратите внимание, что я переместил команду буфера обмена Open, которая блокирует буфер обмена за пределами теста для формата CF_GPX. Это делается для того, чтобы избежать состояния гонки, которое существует в вашем коде. В вашем коде буфер обмена может быть изменен между вызовом HasFormat и вызовом OpenClipboard.

Я также использовал исключительно класс Clipboard. В этом классе есть все, что вам нужно, и вам не нужно использовать API-интерфейс буфера обмена Win32.

Я даже включил проверку ошибок!

...