弹出式窗口管理单元备忘
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.
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.