目录:

  • 滚动条
  • 键盘
  • 鼠标

滚动条ScrollBar

发送消息:WM_VSCROLL和WM_HSCROLL

参数wParam:wParam消息参数被分为一个低字组和一个高字组。wParam的低字组是一个数值,它指出了鼠标对滚动条进行的操作。这个数值被看作一个「通知码」。通知码的值由以SB(代表「scroll bar(滚动条)」)开头的标识符定义。wParam的高字组存当前滚动条的位置信息。

参数lParam: 对于来自作为窗口的一部分而建立的滚动条消息,您可以忽略lParam;它只用于作为子窗口而建立的滚动条(通常在对话框内)。

也带有wParam和lParam消息参数。

以下是在WINUSER.H中定义的通知码:

  1. #define SB_LINEUP 0
  2. #define SB_LINELEFT 0
  3. #define SB_LINEDOWN 1
  4. #define SB_LINERIGHT 1
  5. #define SB_PAGEUP 2
  6. #define SB_PAGELEFT 2
  7. #define SB_PAGEDOWN 3
  8. #define SB_PAGERIGHT 3
  9. #define SB_THUMBPOSITION 4
  10. #define SB_THUMBTRACK 5
  11. #define SB_TOP 6
  12. #define SB_LEFT 6
  13. #define SB_BOTTOM 7
  14. #define SB_RIGHT 7
  15. #define SB_ENDSCROLL 8

