unit uWnTrackPopupWnd;
interface
uses Forms, Windows, Messages;
procedure TrackPopupWnd(
const AForm: TForm; X, Y: Integer);
//
function MouseWndProc(ACode: Integer; AWParam: WPARAM; ALParam: LPARAM): LRESULT;
stdcall;
function CallWndProc(ACode: Integer; AWParam: WPARAM; ALParam: LPARAM): LRESULT;
stdcall;
function GetMsgProc(ACode: Integer; AWParam: WPARAM; ALParam: LPARAM): LRESULT;
stdcall;
implementation
uses
IdGlobal;
const
MouseMessages:
array[
0..
5]
of Cardinal = (
WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_MBUTTONDOWN, WM_NCLBUTTONDOWN, WM_NCRBUTTONDOWN, WM_NCMBUTTONDOWN
);
var
g_TrackForm: TForm;
g_hkCall,
{
g_hkMouse,
} g_hkGetMsg: HHOOK;
function IsMouseMessage(AMsg: Cardinal): Boolean;
var
i: Integer;
begin
Result := False;
for i :=
0
to High(MouseMessages)
do
begin
if MouseMessages[i] = AMsg
then
begin
Result := True;
Break;
end;
end;
end;
procedure AttachHook;
begin
// g_hkMouse := SetWindowsHookEx(WH_MOUSE, MouseWndProc,
0, GetCurrentThreadId);
if g_hkCall =
0
then
begin
g_hkCall := SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc,
0, GetCurrentThreadId);
g_hkGetMsg := SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc,
0, GetCurrentThreadId);
end;
end;
procedure DetachHook;
begin
// UnhookWindowsHookEx(g_hkMouse);
if g_hkCall <>
0
then
begin
UnhookWindowsHookEx(g_hkCall);
UnhookWindowsHookEx(g_hkGetMsg);
g_hkCall :=
0;
g_hkGetMsg :=
0;
end;
end;
procedure TrackPopupWnd(
const AForm: TForm; X, Y: Integer);
begin
if (g_TrackForm <>
nil)
and (g_TrackForm <> AForm)
then
begin
g_TrackForm.Visible := False;
end;
g_TrackForm := AForm;
g_TrackForm.Left := X;
g_TrackForm.Top := Y;
if
not g_TrackForm.Visible
then
begin
g_TrackForm.Visible := True;
end;
g_TrackForm.Left := X;
g_TrackForm.Top := Y;
AttachHook;
end;
//
function MouseWndProc(ACode: Integer; AWParam: WPARAM; ALParam: LPARAM): LRESULT;
stdcall;
//
//
var
// LNeedDetach: Boolean;
//
begin
//
if g_TrackForm =
nil
then
//
begin
// Result := CallNextHookEx(g_hkMouse, ACode, AWParam, ALParam);
// Exit;
//
end;
//
// LNeedDetach := IsMouseMessage(AWParam);
// LNeedDetach := False;
//
if (ACode >=
0)
then
//
begin
//
if (g_TrackForm <>
nil)
and IsMouseMessage(AWParam)
then
//
begin
// g_TrackForm.Visible := False;
//
end;
//
end;
// Result := CallNextHookEx(g_hkMouse, ACode, AWParam, ALParam);
//
//
if LNeedDetach
then
//
begin
// DetachHook;
//
end;
//
end;
function GetMsgProc(ACode: Integer; AWParam: WPARAM; ALParam: LPARAM): LRESULT;
stdcall;
var
LData: PMsg;
LNeedDetach: Boolean;
LHandled: Boolean;
// LRect: TRect;
begin
if g_TrackForm =
nil
then
begin
Result := CallNextHookEx(g_hkGetMsg, ACode, AWParam, ALParam);
Exit;
end;
LNeedDetach := False;
LHandled := False;
if (ACode >=
0)
and (AWParam = PM_REMOVE)
then
begin
if g_TrackForm <>
nil
then
begin
LData := PMsg(ALParam);
if LData.
message = WM_KEYDOWN
then
begin
if LData.wParam = VK_ESCAPE
then
begin
g_TrackForm.Visible := False;
LNeedDetach := True;
LHandled := True;
end
else
if LData.wParam
in [VK_UP, VK_DOWN, VK_RETURN]
then
begin
if SendMessage(g_TrackForm.Handle, LData.
message, LData.wParam, LData.lParam) =
0
then
begin
LHandled := True;
end;
end;
end
else
if IsMouseMessage(LData.
message)
then
begin
g_TrackForm.Visible := False;
LNeedDetach := True;
end;
if LHandled
then
begin
LData.
message := WM_NULL;
end;
end;
end;
Result := CallNextHookEx(g_hkGetMsg, ACode, AWParam, ALParam);
if LNeedDetach
then
begin
DetachHook;
end;
end;
function CallWndProc(ACode: Integer; AWParam: WPARAM; ALParam: LPARAM): LRESULT;
stdcall;
var
LData: PCWPStruct;
LNeedDetach: Boolean;
begin
if g_TrackForm =
nil
then
begin
Result := CallNextHookEx(g_hkCall, ACode, AWParam, ALParam);
Exit;
end;
LNeedDetach := False;
if ACode >=
0
then
begin
LData := PCWPStruct(ALParam);
//APP激活状态取消
if (LData.
message = WM_ACTIVATEAPP)
and (LData.wParam =
0)
then
begin
g_TrackForm.Visible := False;
LNeedDetach := True;
end
//外部程序请求取消隐藏
else
if (LData.
message = WM_SHOWWINDOW)
and (LData.hwnd = g_TrackForm.Handle)
and (LData.wParam =
0)
then
begin
g_TrackForm :=
nil;
LNeedDetach := True;
end
end;
Result := CallNextHookEx(g_hkCall, ACode, AWParam, ALParam);
if LNeedDetach
then
begin
DetachHook;
end;
end;
//
initialization
// g_hkMouse := SetWindowsHookEx(WH_MOUSE, MouseWndProc,
0, GetCurrentThreadId);
// g_hkCall := SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc,
0, GetCurrentThreadId);
// g_hkMsg := SetWindowsHookEx(WH_GETMESSAGE, GetMessageWndProc,
0, GetCurrentThreadId);
end.