为何DLL不能将消息传给后台程序?(100分)

  • 主题发起人 主题发起人 蔡成
  • 开始时间 开始时间

蔡成

Unregistered / Unconfirmed
GUEST, unregistred user!
我需要用一个DLL的程序来做键盘钩子,当它捕捉到键盘按键时,可将近键消息
传给在后台工作的主程序,再由后台工作的主程序将按键消息转换,部分按键
消息需传给当前的应用程序。
我写了一个DLL程序,是根据钱达智的例子改写出,但是只有主程序工作在
前台时才能收到DLL的消息,当主程序工作在后台时便收不到了。
我看过关于moues hook的例子,但那个例子与我的这种做法不太一样。
在此请教各位高手。
DLL文件如下:
unit HKProc;

interface

uses
Windows, Messages,Sysutils,classes;

var
hNextHookProc: HHook;
procSaveExit: Pointer;
var
HWndHotKey : Thandle;


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;
if (IntToHex(wParam,2) = 'FF') then
begin
if ((lparam and _KeyPressMask) = 0 ) then
begin
HWndHotKey:= FindWindow('TMainForm', 'hotkey');
postmessage(HWnDHotKey,WM_keyDown,wParam,lParam);
Result:= 1;
end
else
begin
if (IntToHex(lparam and $80FF0000,8) = '80300000') then
begin
HWndHotKey:= FindWindow('TMainForm', 'hotkey');
postmessage(HWnDHotKey,WM_keyUp,wParam,lParam);
Result:= 1;
end;
end;
end;
end;


function EnableHotKeyHook: BOOL
export;
begin
Result := False;
if hNextHookProc <> 0 then Exit;
hNextHookProc := SetWindowsHookEx(WH_KEYBOARD,
KeyboardHookHandler,HInstance,0);
Result := hNextHookProc <> 0;
end;


function DisableHotKeyHook: BOOL
export;
begin
if hNextHookProc <> 0 then
begin
UnhookWindowshookEx(hNextHookProc);
hNextHookProc := 0;
end;
Result := hNextHookProc = 0;
end;


procedure HotKeyHookExit;
begin
if hNextHookProc <> 0 then DisableHotKeyHook;
ExitProc := procSaveExit;
end;

end.

还有,我编译这个程序可以正常通过,但在运行中会偶尔出现runtime 216错
误,请问问题在哪里?
 
runtime 216错误
D4 or D5?
 
Runtime 216错误 为D4。 不过我用D5编译好象好有(不确定)。
这种错误跟版本有关系吗?

后台收不到DLL的消息该如何解决?
 
等O*O来一眼洞穿吧!
 
var
hNextHookProc: HHook

procSaveExit: Pointer;
var
HWndHotKey : Thandle;

这些变量在各个进程是不同的,所以要把他们放在共享的区域,
一般的简单的做法是使用 CreateFileMapping 。
具体查看一个cakk提的问题
 
那么请问Pipi 以上程序为什么会出现 runtime 216错误呢?
 
虽然那3个变量是所谓“全局变量”,但是却不少跨进程的。
你在初始化时保存的值,在另外一个进程是看不到的(就是说,在其他进程
这些变量是未初始化值的),你直接把它用,作为函数地址,还不出错?
 
虽然那3个变量是所谓“全局变量”,但是却不是跨进程的。
你在初始化时保存的值,在另外一个进程是看不到的(就是说,在其他进程
这些变量是未初始化值的),你直接把它用,作为函数地址,还不出错?
 
再问Pipi:
1。我看沈前卫一篇关于mouse hook的例子,他也没有将上面的hhook,pointer
作共享,只是将窗口句柄处了处理,那是不是也可能出问题?
2。一个比较低级的问题:这个DLL只有我自己的主程序调用,您说的“跨进程”
我不太明白,望详解。
3。能否请您告诉我该如何修改?我的email:keymon@chinaday.net
谢谢。
这100分给您。
 
我认为Pipi.说的有道理,但我认为你的Hook少了不少的东西,特别是初使过程。

