FireMonkey と Windows
OSへの依存が排除されている
FireMonkey はマルチプラットフォームのライブラリなので、プラットフォームに依存した処理は(気軽には)使えないようになっています。
でも、例えば Windows でしか使わないアプリケーションの作成では Windows に依存した処理を使いたいこともあります。
Windows に依存した処理をする
Windows に依存した処理の多くは Win32 API を使うことになるでしょう。
(その他にはファイルパスだったり、改行コードなどがあります)
TWindowHandle
Win32 API を使うということは基本的には Window Handle が必要です。
FireMonkey は Window Handle を隠蔽していますが、簡単に取得できます。
ただし、ここで注意したいのは TCommonCustomForm が持っている Handle は、FireMonkey が管理するための独自のハンドルで Window Handle とは別物ということです。
FireMonkey は、この独自のハンドルと Window Handle を結びつけて管理しています。
その管理をするクラスが TWindowHandle です。
このクラスを取得するためには、WindowHandleToPlatformという関数を使います。
この関数は FMX.Platform.Winに定義されていおり、また TWindowHandle を継承して Windows に特化させた TWinWindowHandleも定義されています。
WindowHandleToPlatform は、この TWinWindowHandle を返します。
TWinWindowHandle.Wnd で Window Handle が取得できます。
ここまでをコードにすると…
function GetWnd(const iForm: TCommonCustomForm): HWND;
begin
Result := WindowHandleToPlatform(iForm.Handle).Wnd;
end;
と、こんな風になります。
ですが!
Window Handle を取るだけなら更に簡単な方法があります。
それは、FormToHWNDです。
これを使うと
function GetWnd(const iForm: TCommonCustoForm): HWND;
begin
Result := FormToHWND(Form);
end;
と、こんな感じになります。
Windows Message に反応する
WindowHandle が取得できたので、Window Procedure を置き換えてみます。
Win32 API の SetWindowLong 関数を使うと Window Procedure を置き換えられます。
具体的なコードは次の通りです。
var
WndProc: Pointer;
function ChangeWndProc(const iForm: TCommonCustomForm): Boolean;
var
Wnd: HWND;
begin
Wnd := FormToHWND(iForm);
WndProc := Pointer(SetWindowLong(Wnd, GWL_WNDPROC, Integer(@WndProc)));
Exit(WndProc <> nil);
end;
ここで、SetWindowLong に渡している Wndproc は下のような関数です。
function WndProc(
hWnd: HWND;
uMsg: DWORD;
wParam: WPARAM;
lParam: LPARAM): LRESULT; stdcall;
begin
case uMsg of
WM_MOUSEMOVE: // などなど
begin
end;
end;
Result := CallWindowProc(WndProc, hWnd, uMsg, wParam, lParam);
end;
これで、置き換え完了です。
あとは uMsg に対して、いくらでも自由に反応できます。
まとめ
Window Handle は FormToHWND や WindowHandleToPlatform を使って取得できます。
#次回
macOS 編に続きます。