Как мне предоставить внутреннее частное невизуальное окно (обработчик) невизуального компонента VCL?

Это дополнительный вопрос.

Мои предыдущие вопросы:

Моя проблема:

TComponent не имеет дескриптора окна, такого как TWinControl. Я не хочу полагаться на внешний.

Это фрагмент моего пользовательского компонента

type
  TMyClipBoardListener = class(TComponent)
  private
    FInnerWindowHandle: HWnd;
    FNextHWnd:  HWnd;
    //...
  protected
    procedure Loaded; override;
    procedure WndProc(var Msg: TMessage); // <<< This is my wouldbe Window to handle messages
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    // ...
  published
    // ...
  end;

Фрагмент реализации моего пользовательского компонента

constructor TMyClipBoardListener .Create(AOwner: TComponent);
begin
  inherited;
  //
  FInnerWindowHandle := ...; // <<< What to do here ? Should I pass it to a function/procedure I missed?
end;

destructor TMyClipBoardListener .Destroy;
begin
  if not(csDesigning in ComponentState) then
  begin
    ChangeClipboardChain(FInnerWindowHandle, FNextHWnd);
  end;
  //
  // <<< Are there some cleaning code related to FInnerWindowHandle to implement here or elsewhereCreates a window that implements a specified window procedure. ?
  //
  inherited;
end;

procedure TMyClipBoardListener.Loaded;
begin
  inherited;
  //
  if not(csDesigning in ComponentState) then
  begin
    FNextHWnd:= SetClipboardViewer(FInnerWindowHandle);
  end;
end;

procedure TMyClipBoardListener.WndProc(var Msg: TMessage);
begin
  with Msg do
  begin
    // Message to handle : WM_CHANGECBCHAIN and WM_DRAWCLIPBOARD
    // ... 
    else
      Result := DefWindowProc(FInnerWindowHandle, Msg, WParam, LParam); // <<< Is this the right way to do default handling properly?
  end;
end;

Мой вопрос:

Как я могу получить для своего пользовательского компонента внутреннее окно, реализующее встроенную оконную процедуру?


person menjaraz    schedule 11.01.2012    source источник
comment
Затем у компонента должен быть родитель @David. И если он помещается в форму во время разработки, его размер и расположение ничего не значат.   -  person Rob Kennedy    schedule 11.01.2012
comment
Я не вижу смысла в ссылке на ваши предыдущие вопросы в этом случае.   -  person Warren P    schedule 12.01.2012
comment
@Warren P: Я планирую написать расширенный (настраиваемый) компонент мониторинга буфера обмена. Может быть, еще не время связывать их, как вы указываете, но позже мне придется собрать все вместе. Будут и другие посты, связанные с этим.   -  person menjaraz    schedule 12.01.2012


Ответы (1)


Вызовите AllocateHwnd из модуля Classes (не Формы).

FInnerWindowHandle := AllocateHwnd(WndProc);

Когда вы закончите, вызовите DeallocateHwnd.

person Rob Kennedy    schedule 11.01.2012
comment
+1 Гах, не могу поверить, что сегодня, из всех дней, я не думал об этом! - person David Heffernan; 11.01.2012
comment
потому что у Forms нету AllocateHwnd? - person OnTheFly; 12.01.2012
comment
@User, AllocateHwnd изначально жил в Forms. С тех пор он был перемещен в Классы. Есть несколько версий Delphi, выпущенных во время перехода, где он находится в обоих модулях, но копия Forms помечена как устаревшая. Если у вас есть версия в Классы, используйте ее. Если ваша версия Delphi слишком старая для этого, используйте версию в Forms. - person Rob Kennedy; 12.01.2012