自从开始做现在这份工作以后,发现自己敲键盘明显增多,日常工作就是以编程以及type in各种各样东西为主,抑或就是在MSN Messenger上“笔谈”,以致我觉得我的键盘都有些承受不了了,“Alt”键有些粘滞。所以我打算短期内去买一个微软人体工学键盘,应该会对我的手腕和手指有好处。突然我又想到,很想知道一下我每天敲击键盘多少下。搜索了一下Google没有找到什么有关的结果,就自己用C#写了一个小程序来统计键盘敲击次数,每一次KeyUp算作一次敲击:
写的时候用的是SetWindowsHookEx函数。但运行后发现抓不住这个counter程序以外其他进程中的键盘敲击,查到一片KB318804 “HOW TO: Set a Windows Hook in Visual C# .NET”,心凉了半截:里面说,“You cannot implement global hooks in Microsoft .NET Framework. To install a global hook, a hook must have a native dynamic-link library (DLL) export to inject itself in another process that requires a valid, consistent function to call into. This requires a DLL export, which .NET Framework does not support. Managed code has no concept of a consistent value for a function pointer because these function pointers are proxies that are built dynamically”,简单翻译过来说,因为.NET的DLL没法被unmanaged code的进程调用,所以.NET无法写全局钩子。
于是不甘心,继续找,在Code Project里面找到一篇文章“Global System Hooks in .NET”,它能在.NET里面实现全局钩子,用的方法是中间夹了一层,managed DLL<--unmanaged DLL<--其他进程。这种做法也挺容易理解的,无非是多做了一层界面出来。我不喜欢这样,原因和接下去一篇文章的作者讲到的一样,“but what I dislike there is an unmanaged DLL in C++ that is a main part of this solution. This unmanaged DLL in C++ and a number of classes make it complicated to integrate it in my own tiny application”。
继续找,终于找到一篇“Processing Global Mouse and Keyboard Hooks in C#”,它没有用增加一层unmanaged界面的方法,用的全部是.NET的。用它提供的方法,可以捕捉到全局的键盘和鼠标事件。当然,这并不代表那篇KB错了,只是作者发现那篇KB有两个例外:WH_KEYBOARD_LL和WH_MOUSE_LL是可以在.NET里面用的全局钩子。剩下的就简单了,把它的source code下载下来,review一下,然后外面加一层壳,做成floating window和托盘图标,就可以用了。在我的机器上,Performance也没有问题。
从现在的计数器显示来看,我写这篇Blog大概敲击了4,700次键盘。
-
2004.10.19,敲击键盘约55,000次
2004.11.10,敲击键盘约38,000次
2004.11.11,敲击键盘约45,000次
打印 | 张贴于 2004-10-18 18:16:00 | Tag:Dot NET

