windows编程学习笔记(6)键盘与鼠标输入

一.键盘输入处理


前面说过,windows程序是由消息驱动的,我们对程序的操作也可以被包装成一个消息,投递到程序的消息队列中,窗口过程函数通过对这个消息处理,达到响应输入的目的。

常见的键盘消息有以下几种:

WM_KEYDOWN //键盘按下

WM_KEYUP //键盘松开

WM_SYSKEYDOWN //系统键按下

WM_SYSKEYUP //系统键松开

WM_CHAR //字符消息

在这里,KEYDOWN和KEYUP都是成对发生的,比如要判断一个瞬时输入,那么用KEYDOWN和KEYUP是一样的,如果要判断连续性的按下,那么就需要同时使用KEYDOWN和KEYUP了,但是还有个更加简单的方法,GetMesageTime可以获取消息的相对时间,详情请查阅MSDN

但是,窗口过程函数接受的只是WM_XXX消息,仅仅判断到了键盘有输入,怎么确定是哪个键被按下了呢?

前面说过,窗口过程函数有接受两个参数,wParam和lParam,消息的结构体里面也有这两个参数。按键的信息就存储在这两个参数里面:

wParam参数存储的就是按键的虚拟键码,lParam存储的是按键的相关信息。在windows中,虚拟键码对应键盘上的一个实际按键,”虚拟“也是windows操作系统常用的东东,比如虚拟存储,虚拟设备,这样有什么好处呢?一方面,就是我们在编程的时候,不需要考虑底层的一些硬件信息,只需要调用windows为我们写好的api就可以操作底层的硬件,大大的方便了我们这些程序猿编写程序,另一方面,我们所编写的程序对操作系统而言是“不可信的”,操作系统需要将我们和底层硬件隔离,以免破坏计算机,假如我们这些菜鸟都可以直接操作硬件,那我们的计算机不知要爆炸多少次了,哈哈!

下面看一个例子:

/*
time: 2014.10.25
topic: windows键盘输入
*/

#include <windows.h>
#include "TCHAR.h"
//窗口过程函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void Paint(HWND, LPCWSTR);
//winmain函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	
	//设计窗口
	WNDCLASSEX wndClass = {
		sizeof(WNDCLASSEX),
		CS_HREDRAW | CS_VREDRAW,
		WndProc,
		0L,
		0L,
		hInstance,
		NULL,
		LoadCursor(NULL, IDC_ARROW),
		(HBRUSH)GetStockObject(GRAY_BRUSH),
		NULL,
		L"hello windows",
		NULL
	};
	//注册窗口
	RegisterClassEx(&wndClass);
	//创建窗口
	HWND hWnd = CreateWindow(L"hello windows", L"hello windows", WS_EX_OVERLAPPEDWINDOW, 0, 0, 400, 400, NULL, NULL, hInstance, NULL);
	//调整设定位置大小函数
	MoveWindow(hWnd, 100, 100, 400, 400, true);
	//显示窗口
	ShowWindow(hWnd, nCmdShow);
	//更新窗口
	UpdateWindow(hWnd);

	
	//getmessage消息循环
	MSG msg = {0};
//从消息队列中取消息
	while(GetMessage(&msg, NULL, 0, 0))
	{
		//只有WM_QUIT消息才会让Getmessage函数返回0,其他时间非0,消息循环判断条件一直为真,直至有WM_QUIT消息
		
		//将虚拟键消息翻译为字符消息
		TranslateMessage(&msg);
		//分发一个消息给窗口程序
		DispatchMessage(&msg);
	}
	return 0;
}

//窗口过程函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case WM_KEYDOWN://处理键盘消息
		switch (wParam)
		{
				//如果是ESC键,关闭程序
		case VK_ESCAPE:
				//销毁窗口
				DestroyWindow(hwnd);
				//退出程序
				PostQuitMessage(0);
				break;
				//如果是FI键,输出F1被按下
		case VK_F1:
				//Paint函数,输出按键信息
			Paint(hwnd, L"F1 is pressed!");
				break;
				//当按键是字母键时,可以直接用字母的字符当做case处理
		case 'A':
				//Paint函数,输出按键信心
			Paint(hwnd, L"A is pressed!");
				break;
		default:
			break;
		}
			
		break;
	default:
		return DefWindowProc(hwnd, message, wParam, lParam);//默认窗口过程函数
	}

	return 0;
}

//输出函数
void Paint(HWND hwnd, LPCWSTR buffer)
{
		//获取设备环境句柄
	HDC hdc = GetDC(hwnd);
		//输出按键信息
	TextOut(hdc, 100, 100, buffer, wcslen(buffer));
		//释放设备环境
	ReleaseDC(hwnd, hdc);
}
运行结果:

windows编程学习笔记(6)键盘与鼠标输入_第1张图片


.鼠标输入处理


和键盘消息一样,鼠标消息也是WM_XXX消息,常见的鼠标消息如下:

WM_LBUTTONDBLCLCK 

WM_LBUTTONDOWN

WM_LBUTTONUP

WM_RBUTTONDBLCLK

WM_RBUTTONDOWN]

WM_RBUTTONUP

WM_MBUTTONDOWN

WM_MBUTTONUP

WM_MOUSEMOVE

WM_MOUSEWHEEL

其实windows的消息从字面上也都很好理解,WM_是windows message的缩写,LBUTTON,MBUTTON,RBUTTON分别代表左键,滚轮,右键,UP,DOWN,DBLCLCK代表松开,按下,双击

MOUSEMOVE是鼠标移动,MOUSEWHEEL是滚轮滚动


同键盘消息处理一样,WM_XXX消息只是代表了鼠标有特定的操作,具体的信息还是保存在wParam和lParam参数中:

wParam参数存储的是鼠标按键以及Ctrl和Shift键的状态信息,这个参数经常用于检测某个键是否被按下,比如:

if(wParam & MK_LBUTTON)
{
	//鼠标左键被按下处理代码
}
最常用的还是lParam参数,这个参数里面存储的是鼠标的位置

但是要读取这个参数,还需要两个宏定义,LOWORD和HIWORD。我们知道,lParam和wParam都是32位整型变量,LOWORD和HIWORD表示的意思就是取低字节位和取高字节位,在lParam参数中,低字节位存储的为X坐标值,高字节位存储的为Y坐标值。

关于字节位,扩展一下知识:一个字节为8个二进制位,有的机器为低字节序(Little Endian),有的机器为高字节序(Big Endian)

所谓低字节序,就是低地址存放低字节数据,高地址存放高字节数据;高字节序则相反。

例如:

把9025H存入1000H地址中 低字节序的存法为 00001000H   25H   00001001H  90H   高字节序存法为  00001000H 90H  00001001H 25H

我们一般使用的Intel CPU采用的是低字节在前的字节序。

好像有点儿远了,还是说LOWORD和HIWORD,对于鼠标消息,我们可以这样获取鼠标的坐标:

case WM_LBUTTONDOWN:
		{
			int x = LOWORD(lParam);
			int y = HIWORD(lParam);
			wchar_t str[20] = {0};
			wsprintf(str, L"坐标为%d.%d", x, y);
			Paint(hwnd, str);
			break;
		}
这里我们还是调用键盘消息那里所写的Paint函数来输出信息,程序运行结果如下:

windows编程学习笔记(6)键盘与鼠标输入_第2张图片


你可能感兴趣的:(windows,鼠标,键盘,输入,winapi)