使用示范代码:

  1. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
  2. { //......
  3. hwnd = CreateWindow (szAppName, TEXT ("Get System Metrics No. 2"),
  4. WS_OVERLAPPEDWINDOW | WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,
  5. NULL, NULL, hInstance, NULL) ; //......
  6. }
  7. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  8. {
  9. switch (message) {
  10. case WM_CREATE:
  11. // Initialization
  12. SetScrollRange (hwnd, SB_VERT, , NUMLINES - , FALSE) ;
  13. SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
  14. return ;
  15. case WM_VSCROLL:
  16.  
  17. switch (LOWORD (wParam)) {
  18. case SB_LINEUP:iVscrollPos++;break;
    case SB_PAGEUP:break;
    case SB_THUMBPOSITION:break;
    //...... } //...... } }

键盘

发送消息:【按键消息】和【字符消息】

【按键消息】:

 

键按下

键释放

非系统键

WM_KEYDOWN

WM_KEYUP

系统键

WM_SYSKEYDOWN

WM_SYSKEYUP

(系统键:WM_SYSKEYDOWN和WM_SYSKEYUP消息经常由与Alt相组合的按键产生,这些按键启动程序菜单或者系统菜单上的选项,或者用于切换活动窗口等系统功能(Alt-Tab或者Alt-Esc),也可以用作系统菜单快捷键(Alt键与一个功能键相结合,例如Alt-F4用于关闭应用程序)。)

【字符消息】:TranslateMessage把字符消息放入消息队列中。此字符消息将是GetMessage从消息队列中得到的按键消息之后的下一个消息。

 

字符

死字符

非系统字符

WM_CHAR

WM_DEADCHAR

系统字符

WM_SYSCHAR

WM_SYSDEADCHAR

参数wParam:对所有四类按键消息,wParam是虚拟键代码,表示按下或释放的键,而lParam则包含属于按键的其它数据。

对于字符消息,wParam是字符的ASCII编码等,lParam 同上

参数lParam:如下图:

重复计数

重复计数是该消息所表示的按键次数,大多数情况下,重复计数设定为1。不过,如果按下一个键之后,您的窗口消息处理程序不够快,以致不能处理自动重复速率(您可以在「控制台」的「键盘」中进行设定)下的按键消息,Windows就把几个WM_KEYDOWN或者WM_SYSKEYDOWN消息组合到单个消息中,并相应地增加重复计数。WM_KEYUP或WM_SYSKEYUP消息的重复计数总是为1。

因为重复计数大于1指示按键速率大于您程序的处理能力,所以您也可能想在处理键盘消息时忽略重复计数。几乎每个人都有文书处理或执行电子表格时画面卷过头的经验,因为多余的按键堆满了键盘缓冲区,所以当程序用一些时间来处理每一次按键时,如果忽略您程序中的重复计数,就能够解决此问题。不过,有时可能也会用到重复计数,您应该尝试使用两种方法执行程序,并从中找出一种较好的方法。

OEM扫描码

OEM扫描码是由硬件(键盘)产生的代码。这对中古时代的汇编程序写作者来说应该很熟悉,它是从PC相容机种的ROM BIOS服务中所获得的值(OEM指的是PC的原始设备制造商(Original Equipment Manufacturer)及其与「IBM标准」同步的内容)。在此我们不需要更多的信息。除非需要依赖实际键盘布局的样貌,不然Windows程序可以忽略掉几乎所有的OEM扫描码信息,参见第二十二章的程序KBMIDI

扩充键旗标

如果按键结果来自IBM增强键盘的附加键之一,那么扩充键旗标为1(IBM增强型键盘有101或102个键。功能键在键盘顶端,光标移动键从数字键盘中分离出来,但在数字键盘上还保留有光标移动键的功能)。对键盘右端的Alt和Ctrl键,以及不是数字键盘那部分的光标移动键(包括Insert和Delete键)、数字键盘上的斜线(/)和Enter键以及Num Lock键等,此旗标均被设定为1。Windows程序通常忽略扩充键旗标。

内容代码

右按键时,假如同时压下ALT键,那么内容代码为1。对WM_SYSKEYUP与WM_SYSKEYDOWN而言,此位总视为1;而对WM_SYSKEYUP与WM_KEYDOW消息而言,此位为0。除了两个之外:

  • 如果活动窗口最小化了,则它没有输入焦点。这时候所有的按键都会产生WM_SYSKEYUP和WM_SYSKEYDOWN消息。如果Alt键未被按下,则内容代码字段被设定为0。Windows使用WM_SYSKEYUP和WM_SYSKEYDOWN消息,从而使最小化了的活动窗口不处理这些按键。
     
  • 对于一些外国语文(非英文)键盘,有些字符是通过Shift、Ctrl或者Alt键与其它键相组合而产生的。这时内容代码为1,但是此消息并非系统按键消息。
     

键的先前状态

如果在此之前键是释放的,则键的先前状态为0,否则为1。对WM_KEYUP或者WM_SYSKEYUP消息,它总是设定为1;但是对WM_KEYDOWN或者WM_SYSKEYDOWN消息,此位可以为0,也可以为1。如果为1,则表示该键是自动重复功能所产生的第二个或者后续消息。

转换状态

如果键正被按下,则转换状态为0;如果键正被释放,则转换状态为1。对WM_KEYDOWN或者WM_SYSKEYDOWN消息,此字段为0;对WM_KEYUP或者WM_SYSKEYUP消息,此字段为1。

位移状态

在处理按键消息时,您可能需要知道是否按下了位移键(Shift、Ctrl和Alt)或开关键(Caps Lock、Num Lock和Scroll Lock)。通过呼叫GetKeyState函数,您就能获得此信息。例如:

  1. iState = GetKeyState (VK_SHIFT) ;
  2. //如果按下了Shift,则iState值为负(即设定了最高位置位)。如果Caps Lock键打开,则从
  3. iState = GetKeyState (VK_CAPITAL) ;
  4. //传回的值低位被设为1。此位与键盘上的小灯保持一致。
  5.  
  6. /*
  7. 您在使用GetKeyState时,会带有虚拟键码VK_SHIFT、VK_CONTROL和VK_MENU(在说明Alt键时呼叫)。使用GetKeyState时,您也可以用下面的标识符来确定按下的Shift、Ctrl或Alt键是左边的还是右边的:VK_LSHIFT、VK_RSHIFT、VK_LCONTROL、VK_RCONTROL、VK_LMENU、VK_RMENU。这些标识符只用于GetKeyState和GetAsyncKeyState
  8.  
  9. 使用虚拟键码VK_LBUTTON、VK_RBUTTON和VK_MBUTTON,您也可以获得鼠标键的状态。
  10.  
  11. 注意GetKeyState的使用,它并非实时检查键盘状态,而只是检查直到目前为止正在处理的消息的键盘状态。多数情况下,这正符合您的要求。如果您需要确定使用者是否按下了Shift-Tab,请在处理Tab键的WM_KEYDOWN消息时呼叫GetKeyState,带有参数VK_SHIFT。如果GetKeyState传回的值为负,那么您就知道在按下Tab键之前按下了Shift键。并且,如果在您开始处理Tab键之前,已经释放了Shift键也没有关系。您知道,在按下Tab键的时候Shift键是按下的。
  12.  
  13. */

使用示范代码:

  1. //对于 IParam 的读取代码 (片段)
  2. //......
  3. TCHAR * szFormat[] = {
  4. TEXT ("%-13s %3d %-15s%c%6u %4d %3s %3s %4s %4s"),
  5. TEXT ("%-13s 0x%04X%1s%c %6u %4d %3s %3s %4s %4s") } ;
  6. //......
  7. TextOut (hdc, , (cyClient / cyChar - - i)*cyChar,szBuffer,
  8. wsprintf (szBuffer, szFormat [iType],
  9. szMessage [pmsg[i].message - WM_KEYFIRST],
  10. pmsg[i].wParam,
  11. (PTSTR) (iType ? TEXT (" ") : szKeyName),
  12. (TCHAR) (iType ? pmsg[i].wParam : ' '),
  13. LOWORD (pmsg[i].lParam),
  14. HIWORD (pmsg[i].lParam) & 0xFF,
  15. 0x01000000 & pmsg[i].lParam ? szYes : szNo,
  16. 0x20000000 & pmsg[i].lParam ? szYes : szNo,
  17. 0x40000000 & pmsg[i].lParam ? szDown : szUp,
  18. 0x80000000 & pmsg[i].lParam ? szUp:szDown));
    //......

鼠标:

发送消息:鼠标定义了21种消息,不过,其中有11个消息和显示区域无关(下面称之为「非显示区域」消息),Windows程序经常忽略这些消息。

【显示区域相关】:WM_MOUSEMOVE +

按下

释放

按下(双键)

WM_LBUTTONDOWN

WM_LBUTTONUP

WM_LBUTTONDBLCLK

WM_MBUTTONDOWN

WM_MBUTTONUP

WM_MBUTTONDBLCLK

WM_RBUTTONDOWN

WM_RBUTTONUP

WM_RBUTTONDBLCLK

【显示区域无关】:WM_NCMOUSEMOVE +

按下

释放

按下(双击)

WM_NCLBUTTONDOWN

WM_NCLBUTTONUP

WM_NCLBUTTONDBLCLK

WM_NCMBUTTONDOWN

WM_NCMBUTTONUP

WM_NCMBUTTONDBLCLK

WM_NCRBUTTONDOWN

WM_NCRBUTTONUP

WM_NCRBUTTONDBLCLK

+ WM_NCHITTEST

参数wParam:【显示区域】wParam的值指示鼠标按键以及Shift和Ctrl键的状态

       【非显示区域】wParam参数指明移动或者按鼠标按键的非显示区域。它设定为WINUSER.H中定义的以HT开头的标识符之一(HT表示「命中测试」)。

参数lParam:   【显示区域】Client鼠标的位置:低字组为x坐标,高字组为y坐标
       【非显示区域】屏幕鼠标的位置:低字组为x坐标,高字组为y坐标

使用小妙招(1):

wParam的值指示鼠标按键以及Shift和Ctrl键的状态。您可以使用表头文件WINUSER.H中定义的位屏蔽来测试wParam。MK前缀代表「鼠标按键」。

MK_LBUTTON

按下左键

MK_MBUTTON

按下中键

MK_RBUTTON

按下右键

MK_SHIFT

按下Shift键

MK_CONTROL

按下Ctrl键

  1. wparam & MK_SHIFT TRUE(非0),您就知道当左键按下时也按下了Shift键。
    妙招实例:
  1. //实现 左键 拖动时 画点
  2. case WM_MOUSEMOVE:
  3. if (wParam & MK_LBUTTON && iCount < )
  4.  
  5. {
  6. pt[iCount ].x = LOWORD (lParam) ;
  7. pt[iCount++].y = HIWORD (lParam) ;
  8.  
  9. hdc = GetDC (hwnd) ;
  10. SetPixel(hdc,LOWORD(lParam),HIWORD(lParam), ) ;
  11. ReleaseDC (hwnd, hdc) ;
  12. }
  13. return ;
  1. 使用小妙招(2):
  2.  
  3. Windows函数GetKeyState(在“指导书”第六章中介绍过)可以使用虚拟键码VK_LBUTTONVK_RBUTTONVK_MBUTTONVK_SHIFTVK_CONTROL来传回鼠标按键与Shift键的状态。
  1. 使用小妙招(3):
  1. 检测双击事件需要在创建窗口时指定参数: wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;

使用小妙招(4):

对于非显示区域的鼠标事件、以及下文将提到的“鼠标拦截”,得到的是整个屏幕的图素坐标,要得到其对应的可以直接使用的Client坐标,

您可以用两个Windows函数将屏幕坐标转换为显示区域坐标或者反之:

  1. ScreenToClient (hwnd, &pt) ;
  2.  
  3. ClientToScreen (hwnd, &pt) ;

  4. 使用小妙招(5):
    21个鼠标消息中的20个,最后一个消息是WM_NCHITTEST,它代表「非显示区域命中测试」。此消息优先于所有其它的显示区域和非显示区域鼠标消息。lParam参数含有鼠标位置的xy屏幕坐标,
    wParam参数没有用。

Windows应用程序通常把这个消息传送给DefWindowProc,然后Windows用WM_NCHITTEST消息产生与鼠标位置相关的所有其它鼠标消息。对于非显示区域鼠标消息,在处理WM_NCHITTEST时,从DefWindowProc传回的值将成为鼠标消息中的wParam参数,这个值可以是任意非显示区域鼠标消息的wParam值再加上以下内容:

HTCLIENT

HTNOWHERE

HTTRANSPARENT

HTERROR

显示区域

不在窗口中

窗口由另一个窗口覆盖

使DefWindowProc产生警示用的哔声

【猜测】【windows 来处理的话,自动处理了坐标转换等等;其返回的HT_... 就可以决定接下来产生的下一个消息:

“相当”于:

if(inClient)  SendClientMessage( hwnd,MOUSETYPE(MK_TEST),wParam(Shift...),lParam(PosTranslate));

else  SendClientMessage( hwnd,MOUSETYPE2(MK_TEST),wParam(HTClient...),lParam(PosOrigon));】
所以:

  1. case WM_NCHITTEST:
  2. return (LRESULT) HTNOWHERE ;

就可以有效地禁用您窗口中的所有显示区域和非显示区域鼠标消息。

使用小妙招(6):

对于一些有需要的应用,可以使用 鼠标拦截

  1. SetCapture (hwnd) ;
  2. ReleaseCapture () ;
  3. /*
  4. 在32位的Windows中,鼠标拦截要比在以前的Windows版本中有多一些限制。特别是,如果鼠标被拦截,而鼠标按键目前并未被按下,并且鼠标光标移到了另一个窗口上,
    那么将不是由拦截鼠标的那个窗口,而是由光标下面的窗口来接收鼠标消息。对于防止一个程序在拦截鼠标之后不释放它而引起整个系统的混乱,这是必要的。
  5. */

windows 编程 —— 消息与参数(滚动条、键盘、鼠标)的更多相关文章

  1. windows 编程 —— 消息与参数(定时器、初始化消息、改变大小)

    目录: 定时器 WM_TIMER 初始化消息 WM_CREATE 改变大小 WM_SIZE 定时器: 接收消息:WM_TIMER 参数wParam:wParam参数等于定时器的ID值(上述情形为1). ...

  2. 深刻:截获windows的消息并分析实例(DefWindowProc),以WM_NCHITTEST举例(Windows下每一个鼠标消息都是由 WM_NCHITTEST 消息产生的,这个消息的参数包含了鼠标位置的信息)

    1,回调函数工作机制 回调函数由操作系统自动调用,回调函数的返回值当然也是返回给操作系统了. 2,截获操作系统发出的消息,截获到后,将另外一个消息返回给操作系统,已达到欺骗操作系统的目的. 下面还是以 ...

  3. Windows 编程 键盘

    键盘对于大家来说可能再也熟悉不过了,它和鼠标是现在最常用的电脑输入设备.虽然在现在的图形界面操作系统下使用鼠标比使用键盘更方便.更广泛,但是鼠标还是一时半会儿取代不了它的老前辈——键盘的地位,尤其是在 ...

  4. Windows 窗体消息大全(速查)

    Windows窗口消息大全,全不全自己撸 通用窗口消息 WM_NULL:--------->空消息,可检测程序是否有响应等 WM_CREATE:--------->新建一个窗口 WM_DE ...

  5. Windows编程 鼠标

    客户区鼠标消息 由上一回我们得知Windows只把键盘消息发送给拥有输入焦点的窗口,而鼠标消息与此不同:只要鼠标跨越窗口或者在某窗口下按下鼠标键,那么窗口过程就会收到鼠标消息,不管该窗口是否活动或者是 ...

  6. 【Visual C++】游戏编程学习笔记之七:键盘输入消息

     本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder  微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...

  7. mac与windows共享键盘鼠标(synergy)

    桌面上有两台电脑, 一台mac一台windows, 由于桌面空间紧张, 放两套键盘鼠标有点浪费空间, 如果能让mac和windows共享键盘鼠标就好了, 经过一番搜寻, 找到了一款名为synergy的 ...

  8. windows编程,消息函数中拦截消息的问题

    很多年没有写windows窗口程序了,今天自制基于vulkan的程序时遇到了一些问题,部分代码如下: LRESULT CALLBACK XWindow::WndProc(HWND hWnd, UINT ...

  9. Windows编程入门程序详解

    引用:http://blog.csdn.net/jarvischu/article/details/8115390 1.     程序 /******************************* ...

随机推荐

  1. Java编程思想-泛型-简单泛型例子

    基本类型无法做为类型参数 代码如下: /** * */ package test.thinkinjava.Generics; import java.util.ArrayList; import ja ...

  2. Android-SVN

    服务器启动svn服务 svnserve -d -r /home/wbp/svn/actia/ 1 .svn  重新定位location , 改变新仓库的uuid , 今天操作SVN Client 发现 ...

  3. xp snapshot.

    snap current active window(alt + Print Screen SysRq). snap the whole window (Print Screen SysRq).

  4. EXPDP IMPDP 知识总结

    Data Pump Export ATTACH Default: job currently in the user's schema, if there is only one Purpose(目的 ...

  5. RSA PKCS1padding 填充模式

    在BouncyCastle实现RSA的PKCS1V1.5模式中,如果是公钥加密信息(forEncryption=true),密钥长度为1024位,那么输出的密文块长度为128个字节,输入的明文块长度为 ...

  6. Hibernate 性能优化之一级缓存

     1.一级缓存的生命周期     一级缓存在session中存放,只要打开session,一级缓存就存在了,当session关闭的时候,一级缓存就不存在了   2.一级缓存是依赖于谁存在的      ...

  7. JDK1.5中LOCK,Condition的使用

    import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.uti ...

  8. Taxi Cab Scheme POJ && HDU

    Online Judge Problem Set Authors Online Contests User Web Board Home Page F.A.Qs Statistical Charts ...

  9. Mysql 数据类型使用说明

    FLOAT 和DOUBLE 类型支持使用标准的浮点运算进行近似计算. DECIMAL类型用于存储精确的小数. 因为cpu不支持对DECIMAL的直接计算,所以在Mysql5.0及更高的版本中,MYSQ ...

  10. InstallShield安装包中集成第三方安装包的方案选择[转]

      我们在制作安装包时,有些情况下会涉及第三方安装的集成,这里将讨论如何调用安装第三方包,以及需要注意的事项. 第三方安装包的介质类型有很多,主要有:单独的一个Setup.exe,单独的一个msi包, ...