第二课(窗口处理函数精讲)

1,消息分类:

进队列消息:

不进队列消息:WM_CREATE,范围在:0- WM_USER(1024);

自定义消息:定义在1024以后;

系统定义的消息:WM_CREATE

2,案例

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
	LPARAM lParam)
{
	wchar_t szMsg[200];
	wsprintf(szMsg, L"hwnd=%#x\tuMsg=%#x\twParam=%d\tlParam=%d\n", hwnd, uMsg, wParam, lParam);
	OutputDebugString(szMsg);
	switch (uMsg)
	{
	case WM_CREATE://窗口创建消息,CreateWindow或者CreateWindowEx发出
		//主窗口创建了,但还没显示出来
	{
		//CREATESTRUCT*lpcs = (CREATESTRUCT*)lParam;
		LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
		//MessageBox(NULL, L"CreateWindow", L"i", MB_OK);
		break;
	}
	case UM_TEST://自定义:SendMessage或PostMessage
		MessageBox(hwnd, L"接受了", L"jj", MB_OK);
		break;
	case WM_LBUTTONDOWN://左键按下
	{
		DWORD t = GetTickCount();
		if (t1 == 0)
		{
			t1 = t;
		}
		else
		{
			t2 = t;
		}
		DWORD cha = t2 - t1;
		if (t1 != 0 && t2 != 0)
		{
			t1 = 0;
		}
		t2 = 0;
		if (cha < 500)
		{
			break;
		}
		int xPos = LOWORD(lParam);
		int yPos = HIWORD(lParam);
		wchar_t szTitle[200];
		wsprintf(szTitle, L"鼠标点击的坐标为:(%d,%d);cha:%d;", xPos, yPos,cha);

		if (wParam&MK_CONTROL)
		{
			wcscat(szTitle, L"按下了Ctrl键");//字符串连接
		}
		if (wParam&MK_SHIFT)
		{
			wcscat(szTitle, L"按下了Shift键");
		}
		//设置窗口标题
		SetWindowText(hwnd, szTitle);
		//MessageBox(hwnd, L"左键按下", L"提示", MB_OK);
		//SendMessage(hwnd, UM_TEST, 1, 2);
		PostMessage(hwnd, UM_TEST, 1, 2);
		/*
		SendMessage:是阻塞函数
		PostMessage:非阻塞函数
		返回值不同;
		进程内发消息建议用SendMessage
		跨进程发消息建议用PostMessage
		*/
		break;
	}
	case WM_MOUSEMOVE://鼠标移动消息
	{
		int xPos = LOWORD(lParam);
		int yPos = HIWORD(lParam);
		wchar_t szTitle[200];
		wsprintf(szTitle, L"鼠标移动的坐标为:(%d,%d);", xPos, yPos);
		SetWindowText(hwnd, szTitle);
		break;
	}
	case WM_CHAR://字符消息
		wchar_t szTitle[200];
		wsprintf(szTitle, L"%c", (char)wParam);
		SetWindowText(hwnd, szTitle);
		break;
	case WM_PAINT://窗口客户区绘图消息
	{
		//开启绘图
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hwnd, &ps);
		//绘制...........
		Ellipse(hdc, 0, 0, 100, 100);//画一个圆
		Rectangle(hdc, 100, 100, 555, 333);
		EndPaint(hwnd, &ps);
		break;

	}

	case WM_KEYDOWN://键盘消息
	{
		switch (wParam)
		{
		case VK_RETURN:
			SetWindowText(hwnd, L"按下了回车键");
			break;
		case 0x41:
			SetWindowText(hwnd, L"按下了A键");
			break;
		}
		if (lParam & 0x40000000)
		{
			//为真则是按下,假为抬起
		}
		break;
	}

	case WM_LBUTTONDBLCLK:
		SetWindowText(hwnd, L"鼠标左键双击了");
		break;
	case WM_RBUTTONDOWN:
		break;
	case WM_RBUTTONUP:
		break;
	case WM_LBUTTONUP:
		//SetWindowText(hwnd, L"鼠标左键抬起");
		break;
	case WM_CLOSE://窗口关闭消息//点击红色插按钮时发出的,窗口并没有真正的关闭
		
		if (IDYES == MessageBox(NULL, L"你确定要关闭吗?", L"提示", MB_YESNO))
		{
			//销毁窗口
			DestroyWindow(hwnd);//会马上调用WM_DESTROY
		}
		else
		{
			return 1;
		}
		//MessageBox(NULL, L"点了关闭", L"提示", MB_OK);
	case WM_DESTROY:	//窗口销毁消息
		PostQuitMessage(0);//发送一个WM_QUIT消息
		break;
	}
	//默认窗口处理函数
	return DefWindowProc(hwnd, uMsg, wParam, lParam);//系统默认的窗口处理函数
}

3,涉及函数

//wsprintf
功能:将格式化的数据写入指定的缓冲区。根据格式字符串中相应的格式规范,将任何参数转换并复制到输出缓冲区。函数将结束null字符添加到它写入的字符中,但是返回值不包含结束null字符。
    例子:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
	LPARAM lParam)
{
	wchar_t szMsg[200];   			 wsprintf(szMsg,L"hwnd=%#x\tuMsg=%#x\twParam=%d\tlParam=%d\n", hwnd, uMsg, wParam,lParam);
OutputDebugString(szMsg);
}
//OutputDebugString
功能:在下方的输出栏中输出字符串数据;
如上例;
//GetTickCount
功能:
对于Release配置,这个函数返回自设备启动以来的毫秒数,不包括系统挂起的任何时间。GetTickCount在启动时从0开始,然后从那里开始计数。
对于Debug调试配置,从设备启动后的毫秒数中减去180秒。这使得使用GetTickCount的代码可以很容易地测试正确的溢出处理。
例子:DWORD t = GetTickCount();
//wcscat
功能:宽字符串连接
char *strcat(
char *strDestination,
const char *strSource 
);
wchar_t *wcscat(
wchar_t *strDestination,
const wchar_t *strSource 
);
例子:
if (wParam&MK_SHIFT)
{
	wcscat(szTitle, L"按下了Shift键");
}
//SetWindowText
功能:设置窗口标题
更改指定窗口标题栏的文本(如果有的话)。如果指定的窗口是控件,则更改控件的文本。但是,SetWindowText不能更改另一个应用程序中的控件的文本。   
例子:SetWindowText(hwnd, szTitle);
//自定义消息的两个发出消息函数
//SendMessage和PostMessage
例子:
#define UM_TEST WM_USER+1//自定义消息
//SendMessage(hwnd, UM_TEST, 1, 2);
PostMessage(hwnd, UM_TEST, 1, 2);
区别:
SendMessage:是阻塞函数
PostMessage:非阻塞函数
返回值不同;
进程内发消息建议用SendMessage
跨进程发消息建议用PostMessage

4,窗口绘图初识

case WM_PAINT://窗口客户区绘图消息
	{
		//开启绘图
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hwnd, &ps);
		//绘制...........
		Ellipse(hdc, 0, 0, 100, 100);//画一个圆
		Rectangle(hdc, 100, 100, 555, 333);//画一个矩形
		EndPaint(hwnd, &ps);//结束绘图
		break;

	}