限制鼠标的活动范围(非矩形)(100分)

  • 主题发起人 主题发起人 LeeChange
  • 开始时间 开始时间
下面把鼠标的移动区域限制在(10,10,200,200)

var rect:TRect;
begin
rect.Left:=10;
rect.Top:=10;
rect.Bottom:=200;
rect.Right:=200;
windows.ClipCursor(@rect);



下面恢复鼠标的移动区域
windows.ClipCursor(0);
 
都说了是非矩形区域
 
用hook取鼠标的位置,即点的坐标
用PtInRegion判断‘点’是否在你定义的不规则区域内,然后再做处理。
CreatePolygonRgn设置区域
 
>这样说好了,,我写了一支 A 程式,A 程式执行时若按 F1 则 run a1.exe
> 按 F2 则 run a2.exe
>
>现在我的 A 程式成被摆到背景去了..不管 User 怎麽按 F1/F2
>我写的 A.exe 就是没法子知道....因为我没有控制权了,,
>我猜要拦 Windows95 的 Keyboard Event,类似萤幕保护程式的作法
>..只是不知要怎麽作...:)

您的问题看来只好挂上 WH_KEYBOARD 这型的 HOOK 才行了, 我试了一
下, 可以用, 目前设定成每次按下 Ctrl+B, 记事本就会被启动. 有时
间的话, 说不定又可以包装一个元件出来, 提供一些诸如OnXXXKeyHit
之类的事件出来.... :)

Delphi 真是太可爱了, 用它来实作 HOOK 竟然如此简单. :)

大家可以按下列步骤试试看:

1. 将以下的文字剪贴存成 HKTest.DPR

--- Cut Here ---
library HKTest;

uses
HKProc in 'HKProc.pas';

exports
EnableHotKeyHook,
DisableHotKeyHook;

begin
hNextHookProc := 0;
procSaveExit := ExitProc;
ExitProc := @HotKeyHookExit;
end.
--- Cut Here ---


2. 将以下的文字剪贴存成 HKProc.PAS
(Note: HKTest.DPR 与 HKProc.PAS 建议储存在同一个目录)

--- Cut Here ---
unit HKProc;

interface

uses
Windows, Messages;

var
hNextHookProc: HHook;
procSaveExit: Pointer;

function KeyboardHookHandler(iCode: Integer;
wParam: WPARAM;
lParam: LPARAM): LRESULT; stdcall; export;
function EnableHotKeyHook: BOOL; export;
function DisableHotKeyHook: BOOL; export;
procedure HotKeyHookExit; far;

implementation

function KeyboardHookHandler(iCode: Integer;
wParam: WPARAM;
lParam: LPARAM): LRESULT; stdcall; export;
const
_KeyPressMask = $80000000;
begin
Result := 0;
If iCode < 0 Then
begin
Result := CallNextHookEx(hNextHookProc, iCode, wParam, lParam);
Exit;
end;
// 侦测 Ctrl + B 组合键
if ((lParam and _KeyPressMask) = 0) and
(GetKeyState(vk_Control) < 0) and (wParam = Ord('B')) then
begin
Result := 1;
WinExec('Notepad.exe', sw_Normal); // 记事本
end;
end;

function EnableHotKeyHook: BOOL; export;
begin
Result := False;
if hNextHookProc <> 0 then Exit;
// 挂上 WH_KEYBOARD 这型的 HOOK, 同时, 传回值必须保留下
// 来, 免得 HOOK 呼叫链结断掉
hNextHookProc := SetWindowsHookEx(WH_KEYBOARD,
KeyboardHookHandler,
HInstance,
0);
Result := hNextHookProc <> 0;
end;

function DisableHotKeyHook: BOOL; export;
begin
if hNextHookProc <> 0 then
begin
UnhookWindowshookEx(hNextHookProc); // 解除 Keyboard Hook
hNextHookProc := 0;
MessageBeep(0);
MessageBeep(0);
end;
Result := hNextHookProc = 0;
end;

procedure HotKeyHookExit;
begin
// 如果忘了解除 HOOK, 自动代理解除的动作
if hNextHookProc <> 0 then DisableHotKeyHook;
ExitProc := procSaveExit;
end;

