#include
HANDLE g_hOutput = 0;
void OnPaint(HWND hWnd){
char* pszText = "WM_PAINT\n";
WriteConsole(g_hOutput,pszText,strlen(pszText),NULL,NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
AllocConsole();
g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
BOOL InvalidateRect(
HWND hWnd, // handle to window 窗口句柄
CONST RECT* lpRect, // rectangle coordinates 区域的矩形坐标(如果为NULL指的是整个窗口)
BOOL bErase // erase state 重绘前是否先擦除
);
示例代码:
#include
HANDLE g_hOutput = 0;
void OnPaint(HWND hWnd){
char* pszText = "WM_PAINT\n";
WriteConsole(g_hOutput,pszText,strlen(pszText),NULL,NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_LBUTTONDOWN://点击鼠标的左键消息
InvalidateRect(hWnd,NULL,TRUE);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
AllocConsole();
g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
HDC BeginPaint(
HWND hwnd, // handle to window 绘制窗口句柄
LPPAINTSTRUCT lpPaint // paint information 绘图参数的BUFF
);//返回绘图设备句柄HDC
BOOL EndPaint(
HWND hWnd, // handle to window 绘制窗口句柄
CONST PAINTSTRUCT *lpPaint // paint data 绘图参数的指针BeginPaint返回
);
示例代码:
#include
HANDLE g_hOutput = 0;
void OnPaint(HWND hWnd){
char* pszText = "WM_PAINT\n";
WriteConsole(g_hOutput,pszText,strlen(pszText),NULL,NULL);
//这个结构体内部的内容不用管
PAINTSTRUCT ps = {0};
//开始绘图
HDC hdc = BeginPaint(hWnd, &ps);
//正式绘图
TextOut(hdc, 100, 100, "hello", 5);
//结束绘图
EndPaint(hWnd, &ps);
//以上绘图的代码,必须放在处理WM_PAINT消息时调用
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_LBUTTONDOWN://点击鼠标的左键消息
InvalidateRect(hWnd,NULL,TRUE);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
AllocConsole();
g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
WM_KEYDOWN
按键被按下时产生WM_KEYUP
按键被放开时产生WM_SYSKEYDOWN
系统按键下时产生,比如:ALT、F10WM_SYSKEYUP
系统按键放开时产生#include
#include
HANDLE g_hOutput = 0;
void OnKeyDown(HWND hWnd,WPARAM wParam){
char szText[256] = {0};
sprintf(szText,"WM_KEYDOWN:键码值=%d\n",wParam);
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
void OnKeyUp(HWND hWnd,WPARAM wParam){
char szText[256] = {0};
sprintf(szText,"WM_KEYUP:键码值=%d\n",wParam);
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_KEYDOWN:
OnKeyDown(hWnd,wParam);
break;
case WM_KEYUP:
OnKeyUp(hWnd,wParam);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
AllocConsole();
g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
图中笔误TransMessage应该是TranslateMessage
TreanslateMessage
在转换WM_KEYDOWN
消息时,对于可见字符可以产生WM_CHAR
,不可见字符没有此消息TranslateMessage
函数执行过程的伪代码:TranslateMessage(&Msg){
if(nMsg.message != WM_KEYDOWN){
return;
}
//根据nMsg.wParam(键码值)可以获取哪个按键被按下
if(不可见字符的按键){
return;
}
//查看CapsLock(大写锁定键)是否处于打开状态
if(打开)
//65是A的键码值(示例按下的是A键)
PostMessage(nMsg.hwnd,WM_CHAR,65,...);
else
//97是a的键码值
PostMessage(nMsg.hwnd,WM_CHAR,97,...);
}
示例代码
#include
#include
HANDLE g_hOutput = 0;
void OnKeyDown(HWND hWnd,WPARAM wParam){
char szText[256] = {0};
sprintf(szText,"WM_KEYDOWN:键码值=%d\n",wParam);
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
void OnKeyUp(HWND hWnd,WPARAM wParam){
char szText[256] = {0};
sprintf(szText,"WM_KEYUP:键码值=%d\n",wParam);
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
void OnChar(HWND hWnd,WPARAM wParam){
char szText[256] = {0};
sprintf(szText,"WM_KEYUP:键码值=%d\n",wParam);
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_CHAR:
OnChar(hWnd,wParam);
break;
case WM_KEYDOWN:
OnKeyDown(hWnd,wParam);
break;
case WM_KEYUP:
OnKeyUp(hWnd,wParam);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
AllocConsole();
g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
WM_LBUTTONDOWN
鼠标左键按下WM_LBUTTONUP
鼠标左键抬起WM_RBUTTONDOWN
鼠标右键按下WM_RBUTTONUP
鼠标右键抬起WM_MOUSEMOVE
鼠标移动消息WM_LBUTTONDBLCLK
鼠标左键双击WM_RBUTTONDBLCLK
鼠标右键双击WM_MOUSEWHEEL
鼠标滚轮消息LOWORD
x坐标的位置HIWORD
y坐标的位置WM_MOUSEMOVE
消息#include
#include
HANDLE g_hOutput = 0;
void OnLButtonDown(HWND hWnd,WPARAM wParam,LPARAM lParam){
char szText[256] = {0};
sprintf(szText,"WM_LBUTTONDOWN:其他按键状态:%d, X=%d,Y=%d\n",
wParam,LOWORD(lParam),HIWORD(lParam));
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
void OnLButtonUp(HWND hWnd,WPARAM wParam,LPARAM lParam){
char szText[256] = {0};
sprintf(szText,"WM_LBUTTONUP:其他按键状态:%d, X=%d,Y=%d\n",
wParam,LOWORD(lParam),HIWORD(lParam));
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
void OnMouseMove(HWND hWnd,WPARAM wParam,LPARAM lParam){
char szText[256] = {0};
sprintf(szText,"WM_MOUSEMOVE:其他按键状态:%d, X=%d,Y=%d\n",
wParam,LOWORD(lParam),HIWORD(lParam));
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_MOUSEMOVE:
OnMouseMove(hWnd,wParam,lParam);
break;
case WM_LBUTTONDOWN:
OnLButtonDown(hWnd,wParam,lParam);
break;
case WM_LBUTTONUP:
OnLButtonUp(hWnd,wParam,lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
AllocConsole();
g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
LOWORD
x坐标的位置HIWORD
y坐标的位置WM_LBUTTINDOWN
WM_LBUTTONUP
WM_LBUTTONBLACK
WM_LBUTTONUP
注意
:使用时需要在注册窗口类的时候加上CS_DBLCLKS
风格#include
#include
HANDLE g_hOutput = 0;
void OnLButtonDown(HWND hWnd,WPARAM wParam,LPARAM lParam){
char szText[256] = {0};
sprintf(szText,"WM_LBUTTONDOWN:其他按键状态:%d, X=%d,Y=%d\n",
wParam,LOWORD(lParam),HIWORD(lParam));
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
void OnLButtonUp(HWND hWnd,WPARAM wParam,LPARAM lParam){
char szText[256] = {0};
sprintf(szText,"WM_LBUTTONUP:其他按键状态:%d, X=%d,Y=%d\n",
wParam,LOWORD(lParam),HIWORD(lParam));
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
void OnMouseMove(HWND hWnd,WPARAM wParam,LPARAM lParam){
char szText[256] = {0};
sprintf(szText,"WM_MOUSEMOVE:其他按键状态:%d, X=%d,Y=%d\n",
wParam,LOWORD(lParam),HIWORD(lParam));
//WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
void OnButtonDoubleClick(HWND hWnd,WPARAM wParam,LPARAM lParam){
char* szText = "WM_LBUTTONDBLCLK\n";
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_LBUTTONDBLCLK:
OnButtonDoubleClick(hWnd,wParam,lParam);
break;
case WM_MOUSEMOVE:
OnMouseMove(hWnd,wParam,lParam);
break;
case WM_LBUTTONDOWN:
OnLButtonDown(hWnd,wParam,lParam);
break;
case WM_LBUTTONUP:
OnLButtonUp(hWnd,wParam,lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
AllocConsole();
g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
LOWORD
其他按键的状态HIWORD
滚轮的偏移量,通过正负值表示滚动的方向(正:向前滚动,负:向后滚动)LOWORD
x坐标的位置HIWORD
y坐标的位置方向
和距离
#include
#include
HANDLE g_hOutput = 0;
void OnLButtonDown(HWND hWnd,WPARAM wParam,LPARAM lParam){
char szText[256] = {0};
sprintf(szText,"WM_LBUTTONDOWN:其他按键状态:%d, X=%d,Y=%d\n",
wParam,LOWORD(lParam),HIWORD(lParam));
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
void OnLButtonUp(HWND hWnd,WPARAM wParam,LPARAM lParam){
char szText[256] = {0};
sprintf(szText,"WM_LBUTTONUP:其他按键状态:%d, X=%d,Y=%d\n",
wParam,LOWORD(lParam),HIWORD(lParam));
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
void OnMouseMove(HWND hWnd,WPARAM wParam,LPARAM lParam){
char szText[256] = {0};
sprintf(szText,"WM_MOUSEMOVE:其他按键状态:%d, X=%d,Y=%d\n",
wParam,LOWORD(lParam),HIWORD(lParam));
//WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
void OnButtonDoubleClick(HWND hWnd,WPARAM wParam,LPARAM lParam){
char* szText = "WM_LBUTTONDBLCLK\n";
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
void OnMouseWheel(HWND hWnd, WPARAM wParam){
short nDelta = HIWORD(wParam);
char szText[256] = {0};
sprintf(szText,"WM_MOUSEWHEEL:nDelta=%d\n", nDelta);
WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_MOUSEWHEEL:
OnMouseWheel(hWnd, wParam);
break;
case WM_LBUTTONDBLCLK:
OnButtonDoubleClick(hWnd,wParam,lParam);
break;
case WM_MOUSEMOVE:
OnMouseMove(hWnd,wParam,lParam);
break;
case WM_LBUTTONDOWN:
OnLButtonDown(hWnd,wParam,lParam);
break;
case WM_LBUTTONUP:
OnLButtonUp(hWnd,wParam,lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
AllocConsole();
g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
WM_TIMER
消息(实际上是GetMessage发送的消息)
。定时器的精度是毫秒
,但是准确度很低。例如设置时间间隔为1000ms,但是会在非1000毫秒到达消息。wParam
:定时器IDlParam
:定时器处理函数指针UINT_PTR SetTimer(
HWND hWnd,//定时器窗口句柄
UINT_PTR nIDEvent,//定时器ID
UINT uElapse,//时间间隔
TIMERPROC lpTimerFunc//定时器处理函数指针(一般不使用,为NULL)
);//创建成功返回非0
BOOL KillTimer(
HWND hWnd,//定时器窗口句柄
UINT_PTR uIDEvent//定时器ID
);
示例代码:
#include
#include
HANDLE g_hOutput = 0;
void OnTimer(HWND hWnd,WPARAM wParam){
char szText[256] = {0};
sprintf(szText,"WM_TIMER:定时器ID=%d\n",wParam);
WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_TIMER:
OnTimer(hWnd, wParam);
break;
case WM_CREATE:
SetTimer(hWnd, 1, 1000, NULL);
SetTimer(hWnd, 2,2000, NULL);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
AllocConsole();
g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
HMENU
(菜单句柄)类型表示菜单,ID
表示菜单项WM_CREATE
消息中利用SetMenu
函数设置菜单//加载资源
HMENU LoadMenu(
HINSTANCE hInstance,//handle to module
LPCTSTR lpMenuName//menu name or resource identifier
);
示例代码:
#include
#include "resource.h"
//***********************
//保存全局窗口实例,为了第三种方法加载菜单中使用SetMenu()函数中获取实例
HINSTANCE g_hIns = 0;
//第三种方法加载菜单在创建窗口消息中触发加载菜单
void OnCreate(HWND hWnd){
HMENU hMenu = LoadMenu(g_hIns, (char*)IDR_MENU1);
SetMenu(hWnd, hMenu);
}
//***********************
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
//*****************
//第三种加载菜单的的方法:在创建窗口消息中加载菜单
case WM_CREATE:
OnCreate(hWnd);
break;
//****************
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//将当前窗口实例保存到全局变量中
g_hIns = hIns;
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
//第一种加载菜单的方法:(char*)IDR_MENU1
wc.lpszMenuName = NULL;//(char*)IDR_MENU1;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//***********************
//第二种加载菜单的方法:在创建窗口时使用LoadMenu()函数加载菜单
//HMENU hMenu = LoadMenu(hIns,(char*)IDR_MENU1);
//在内存创建窗口,添加菜单
//HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,hMenu,hIns,NULL);
//***********************
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
WM_CIMMADN
点击菜单项发出的消息示例代码:
#include
#include "resource.h"
//***********************
//保存全局窗口实例,为了第三种方法加载菜单中使用SetMenu()函数中获取实例
HINSTANCE g_hIns = 0;
//第三种方法加载菜单在创建窗口消息中触发加载菜单
void OnCreate(HWND hWnd){
HMENU hMenu = LoadMenu(g_hIns, (char*)IDR_MENU1);
SetMenu(hWnd, hMenu);
}
//***********************
void OnCommand(HWND hWnd,WPARAM wParam){
switch(LOWORD(wParam)){
case ID_NEW:
MessageBox(hWnd, "新建被点击", "Infor", MB_OK);
break;
case ID_EXIT:
MessageBox(hWnd, "退出被点击", "Infor", MB_OK);
break;
case ID_ABOUT:
MessageBox(hWnd, "关于被点击", "Infor", MB_OK);
break;
}
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_COMMAND:
OnCommand(hWnd,wParam);
break;
//*****************
//第三种加载菜单的的方法:在创建窗口消息中加载菜单
case WM_CREATE:
OnCreate(hWnd);
break;
//****************
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//将当前窗口实例保存到全局变量中
g_hIns = hIns;
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
//第一种加载菜单的方法:(char*)IDR_MENU1
wc.lpszMenuName = NULL;//(char*)IDR_MENU1;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//***********************
//第二种加载菜单的方法:在创建窗口时使用LoadMenu()函数加载菜单
//HMENU hMenu = LoadMenu(hIns,(char*)IDR_MENU1);
//在内存创建窗口,添加菜单
//HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,hMenu,hIns,NULL);
//***********************
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
BOOL TrackPopupMenu(
HMENU hMenu, //菜单句柄
UINT uFlags, //显示方式
int x, //鼠标水平位置,屏幕坐标系
int y, //鼠标垂直位置,屏幕坐标系
int nReserved, //保留,必须为0
HWND hWnd, //处理菜单消息的窗口句柄
const RECT* prcRect //NULL,此参数可忽略
); //TrackPopupMenu是阻塞函数
WM_RBUTTONUP
:鼠标右键抬起消息为窗口坐标系,要使用需将其转成屏幕坐标系坐标,可通过ClientToScreen
函数进行转换WM_CONTEXTMENU
WPARAM
:右键点击的窗口句柄LPARAM
:对于菜单为0
HIWORD
:X坐标,屏幕坐标LOWORD
:Y坐标,屏幕坐标WM_CONTEXTMENU
消息是在WM_RBUTTONUP
消息之后产生BOOL ClientToScreen(
HWND hWnd, // handle to window
LPPOINT lpPoint // screen coordinates
);
示例代码1:通过WM_RBUTTONUP消息进行弹出,这种方式显示的上下文菜单有一点问题,因为我们所需要的鼠标位置是屏幕坐标系下的坐标,而通过lParam获取的是客户窗口坐标系的坐标,所以导致鼠标右键点击出现的上下文菜单和鼠标的位置有一定的距离,偏差较大
#include
#include "resource.h"
//***********************
//保存全局窗口实例,为了第三种方法加载菜单中使用SetMenu()函数中获取实例
HINSTANCE g_hIns = 0;
//第三种方法加载菜单在创建窗口消息中触发加载菜单
void OnCreate(HWND hWnd){
HMENU hMenu = LoadMenu(g_hIns, (char*)IDR_MENU1);
SetMenu(hWnd, hMenu);
}
//***********************
void OnCommand(HWND hWnd,WPARAM wParam){
switch(LOWORD(wParam)){
case ID_NEW:
MessageBox(hWnd, "新建被点击", "Infor", MB_OK);
break;
case ID_EXIT:
MessageBox(hWnd, "退出被点击", "Infor", MB_OK);
break;
case ID_ABOUT:
MessageBox(hWnd, "关于被点击", "Infor", MB_OK);
break;
}
}
void OnRButtonUp(HWND hWnd,LPARAM lParam){
HMENU hMain = LoadMenu(g_hIns, (char*)IDR_MENU1);
//GetSubMenu函数获取hMain大菜单[文件0,帮助1]中的小菜单[文件0]
HMENU hPopup = GetSubMenu(hMain,0);
TrackPopupMenu(hPopup,TPM_CENTERALIGN|TPM_VCENTERALIGN,LOWORD(lParam),HIWORD(lParam),0,hWnd,NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
//上下文菜单弹出的时机:在鼠标右键抬起时弹出上下文菜单
case WM_RBUTTONUP:
OnRButtonUp(hWnd,lParam);
break;
case WM_COMMAND:
OnCommand(hWnd,wParam);
break;
//*****************
//第三种加载菜单的的方法:在创建窗口消息中加载菜单
case WM_CREATE:
OnCreate(hWnd);
break;
//****************
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//将当前窗口实例保存到全局变量中
g_hIns = hIns;
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
//第一种加载菜单的方法:(char*)IDR_MENU1
wc.lpszMenuName = NULL;//(char*)IDR_MENU1;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//***********************
//第二种加载菜单的方法:在创建窗口时使用LoadMenu()函数加载菜单
//HMENU hMenu = LoadMenu(hIns,(char*)IDR_MENU1);
//在内存创建窗口,添加菜单
//HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,hMenu,hIns,NULL);
//***********************
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
示例代码2:通过WM_CONTEXTMENU方式弹出
#include
#include "resource.h"
//***********************
//保存全局窗口实例,为了第三种方法加载菜单中使用SetMenu()函数中获取实例
HINSTANCE g_hIns = 0;
//第三种方法加载菜单在创建窗口消息中触发加载菜单
void OnCreate(HWND hWnd){
HMENU hMenu = LoadMenu(g_hIns, (char*)IDR_MENU1);
SetMenu(hWnd, hMenu);
}
//***********************
void OnCommand(HWND hWnd,WPARAM wParam){
switch(LOWORD(wParam)){
case ID_NEW:
MessageBox(hWnd, "新建被点击", "Infor", MB_OK);
break;
case ID_EXIT:
MessageBox(hWnd, "退出被点击", "Infor", MB_OK);
break;
case ID_ABOUT:
MessageBox(hWnd, "关于被点击", "Infor", MB_OK);
break;
}
}
void OnContextMenu(HWND hWnd,LPARAM lParam){
HMENU hMain = LoadMenu(g_hIns, (char*)IDR_MENU1);
//GetSubMenu函数获取hMain大菜单[文件0,帮助1]中的小菜单[文件0]
HMENU hPopup = GetSubMenu(hMain,0);
TrackPopupMenu(hPopup,TPM_LEFTALIGN|TPM_TOPALIGN,LOWORD(lParam),HIWORD(lParam),0,hWnd,NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
//上下文菜单弹出的时机
case WM_CONTEXTMENU:
OnContextMenu(hWnd,lParam);
break;
case WM_COMMAND:
OnCommand(hWnd,wParam);
break;
//*****************
//第三种加载菜单的的方法:在创建窗口消息中加载菜单
case WM_CREATE:
OnCreate(hWnd);
break;
//****************
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//将当前窗口实例保存到全局变量中
g_hIns = hIns;
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
//第一种加载菜单的方法:(char*)IDR_MENU1
wc.lpszMenuName = NULL;//(char*)IDR_MENU1;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//***********************
//第二种加载菜单的方法:在创建窗口时使用LoadMenu()函数加载菜单
//HMENU hMenu = LoadMenu(hIns,(char*)IDR_MENU1);
//在内存创建窗口,添加菜单
//HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,hMenu,hIns,NULL);
//***********************
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}