第二课(窗口处理函数精讲)
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;
}