end.
--- Cut Here ---

3. 启动 Delphi 2.0

4. 开启 HKTest.DPR, 然後 Project | Build All 以产生 HKTest.DLL

5. File | New Application 开启一个新的专案

6. 将此专案 unit1 与 project1 存档, 请注意: 请存到与 HKTest.DLL
相同的目录中.

7. 在 Form1 上安置二个 TButton, 并撰写 OnClick 程式, 同时,
在 implementation 节中宣告 EnableHotKeyHook() 与
DisableHotKeyHook(), 修改後的程式应类似:
...
...
implementation

{$R *.DFM}

function EnableHotKeyHook: BOOL; external 'HKTEST.DLL';
function DisableHotKeyHook: BOOL; external 'HKTEST.DLL';

procedure TForm1.Button1Click(Sender: TObject);
begin
if EnableHotKeyHook then
ShowMessage('HotKey Testing...');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
if DisableHotKeyHook then
ShowMessage('HotKey Testing..., DONE!!');
end;

end.

8. 专案再存档一次, 执行.

OK! 执行後, 滑鼠点一下 Button1, 然後, 不管 form1 在不在前景, 极小化
也可以, 按下 Ctrl + B 这个组合键, 记事本就启动了.

regards,
Wolfgang Chien


X-Sender: wolfgang@ms2.hinet.net
Date: Sat, 19 Oct 1996 02:48:32 +0800
To: delphichat@ibmsrv.cc.nthu.edu.tw
From: Wolfgang Chien <wolfgang@ms2.hinet.net>
Subject: Re: [Delphi][Form] 如何拦截 Windows95 的按键 ?
Sender: owner-delphichat@ibmsrv.cc.nthu.edu.tw
Reply-To: delphichat@ibmsrv.cc.nthu.edu.tw

earthian <earthian@ms2.hinet.net> wrote:
>> 您的问题看来只好挂上 WH_KEYBOARD 这型的 HOOK 才行了, 我试了一
>> 下, 可以用, 目前设定成每次按下 Ctrl+B, 记事本就会被启动. 有时
>> 间的话, 说不定又可以包装一个元件出来, 提供一些诸如OnXXXKeyHit
>> 之类的事件出来.... :)
>> Delphi 真是太可爱了, 用它来实作 HOOK 竟然如此简单. :)
>> 大家可以按下列步骤试试看:
>> 1. 将以下的文字剪贴存成 HKTest.DPR
>> --- Cut Here ---
>> library HKTest;
>> :
>> <Code...Skiped..>
>试了一下..
>如果把 DLL 的程式码一并放到 Project1 里面, 合并成一个 .exe 时,
>当 Focus 不是 Project1 时, 就无法栏到 Hot key...为甚麽呢??

HOOK可分成 task scope 与 system scope 两种, Windows 系统会先呼
叫 task scope 的函式, 然後才呼叫 system scope 的函式; 但如果当
时挂上 task scope hook 的程式不在前景, 则其所属的 task scope
hook 当然没有作用. (不然怎麽叫 task scope 嘛! :p)

以您的情形, 如果不是实作成 DLL, 而是将之移入 .exe 的Project中,
那它就从 system scope 变成 task scope 的 hook, 当程式在背景时,
Windows 当然就不理会这个 hook 函式了.

换句话说, system scope 的 HOOK 必须实作成 DLL. 而且, 某些类型
的 HOOK 还必须要求只能以 system scope 的方式挂上去, 像是
WH_JOURNALPLAYBACK, 就是其中一个. 进一步的资讯, 您可以参考Win
SDK Reference. 市面上讲 Windows 程式设计比较深入的我认为应该要
涵盖这个题目.

>
>另外..
>如何 Hook 到 Mouse 同时按下 Left & Right Button..
>或者其中任意两键同时按..
>

上次我举的是 WH_KEYBOARD 这型的例子, 如果要过滤 Mouse Message,
那您可以考虑 WH_MOUSE 或 WH_HARDWARE 型.
 
接受答案了.
 
后退
顶部