弹出式窗口管理单元备忘

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..5of 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 <> niland (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 >= 0then
//  begin
//    if (g_TrackForm <> niland 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 >= 0and (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.messagethen
      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 = 0then
    begin
      g_TrackForm.Visible := False;
      LNeedDetach := True;
    end
    //外部程序请求取消隐藏
    else if (LData.message = WM_SHOWWINDOW) and (LData.hwnd = g_TrackForm.Handle) and (LData.wParam = 0then
    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.
posted @ 2012-06-01 14:51  Enli  阅读(403)  评论(0编辑  收藏  举报