nullnull第5讲
Windows应用程序中的键盘与鼠标工控机和上位软件讨论:讨论上位系统:WINCC LABVIEW INTOUCH MATLAB VB VC群 号:20423623
电子学习共同促进群学习探讨单片机 电子线路等电子技术。
群 号:234742235
电气制图软件交流促进
群 号:182667049
自动化行业非标PLC编程
群 号:170665069
null 扫描码是依赖于具体设备的,为达到设备无关性的要求,往往使用与具体设备无关的虚拟码,虚拟码是由Windows系统定义的与设备无关的键的标识6.1 键盘在应用程序中的应用null键盘上每一个键都有一个唯一值,这个唯一值就称为“扫描码”(scan code),对于键盘上每个键来说,“扫描码”是设备相关的。当用户按键时会产生两次扫描码,一次是按下键时,一次是放开时。
然后,键盘驱动把扫描码解释并转换(映射)为“虚键码”(virtual-key code),这个码是设备无关的,其值被系统所定义并用来标识每一个键。转换扫描码后,键盘布局会创建一个包含扫描码、虚键码以及其他按键信息的消息,并把这个消息放入系统消息队列。接着,系统从系统消息队列中删除该消息,再投递到相应线程的消息队列中。最后,线程的消息循环移除该消息并传递到相应窗口过程以进行处理。 null 虚拟码是一种与设备无关的键盘编码,它的值存放在键盘消息的wParam参数中,用以标识哪一个键被按下或释放,最常用的虚拟码已经在Windows.h中定义,null应用程序一般有几个窗
口,但当按下某一个键
时,只有一个窗口能接
收到该键盘消息,接收
这个键盘消息的窗口称
为有“输入焦点”的窗口有“输入焦点”
的窗口应是活
动窗口或者活
动窗口的子窗口null键盘消息按键消息字符消息按下或松开一个键时
就产生了一按键消息一个按键的组合产生了
一个可以显示的字符时,
就产生了一个字符消息”A”=shift+”a”系统按键消息非系统按键消息Alt键与相关输入键的组合
产生的消息,这些键一般
由Windows系统内部直接
处理,应用程序不处理若应用程序处理了这
些系统键消息,还要调
用DefWindowsProc()函
数,以便不影响系统对
它们的处理不使用Alt键组合
的的按键消息null32位的变量包含了识别按下
的键的虚键码重复次数重复次数
你可以通过检查重复次数,来确定一次按键是否产生了多个按键消息。如果键盘产生WM_KEYDOWN或WM_SYSKEYDOWN消息后,超过一定时间应用程序还未处理这些消息的话,系统就会增加重复计数。通常,是因为用户保持按键状态较长时间,而启动了键盘的自动重复技术机制。系统不会因此产生多个键盘消息,相反,系统会组合这些消息,并增加这个消息的重复次数。释放一个按键时不会启动自动重复机制,所以WM_KEYUP与WM_SYSKEYUP消息的重复次数总会是1。扩充键标志
扩充键标志
扩充键标志用来标识按键消息中是否包含了增强型键盘的附加键,这些扩充键包括:键盘右手边的ALT、CTRL键,INS、DEL、HOME、END、PAGE UP、PAGE DOWN,小键盘左边的方向键,NUM LOCK、BREAK(CTRL+PAUSE)、PRINT SCRNT以及小键盘上的除号(/)键及ENTER键。如果键为以上键的话,扩充键标志即会设置。上下文标志
上下文标志
上下文标志是为了说明按键消息产生时,ALT键是否已经按下,如果为1,
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示ALT键已经按下,否则没有按下。前键状态标志
前键状态标志
前键状态标志用来说明产生按键消息的键原来是抬起的还是按下的。如果为1,表示原来是按下的,0原来是抬起的。你可以通过该标志来辨别该消息是否是由键盘自动重复机制产生的。如果为1,表示WM_KEYDOWN与WM_SYSKEYDOWN消息是自动产生的,对于WM_KEYUP与WM_SYSKEYUP消息来说,该标志总会为0。转换状态标志
转换状态标志
转换状态标志用来说明该消息是按下键时还是释放键时产生的,对于WM_KEYDOWN、WM_SYSKEYDOWN来说该标志总会为0,对于WM_KEYUP、WM_SYSKEYUP总会是1。null 在WinMain函数的消息循环中包含了TranslateMessage函数,其功能是把按键消息转化为字符消息,但只有当键盘驱动程序把键盘字符映射成ASCII码后才能产生WM_CHAR消息null消息循环中 while(GetMessage(&Msg,NULL,0,0)) { TranslateMessage(&Msg);//翻译消息 DispatchMessage(&Msg);//将消息传递给窗口处理函数 } return Msg.wParam; TranslateMessage函数首先将按健消息转换成字符消息,最后WndProc函数中进行case选择。 WM_CHAR能区分1和! . WM_KEYDOWN只处理某个按键
所以ctrl+E 选WM_KEYDOWN GetKeyStateGetKeyStateshort GetKeyState (int nVirtKey); 它返回大小写字母键盘(换挡键)、Ctrl、Alt和Shift的按下/释放状态,指出这些键是否在转换状态。如果键盘有两个键具有同样的功能,例如,键盘两边的那两个Shift键,则该函数可以用来区分是哪个被按下。(大部分键盘有左右Shife键,一些有左右Ctrl和Alt键。)
nVirKey表示要查询的键的虚拟键码。如果返回值的高位被设置,则该键被按下。如果返回值的最低有效位被设置,则该键在转换状态;也就是说,自从系统启动开始,该键已被按下奇数次。返回的状态是消息从消息队列里读出时的状态,并不是键的实时状态。需要注意的是,Alt键的虚拟键是VK_MENU。WM_KEYDOWN和WM_CHAR的区别WM_KEYDOWN和WM_CHAR的区别1、WM_KEYDOWN按下任何键都发,WM_CHAR是按下可显示的符号键才有.
2、有时用户按动一下某个键, 我们想得到一条表示用户输入了某个字符的消息,并在消息补充参数中提供字符的编码。TranslateMessage能将可行的WM_KEYDOWN, WM_KEYUP消息对转换成一条WM_CHAR消息,
当按键被释放,Windows会发送一个WM_KEYUP消息。如果按键按的时间长一些,则自动重复功能就会开启,多条WM_KEYDOWN消息和WM_CHAR消息会被送出,直到最后键被释放,发出WM_KEYUP消息。当Alt键和另一个键一起被按下时,上面讨论的消息会被WM_SYSKEYDOWN、WM_SYSKEYCHAR和WM_SYSKEYUP消息替代转换过程不会影响原来的消息,只在消息队列中增加新消息。
4、对于WM_KEYDOWN消息中的wParam,假如用到控制键如ctrl的时候,可以用VK_CONTROL来表示
//假如用到字母键和数字键的时候,(如q)可以用'Q'来表示,(又如2)可以用'2'来表示。
5、WM_CHAR消息的lParam参数的含义与其它键盘消息一样, 而它的wParam则表示相应字符的ASCII编码 .
null6、WM_CHAR消息是俘获某一个字符的消息,WM_KEYDOWN消息是俘获某一个键按下的消息 //假如分别按下“q”和“shift+q”,发出的WM_KEYDOWN消息都是代表q键,而发出的WM_CHAR消息分别是“q”和“Q”
7、WM_KEYDOWN消息可以处理键盘上的所有键,但不能区分1和!的不同,WM_CHAR消息只能处理某个字符,将1和!作为两个不同的字符来处理
8、对WM_CHAR和WM_SYSCHAR消息来说,wParam的低四位为按键的ASCII值,如果该值大于 127表示为中文,和下一个WM_CHAR消息一起组成一个汉字. lParam为该按键按的数次。 多数情况下,应用程序只是处理WM_CHAR消息,而忽略WM_KEYDOWN和WM_KEYUP消息。WM_CHAR消息作为第2级抽象,使应用程序不必考虑键的释放或按下状态,而将精力集中在键盘输入的字符上。键盘输入的处理过程键盘输入的处理过程分二步:
1、Windows给窗口发送WM_KEYDOWN 和WM_KEYUP消息时用的是虚拟键盘码,但在它们到达窗口之前,又被翻译过.
2、如果按下一个ANSI字符(引发一个WM_KEYDOWN消息),则该翻译函数将检查键盘的Shift键状态,然后发送一个WM_CHAR消息,该消息带着正常的键码,可能是大写或者是小写.光标键和功能键没有码,因而它们不被翻译,窗口只是得到MM_KEYDOWN和WM_KEYUP消息.
所以在WM_CHAR消息响应中对于wParam参数中没有所击字符的ASCII与VK_SHIFT的组合,而可以有VK_CONTROL.
WM_CHAR、WM_KEYDOWN、WM_KEYUPWM_CHAR、WM_KEYDOWN、WM_KEYUP这三个消息用来处理用户的键盘数据,当用户在键盘上按下某个键的时候,会产生WM_KEYDOWN消息,释放按键的时候又回产生WM_KEYUP消息,所以WM_KEYDOWN与WM_KEYUP消息一般总是成对出现的.
至于WM_CHAR消息是在用户的键盘输入能产生有效的ASCII码时才会发生。
这里特别提醒要注意前两个消息与WM_CHAR消息在使用上是有区别的。在前两个消息中,伴随消息传递的是按键的虚拟键码,所以这两个消息可以处理非打印字符,如方向键,功能键等。而伴随WM_CHAR消息的参数是所按的键的ASCII码,ASCII码是可以区分字母的大小写的。而虚拟键码是不能区分大小写的。按键的次序不同,产生的消息也不相同。按键的次序不同,产生的消息也不相同。
例如:
1、按下并释放1键,读过程依次产生如表所示三条消息。按下1键所产生的消息和wParam的取值 消息 wParam变量取值 WM_KEYDOWN 虚拟码1 WM_CHAR ASCII码“1” WM_KEYUP 虚拟码1 2、如果按下Shift键后再按下1键并释放,则依次产生如表所示的消息。按下 Shift键后按 1健所产生的消息和 wParam的取值 消息 wParam变量取值 WM_KEYDOWN 虚拟码 VK_SHIFT WM_KEYDOWN 虚拟码 VK_1 WM_CHAR ASCII码 “1” WM_KEYUP 虚拟码 VK_1 WM_KEYUP 虚拟码 VK_SHIFT 复合键问题复合键问题使用复合键不但能减少按键数目,而且操作安全性好,对一些重要操作用复合键可以减少误碰键盘引起的差错。
复合键是利用两个以上的按键同时按下所完成的功能,但实际情况中很难实现真正的“同时按下”,它们的时间差别可以长到50ms左右,这对计算机来说是足够长了,完全可能产生额外的动作。
对WM_CHAR和WM_SYSCHAR消息来说,wParam包含键对应的Unicode字符。多数情况下,应用程序只是处理WM_CHAR消息,而忽略WM_KEYDOWN和WM_KEYUP消息。WM_CHAR消息作为第2级抽象,使应用程序不必考虑键的释放或按下状态,而将精力集中在键盘输入的字符上。null【6-1】
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
一个窗口,在该窗口中练习键盘的响应,要求如下:
(1) 单击键盘上的向上箭头时,窗口中显示“You had hitted the up key”
(2) 单击
键时,窗口中显示“You had hitted the SHIFT key”
(3) 单击键时,窗口中显示“You had hitted the CTRL key”
(4) 单击键时,窗口中显示“You had hitted the CTRL A key”
(5) 单击键时,窗口中显示“You had hitted the SHIFT B key”nulllong WINAPI WndProc(HWND hWnd,UINT iMessage,UINT wParam,LONG lParam)
{HDC hDC; //定义设备环境句柄.
PAINTSTRUCT ps; //定义包含绘图信息的结构体变量
HPEN hPen; //定义画笔句柄。
HBRUSH hBrush; //定义画刷句柄 //以下定义输出的字符串。
static char cUp[]="You had hitted the UP key";
static char cCtrl[]="You had hitted the Ctrl key";
static char cShift[]="You had hitted the SHIFT key";
static char cCtrl_A[]="You had hitted the CTRL A key";
static char cShift_B[]="You had hitted the SHIFT B key";//下面定义并初始化按键标志变量。
static BOOL nUpKeyDown=FALSE,
nShiftKeyDown=FALSE,
nCtrlKeyDown=FALSE,
nCtrlAKeyDown=FALSE,
nShiftBKeyDown=FALSE; nullswitch(iMessage)
{ case WM_KEYDOWN:
{ switch(wParam)
{ case VK_UP: //当按上箭头键时,变量置为真。
nUpKeyDown = TRUE; break;
case VK_SHIFT: //当按shift键时,变量置为真。
nShiftKeyDown = TRUE; break;
case VK_CONTROL: //当按control键时,变量置为真
nCtrlKeyDown = TRUE; break;
default: break;
}
}
break;
case WM_KEYUP:
InvalidateRect(hWnd,NULL,FALSE); break;null case WM_CHAR:
if(wParam==(65&VK_CONTROL))
{ if(nCtrlKeyDown == TRUE)
{ nCtrlAKeyDown = TRUE; nCtrlKeyDown = FALSE; }
}
else if(wParam==98||wParam==66) //当按下b键时
{ if(nShiftKeyDown == TRUE) //检查shift键是否处于按下状态。
{nShiftBKeyDown = TRUE; //当SHIFT键按下时,变量置为真
nShiftKeyDown = FALSE;}
}
break;case WM_PAINT: //处理绘图消息.
hDC=BeginPaint(hWnd,&ps);
hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH); //创建 白画刷。
hPen = (HPEN)GetStockObject(WHITE_PEN); //创建白画笔。
SelectObject(hDC,hPen); //选入白画刷
SelectObject(hDC,hBrush); //选入白画笔
SetTextColor(hDC,RGB(255,0,0)); //设置字体颜色为红色。null//输出信息。
if(nUpKeyDown == TRUE)
{ Rectangle(hDC,0,0,300,200);
TextOut(hDC,0,0,cUp,strlen(cUp));
nUpKeyDown = FALSE;
} else if(nCtrlAKeyDown == TRUE)
{ Rectangle(hDC,0,0,300,200);
TextOut(hDC,0,100,cCtrl_A,strlen(cCtrl_A));
nCtrlAKeyDown = FALSE;
nCtrlKeyDown = FALSE;
}else if(nCtrlAKeyDown == TRUE)
else if(nCtrlKeyDown == TRUE&&nCtrlAKeyDown == FALSE)
{ Rectangle(hDC,0,0,300,200);
TextOut(hDC,0,60,cCtrl,strlen(cCtrl));
nCtrlKeyDown = FALSE;
}nullelse if(nShiftBKeyDown == TRUE)
{ Rectangle(hDC,0,0,300,200);
TextOut(hDC,0,0,cShift_B,strlen(cShift_B));
nShiftBKeyDown = FALSE;
nShiftKeyDown = FALSE; }else if(nShiftBKeyDown == FALSE&&nShiftKeyDown == TRUE)
{ Rectangle(hDC,0,0,300,200);
TextOut(hDC,0,0,cShift,strlen(cShift));
nShiftKeyDown = FALSE; }
Else{
TextOut(hDC,0,0,"Input Error!\n",13);
break; }
//删除画笔和画刷
DeleteObject(hPen);
DeleteObject(hBrush);
EndPaint(hWnd,&ps);
break;case WM_DESTROY:
PostQuitMessage(0); return 0;
default: return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
return 0;
}null程序中缓冲区大小只设30个字符,当缓冲区满时若再输入任何字符,就出现(1)号错误提示用户按下左箭头键直至光标到达本行起始位置时,就无法再往左移动,则出现(2)号错误信息若此时您按下Esc键,就出现(3)号错误提示信息若当前光标位置处于本行的起始位置,此时按下回退键(BackSpace),则出现编号为(4)的错误提示信息若字符缓冲区中已没有任何字符,此时按下了Delete键,则出现(5)号错误提示信息6.2 键盘操作应用举例例6-2:本例演示键盘输入时所产生的消息序列并在窗口的客户区显示对应的字符nulllong WINAPI WndProc(HWND hWnd,UINT iMessage,UINT wParam,LONG lParam)
{
#define BufSize 15 //设置存放字符的缓冲区大小
static char cCharBuf[BufSize]; //设置静态字符数组,存放输入的字符,字符个数不能超出缓冲区大小
static int nNumChar=0; //现有字符个数
static int nArrayPos=0; //字符的位置
static int nLnHeight;
static int nCharWidth;
int x;
HDC hDC;
TEXTMETRIC tm;
PAINTSTRUCT PtStr; //定义指向包含绘图信息的结构体变量 nullswitch(iMessage) //处理消息
{case WM_CHAR: //遇到非系统字符所作的处理
{if(wParam==VK_BACK) //处理“遇到回退键的消息”
{if(nArrayPos==0) //若已在一行文字的开始处,则提示用户"不能回退"
MessageBox(hWnd,"当前位置是文本的起始位置,不能回退",NULL,MB_OK);
else
{nArrayPos=nArrayPos-1; //每按一次回退键就回退一个字符的位置
nNumChar=nNumChar-1; //对现有字符总数进行计数
InvalidateRect(hWnd,NULL,TRUE); //刷新用户区,并序发送WM_PAINT消息
}
break;
}
if(wParam==VK_ESCAPE) //处理按下Escape键消息
{MessageBox(hWnd,"您现在不能按ESC键,请继续其它操作",NULL,MB_OK);
break;
}nullif(nNumChar>=BufSize) //如果写入的字符数超过缓冲区大小,则报警
{MessageBox(hWnd,"缓冲区已满,不能再输入字符了\n若需要删除字符,
请用BackSpace键",NULL,MB_OK);
break;
}
for(x=nNumChar;x>nArrayPos;x=x-1)
cCharBuf[x]=cCharBuf[x-1];
cCharBuf[nArrayPos]=(unsigned char)wParam;
nArrayPos=nArrayPos+1;
nNumChar=nNumChar+1;
InvalidateRect(hWnd,NULL,TRUE);
}
break; nullcase WM_CREATE: //处理窗口创建消息
{ hDC=GetDC(hWnd);
GetTextMetrics(hDC,&tm); //获取字体信息
nLnHeight=tm.tmHeight+tm.tmExternalLeading;
nCharWidth=tm.tmAveCharWidth;
ReleaseDC(hWnd,hDC);
}
break;
case WM_KEYDOWN: //处理按下键消息
{switch(wParam)
{case VK_END: //处理按下键为End时的消息
nArrayPos=nNumChar; //输入位置从本行的末尾开始
break;
case VK_HOME: //处理按下键为Home时的消息
nArrayPos=0; //输入位置为本行的起始位置
break;nullcase VK_DELETE: //处理按下键为Delete时的消息
if(nArrayPos==nNumChar) //输入位置处于本行的末尾
MessageBox(hWnd,"缓冲区已空,没有字符可供删除",NULL,MB_OK);
else
{ for(x=nArrayPos;x0)
nArrayPos=nArrayPos-1; //当前输入位置往前移一个位置
else
MessageBox(hWnd,"您已经移动到起始位置,不能再往左移动了",NULL,MB_OK);
break;
case VK_RIGHT://处理按下右方向键时的消息
if(nArrayPos
#include
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain( HINSTANCE hInstance,HINSTANCE hPrevInst,LPSTR lpszCmdLine,int nCmdShow)
{ HWND hwnd; MSG Msg;
WNDCLASS wndclass;
char lpszClassName[]="窗口";
char lpszTitle[]="My_Windows";
wndclass.style=0;
… …
wndclass.lpszClassName=lpszClassName;
if(!RegisterClass(&wndclass))
{ MessageBeep(0); return FALSE; }
hwnd=CreateWindow(lpszClassName,lpszTitle,WS_VISIBLE|WS_SYSMENU|WS_MINIMIZEB
OX,50,50,450,450,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg,NULL,0,0))
{ TranslateMessage(&Msg); DispatchMessage(&Msg);}
return Msg.wParam;
}nullLRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{ PAINTSTRUCT ps;
HDC hdc;
TEXTMETRIC tm;
HBRUSH hbrush;
HPEN hpen;
HCURSOR hcursor;
char str[15];
static int x,y;
switch(message)
{
case WM_MOUSEMOVE:
x=LOWORD(lParam);
y=HIWORD(lParam);
if(x>50&&x<150&&y>50&&y<150)
{ hcursor=LoadCursor(NULL,IDC_CROSS); //十字光标
SetCursor(hcursor);
} if(x>150&&x<250&&y>50&&y<150)
{
hcursor=LoadCursor(NULL,IDC_SIZEALL);//十字箭头光标
SetCursor(hcursor);
}nullif(x>250&&x<350&&y>50&&y<150)
{ hcursor=LoadCursor(NULL,IDC_SIZENESW);SetCursor(hcursor);}//西南-东北光标if(x>50&&x<150&&y>150&&y<250)
{ hcursor=LoadCursor(NULL,IDC_IBEAM);SetCursor(hcursor);}//I字型光标if(x>50&&x<150&&y>250&&y<350)
{ hcursor=LoadCursor(NULL,IDC_SIZEWE);SetCursor(hcursor); } //东西向箭头if(x>150&&x<250&&y>150&&y<250)
{ hcursor=LoadCursor(NULL,IDC_WAIT);SetCursor(hcursor);} //沙漏光标if(x>250&&x<350&&y>150&&y<250)
{ hcursor=LoadCursor(NULL,IDC_UPARROW);SetCursor(hcursor);} //向上箭头光标if(x>150&&x<250&&y>250&&y<350)
{ hcursor=LoadCursor(NULL,IDC_SIZENWSE);SetCursor(hcursor);} //西北-东南箭头if(x>250&&x<350&&y>250&&y<350)
{ hcursor=LoadCursor(NULL,IDC_SIZENS);SetCursor(hcursor); } //南北向箭头null hdc=GetDC(hwnd);
GetTextMetrics(hdc,&tm);
hbrush=(HBRUSH)GetStockObject(WHITE_BRUSH);
SelectObject(hdc,hbrush);
hpen=(HPEN)GetStockObject(WHITE_PEN);
SelectObject(hdc,hpen);
Rectangle(hdc,5,5,tm.tmAveCharWidth*8,tm.tmHeight+3);
sprintf(str,"%d,%d\0",x,y);
TextOut(hdc,5,5,str,lstrlen(str));
EndPaint(hwnd,&ps);
break;nullcase WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
hpen=(HPEN)GetStockObject(BLACK_PEN);
SelectObject(hdc,hpen);
Rectangle(hdc,50,50,350,350);
MoveToEx(hdc,50,150,NULL); LineTo(hdc,350,150);
MoveToEx(hdc,50,250,NULL); LineTo(hdc,350,250);
MoveToEx(hdc,150,50,NULL); LineTo(hdc,150,350);
MoveToEx(hdc,250,50,NULL); LineTo(hdc,250,350);
EndPaint(hwnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
default: return DefWindowProc(hwnd,message,wParam,lParam);
}
return(0);
}逻辑坐标与设备坐标的使用逻辑坐标与设备坐标的使用一旦设置了设备环境的映射模式,则对大多数(并不是所有的)CDC成员函数来说,我们就可以以逻辑坐标为其参数.
1、windows鼠标消息(如onlbuttondown的point参数)所获得的鼠标指针的坐标值是设备坐标。许多其他的MFC库函数,尤其是类CRect的成员函数,则只能在设备坐标下才能正确工作;
2、CDC 的所有成员函数都以逻辑坐标作为其参数;
3、CWnd的成员函数都以设备坐标作为其参数;
4、区域的定义采用设备坐标;某些像CRect::PtInrect之类的函数只有在设备坐标下才会保证有正确的结果;null如:我们需要知道当用户按下鼠标左键时,鼠标指针是否落在某个矩形之内,则可用如下的代码:
Void cMyView ::OnLButtonDown(UNIT nFlags,CPoint point)
{
CRECT rect=m_rect;
CClientDC dc(this);
dc.SetMapMode(MM_LOENGLISH);
dc.LPTODP(rect);
If(rect.PtInRect(point))
{TRACE(“Mouse cursor is inside the rectangle.\n”);
}
}null【6-4】编写一个鼠标应用程序,按下鼠标左键在窗口中移动时,将按下左键时所在点和当前点所形成的矩形涂成灰色,此时光标为十字型。当抬起鼠标左键时,将前面所绘
制度
关于办公室下班关闭电源制度矿山事故隐患举报和奖励制度制度下载人事管理制度doc盘点制度下载
矩形拉伸到整个窗口,拉伸过程中将光标设置为沙漏型。然后,若双击鼠标的左键,则灰色消失,窗口恢复到初始状态。void InvertBlock (HWND hwnd, POINT ptBeg, POINT ptEnd)
{
HDC hdc ;
hdc = CreateDC ("DISPLAY", NULL, NULL, NULL) ;
ClientToScreen (hwnd, &ptBeg) ;
//转换指定窗口的客户区内的点的坐标,上下文是windows
ClientToScreen (hwnd, &ptEnd) ;//将客户区坐标转换成屏幕windows坐标
PatBlt (hdc, ptBeg.x, ptBeg.y, ptEnd.x - ptBeg.x, ptEnd.y - ptBeg.y,DSTINVERT) ;
//这个函数在矩形区内用当前的画笔变换背景和前景*/
DeleteDC (hdc) ;
}LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wParam,LPARAM lParam)
{ static BOOL fCapturing=FALSE,fBlocking=FALSE;
static POINT BeginP,EndP;
static RECT rect={0,0,0,0} ;
HDC hdc ;
PAINTSTRUCT PtStr;
HBRUSH hBrush;nullswitch (message)
{ case WM_LBUTTONDOWN:
if ((!fCapturing)&&(!fBlocking)
{ fCapturing=TRUE ; //左键击活俘获
fBlocking=TRUE;
SetCapture (hwnd) ;//把所有的鼠标信息输入到被左键击活的窗口.
SetCursor (LoadCursor (NULL, IDC_CROSS)) ; //载入光标
BeginP.x=LOWORD(lParam);
BeginP.y=HIWORD(lParam);
}
return 0 ;case WM_MOUSEMOVE:
if (fCapturing)
{ EndP.x=LOWORD(lParam);
EndP.y=HIWORD(lParam);
rect.left=BeginP.xEndP.x?BeginP.x:EndP.x;
rect.top=BeginP.yEndP.y?BeginP.y:EndP.y;
SetCursor (LoadCursor (NULL, IDC_WAIT)) ; //载入沙漏光标
InvalidateRect(hwnd,NULL,TRUE);
}
return 0 ;null case WM_PAINT:
if(fBlocking==TRUE)
{ hdc=BeginPaint(hwnd,&PtStr);
hBrush=(HBRUSH)GetStockObject(LTGRAY_BRUSH);
SelectObject(hdc,hBrush);
Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom
//rect为开始点和释放点之间形成的矩形
DeleteObject(hBrush); EndPaint(hwnd,&PtStr);
}
else
{ hdc=BeginPaint(hwnd,&PtStr);
GetClientRect(hwnd,&rect);
Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom);
EndPaint(hwnd,&PtStr);
}
return 0; case WM_LBUTTONUP:
if (fCapturing)
{ fCapturing=FALSE;
SetCursor (LoadCursor (NULL, IDC_WAIT));
GetClientRect (hwnd, &rect) ;
InvalidateRect(hwnd,NULL,TRUE);
SetCursor(LoadCursor(NULL,IDC_ARROW));
ReleaseCapture () ; //把鼠标从当前窗口中释放出来
}
return 0 ;nullcase WM_LBUTTONDBLCLK:
if(fBlocking==TRUE)
{ fBlocking=FALSE;
InvalidateRect(hwnd,NULL,TRUE);
}
return 0;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}nullnull.h文件:nullnull