windows程序设计学习笔记-键盘,鼠标,计时器

6.键盘

当在键盘上按下一个键时,只有一个窗口过程能收到该键盘消息。
接收这个键盘事件的窗口为有输入焦点的窗口。
活动窗口总是最上层的窗口,有输入焦点的窗口只能是活动窗口或其子窗口。

子窗口控件通常通过一个闪烁的插入符号或虚线指出其输入焦点。
当所有程序都最小化时,没有窗口有输入焦点。此时Windows仍把键盘消息发给活动窗口。此时所有击键将产生WM_SYSKEYDOWN/WM_SYSKEYUP。

窗口过程通过WM_SETFOCUS表示窗口正在接受输入焦点。WM_KILLFOCUS表示窗口正在失去输入焦点。

用户按下或释放键盘上一个键时,Windows产生格式化消息,消息先存储在系统消息队列中。仅当Windows应用程序完成了对前一个用户输入消息的处理后,windows才从系统消息队列中取下一条消息,并把它放入应用程序消息队列。

对产生可显示字符的击键组合,windows在发送击键消息的同时还发送字符消息。

当用户按下一个键时,windows将WM_KEYDOWN或WM_SYSKEYDOWN消息放入具有输入焦点的窗口的消息队列中,按下不放时,产生多个。当该键被释放时,,windows把WM_KEYUP或WM_SYSKEYUP消息放入相应的消息队列中。

当输入键和Alt键组合时通常产生WM_SYSKEYDOWN,WM_SYSKEYUP。Windows会在DefWindowProc中处理须处理的系统击键消息。

对四类击键消息,wParam是虚拟键代码,标识那个键被按下。
lParam:

位数含义解释
0-15重复计数按下不放,产生速度大于处理速度,把多条WM_KEYDOWN/SYSKEYDOWN合并成一条,此字段表示合并条数
29内容代码击键时按下了Alt,此位为1.
30键的先前状态先前状态为释放,此位为0下,此位为1
31转换状态键正在被按下,此位为0。正在被释放此位为1

iState = GetKeyState(虚拟键代码)
获取的是这条消息产生时,记录的对应键的状态。
GetAsyncKeyState
获取键的实时状态。

SendMessage(hwnd,message, wParam, lParam)
把消息直接发给hwnd的窗口过程,消息被处理后,才返回。

TranslateMessage:负责把击键消息转换为字符消息,并把产生的字符消息放入应用程序的消息队列。字符消息也就放在了击键消息的后面。

6.1.字符消息

字符消息分四类:
WM_CHAR,WM_DEADCHAR
WM_SYSCHAR, WM_SYSDEADCHAR
四类字符消息中, lParam和产生此字符码消息的击键消息的lParam一样。
wParam是ANSI或Unicode字符码。【RegisterClassW对应Unicode字符码,RegisterClassA对应ANSI】

IsWindowUnicode(hwnd)//确认窗口是否为Unicode。

单按A产生,‘a’。Shift + A产生’A’。Ctrl + M产生’\r’。
Windows在采用了Ctrl+字母键作为键盘快捷键时,组合不再产生字符消息。

6.2.插入符号

Windows中5个基本的插入符号函数:
CreateCaret:创建和窗口关联的插入符号。
SetCaretPos:设置窗口内插入符号的位置。
ShowCaret:显示插入符号。
HideCaret:隐藏插入符号。
DestroyCaret:销毁插入符号。

GetCaretPos:获取当前插入符号位置
GetCaretBlinkTime/SetCaretBlinkTime

一个消息队列仅能够支持一个插入符号。任何时候仅有一个窗口具有输入焦点。
插入符号使用的主要规则:
在窗口过程处理WM_SETFOCUS时调用CreateCaret。处理WM_KILLFOOCUS时调用DestroyCaret。

创建的插入符号是隐藏的,须用ShowCaret来显示。
HideCaret。【多次HideCaret后同样多次ShowCaret才能使显示】

7.鼠标

windows用户移动鼠标时,Windows在显示设备上显示小图标叫“鼠标指针”。鼠标指针有一单像素精度热点,来标明位置。

Windows只把键盘消息发到当前具有输入焦点的窗口。
鼠标消息:鼠标经过窗口或在窗口内被单击,该窗口的窗口过程会收到鼠标消息。【无论其是否是活动窗口或有焦点】。

