WPARAM和LPARAM参数详解
- 格式:doc
- 大小:34.00 KB
- 文档页数:3
钩⼦函数讲解钩⼦,⼏乎所有的键盘监控程序都使⽤钩⼦机制来捕获系统的击键信息。
⼤家知道,在DOS操作系统下,如果要截获某种系统功能,可以在编程中采取截获中断的办法,⽐如要获取击键信息,可以使⽤9号中断调⽤,要获取应⽤程序对⽂件操作功能的调⽤可以截获21号中断。
DOS下截获中断的⽅法是这样的随意和⽅便,不论是驱动程序还是应⽤程序都可以操作,这样就给⼀些恶意程序留下了可乘之机,对系统的安全造成了极⼤的隐患。
⽽在Windows 2000下就不同了,Windows 2000采⽤了保护模式,在保护模式下的中断描述符表是受系统保护的,应⽤程序是不可能再通过修改中断向量来截获系统中断了。
这在提供了更⾼安全性的同时,实际上对应⽤程序在调⽤底层功能⽅⾯造成了很⼤的不便。
不过,Windows采取了⼀些变通的⽅法,将⼀些系统的底层调⽤封装在了⾃⼰的API函数中,通过向⽤户提供接⼝使⽤户可以受限的使⽤⼀些系统调⽤。
钩⼦,⼏乎所有的键盘监控程序都使⽤钩⼦机制来捕获系统的击键信息。
⼤家知道,在DOS操作系统下,如果要截获某种系统功能,可以在编程中采取截获中断的办法,⽐如要获取击键信息,可以使⽤9号中断调⽤,要获取应⽤程序对⽂件操作功能的调⽤可以截获21号中断。
DOS下截获中断的⽅法是这样的随意和⽅便,不论是驱动程序还是应⽤程序都可以操作,这样就给⼀些恶意程序留下了可乘之机,对系统的安全造成了极⼤的隐患。
⽽在Windows 2000下就不同了,Windows 2000采⽤了保护模式,在保护模式下的中断描述符表是受系统保护的,应⽤程序是不可能再通过修改中断向量来截获系统中断了。
这在提供了更⾼安全性的同时,实际上对应⽤程序在调⽤底层功能⽅⾯造成了很⼤的不便。
不过,Windows采取了⼀些变通的⽅法,将⼀些系统的底层调⽤封装在了⾃⼰的API函数中,通过向⽤户提供接⼝使⽤户可以受限的使⽤⼀些系统调⽤。
TIPS:钩⼦是Windows的消息处理机制中提供的⼀个监视点,应⽤程序可以在这⾥安装⼀个过滤程序,这样就可以在系统中的消息流到达⽬的程序前监控它们。
自己看核心编程,对消息分流器不太理解,这篇写的不错,所以转载。
很好理解,windows操作系统使用消息处理机制,那么,我们所设计的程序如何才能分辨和处理系统中的各种消息呢?这就是消息分流器的作用.简单来说,消息分流器就是一段代码,在我的讲述中,将分7重来循序渐进的介绍它.从最初的第1重到最成熟的第7重,它的样子会有很大的变化.但,实现的功能都是一样的,所不同的,仅仅是变得更加简练罢了.程序开始时候,会是main函数,然后会生成初始的窗口,同时会调用WndProc函数.这是一个自定义的函数,名字也会有变化,但其功能是一样的,就是运行消息分流器.WndProc函数如下: LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,WPARAM wParam, LPARAM lParam){//......return DefWindowProc(hwnd, msg, wParam, lParam);}这其中,hwnd是窗口的句柄,msg是系统发送来的消息的名字.wParam和lParam则是随消息一起发送来的消息参数.WndProc函数使用了消息分流器,下面把消息分流器的内容解释一下:一重,当不同的消息出现时,在其中写入相应的程序语句即可。
LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,WPARAM wParam, LPARAM lParam){switch(msg){case WM_CREATE:// ...return 0;case WM_PAINT:// ...return 0;case WM_DESTROY://...return 0;}return DefWindowProc(hwnd, msg, wParam, lParam);}二重,运用三个消息分流器进行处理。
LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg)case WM_CREATE:return HANDLE_WM_CREATE(hwnd, wParam, lParam, Cls_OnCreate);case WM_PAINT:return HANDLE_WM_PAINT(hwnd, wParam, lParam, Cls_OnPaint);case WM_DESTROY:return HANDLE_WM_DESTROY(hwnd, wParam, lParam, Cls_OnDestroy);}return DefWindowProc(hwnd, msg, wParam, lParam);}这里的HANDLE_WM_CREATE,HANDLE_WM_PAINT,HANDLE_WM_DESTROY就是消息分流器。
利用钩子函数来捕捉键盘响应的windows应用程序一:引言:你也许一直对金山词霸的屏幕抓词的实现原理感到困惑,你也许希望将你的键盘,鼠标的活动适时的记录下来,甚至你想知道木马在windows操作系统是怎样进行木马dll的加载的…..其实这些都是用到了windows的钩子函数。
因此本文将对钩子函数的相关知识进行阐述。
当然,本文的目的并不是想通过此程序让读者去窃取别人的密码,只是由于钩子函数在windows系统中是一个非常重要的系统接口函数,所以想和大家共同的探讨,当然本文也对怎样建立动态连结库(DLL)作了一些简单的描述。
(本文的程序为vc6.0的开发环境,语言是:C和win32 api)。
二:钩子概述:微软的windowsX操作系统是建立在事件驱动的机制上的,也就是通过消息传递来实现。
而钩子在windows操作系统中,是一种能在事件(比如:消息、鼠标激活、键盘响应)到达应用程序前中途接获事件的机制。
而且,钩子函数还可以通过修改、丢弃等手段来对事件起作用。
Windows 有两种钩子,一种是特定线程钩子(Thread specific hooks),一种是全局系统钩子(Systemwide hooks)。
特定线程钩子只是监视指定的线程,而全局系统钩子则可以监视系统中所有的线程。
无论是特定线程钩子,还是全局系统钩子,都是通过SetWindowsHookEx ()来设置钩子的。
对于特定线程钩子,钩子的函数既可以是包含在一个.exe也可以是一个.dll。
但是对于一个全局系统钩子,钩子函数必须包含在独立的dll中,因此,当我们要捕捉键盘响应时,我们必须创建一个动态链接库。
但是当钩子函数在得到了控制权,并对相关的事件处理完后,如果想要该消息得以继续的传递,那么则必须调用另一个函数:CallNextHookEx。
由于系统必须对每个消息处理,钩子程序因此增加了处理的负担,因此也降低了系统的性能。
鉴于这一点,在windows ce中对钩子程序并不支持。
c语言sendmessage函数用法摘要:1.C语言SendMessage函数简介2.SendMessage函数的参数3.SendMessage函数的用法示例4.注意事项正文:C语言SendMessage函数是一种在Windows操作系统中发送消息的函数,它主要用于窗口程序设计。
SendMessage函数的原型为:```INT WINAPI SendMessage(HWND hWnd, // 窗口句柄UINT uMsg, // 消息码WPARAM wParam, // 消息参数LPARAM lParam // 消息附加参数);```SendMessage函数共有四个参数,分别是:1.hWnd:窗口句柄,表示要发送消息的窗口。
2.uMsg:消息码,表示要发送的消息类型。
例如:WM_NULL、WM_KEYDOWN、WM_LBUTTONDOWN等。
3.wParam:消息参数,根据不同消息类型,传递相应的信息。
例如,在WM_KEYDOWN消息中,wParam表示按下的键码。
4.lParam:消息附加参数,用于提供消息的相关信息。
例如,在WM_MOUSEMOVE消息中,lParam表示鼠标移动的坐标。
下面举一个SendMessage函数的用法示例:```c#include <windows.h>LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){switch (message){case WM_DESTROY:PostQuitMessage(0);return 0;case WM_KEYDOWN:switch (wParam){case VK_SPACE:MessageBox(NULL, TEXT("你按下了空格键"), TEXT("提示"), MB_OK);break;}return 0;default:return DefWindowProc(hWnd, message, wParam, lParam);}}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){WNDCLASS wc = {0};wc.lpfnWndProc = WndProc;wc.hInstance = hInstance;wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);wc.hCursor = LoadCursor(NULL, IDC_ARROW);wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);wc.lpszClassName = TEXT("SendMessageExample");if (!RegisterClass(&wc)){MessageBox(NULL, TEXT("注册窗口类失败"), TEXT("错误"), MB_OK);return 1;}HWND hWnd = CreateWindowEx(0,TEXT("SendMessageExample"),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,NULL,NULL,hInstance,NULL);if (!hWnd){MessageBox(NULL, TEXT("创建窗口失败"), TEXT("错误"), MB_OK);return 1;}ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);MSG msg;while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}```以上示例创建了一个简单的窗口程序,当用户按下空格键时,会弹出一个提示框显示“你按下了空格键”。
sendmessage用法Sendmessage是一种非常常见的Windows API,它能够在应用程序之间传递消息,并执行一些操作。
在本篇文章中,我们将深入探讨sendmessage的用法,为大家提供一些有用的技巧和技巧。
一、理解Sendmessage函数的原理及参数Sendmessage可以理解为发送消息的函数。
它的完整原型如下:LRESULT SendMessage(HWND hWnd, //消息目标窗口的句柄UINT Msg, //消息IDWPARAM wParam, //消息的额外参数(可能是一个值或者指针)LPARAM lParam //消息的额外参数(可能是一个值或者指针));其中,hWnd为消息目标窗口的句柄,Msg为消息ID,wParam和lParam 分别是消息所需要的参数。
例如,如果您想要发送一条命令消息(如WM_COMMAND)给一个窗口控件,您需要提供控件的句柄(hWnd)和控件的ID(Msg),并将wParam和lParam设置为所需的附加参数。
二、使用Sendmessage函数发送消息发送消息的过程非常简单。
首先,您需要确定消息的接收方窗口的句柄。
一旦您有了这个,您只需要使用Sendmessage函数提供的控制信息,将消息发送给这个句柄就可以了。
下面是一个示例,展示了如何使用sendmessage函数在一个应用程序之间发送消息:例子1:向另一程序发送消息HWND hWndTarget = FindWindow(NULL, L"目标应用程序"); //查找目标窗口的句柄int msgID = RegisterWindowMessage(L"MY_MESSAGE"); //注册自定义消息SendMessage(hWndTarget, msgID, (WPARAM)hwnd, (LPARAM)nIndex); //发送自定义消息在这个例子中,由于使用了注册自定义消息的办法,你可以在不同的应用程序之间发送消息,并进行一些交互操作。
消息映射的实现Windows消息概述Windows应用程序的输入由Windows系统以消息的形式发送给应用程序的窗口。
这些窗口通过窗口过程来接收和处理消息,然后把控制返还给Windows。
消息的分类队列消息和非队列消息从消息的发送途径上看,消息分两种:队列消息和非队列消息。
队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。
这里,对消息队列阐述如下:Windows维护一个系统消息队列(System message queue),每个GUI线程有一个线程消息队列(Thread message queue)。
鼠标、键盘事件由鼠标或键盘驱动程序转换成输入消息并把消息放进系统消息队列,例如WM_MOUSEMOVE、WM_LBUTTONUP、WM_KEYDOWN、WM_CHAR等等。
Windows 每次从系统消息队列移走一个消息,确定它是送给哪个窗口的和这个窗口是由哪个线程创建的,然后,把它放进窗口创建线程的线程消息队列。
线程消息队列接收送给该线程所创建窗口的消息。
线程从消息队列取出消息,通过Windows把它送给适当的窗口过程来处理。
除了键盘、鼠标消息以外,队列消息还有WM_PAINT、WM_TIMER和WM_QUIT。
这些队列消息以外的绝大多数消息是非队列消息。
系统消息和应用程序消息从消息的来源来看,可以分为:系统定义的消息和应用程序定义的消息。
系统消息ID的范围是从0到WM_USER-1,或0X80000到0XBFFFF;应用程序消息从WM_USER(0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USER到0X7FFF范围的消息由应用程序自己使用;0XC000到0XFFFF范围的消息用来和其他应用程序通信,为了ID的唯一性,使用::RegisterWindowMessage来得到该范围的消息ID。
消息结构和消息处理消息的结构为了从消息队列获取消息信息,需要使用MSG结构。
pywin32常⽤模块函数⽤法整理Win32gui: Windows图形界⾯接⼝模块。
主要负责操作窗⼝切换以及窗⼝中元素id标签的获取Win32api: Windows开发接⼝模块。
主要负责模拟键盘和⿏标操作,对win32gui获取的标签进⾏点击/获取值/修改值等操作Win32con:全⾯的库函数,提供Win32gui和Win32api需要的操作参数Win32gui 函数FindWindowhld=win32gui.FindWindow(ClassName,Title)ClassName:窗⼝的类名Title:窗⼝的标题名称,即左上⾓的⽂字描述信息hld:返回结果为当前窗⼝的句柄信息,以下是使⽤AutoItv3抓取的Windows【另存为】窗⼝信息:hld=win32gui.FindWindow("#32770",u"另存为")>>>> Window <<<<Title: 另存为 #这⾥就是上⾯的TitleClass: #32770 #这⾥就是上⾯的ClassNamePosition: 0, 0Size: 680, 480Style: 0x96CC02C4ExStyle: 0x00010101Handle: 0x001E03A0 #这⾥就是上⾯函数返回值SetForegroundWindowwin32gui.SetForegroundWindow(hld)hld:为上⾯获取到的窗⼝句柄信息主要⽤于激活该窗⼝,此时窗⼝会是最前⾯⼀层在找到窗⼝句柄后,需要先将窗⼝设置为最前⾯⼀层才能模拟⿏标键盘操作当前窗⼝上的元素。
FindWindowExwin32gui. FindWindowEx(hld,Child, ClassName, Title)hld:⽬标窗⼝的⽗窗⼝,也是上⾯获取到的窗⼝句柄信息。
通过⽗向下找⼦Child:⽬标窗⼝的⼦窗⼝。
WPARAM 和LPARAM,消息响应机制
wParam和lParam 这两个是Win16系统遗留下来的产物,在Win16API中WndProc有两个参数:
一个是WORD类型的16位整型变量;另一个是LONG类型的32位整型变量。
因此根据匈牙利命名法,16位的变量就被命名为wParam, 32位的变量就被命名为lParam。
到了Win32API中,原来的16位变量也被扩展为32位,因此此时wParam和lParam的大小完全相同。
在Win32API的早期,为了保证和Win16API的代码可移植性MS定义了WPARAM和LPARAM两个宏。
当时保留了w前缀的原因一方面是由于WPARAM宏也已W开头,还有也因为要提醒程序员注意到可移植性,当然到了现在Win16早已退出历史舞台,这个前缀也就约定俗成的沿用下来了。
例如:主程序MyDlg.cpp
1.自定义消息:#define WM_TRAY WM_USER 100
2.函数原形:afx_msg LRESULT OnTrayNotify(WPARAM wParam,LPARAM lParam);
3.消息映射:ON_MESSAGE(WM_TRAY,OnTrayNotify)
4.原函数:
LRESULT CMyDlg::OnTrayNotify(WPARAM wParam,LPARAM lParam)
{
return m_tray.OnTrayNotify(wParam,lParam);
}
托盘类的实现程序Tray.cpp
成员函数:
int OnTrayNotify(WPARAM wID,LPARAM lEvent)
{
if(wID == TRAYNOTIFYDATA.uID)
return 0;
if(lEvent == WM_LBUTTONDOWN){
处理代码
}
else if(lEvent == WM_RBUTTONDOWN){
处理代码
}
return 0;
}
WPARAM 和LPARAM 本质上没有什么区别:都是32位数,
但是区别也还是有的:除了上面几位若仁兄说的关于16位的的历史问题外,MICROSOFT 在使用时两种参数分别代表不同的含义和内容,WPARAM常常代表一些控件的ID或者高位底位组合起来分别表示鼠标的位置,如果消息的发送者需要将某种结构的指针或者是某种类型的句柄时,习惯上用LPARAM来传递,可以参考各种控件的通知消息:可以查看:EN_CHANGE (EDIT控件的一个通知消息),CBEM_INSERTITEM(可扩展组合框的
可接受消息)等等来加以领会。
理论上在使用自定义消息时,WPARAM LPARAM的含义可以程序员任意指定的,但是最好遵从MFC中的习惯。
在调用SendMessage()函数时,第二个参数是WPARAM,第三个参数是这个消息的LPARAM,但是你在程序中某个类中写下ON_MESSAGE()宏来处理这个消息时,处理函数SomeHandler(WPARAM,LPRAM(默认是0))中解释这两个参数时必须按照SendMessage调用中的意义来进行。
消息响应机制
1、消息的组成:一个消息由一个消息名称(UINT),和两个参数(WPARAM,LPARAM)。
当用户进行了输入或是窗口的状态发生改变时系统都会发送消息到某一个窗口。
例如当菜单转中之后会有WM_COMMAND消息发送,WPARAM的高字中(HIWORD(wParam))是命令的ID号,对菜单来讲就是菜单ID。
当然用户也可以定义自己的消息名称,也可以利用自定义消息来发送通知和传送数据。
2、谁将收到消息:一个消息必须由一个窗口接收。
在窗口的过程(WNDPROC)中可以对消息进行分析,对自己感兴趣的消息进行处理。
例如你希望对菜单选择进行处理那么你可以定义对WM_COMMAND进行处理的代码,如果希望在窗口中进行图形输出就必须对WM_PAINT进行处理。
3、未处理的消息到那里去了:M$为窗口编写了默认的窗口过程,这个窗口过程将负责处理那些你不处理消息。
正因为有了这个默认窗口过程我们才可以利用Windows的窗口进行开发而不必过多关注窗口各种消息的处理。
例如窗口在被拖动时会有很多消息发送,而我们都可以不予理睬让系统自己去处理。
4、窗口句柄:说到消息就不能不说窗口句柄,系统通过窗口句柄来在整个系统中唯一标识一个窗口,发送一个消息时必须指定一个窗口句柄表明该消息由那个窗口接收。
而每个窗口都会有自己的窗口过程,所以用户的输入就会被正确的处理。
例如有两个窗口共用一个窗口过程代码,你在窗口一上按下鼠标时消息就会通过窗口一的句柄被发送到窗口一而不是窗口二。
5、示例:下面有一段伪代码演示如何在窗口过程中处理消息
LONG yourWndProc(HWND hWnd,UINT uM essageType,WPARAM wP,LPARAM)
{
switch(uM essageType)
{//使用SWITCH语句将各种消息分开
case(WM_PAINT):
doYourWindow(...);//在窗口需要重新绘制时进行输出
break;
case(WM_LBUTTONDOWN):
doYourWork(...);//在鼠标左键被按下时进行处理
break;
default:
callDefaultWndProc(...);//对于其它情况就让系统自己处理
break;
}
}
接下来谈谈什么是消息机制:系统将会维护一个或多个消息队列,所有产生的消息都回被放入或是插入队列中。
系统会在队列中取出每一条消息,根据消息的接收句柄而将该消息发送给拥有该窗口的程序的消息循环。
每一个运行的程序都有自己的消息循环,在循环中得到属于自己的消息并根据接收窗口的句柄调用相应的窗口过程。
而在没有消息时消息循环就将控制权交给系统所以Windows可以同时进行多个任务。
下面的伪代码演示了消息循环的用法:
while(1)
{
id=getM essage(...);
if(id == quit)
break;
translateMessage(...);
}
当该程序没有消息通知时getMessage就不会返回,也就不会占用系统的CPU时间。