zoukankan      html  css  js  c++  java
  • [Win32]Win32 SDK编程系列文章——键盘输入消息

    理论

    因为大多数的PC只有一个键盘,所以所有运行中的WINDOWS程序必须共用它。WINDOWS 将负责把击键消息送到具有输入焦点的那个应用程序中去。尽管屏幕上可能同时有几个应用程序窗口,但一个时刻仅有一个窗口有输入焦点。有输入焦点的那个应用程序的标题条总是高亮度显示的。 实际上您可以从两个角度来看键盘消息:一是您可以把它看成是一大堆的按键消息的集合,在这种情况下,当您按下一个键时,WINDOWS就会发送一个WM_KEYDOWN给有输入焦点的那个应用程序,提醒它有一个键被按下。当您释放键时,WINDOWS又会发送一个WM_KYEUP消息,告诉有一个键被释放。您把每一个键当成是一个按钮;另一种情况是:您可以把键盘看成是字符输入设备。当您按下“a”键时,WINDOWS发送一个WM_CHAR消息给有输入焦点的应用程序,告诉它“a”键被按下。实际上WINDOWS 内部发送WM_KEYDOWN和WWM_KEYUP消息给有输入焦点的应用程序,而这些消息将通过调用TranslateMessage翻译成WM_CHAR消息。WINDOWS窗口过程函数将决定是否处理所收到的消息,一般说来您不大会去处理WM_KEYDOWN、WM_KEYUP消息,在消息循环中TranslateMessage函数会把上述消息转换成WM_CHAR消息

    实例

    关键代码
    TCHAR FontName[]=_T("script");
    WPARAM keyChar =0x20;//0x20(十六进制)是空格的ascii码,亳州没有按键的时候程序正常显示
    TCHAR keyDownUp[50]; 
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	int wmId, wmEvent;
    	PAINTSTRUCT ps;
    	HDC hdc;
    	HFONT hFont,hOldFont;
    	switch (message)
    	{
    	case WM_COMMAND:
    		wmId    = LOWORD(wParam);
    		wmEvent = HIWORD(wParam);
    		// 分析菜单选择:
    		switch (wmId)
    		{
    		case IDM_ABOUT:
    			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
    			break;
    		case IDM_EXIT:
    			DestroyWindow(hWnd);
    			break;
    		default:
    			return DefWindowProc(hWnd, message, wParam, lParam);
    		}
    		break;
    	case WM_PAINT:
    		hdc = BeginPaint(hWnd, &ps);
    		// TODO: 在此添加任意绘图代码...
    		hFont=CreateFont(24,16,0,0,400,0,0,0,OEM_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_SCRIPT,FontName);
    		hOldFont =(HFONT)SelectObject(hdc,hFont);
    		SetTextColor(hdc,RGB(200,200,50));
    		SetBkColor(hdc,RGB(0,0,255));
    		TextOut(hdc,40,40,(TCHAR*)&keyChar,1);//在设备环境的坐标(40,40)处,化长度为1的keyChar字符串
    		EndPaint(hWnd, &ps);
    		break;
    	case WM_CHAR://按下某键, 并已发出WM_KEYDOWN, WM_KEYUP消息 
    		keyChar=wParam;//接收到的字符放入变量keyChar中,接着调用InvalidateRect,而InvalidateRect使得窗口的客户区无效,这样它会发出WM_PAINT消息,而WM_PAINT消息迫使Windows重新绘制它的客户区。
    		InvalidateRect(hWnd,NULL,TRUE);
    		//我们将保存所有有关重绘客户区的数据,然后发送WM_PAINT消息,处理该消息的程序段然后根据相关数据重新绘制客户区。尽管这么做事有点像走了弯路,但WINDOWS要处理那么庞大的消息群,没有一定的规矩可不行。 实际上我们完全可以通过调用GetDC 获得设备上下文句柄,然后绘制字符,然后再调用ReleaseDC释放设备上下文句柄,毫无疑问这样也能在客户区绘制出正确的字符。但是如果这之后接收到WM_PAINT消息要处理时,客户区会重新刷新,而我们这稍前所绘制的字符就会消失掉。所以为了让字符一直正确地显示,就必须把它们放到WM_PAINT的处理过程中处理。而在本消息处理中发送WM_PAINT消息即可。
    		break;
    	case WM_KEYDOWN://按下一个键,当一个非系统键被按下时该消息发送给具有键盘焦点的窗口。非系统键即不与ALT联用的情况。 
    		wsprintf(keyDownUp,L"keyDown:%c",wParam);
    	    SetWindowText(hWnd,keyDownUp);
    		break;
    	case WM_SYSKEYUP://释放一个系统键,系统键alt+x
    		wsprintf(keyDownUp,L"SysKeyUp:%c",wParam);
    		SetWindowText(hWnd,keyDownUp);
    		break; 
    	case WM_KEYUP:
    		if (GetAsyncKeyState(VK_CONTROL))//GetAsyncKeyState()实时检查键盘硬件状态返回结果。GetKeyState函数并非实时检查键盘状态,它只是检查当前正在处理的消息发生之前和发生之时的键盘状态,它是通过读取消息队列中该键的按键消息来实现的。
    		{
    			if (wParam == VK_NUMPAD1)
    			{
    				wsprintf(keyDownUp,L"Control+%c",wParam);//组合键消息
    				SetWindowText(hWnd,keyDownUp);
    			}		
    		}
    		break;
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		break;
    	default:
    		return DefWindowProc(hWnd, message, wParam, lParam);
    	}
    	return 0;
    }
    /* 1.  BOOL InvalidateRect(
    __in_opt HWND hWnd,
    __in_opt CONST RECT *lpRect,//是指向客户区我们想要其无效的一个正方形结构体的指针。如果为NULL,则整个客户区都无效
    __in BOOL bErase);//是否擦除背景
    */
    效果图:
  • 相关阅读:
    idea 中main 方法运行错误二
    shiro 忘记加密后的密码怎么办?
    idea 中 Caused by: java.lang.ClassNotFoundException: org.springframework.web.util.IntrospectorCleanupListener
    Date 类型的比较
    oracle中数据类型对应java类型[转载]
    mybitis面试题基础必考 Mybatis 中$与#的区别
    301
    201
    0
    Apache负载 均衡
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3119875.html
Copyright © 2011-2022 走看看