留言反馈
liudong3456789@163.com
wzc_0267@sina.com
再次谢谢了.............
zhuping618@163.com
谢谢了
谢谢了
zhaoyugede@163.com
lyp0722@163.com
我还是抱着一线希望,希望有分代码发到我信箱里
hnxiaozhao@163.com
我也想要一份源码学习一下
谢谢
yxm555111@163.com
beyond_idle@hotmail.com
SetWindowsHookEx时总是抛出异常
大哥,能不能给看一下?
我怎么没看到啊
希望搂主共享一下
能不能给份源代码啊,学习一下
多谢!!
这个咚咚我找了好久
还是让我找到这里来了
留了联系方式,希望能和大家交流
public event KeyEventHandler KeyDown;
if (KeyDown!=null)
转换成VB。NET应该怎么写
第一句是不是这样?
public event keydown as KeyEventHandle
第二句呢?
If (nCode >= 0) And (KeyDown <> Nothing....
这儿的KeyDown应该换成什么写法?希望楼主能发个vb.net版本的。
我的email:cqucly@163.com
谢谢了先
谢谢你的回复。
第一个问题我回家再去试试,我觉得很可能就是你说的这样,控件抓住了消息,没有给Form。赫赫,没有研究过C#的消息传递机制,我需要仔细看看msdn才行啊
第二个问题,我在Menu的响应函数中,也是使用的application.exit ...
关于form消息,我的mouseenter什么的都是放在lable上的而不是form上的。我有点记不得了,好像mouse事件通常会先到控件然后再到form。也可以反过来,设一个什么属性。你遇到的这个问题多半是这个原因吧
关于图标不消失,是不是因为你的程序不是正常推出?我用application.exit就没这个问题。看看其他人有什么见解。
过两天或许会好的
我看了你的这篇文章,觉得很有意思,于是也自己写了一个小程序,也来Hook按键和鼠标位置的消息,界面风格什么的和你这个挺像的,学到了不少C#知识。
做下来以后,有两个地方一直没有解决。
第一个是,我给主Form加入了一些消息的事件响应函数。发现Form双击消息和MouseEnter,MouseLeave消息都接收不到。具体表现在响应函数中设置断点,但是停不住。
第二个是,程序结束后,任务栏的图标还在,要鼠标晃一下,刷新一下才能消失。
这两个问题能帮忙解答一下么??我是一个VC++程序员,对C#不熟啊~~谢谢!
把你的顶掉了
我不太清楚如果CS也用了钩子,接下去会是怎样
统计了一小段时间,在1800次敲击中,排名前20的key是:
Space 220
Return 166
A 129
I 118
N 110
E 78
O 74
H 73
Back 71
LShiftKey 63
G 57
U 57
LMenu 54
Left 43
C 41
B 33
Tab 32
Y 31
Z 29
W 27
我得emai
chenxf@lianchuang.com
我也刚装sp2不久
或许kb里面或者groups.google.com会有答案
就是在注册表的HKLM\\software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug项中Debugger的值是例如"C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin\msdev.exe" -p %ld -e %ld指向一个调试器,
这样在进程出现异常的时候,在出错对话框中按调试按钮就可以调试这个进程了.但在安装了xp sp2后好象这个功能没有了,一按调试就会直接终止这个进程,不知道有没有什么方法恢复?
在google上搜了一下,好象没有什么满意的答案,这样对程序员来说太不方便了,不知道楼主知道怎么解决吗?
就是移动距离太麻烦,要折算像素和实际距离的关系,麻烦。不高兴做了。本来就是图个好玩嘛
不方便说,不是知道是不是可以说
> microsoft在中国主要开发什么项目?
不方便说,不是知道是不是可以说
> 听人说好象微软在中国的开发主要是本地化什么的?
不是的
> 主要的技术开发都在美国,不知道是不是这样?
我想是的。这也符合常理。
microsoft在中国主要开发什么项目?
听人说好象微软在中国的开发主要是本地化什么的?
主要的技术开发都在美国,不知道是不是这样?
原理是做一个无边匡的form,然后处理mouse on, mouse move 和mouse up事件
private void label1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
this.isMoving=true;
mouse_offset=new Point(-e.X,-e.Y);
}
private void label1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if(this.isMoving)
{
if(e.Button==MouseButtons.Left)
{
Point mousePos=Control.MousePosition;
mousePos.Offset(mouse_offset.X,mouse_offset.Y);
this.Location=mousePos;
}
}
}
private void label1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
this.isMoving=false;
}
可以给一个示例吗??以前一直做web,很少做这样的程序
偶的wish是不是比较多啊,哈哈
SOURCE CODE, NOW!
1. Open Source
2. Remember window position
3. Window transparent
4.
5.
6.
7.
8.
其他的还没有想好... ;)
如果是,这是一个open issue,我也遇到过
不太清楚。debug一下应该就知道了,我想无非windows xp和2003之间的一些微小区别导致的
Strictly speaking, it may not be appropriate to call these "global hooks". The callback functions are executed with the context of the original thread that installs the hooks, instead of the context of the target process.
ripper提供的信息很有用....
谢谢分享