//初试话,每进不同的进程都会调用初试话过程
begin
Intodll;
MapCommonData;
// ShowMessage('OK, I''m in new Proccess')
//注意,使用时不要这样,会死机。
hNextHookProc := 0;
procSaveExit := ExitProc;
ExitProc := @MouseHookExit;
end.


好好看看这里:
http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=198085
 
Pipi及沈先生:

我现在用198085的例子改写了hook,后台是可以收到自定义的消息了,
但后台却不能将我另加的用keybd_event(还有bringwindowtotop)模拟
的按键消息传到我指向的句柄窗口。请问何故?
而且,我现在用沈先生的例子时也出现了runtime 216错误。
真是头大了。
 
你的程序有一些问题,比如你老是使用FindWindow,当你在IDE中运行时,Delphi中
也有个窗口的类与窗口名与你运行的程序一样,FindWindow可能得到的是IDE中的
那个窗口,当然得不到keybd_event了。可以这样,在程序运行中设置窗体得名称。
这样不会与IDE中得窗体冲突。

》我现在用沈先生的例子时也出现了runtime 216错误。
你也将所有数据都放到FileMapping中试试,如果还出现,我认为就不是Hook得问题,
我还想知道出现了runtime 216错误的频率怎样,我作晚好象没得到错误。你寄给我
的程序有许多代码都注释掉,那个程序是否也会出现出现了runtime 216错误。

btw:
我已经将程序转寄给了Pipi.看看他能不能找到毛病,我现在比较忙,我会凑空看
看。人多力量大! 呵呵......
 
我不运行IDE,单独运行程序进行测试的时候,目标程序还是收不到。
目标程序的标题栏隐藏起来了,不会是因为这样吧。

>>你也将所有数据都放到FileMapping中试试
您能否将代码写出来?

runtime 216出现的频率不高,但每天一次老板都要杀死我。
我给您的程序即是有216错误的。
我试过分别将 vxd,dll拿掉,当dll拿掉时,216错误一直没有出现。
所以,我还是认为是dll的问题。
您在189805例子中部分代码我不明白
type TCommonData = record
HookID:HHook
《---hookid程序中没有用到啊,
// hNextHookProc: HHook
《---是不是用这个?
CallBackHandle:HWnd;
end;

var
hNextHookProc: HHook;
procSaveExit: Pointer;
receiver,msg_id:integer
《-receiver 只定义并赋了一下初值,
并没有派上用场。

var
HMapFile:THandle;
CommonData:^TCommonData;

如果都放进filemapping里面,代码要如何改?
我的头真的很大,请各位救救急,千谢万谢。

 
type TCommonData = record
hNextHookProc: HHook;
CallBackHandle:HWnd;
end;

var
hNextHookProc: HHook;
procSaveExit: Pointer

receiver,msg_id:integer


这样写对吗?
我刚才又出现一次216错误,据经验主要是在IE关闭窗口
时发生的。在关的时候感觉窗口稍微停一下,然后便出现
216错误。
晕倒了。
 
等我空了,我将他改了寄过来.(24:00 后)
 
你要到的3个变量:
其中
hNextHookProc: HHook

HWndHotKey : Thandle
会在跨进程使用(在别的进程激活的时候按键盘了的时候),所以要放在filemapping中

procSaveExit: Pointer;
指向什么过程?在exe中吗?你要把这个过程procSaveExit写在dll里面,
直接使用 @procSaveExit
 
修改后的dll以发到keymon@chinaday.net,查收。但不知是否可解决问题。
 
Pipi:出现216错误与我按键盘与否无关。所我的经验,使用
IE尤其是在上网的时候关闭IE窗口时容易出现。
等下我将根据沈前卫先生关于mouse hook的例子改写的
键盘hook程序寄给您看一下。
 
经过我的研究,发现 ExitProc 变量不能在dll中用
根本起不到作用。
在delphi中
直接写 dll的入口 DllEntryPoint 也不行

DllEntryPoint报告4种情况:
attach process、detach process、attach thread、detach thread
前1个应该在工程文件的begin。。。end中间
后3个在 DllProc 变量指定的过程中实现
 
后退
顶部