按钮按下释放第二次按下按钮
左键WM_LBUTTONDOWNWM_LBUTTONUPWM_LBUTTONDBLCLK
中键WM_MBUTTONDOWNWM_MBUTTONUPWM_MBUTTONDBLCLK
右键WM_RBUTTONDOWNWM_RBUTTONUPWM_RBUTTONDBLCLK

对上述消息,
LOWORD(lParam):x坐标
HIWORD(lParam):y坐标
坐标是相对于窗口客户区左上角的来的
wParam:表示鼠标按钮,Shift,Ctrl状态。
MK_LBUTTON/MBUTTON/RBUTTON:按下左键/中键/右键
MK_SHIFT:按下Shift键
MK_CONTROL:按下Ctrl键

鼠标移经窗口客户区时,产生多个WM_MOUSEMOVE,消息队列中没有WM_MOUSEMOVE时,才将其放入。

在非活动窗口的客户区按下鼠标左键,windows将该窗口变为活动窗口【在单击子窗口时,获得输入焦点的是父窗口,而不是子窗口。
】,向窗口过程发送WM_LBUTTONDOWN。此时如果此时将鼠标移到另一个窗口后释放,前一个窗口过程接收不到WM_LBUTTONUP。
例外:
可以通过让窗口过程捕获鼠标来实现,鼠标在窗口的客户区外时,也能使窗口过程接收鼠标消息。
在显示一个系统模式消息框或系统模式对话框时,其他程序无法接收鼠标消息。

鼠标双击:
两次单击要在物理位置上十分靠近【默认下,一个系统字体平均字符宽度,半个字符高度】,时间上十分靠近。
只有在窗口对应的窗口类风格有CS_DBLCLKS时,窗口过程才能接收双击消息。

在含CS_DBLCLKS风格的窗口类的窗口上双击鼠标,产生消息:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_LBUTTONUP

如果鼠标位于窗口内部除客户区外的其他区域,Windows会向窗口过程发送一条“非客户区鼠标消息”。【窗口的非客户区包括标题栏,菜单和窗口滚动条】

按钮按下释放第二次按下按钮
左键WM_NCLBUTTONDOWNWM_NCLBUTTONUPWM_NCLBUTTONDBLCLK
中键WM_NCMBUTTONDOWNWM_NCMBUTTONUPWM_NCMBUTTONDBLCLK
右键WM_NCRBUTTONDOWNWM_NCRBUTTONUPWM_NCRBUTTONDBLCLK

对上述这些消息:
wParam:非客户区鼠标移动或单击的位置
LOWORD(lParam):x坐标
HIWORD(lParam):y坐标
这些坐标是相对于屏幕左上角得来的。

ScreenToClient/ClientToScreen:完成屏幕坐标与客户区坐标的转换。

WM_NCHITEST
这个消息的优先级高于其他所有的客户区和非客户区鼠标消息。
wParam:没有用到
LOWORD(lParam):x坐标
HIWORD(lParam):y坐标

应用程序通常把这个消息发给DefWindowProc,然后Windows利用WM_NCHITTEST产生所有其他和鼠标位置相关的鼠标消息。
对非客户区消息,DefWindowProc处理WM_NCHITTEST后,返回一个可用于鼠标消息参数的wParam值。
wParam:
非客户区鼠标消息的wParam/HTCLIENT/HTNOWHERE/HTTRANSPARENT/HTERROR。

如返回HTCLIENT,Windows将屏幕坐标转换为客户区坐标,产生一个客户区鼠标消息。

Windows利用WM_NCHITTEST消息来产生其他所有的鼠标消息。
举例:
双击Windows程序系统菜单图标来关闭窗口过程:
1.双击产生一系列WM_NCHITTEST。
2.鼠标位于系统菜单图标上,DefWindowProc返回HTSYSMENU,
3.对此返回值,Windows在消息队列中添加一个WM_NCLBUTTONDBLCLK,其中wParam等于HTSYSMENU。
4.DefWindowProc处理wParam为HTSYSMENU的WM_NCLBUTTONDBLCLK时,Windows在消息队列中添加一个WM_SYSCOMMAND,wParam为SC_CLOSE。
5.DefWindowProc处理此消息,产生一个WM_CLOSE消息。
6.DefWindowProc会调用DestroyWindow函数来处理此消息。
7.DestroyWindow做一些处理同时向窗口过程 发送一个WM_DESTROY消息。
8.一般窗口过程处理WM_DESTROY消息按如下方式:
case WM_DESTROY:
PostQuitMessage(0);
break;
9.PostQuitMessage使Windows在消息队列中添加一个WM_QUIT消息。
10.GetMessage在取到WM_QUIT时返回0,从而跳出消息循环,使程序结束。

