home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 April A / Pcwk4a98.iso / PROGRAM / DELPHI16 / Calmira / Src / SRC / WNDHOOKS.DPR < prev    next >
Text File  |  1997-02-15  |  8KB  |  272 lines

  1. {**************************************************************************}
  2. {                                                                          }
  3. {    Calmira shell for Microsoft« Windows(TM) 3.1                          }
  4. {    Source Release 1.0                                                    }
  5. {    Copyright (C) 1997  Li-Hsin Huang                                     }
  6. {                                                                          }
  7. {    This program is free software; you can redistribute it and/or modify  }
  8. {    it under the terms of the GNU General Public License as published by  }
  9. {    the Free Software Foundation; either version 2 of the License, or     }
  10. {    (at your option) any later version.                                   }
  11. {                                                                          }
  12. {    This program is distributed in the hope that it will be useful,       }
  13. {    but WITHOUT ANY WARRANTY; without even the implied warranty of        }
  14. {    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         }
  15. {    GNU General Public License for more details.                          }
  16. {                                                                          }
  17. {    You should have received a copy of the GNU General Public License     }
  18. {    along with this program; if not, write to the Free Software           }
  19. {    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             }
  20. {                                                                          }
  21. {**************************************************************************}
  22.  
  23. library WndHooks;
  24.  
  25. { Calmira's Windows hooks and other low level stuff.
  26.  
  27.   This DLL implements:
  28.  
  29.   Shell hook - detects and reports top-level windows being created or
  30.     destroyed (perfect for a taskbar)
  31.  
  32.   WndProc hook - detects and reports WM_ACTIVATE messages sent to
  33.     any window.  Detects user maximizing a window, and can adjust its
  34.     size so as not to overlap with the taskbar.
  35.  
  36.   Mouse hook - detects and reports WM_MOUSEMOVE messages sent to
  37.     any window (used by taskbar to hide after the cursor has moved off).
  38.     Also detects WM_NCRBUTTONDOWN so that right clicks on minimize or
  39.     maximize boxes can be used to close a window.
  40.  
  41.   Desktop WndProc - detects and reports the user right clicking on
  42.     the desktop, so that host program can display a popup menu.
  43.  
  44.   Thanks to Ralf Scheiner for the code to constrain maximized windows.
  45. }
  46.  
  47. uses WinProcs, WinTypes, Messages, CalMsgs;
  48.  
  49. type
  50.   LongRec = record
  51.     Lo, Hi: Word;
  52.   end;
  53.  
  54.  
  55. var
  56.   CallBackWnd : HWND;
  57.  
  58.   TaskHook  : HHook;
  59.   WndHook   :HHook;
  60.   MouseHook : HHook;
  61.  
  62.   ScreenWidth, ScreenHeight, YLimit: Integer;
  63.   MaxEnabled : Boolean;
  64.   MouseEnabled : Boolean;
  65.   RCloseEnabled : Boolean;
  66.  
  67.   DeskWndProc : TFarProc;
  68.   DeskCallBack: HWND;
  69.  
  70. { shell hook }
  71.  
  72. function ShellProc(Code : Integer; wParam: Word; lParam: Longint): Longint; export;
  73. begin
  74.   case Code of
  75.   HSHELL_WINDOWCREATED   : PostMessage(CallbackWnd, WM_SHELLWNDCREATE, wParam, lParam);
  76.   HSHELL_WINDOWDESTROYED : PostMessage(CallBackWnd, WM_SHELLWNDDESTROY, wParam, lParam);
  77.   end;
  78.   Result := CallNextHookEx(TaskHook, Code, wParam, lParam);
  79. end;
  80.  
  81.  
  82. procedure StopTaskMonitor; export;
  83. begin
  84.   if TaskHook > 0 then UnhookWindowsHookEx(TaskHook);
  85.   TaskHook := 0;
  86. end;
  87.  
  88. procedure StartTaskMonitor; export;
  89. begin
  90.   StopTaskMonitor;
  91.   TaskHook := SetWindowsHookEx(WH_SHELL, ShellProc, HInstance, 0);
  92. end;
  93.  
  94.  
  95. { WndProc hook }
  96.  
  97. function WndProcHook(code: integer; wParam:word; lParam:Longint):LongInt; export;
  98. type
  99.   PHookMsg=^THookMsg;
  100.  
  101.   THookMsg=record
  102.    lParam: Longint;
  103.    wParam: Word;
  104.    uMsg: Word;
  105.    hWnd: THandle;
  106.   end;
  107. var
  108.   Wnd: HWnd;
  109. begin
  110.   if code >= 0 then with PHookMsg(lParam)^ do
  111.  
  112.     if MaxEnabled and (uMsg = WM_WINDOWPOSCHANGING) then begin
  113.       { Adjust size of maximized window }
  114.       with pWindowPos(lParam)^ do
  115.         if (Y+cY>ScreenHeight) and (X+cX>ScreenWidth) then begin
  116.           cY := YLimit - Y;
  117.           if GetWindowLong(HWnd, GWL_STYLE) and WS_THICKFRAME > 0 then
  118.             Inc(cY, GetSystemMetrics(SM_CYFRAME))
  119.           else
  120.             Inc(cY);
  121.         end;
  122.     end
  123.  
  124.     else if (uMsg = WM_ACTIVATE) and (CallBackWnd > 0) then
  125.       { inform host program about activation message }
  126.       case wParam of
  127.         WA_INACTIVE    : if Bool(LongRec(lParam).Hi) then
  128.                          SendMessage(CallBackWnd, WM_HIDEQUERY, hWnd, 0);
  129.         WA_ACTIVE      : SendMessage(CallBackWnd, WM_WINACTIVE, hWnd, 1);
  130.         WA_CLICKACTIVE : SendMessage(CallBackWnd, WM_WINACTIVE, hWnd, 1);
  131.       end;
  132.  
  133.   CallNextHookEx(WndHook,Code,wParam,lParam);
  134. end;
  135.  
  136. procedure SetYLimit(y: Integer); export;
  137. begin
  138.    YLimit := y;
  139. end;
  140.  
  141. procedure UnhookWndHook; export;
  142. begin
  143.   if WndHook> 0 then UnHookWindowsHookEx(WndHook);
  144.   WndHook:= 0;
  145. end;
  146.  
  147. procedure SetWndHook; export;
  148. begin
  149.   UnhookWndHook;
  150.   WndHook := SetWindowsHookEx(WH_CallWndProc,WndProcHook,hInstance,0);
  151. end;
  152.  
  153. { Mouse hook }
  154.  
  155. function MouseProc(Code : Integer; wParam: Word; lParam: Longint): Longint; export;
  156. var
  157.   y: Integer;
  158. begin
  159.   if MouseEnabled and (wParam = WM_MOUSEMOVE) then begin
  160.     { inform host about mouse movement }
  161.     y := TMouseHookStruct(Pointer(lParam)^).Pt.y;
  162.     if y < YLimit then PostMessage(CallbackWnd, WM_MOUSEHOOK, y, 0);
  163.   end
  164.  
  165.   else if RCloseEnabled and (wParam = WM_NCRBUTTONDOWN) then begin
  166.     { close the window if right click on minimize/maximize boxes }
  167.     with TMouseHookStruct(Pointer(lParam)^) do
  168.       if (wHitTestCode = HTMAXBUTTON) or (wHitTestCode = HTMINBUTTON) then begin
  169.         Result := 1;
  170.         PostMessage(hWnd, WM_CLOSE, 0, 0);
  171.         Exit;
  172.       end;
  173.   end;
  174.  
  175.   Result := CallNextHookEx(MouseHook, Code, wParam, lParam);
  176. end;
  177.  
  178.  
  179. procedure StopMouseMonitor; export;
  180. begin
  181.   if MouseHook > 0 then UnhookWindowsHookEx(MouseHook);
  182.   MouseHook := 0;
  183. end;
  184.  
  185. procedure StartMouseMonitor; export;
  186. begin
  187.   StopMouseMonitor;
  188.   MouseHook := SetWindowsHookEx(WH_MOUSE, MouseProc, HInstance, 0);
  189. end;
  190.  
  191. procedure EnableMouseMonitor; export;
  192. begin
  193.   MouseEnabled := True;
  194. end;
  195.  
  196. procedure DisableMouseMonitor; export;
  197. begin
  198.   MouseEnabled := False;
  199. end;
  200.  
  201.  
  202. procedure SetCallBackWnd(Wnd: HWND); export;
  203. begin
  204.   CallBackWnd := Wnd;
  205. end;
  206.  
  207. procedure SetMaxEnabled(value : Boolean); export;
  208. begin
  209.   MaxEnabled := value;
  210. end;
  211.  
  212. { Desktop window procedure to catch right clicks }
  213.  
  214. function NewDeskWndProc(Handle: HWND; Msg: Word; wParam: Word;
  215.   lParam: Longint): Longint; export;
  216. begin
  217.   if (Msg = WM_RBUTTONDOWN) then
  218.     PostMessage(DeskCallBack, WM_DESKMENU, wParam, lParam);
  219.  
  220.   Result := CallWindowProc(DeskWndProc, Handle, Msg, wParam, lParam);
  221. end;
  222.  
  223. procedure ReleaseDesktopHook; export;
  224. begin
  225.   { restore Windows's wndproc }
  226.   if DeskWndProc <> nil then begin
  227.     SetWindowLong(GetDesktopWindow, GWL_WNDPROC, Longint(DeskWndProc));
  228.     DeskWndProc := nil;
  229.   end;
  230. end;
  231.  
  232. procedure SetDesktopHook(CallBack : HWND); export;
  233. begin
  234.   { replace desktop wndproc with our one }
  235.   ReleaseDesktopHook;
  236.   DeskCallback := CallBack;
  237.   DeskWndProc := Pointer(SetWindowLong(GetDesktopWindow, GWL_WNDPROC,
  238.     Longint(@NewDeskWndProc)));
  239. end;
  240.  
  241.  
  242. { Right click on min/max buttons to close }
  243.  
  244. procedure SetRCloseEnabled(value : Boolean); export;
  245. begin
  246.   RCloseEnabled := value;
  247. end;
  248.  
  249.  
  250.  
  251. exports
  252.   StartTaskMonitor index 1,
  253.   StopTaskMonitor index 2,
  254.   SetWndHook index 3,
  255.   UnhookWndHook index 4,
  256.   SetYLimit index 5,
  257.   StartMouseMonitor index 6,
  258.   StopMouseMonitor index 7,
  259.   EnableMouseMonitor index 8,
  260.   DisableMouseMonitor index 9,
  261.   SetCallBackWnd index 10,
  262.   SetMaxEnabled index 11,
  263.   SetRCloseEnabled index 12,
  264.   SetDesktopHook index 13,
  265.   ReleaseDesktopHook index 14;
  266.  
  267. begin
  268.   ScreenWidth := GetSystemMetrics(SM_CXSCREEN);
  269.   ScreenHeight := GetSystemMetrics(SM_CYSCREEN);
  270.   YLimit := ScreenHeight - 32;
  271. end.
  272.