win32编程(003)——绘图消息,键鼠消息,定时器消息和菜单的使用
本帖最后由 zzxwbs 于 2017-6-18 00:44 编辑1.绘图消息WM_PAINT
当窗口需要绘制的时候,会发送窗口处理函数。
#include "stdafx.h"
HANDLE g_hOutout = 0;
void OnPaint(HWND hWnd)
{
char *pszText = "WM_PAINT\n";
WriteConsole(g_hOutout,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);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
1.1InvalidateRect函数
在程序中,如果需要绘制窗口,调用函数声明窗口无效区域。向指定的窗体更新区域添加一个矩形,然后窗口客户区域的这一部分将被重新绘制。
窗口无效区域:被声明成需要重新绘制的区域。
BOOL InvalidateRect(
HWND hWnd,//窗口句柄
CONST RECT* lpRect,//区域的矩形坐标
BOOL bErase//重绘前是否先擦除
);
#include "stdafx.h"
HANDLE g_hOutout = 0;
void OnPaint(HWND hWnd)
{
char *pszText = "WM_PAINT\n";
WriteConsole(g_hOutout,pszText,strlen(pszText),NULL,NULL);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
switch (msgID)
{
case WM_LBUTTONDOWN://鼠标左点击
InvalidateRect(hWnd,NULL,TRUE);//将窗口声明为需要重绘
break;
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
1.2绘图编程(今天只做简单介绍)
画图的几个步骤
消息处理步骤
1.2.1开始绘图处理
HDC BeginPaint(
HWND hwnd, //绘图窗口
LPPAINTSTRUCT lpPaint //绘图参数的BUFF
); 返回绘图设备句柄HDC
1.2.2绘图
1.2.3结束绘图处理
BOOL EndPaint(
HWND hWnd, //绘图窗口
CONST PAINTSTRUCT *lpPaint//绘图参数的指针BeginPaint返回
);
#include "stdafx.h"
HANDLE g_hOutout = 0;
void OnPaint(HWND hWnd)
{
char *pszText = "WM_PAINT\n";
WriteConsole(g_hOutout,pszText,strlen(pszText),NULL,NULL);
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
TextOut(hdc,100,100,"fishc",5);
EndPaint(hWnd,&ps);
//以上绘图的代码必须放在WM_PAINT消息处理中调用
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
switch (msgID)
{
case WM_LBUTTONDOWN://鼠标左点击
InvalidateRect(hWnd,NULL,TRUE);//将窗口声明为需要重绘
break;
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
2.键盘消息
2.1键盘消息
WM_KEYDOWN - 按键被按下时产生
WM_KEYUP - 按键被放开时产生
WM_SYSKEYDOWN - 系统键按下时产生比如ALT、F10
WM_SYSKEYUP - 系统键放开时产生
WM_CHAR - 字符消息
2.2消息参数
2.2.1按键消息:
WPARAM - 按键的Virtual Key(虚拟键码),无法区分大小写
LPARAM - 按键的参数,例如按下次数
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
void OnPaint(HWND hWnd)
{
char *pszText = "WM_PAINT\n";
WriteConsole(g_hOutout,pszText,strlen(pszText),NULL,NULL);
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
TextOut(hdc,100,100,"fishc",5);
EndPaint(hWnd,&ps);
//以上绘图的代码必须放在WM_PAINT消息处理中调用
}
void OnKeyDown( HWND hWnd, WPARAM wParam )
{
char szText = { 0 };
sprintf( szText, "WM_KEYDOWN:%08X\n", wParam );
WriteConsole( g_hOutout, szText, strlen(szText), NULL,
NULL );
}
void OnKeyUp( HWND hWnd, WPARAM wParam )
{
char szText = { 0 };
sprintf( szText, "WM_KEYUP:%08X\n", wParam );
WriteConsole( g_hOutout, 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_LBUTTONDOWN://鼠标左点击
InvalidateRect(hWnd,NULL,TRUE);//将窗口声明为需要重绘
break;
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
用上下左右键控制fishc的位置
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
int g_xPos = 100;
int g_yPos = 100;
void OnPaint(HWND hWnd)
{
char *pszText = "WM_PAINT\n";
WriteConsole(g_hOutout,pszText,strlen(pszText),NULL,NULL);
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
TextOut(hdc,g_xPos,g_yPos,"fishc",5);
EndPaint(hWnd,&ps);
//以上绘图的代码必须放在WM_PAINT消息处理中调用
}
void OnKeyDown( HWND hWnd, WPARAM wParam )
{
char szText = { 0 };
sprintf( szText, "WM_KEYDOWN:%08X\n", wParam );
WriteConsole( g_hOutout, szText, strlen(szText), NULL,
NULL );
switch(wParam)
{
case VK_UP:
g_yPos--;
break;
case VK_DOWN:
g_yPos++;
break;
case VK_LEFT:
g_xPos--;
break;
case VK_RIGHT:
g_xPos++;
break;
}
InvalidateRect(hWnd,NULL,TRUE);
}
void OnKeyUp( HWND hWnd, WPARAM wParam )
{
char szText = { 0 };
sprintf( szText, "WM_KEYUP:%08X\n", wParam );
WriteConsole( g_hOutout, 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_LBUTTONDOWN://鼠标左点击
InvalidateRect(hWnd,NULL,TRUE);//将窗口声明为需要重绘
break;
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
2.2.2WM_CHAR消息:
WPARAM - 输入的字符(ASC字符编码),可以区分大小写
LPARAM - 按键的相关参数
2.3消息的使用总结
2.3.1KEYDOWN可以重复出现,KEYUP只能在按键松开时出现1次
2.3.2TranslateMessage在转换WM_KEYDOWN消息时,对于可见字符可以产生WM_CHAR,不可见字符无此消息。
2.3.3WM_KEYDOWN/UP的wParam是表示的按键,WM_CHAR是表示输入的字符。
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
int g_xPos = 100;
int g_yPos = 100;
void OnPaint(HWND hWnd)
{
char *pszText = "WM_PAINT\n";
WriteConsole(g_hOutout,pszText,strlen(pszText),NULL,NULL);
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
TextOut(hdc,g_xPos,g_yPos,"fishc",5);
EndPaint(hWnd,&ps);
//以上绘图的代码必须放在WM_PAINT消息处理中调用
}
void OnKeyDown( HWND hWnd, WPARAM wParam )
{
char szText = { 0 };
sprintf( szText, "WM_KEYDOWN:%08X\n", wParam );
WriteConsole( g_hOutout, szText, strlen(szText), NULL,
NULL );
}
void OnKeyUp( HWND hWnd, WPARAM wParam )
{
char szText = { 0 };
sprintf( szText, "WM_KEYUP:%08X\n", wParam );
WriteConsole( g_hOutout, szText, strlen(szText), NULL,
NULL );
}
void OnChar(HWND hWnd,WPARAM wParam)
{
char szText = {0};
sprintf(szText,"WM_CHAR:0x%08X\n",wParam);
WriteConsole( g_hOutout, 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_LBUTTONDOWN://鼠标左点击
InvalidateRect(hWnd,NULL,TRUE);//将窗口声明为需要重绘
break;
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);//处理大小写
DispatchMessage(&nMsg);
}
return 0;
}
3.鼠标消息
3.1 基本鼠标消息
WM_LBUTTONDOWN - 鼠标左键按下
WM_LBUTTONUP - 鼠标左键抬起
WM_RBUTTONDOWN - 鼠标右键按下
WM_RBUTTONUP - 鼠标右键抬起
WM_MOUSEMOVE - 鼠标移动消息
3.2 双击消息
WM_LBUTTONDBLCLK - 鼠标左键双击
WM_RBUTTONDBLCLK - 鼠标右键双击
3.3 滚轮消息
WM_MOUSEWHEEL - 鼠标滚轮消息
3.4鼠标消息总结
3.4.1基本鼠标消息
3.4.1.1消息参数
WPARAM - 其他按键的状态,例如Ctrl/Shift等
LPARAM - 鼠标的位置,窗口客户区坐标系。
LOWORD X坐标位置
HIWORD Y坐标位置
3.4.1.2鼠标消息使用
一般情况鼠标按下/抬起成对出现。在鼠标移动过程中,会根据移动速度产生一系列的WM_MOUSEMOVE消息。
3.4.2双击鼠标消息
3.4.2.1消息参数
WPARAM - 其他按键的状态,例如Ctrl/Shift等
LPARAM - 鼠标的位置,窗口客户区坐标系。
LOWORD X坐标位置
HIWORD Y坐标位置
3.4.2.2使用时需要在注册窗口类的时候添加CS_DBLCLKS 风格。
3.4.2.3消息产生顺序
以WM_LBUTTONDBLCLK为例:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_LBUTTONUP
3.4.3鼠标滚轮 WM_MOUSEWHEEL
3.4.3.1消息参数
WPARAM:
LOWORD - 其他按键的状态
HIWORD - 滚轮的偏移量,是120的倍数,通过正负值表示表示滚动方向。
正:向前滚动
负:向后滚动
LPARAM:鼠标当前的位置,【屏幕】坐标系
LOWORD - X坐标
HIWORD - Y坐标
3.4.3.2使用:通过偏移量,获取滚动的方向和倍数。
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
void OnLButtonDown(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
char szText = {0};
sprintf(szText,"WM_LBUTTONDOWN:按键状态=%08X,X=%d,Y=%d\n",wParam,LOWORD(lParam),HIWORD(lParam));
WriteConsole(g_hOutout,szText,strlen(szText),NULL,NULL);
}
void OnLButtonUp(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
char szText = {0};
sprintf(szText,"WM_LBUTTONUP:按键状态=%08X,X=%d,Y=%d\n",wParam,LOWORD(lParam),HIWORD(lParam));
WriteConsole(g_hOutout,szText,strlen(szText),NULL,NULL);
}
void OnMouseMove(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
char szText = {0};
sprintf(szText,"WM_MOUSEMOVE:x=%d,y=%d\n",LOWORD(lParam),HIWORD(lParam));
WriteConsole(g_hOutout,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);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
fishc跟着鼠标移动而移动
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
int g_xPos = 100;
int g_yPos = 100;
void OnMouseMove(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
g_xPos = LOWORD(lParam);
g_yPos = HIWORD(lParam);
InvalidateRect(hWnd,NULL,TRUE);
}
void OnPaint(HWND hWnd)
{
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
TextOut(hdc,g_xPos,g_yPos,"fishc",5);
EndPaint(hWnd,&ps);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
switch (msgID)
{
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_MOUSEMOVE:
OnMouseMove(hWnd,wParam,lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
void OnMouseWheel(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
short nDelta = HIWORD(wParam);//偏移量
char szText = {0};
sprintf(szText,"偏移量=%d\n,x=%d,y=%d\n",nDelta,LOWORD(lParam),HIWORD(lParam));
WriteConsole(g_hOutout,szText,strlen(szText),NULL,NULL);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
switch (msgID)
{
case WM_MOUSEWHEEL:
OnMouseWheel(hWnd,wParam,lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
4.定时器消息
可以在程序中设置定时器,当到达时间间隔时,定时器会向程序发送一个WM_TIMER消息。
定时器的精度是毫秒,但是准确度很低。例如设置时间间隔为1000ms,但是会在非1000毫秒到达。
4.1消息的参数
WPARAM - 定时器ID
LPARAM - 定时器处理函数的指针
4.2定时器使用
4.2.1 创建定时器
UINT_PTR SetTimer(
HWND hWnd,//定时器窗口句柄
UINT_PTR nIDEvent, //定时器ID
UINT uElapse,//时间间隔
TIMERPROC lpTimerFunc //定时器处理函数指针
);创建成功,返回非0。
使用窗口处理函数,做为定时器处理函数,lpTimerFunc为NULL
使用定时器处理函数处理定时器消息。
4.2.2 消息处理WM_TIMER
4.2.3 关闭定时器
BOOL KillTimer(
HWND hWnd,//定时器窗口句柄
UINT_PTR uIDEvent //定时器ID
);
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
void OnTimer(HWND hWnd,WPARAM wParam)
{
char szText = {0};
sprintf(szText,"定时器:%d\n",wParam);
WriteConsole(g_hOutout,szText,strlen(szText),NULL,NULL);
}
//自定义(定时器处理函数)处理WM_TIMER消息
VOID CALLBACK TimerProc(HWND hWnd,UINT msgID,UINT timeID,DWORD dwTimer)
{
char szText = {0};
sprintf(szText,"定时器处理函数处理:%d\n",timeID);
WriteConsole(g_hOutout,szText,strlen(szText),NULL,NULL);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
switch (msgID)
{
case WM_LBUTTONDOWN:
KillTimer(hWnd,1);//鼠标左键关闭定时器1
break;
case WM_TIMER:
OnTimer(hWnd,wParam);
break;
case WM_CREATE:
SetTimer(hWnd,1,1000,NULL);
SetTimer(hWnd,2,2000,TimerProc);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
5.菜单的使用
5.1菜单的分类
5.1.1 窗口的顶层菜单
5.1.2 弹出式菜单(鼠标右键,下拉菜单)
5.1.3 系统菜单(标题栏右键)
HMENU类型表示菜单,菜单每一项有相应的ID。
5.2窗口的顶层菜单
5.2.1创建菜单
HMENU CreateMenu(VOID); //创建成功返回菜单句柄
增加菜单项
BOOL AppendMenu(
HMENU hMenu, //菜单句柄
UINT uFlags, //菜单项风格
UINT_PTR uIDNewItem, //菜单项ID或下拉菜单句柄
LPCTSTR lpNewItem //菜单项的名称
);
uFlags:
MF_POPUP - 具有这种风格的菜单项,被点击后弹出下拉菜单,uIDNewItem参数必须填写下拉菜单的句柄。
MF_SEPARATOR - 具有这种风格的菜单项,为分隔线
MF_STRING - 具有这种风格的菜单项,被点击后能够发出消息(WM_COMMAND),uIDNewItem参数必须填写菜单项ID
设置到窗口
BOOL SetMenu(
HWND hWnd,//窗口句柄
HMENU hMenu //菜单句柄
);
5.3菜单命令处理
5.3.1WM_COMMAND 消息
WPARAM:
HIWORD - 对于菜单为0
LOWORD - 菜单项的ID
LPARAM - 对于菜单为NULL
5.3.2命令处理过程
获取WPARAM菜单ID,根据ID处理。
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
void OnCreate(HWND hWnd)
{
HMENU hMain = CreateMenu();
HMENU hFile = CreatePopupMenu();
AppendMenu(hFile, MF_STRING | MF_CHECKED, 1003, "新建");
AppendMenu(hFile, MF_SEPARATOR, 0, "");
AppendMenu(hFile, MF_STRING | MF_MENUBARBREAK, 1004, "退出");
HMENU hHelp = CreatePopupMenu();
AppendMenu(hHelp, MF_STRING | MF_DISABLED, 1005, "关于");
AppendMenu(hMain, MF_POPUP, (UINT)hFile, "文件");
AppendMenu(hMain, MF_POPUP, (UINT)hHelp, "帮助");
SetMenu(hWnd, hMain);
}
void OnCommand(HWND hWnd, WPARAM wParam)
{
switch (LOWORD(wParam))
{
case 1003:
MessageBox(hWnd, "新建被点击", "信息", MB_OK);
break;
case 1004:
MessageBox(hWnd, "退出被点击", "信息", MB_OK);
break;
case 1005:
MessageBox(hWnd, "关于被点击", "信息", 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);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hInstance, pszText);
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg = { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
5.3.3菜单项的状态
在增加菜单项可以设置菜单项的状态。
可以使用菜单API修改状态
CheckMenuItem
//更改菜单项 勾选/非勾选 状态
DWORD CheckMenuItem(
HMENU hmenu, // 菜单句柄
UINT uIDCheckItem,// 菜单项ID或菜单项位置(索引)
UINT uCheck // 具体状态
);
uCheck:
MF_BYCOMMAND - 指明uIDCheckItem参数必须填写菜单项ID
MF_BYPOSITION - 指明uIDCheckItem参数必须填写菜单项位置
MF_CHECKED - 勾选
MF_UNCHECKED - 非勾选
EnableMenuItem
//更改菜单项 可用/不可用 状态
BOOL EnableMenuItem(
HMENU hMenu, // 菜单句柄
UINT uIDEnableItem,// 菜单项ID或菜单项位置(索引)
UINT uEnable // 具体状态 / 还指明第二个参数填的是什么
);
函数使用时,需要通过设置MF_BYPOSITION或者MF_BYCOMMAND,确定使用菜单索引或者菜单ID。
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
int g_state = 0;//标志量
HMENU hFile;
void OnCreate(HWND hWnd)
{
HMENU hMain = CreateMenu();
hFile = CreatePopupMenu();
AppendMenu(hFile,MF_STRING|MF_CHECKED,1003,"新建");
AppendMenu(hFile,MF_SEPARATOR,0,"");
AppendMenu(hFile,MF_STRING|MF_MENUBARBREAK,1004,"退出");
HMENU hHelp = CreatePopupMenu();
AppendMenu(hHelp,MF_STRING|MF_DISABLED,1005,"关于");
AppendMenu(hMain,MF_POPUP,(UINT)hFile,"文件");
AppendMenu(hMain,MF_POPUP,(UINT)hHelp,"帮助");
SetMenu(hWnd,hMain);
}
void OnCommand(HWND hWnd,WPARAM wParam)
{
switch(LOWORD(wParam))
{
case 1003:
if(g_state == 0)
{
CheckMenuItem(hFile,1003,MF_BYCOMMAND|MF_UNCHECKED);
}
else
{
CheckMenuItem(hFile,0,MF_BYPOSITION|MF_CHECKED);
}
g_state = !g_state;
break;
case 1004:
MessageBox(hWnd,"退出被点击","信息",MB_OK);
break;
case 1005:
MessageBox(hWnd,"关于被点击","信息",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);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
5.3.4WM_INITMENUPOPUP
在菜单被激活但是未显示,窗口会收到这个消息
WPARAM – 即将显示的菜单句柄
LPARAM - LOWORD 是被点击的菜单项索引
HIWORD 是窗口菜单标识
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
int g_state = 0;//标志量
HMENU hFile;
void OnCreate(HWND hWnd)
{
HMENU hMain = CreateMenu();
hFile = CreatePopupMenu();
AppendMenu(hFile,MF_STRING|MF_CHECKED,1003,"新建");
AppendMenu(hFile,MF_SEPARATOR,0,"");
AppendMenu(hFile,MF_STRING|MF_MENUBARBREAK,1004,"退出");
HMENU hHelp = CreatePopupMenu();
AppendMenu(hHelp,MF_STRING|MF_DISABLED,1005,"关于");
AppendMenu(hMain,MF_POPUP,(UINT)hFile,"文件");
AppendMenu(hMain,MF_POPUP,(UINT)hHelp,"帮助");
SetMenu(hWnd,hMain);
}
void OnCommand(HWND hWnd,WPARAM wParam)
{
switch(LOWORD(wParam))
{
case 1003:
if(g_state == 0)
{
CheckMenuItem(hFile,1003,MF_BYCOMMAND|MF_UNCHECKED);
}
else
{
CheckMenuItem(hFile,0,MF_BYPOSITION|MF_CHECKED);
}
g_state = !g_state;
break;
case 1004:
MessageBox(hWnd,"退出被点击","信息",MB_OK);
break;
case 1005:
MessageBox(hWnd,"关于被点击","信息",MB_OK);
break;
}
}
void OnInitMenuPopup(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
char szText = {0};
sprintf(szText,"即将显示的菜单句柄:%d,被点击顶层菜单项位置:%d,即将显示的菜单是否为窗口菜单:%d\n",wParam,LOWORD(lParam),HIWORD(lParam));
WriteConsole(g_hOutout,szText,strlen(szText),NULL,NULL);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
switch (msgID)
{
case WM_INITMENUPOPUP:
OnInitMenuPopup(hWnd,wParam,lParam);
break;
case WM_COMMAND:
OnCommand(hWnd,wParam);
break;
case WM_CREATE:
OnCreate(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
5.4系统菜单的使用(了解)
5.4.1 系统菜单的获取
HMENU GetSystemMenu(
HWND hWnd,//窗口句柄
BOOL bRevert //重置选项
); 返回获取到的系统菜单句柄
bRevert:TRUE - 删除旧菜单,恢复到默认的系统菜单
FALSE - 返回当前的系统菜单句柄。
5.4.2 系统菜单的修改
AppendMenu函数
DeleteMenu函数
5.4.3 系统菜单命令响应
通过WM_SYSCOMMAND响应菜单命令。
WPARAM的LOWORD是命令ID
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
int g_state = 0;//标志量
HMENU hFile;
void OnCreate(HWND hWnd)
{
HMENU hMain = CreateMenu();
hFile = CreatePopupMenu();
AppendMenu(hFile,MF_STRING|MF_CHECKED,1003,"新建");
AppendMenu(hFile,MF_SEPARATOR,0,"");
AppendMenu(hFile,MF_STRING|MF_MENUBARBREAK,1004,"退出");
HMENU hHelp = CreatePopupMenu();
AppendMenu(hHelp,MF_STRING|MF_DISABLED,1005,"关于");
AppendMenu(hMain,MF_POPUP,(UINT)hFile,"文件");
AppendMenu(hMain,MF_POPUP,(UINT)hHelp,"帮助");
SetMenu(hWnd,hMain);
HMENU hSys = GetSystemMenu(hWnd,FALSE);
for(int i=0;i<6;i++)
{
DeleteMenu(hSys,0,MF_BYPOSITION);
}
AppendMenu(hSys,MF_SEPARATOR,0,"");
AppendMenu(hSys,MF_STRING,1001,"我的菜单项");
}
void OnCommand(HWND hWnd,WPARAM wParam)
{
switch(LOWORD(wParam))
{
case 1003:
if(g_state == 0)
{
CheckMenuItem(hFile,1003,MF_BYCOMMAND|MF_UNCHECKED);
}
else
{
CheckMenuItem(hFile,0,MF_BYPOSITION|MF_CHECKED);
}
g_state = !g_state;
break;
case 1004:
MessageBox(hWnd,"退出被点击","信息",MB_OK);
break;
case 1005:
MessageBox(hWnd,"关于被点击","信息",MB_OK);
break;
}
}
void OnSysCommand(HWND hWnd,WPARAM wParam)
{
switch(LOWORD(wParam))
{
case 1001:
MessageBox(hWnd,"我的菜单项被点击","信息",MB_OK);
break;
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
switch (msgID)
{
case WM_SYSCOMMAND:
OnSysCommand(hWnd,wParam);
break;
case WM_COMMAND:
OnCommand(hWnd,wParam);
break;
case WM_CREATE:
OnCreate(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
5.5右键菜单 Context Menu的使用
5.5.1 创建菜单
右键菜单是一个弹出式菜单,使用CreatePopupMenu创建。
5.5.2 显示菜单
BOOL TrackPopupMenu(
HMENU hMenu, //菜单句柄
UINT uFlags, //显示方式
int x,//水平位置,屏幕坐标系
int y,//垂直位置,屏幕坐标系
int nReserved, //保留,必须0
HWND hWnd, //处理菜单消息的窗口句柄
CONST RECT *prcRect //NULL,忽略
); TrackPopupMenu是阻塞函数
5.5.3 命令处理
WM_COMMAND,与窗口菜单一致
如果TrackPopupMenu设置了TPM_RETURNCMD选项,那么点击的菜单项ID通过函数的返回值获取。
5.5.4 菜单项的状态
WM_INITMENUPOPUP,按照弹出菜单处理
5.5.5菜单处理位置
5.5.5.1 鼠标右键抬起
WM_RBUTTONUP 鼠标右键消息窗口坐标系坐标,要使用需要转换成屏幕坐标系
ClientToScreen
ScreenToClient
//将 客户区坐标系下的坐标 转换为 屏幕坐标系下的坐标
BOOL ClientToScreen(
HWND hWnd, // 窗口句柄
LPPOINT lpPoint//
输入:客户区坐标系下的一个坐标
输出 : 转换后屏幕坐标系下的坐标
);
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
int g_state = 0;//标志量
HMENU hFile;
void OnCreate(HWND hWnd)
{
HMENU hMain = CreateMenu();
hFile = CreatePopupMenu();
AppendMenu(hFile,MF_STRING|MF_CHECKED,1003,"新建");
AppendMenu(hFile,MF_SEPARATOR,0,"");
AppendMenu(hFile,MF_STRING|MF_MENUBARBREAK,1004,"退出");
HMENU hHelp = CreatePopupMenu();
AppendMenu(hHelp,MF_STRING|MF_DISABLED,1005,"关于");
AppendMenu(hMain,MF_POPUP,(UINT)hFile,"文件");
AppendMenu(hMain,MF_POPUP,(UINT)hHelp,"帮助");
SetMenu(hWnd,hMain);
}
void OnCommand(HWND hWnd,WPARAM wParam)
{
switch(LOWORD(wParam))
{
case 1003:
if(g_state == 0)
{
CheckMenuItem(hFile,1003,MF_BYCOMMAND|MF_UNCHECKED);
}
else
{
CheckMenuItem(hFile,0,MF_BYPOSITION|MF_CHECKED);
}
g_state = !g_state;
break;
case 1004:
MessageBox(hWnd,"退出被点击","信息",MB_OK);
break;
case 1005:
MessageBox(hWnd,"关于被点击","信息",MB_OK);
break;
case 1010:
MessageBox(hWnd,"右键新建被点击","信息",MB_OK);
break;
case 1011:
MessageBox(hWnd,"右键退出被点击","信息",MB_OK);
break;
}
}
void OnRButtonUp(HWND hWnd,LPARAM lParam)
{
HMENU hPopup = CreatePopupMenu();
AppendMenu(hPopup,MF_STRING,1010,"新建");
AppendMenu(hPopup,MF_SEPARATOR,0,"");
AppendMenu(hPopup,MF_STRING,1011,"退出");
POINT pt = {0};
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
ClientToScreen(hWnd,&pt);
TrackPopupMenu(hPopup,TPM_CENTERALIGN|TPM_VCENTERALIGN,pt.x,pt.y,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);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
int g_state = 0;//标志量
HMENU hFile;
void OnCreate(HWND hWnd)
{
HMENU hMain = CreateMenu();
hFile = CreatePopupMenu();
AppendMenu(hFile,MF_STRING|MF_CHECKED,1003,"新建");
AppendMenu(hFile,MF_SEPARATOR,0,"");
AppendMenu(hFile,MF_STRING|MF_MENUBARBREAK,1004,"退出");
HMENU hHelp = CreatePopupMenu();
AppendMenu(hHelp,MF_STRING|MF_DISABLED,1005,"关于");
AppendMenu(hMain,MF_POPUP,(UINT)hFile,"文件");
AppendMenu(hMain,MF_POPUP,(UINT)hHelp,"帮助");
SetMenu(hWnd,hMain);
}
void OnCommand(HWND hWnd,WPARAM wParam)
{
switch(LOWORD(wParam))
{
case 1003:
if(g_state == 0)
{
CheckMenuItem(hFile,1003,MF_BYCOMMAND|MF_UNCHECKED);
}
else
{
CheckMenuItem(hFile,0,MF_BYPOSITION|MF_CHECKED);
}
g_state = !g_state;
break;
case 1004:
MessageBox(hWnd,"退出被点击","信息",MB_OK);
break;
case 1005:
MessageBox(hWnd,"关于被点击","信息",MB_OK);
break;
case 1010:
MessageBox(hWnd,"右键新建被点击","信息",MB_OK);
break;
case 1011:
MessageBox(hWnd,"右键退出被点击","信息",MB_OK);
break;
}
}
void OnRButtonUp(HWND hWnd,LPARAM lParam)
{
HMENU hPopup = CreatePopupMenu();
AppendMenu(hPopup,MF_STRING,1010,"新建");
AppendMenu(hPopup,MF_SEPARATOR,0,"");
AppendMenu(hPopup,MF_STRING,1011,"退出");
POINT pt = {0};
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
ClientToScreen(hWnd,&pt);
BOOL nRet = TrackPopupMenu(hPopup,TPM_CENTERALIGN|TPM_VCENTERALIGN|TPM_RETURNCMD,pt.x,pt.y,0,hWnd,NULL);
switch(nRet)
{
case 1010:
MessageBox(hWnd,"没发出COMMAND消息,右键新建被点击","信息",MB_OK);
break;
case 1011:
MessageBox(hWnd,"没发出COMMAND消息,右键退出被点击","信息",MB_OK);
break;
}
}
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);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
5.5.5.2 WM_CONTEXTMENU
WParam - 右键点击的窗口句柄
LPARAM - LOWORD X坐标,屏幕坐标系
HIWORD Y坐标,屏幕坐标系
WM_CONTEXTMENU消息是在WM_RBUTTONUP消息之后产生。
#include "stdafx.h"
#include "stdio.h"
HANDLE g_hOutout = 0;
int g_state = 0;//标志量
HMENU hFile;
void OnCreate(HWND hWnd)
{
HMENU hMain = CreateMenu();
hFile = CreatePopupMenu();
AppendMenu(hFile,MF_STRING|MF_CHECKED,1003,"新建");
AppendMenu(hFile,MF_SEPARATOR,0,"");
AppendMenu(hFile,MF_STRING|MF_MENUBARBREAK,1004,"退出");
HMENU hHelp = CreatePopupMenu();
AppendMenu(hHelp,MF_STRING|MF_DISABLED,1005,"关于");
AppendMenu(hMain,MF_POPUP,(UINT)hFile,"文件");
AppendMenu(hMain,MF_POPUP,(UINT)hHelp,"帮助");
SetMenu(hWnd,hMain);
}
void OnCommand(HWND hWnd,WPARAM wParam)
{
switch(LOWORD(wParam))
{
case 1003:
if(g_state == 0)
{
CheckMenuItem(hFile,1003,MF_BYCOMMAND|MF_UNCHECKED);
}
else
{
CheckMenuItem(hFile,0,MF_BYPOSITION|MF_CHECKED);
}
g_state = !g_state;
break;
case 1004:
MessageBox(hWnd,"退出被点击","信息",MB_OK);
break;
case 1005:
MessageBox(hWnd,"关于被点击","信息",MB_OK);
break;
case 1010:
MessageBox(hWnd,"右键新建被点击","信息",MB_OK);
break;
case 1011:
MessageBox(hWnd,"右键退出被点击","信息",MB_OK);
break;
}
}
void OnContextMenu(HWND hWnd,LPARAM lParam)
{
HMENU hPopup = CreatePopupMenu();
AppendMenu(hPopup,MF_STRING,1010,"新建");
AppendMenu(hPopup,MF_SEPARATOR,0,"");
AppendMenu(hPopup,MF_STRING,1011,"退出");
POINT pt = {0};
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
BOOL nRet = TrackPopupMenu(hPopup,TPM_CENTERALIGN|TPM_VCENTERALIGN|TPM_RETURNCMD,pt.x,pt.y,0,hWnd,NULL);
switch(nRet)
{
case 1010:
MessageBox(hWnd,"没发出COMMAND消息,右键新建被点击","信息",MB_OK);
break;
case 1011:
MessageBox(hWnd,"没发出COMMAND消息,右键退出被点击","信息",MB_OK);
break;
}
}
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);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLince, int iCmdShow)
{
AllocConsole();//创建一个控制台
g_hOutout = GetStdHandle(STD_OUTPUT_HANDLE);
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.hIconSm = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "fishc";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
char *pszText = "fishc";
HWND hWnd = CreateWindow("fishc", "fishc",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hInstance,pszText);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
MSG nMsg= { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
return 0;
}
下期预告:资源的使用,windows 绘图
题外话:好多东西我都没有细说,等你们问呢,win32好多都是实践和思考的东西,并不难,然而发了这么多,连回复都没有几个。。。
不定时停更 用vs2015如何创建菜单资源,能把过程详细说一下吗?包括.rc文件的创建
页:
[1]