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

来源:互联网 发布:shell脚本编程pdf 编辑:程序博客网 时间:2024/05/18 12:42

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_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK 中键 WM_MBUTTONDOWN WM_MBUTTONUP WM_MBUTTONDBLCLK 右键 WM_RBUTTONDOWN WM_RBUTTONUP WM_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_NCLBUTTONDOWN WM_NCLBUTTONUP WM_NCLBUTTONDBLCLK 中键 WM_NCMBUTTONDOWN WM_NCMBUTTONUP WM_NCMBUTTONDBLCLK 右键 WM_NCRBUTTONDOWN WM_NCRBUTTONUP WM_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消息给所有正在运行的应用程序。

0 0
原创粉丝点击