Windows为鼠标指针保留了一个显示计数。
安装鼠标下,显示计数初始值为0。否则,为-1。
只有显示计数为非负时,系统才显示鼠标指针。
ShowCursor(TRUE):使显示计数加1;
ShowCursor(FALSE):使显示计数减1;

GetCursorPos(&pt)/SetCursorPos(x, y):获取/设置鼠标指针位置。坐标均基于屏幕坐标。
GetCursorPos返回的是鼠标的当前位置。
鼠标消息lParam参数中的位置是消息产生时的位置。

7.1.子窗口

在单击子窗口时,获得输入焦点的是父窗口,而不是子窗口。

鼠标左键单击窗口,如果窗口为非活动窗口,第一步Windows向单击位置的父窗口发送WM_SETFOCUS,之后把WM_LBUTTONDOWN发送给具有输入焦点的窗口。

获得子窗口ID:
id = GetWindowLong(hwndChild, GWL_ID);
id = GetDlgCtrlID(hwndChild);
获得子窗口句柄:
hwndChild = GetDlgItem(hwndParent, idChild);

捕获鼠标:
SetCapture(hwnd);
之后,Windows会将所有鼠标消息发送给句柄为hwnd的窗口的窗口过程。此时鼠标消息总是以客户区消息的形式存在。
ReleaseCapture();
规则:
当鼠标在客户区内被按下时,才捕获。当释放按钮时,停止捕获。

鼠标滚轮:
滚轮的滚动产生WM_MOUSEWHEEL消息,并发送给具有输入焦点的窗口。
坐标值是相对于屏幕左上角得到的。
LOWORD(lParam):x坐标
HIWORD(lParam):y坐标

wParam:
LOWORD(wParam):包含一系列标志,来指明鼠标按钮,Shift,Ctrl键状态。
HIWORD(wParam):一个增量数值。120,表示文档向上滚动三行。-120,表示文档向下滚动三行。
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &ulScrollLines, 0); // ulScrollLines表示每个增量数值能滚动多少行。

8.计时器

SetTimer:设置一个定时器。
定时范围【1ms,4294967295ms】//最大约为50天
表示Windows每隔这么长时间向你的程序发送一条WM_TIMER消息。

KillTimer:停止计时器消息。
使程序不再收到WM_TIMER消息,同时清除消息队列中没被处理的WM_TIMER消息。

对当前设定的每一个计时器,Windows都会保持一个计数值,硬件始终滴答每出现一次,这个值会减1,当计数值减到0,Windows会把一个WM_TIMER消息放到适当的应用程序的消息队列中。
故实际的计时器间隔,为时钟滴答的整数倍。
Windows在程序的消息队列中至多放一条WM_TIMER消息。如果产生一条WM_TIMER时,程序在处理某消息,直到下一条WM_TIMER来时,上一个WM_TIMER还没得到处理,上一条WM_TIMER相当于被程序忽略了。

WM_TIMER:
wParam:等于计时器ID

回调函数须定义为CALLBACK类型。
Windows是从程序的代码空间外调用这个函数的。

使用计时器的方法
1.使用SetTimer,KillTimer,处理WM_TIMER消息。
SetTimer(hwnd, iTimerID, iMsecInterval, NULL);
KillTimer(hwnd, iTimerID);
2.
void CALLBACK TimerProc(HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime);
dwTime:记录了Windows从启动到现在逝去的毫秒数。
message:固定为WM_TIMER。
SetTimer(hwnd, iTimerID, iMsecInterval, TimerProc);
KillTimer(hwnd, iTimerID);
3.
iTimerID = SetTimer(NULL, 0, wMsecInterval, TimerProc);
计时器ID由Windows帮你分配。
KillTimer(NULL, iTimerID);

获取当前时间:
SYSTEMTIME st;
GetLocalTime(&st);/GetSystemTime
一个获取本机设置时区得到的时间,一个获取采用格林威治标准时间得到的时间。获取的时间是从本机获取的。
typedef struct SYSTEMTIME
{
WORD wYear;
WORD wMonth;// 1-12
WORD wDayOfWeek;//0-6
WORD wDay;//1-31
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
};

GetLocalInfo

如果用户改变任何系统设置,Windows会广播一个WM_SETTINGCHANGE消息给所有正在运行的应用程序。
系统日期或时间变化时,Windows会广播一个WM_TIMECHANGE消息给所有正在运行的应用程序。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raindayinrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值