世界杯举办地_世界杯预选赛巴西 - emsxbc.com

Window核心编程笔记(5)

文章目录

1.键盘消息2.鼠标消息3.定时器消息4.菜单资源5.上下文菜单

1.键盘消息

键盘消息分类:

· WM_KEYDOWN - 摁键被摁下时产生

· WM_KEYUP - 摁键被放开时产生

· WM_SYSKEYDOWN - 系统键按下时产生,例如ALT、F10

· WM_SYSKEYUP - 系统键放开时产生

附带信息: WPARAM - 摁键的Virtual Key LPARAM - 按键的参数,例如按下次数 测试一下效果:

void on_keydown(HWND hwnd,WPARAM wParam)

{

wchar_t text[256] = {0};

wsprintf(text, L"键值为%d", wParam);

WriteConsole(g_out, text, wcslen(text), NULL, NULL);

}

void on_keyup(HWND hwnd)

{

MessageBox(hwnd, L"按键被释放", L"infor", MB_OK);

}

摁下按键时在DOS窗口打印键值,松开摁键后跳出提示窗口

2.字符消息 · TranslateMessage在转换WM_KEYDOWN消息时,对于可见字符可以产生WM_CHAR,不可见字符无此消息

· 附带信息: WPARAM - 输入的字符的ASCII字符编码 LPARAM - 按键的相关参数

2.鼠标消息

1.鼠标消息分类 · 基本鼠标消息 WM_LBUTTONDOWN - 鼠标左键摁下 WM_LBUTTONUP - 鼠标做键抬起 WM_LBUTTONDOWN - 鼠标右键摁下 WM_LBUTTONUP - 鼠标右键抬起 WM_MOUSEMOVE - 鼠标移动消息

· 双击消息 WM_LBUTTONBLCLK - 鼠标左键双击 WM_RBUTTONBLCLK - 鼠标右键双击

· 滚轮消息 WM_MOUSEWHEEL - 鼠标滚轮消息

鼠标基本消息: wPARAM : 其他按键状态,例如Ctrl/Shift等 lPARAM : 鼠标的位置,窗口客户区坐标系 LOWORD X坐标位置 HIWORD Y坐标位置

一般情况鼠标按下\抬起成对出现,在鼠标移动过程中,会根据移动速度产生一系列的WM_MOUSEMOVE消息

鼠标双击消息: wPARAM : 其他按键状态,例如Ctrl/Shift等 lPARAM : 鼠标的位置,窗口客户区坐标系 LOWORD X坐标位置 HIWORD Y坐标位置

消息产生顺序 以左键双击为例: WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONBLCLK WM_LBUTTONUP 使用时需要在注册窗口类的时候添加CS_DBLCLKS风格

wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;

鼠标滚轮消息: wPARAM: LOWORD - 其他按键状态 HIWORD - 滚轮的偏移量,通过正负值表示滚动方向,正:向前滚动 , 负:向后滚动 lPARAM:鼠标当前的位置,屏幕坐标系 LOWORD - X坐标系 HIWORD - Y坐标系

使用: 通过偏移量,获取滚动的方向和距离

3.定时器消息

定时器消息介绍: 产生时间: 在程序中创建定时器,当到达时间间隔时,定时器会向程序发送一个WM_TIMER消息。定时器的精度是毫秒,但是准确度很低。例如设置时间间隔为1000ms,但是会在非1000ms到达消息

附带信息: wPARAM: 定时器ID 了PARAM:定时器处理函数的指针

创建和销毁定时器: 创建定时器

//创建定时器

UINT_PTR SetTimer(

HWND hWnd,//定时器窗口句柄

UINT_PTR nIDEvent,//定时器ID

UINT uElapse,//时间间隔

TIMERPROC lpTimerFunc//定时器处理函数指针(一般不使用,为NULL)

)

//关闭定时器

BOOL KillTimer(

HWND hWnd,//定时器窗口句柄

UINT_PTR uIDEvent//定时器ID

)

尝试实现定时器:

//打印定时器函数

void on_Timer(HWND hwnd,WPARAM wParam)

{

wchar_t text[256] = {0};

wsprintf(text,L"定时器ID = %d",wParam);

WriteConsole(g_out, text, wcslen(text), NULL, NULL);

}

//当窗口创建时,创建两个定时器

case WM_CREATE:

SetTimer(hwnd, 1, 1000, NULL);//创建第一个定时器,ID:1,间隔:1S

SetTimer(hwnd, 2, 1000, NULL);//创建第一个定时器,ID:2,间隔:2S

定时器1每1s打印一次,定时器2每2s打印一次

4.菜单资源

1.菜单分类 · 窗口顶层菜单 · 弹出式菜单 · 系统菜单

HMENU(菜单句柄)类型表示菜单,ID表示菜单项

2.资源相关 资源脚本文件:.rc文件 编译器:RC.exe .rc–RC.exe–>.res .obj+.res–LINK.exe–>exe

3.菜单资源的使用 · 添加菜单资源 · 加载菜单资源 a.注册窗口类时设置菜单 b.创建窗口传参设置菜单 c.在主窗口WM_CREATE消息中利用SetMenu函数设置菜单

HMENU LoadMenu(

HINSTANCE hInstance,//

LPCTSTR lpMenuName

)

1.添加资源文件 2.在资源视图管理器中右击选择添加资源,选择menu资源 3.直接图形化开始编辑界面,可以在属性中修改菜单ID 4.挂菜单的三种方式

//注册窗口类时设置菜单

wc.lpszMenuName = (LPCWSTR)IDR_MENU1;

//在内存中创建窗口时

HMENU menu1 = LoadMenu(hInstance, (LPCWSTR)IDR_MENU1);//获取窗口句柄

HWND hwnd = CreateWindow((LPCWSTR)L"main", (LPCWSTR)L"hello world", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, menu1, hInstance, NULL);

//窗口处理函数里挂菜单

case WM_CREATE:

on_create(hwnd);

break;

//定义一个全局变量保存当前进程,以便访问

HINSTANCE g_hIn = 0;

void on_create(HWND hwnd)

{

HMENU Hmenu = LoadMenu(g_hIn, (LPCWSTR)IDR_MENU1);

SetMenu(hwnd, Hmenu);

}

完整代码:

#include

#include

#include "resource.h"

#define MY_MESS WM_USER + 100

HANDLE g_out = 0;

HINSTANCE g_hIn = 0;

void on_create(HWND hwnd)

{

HMENU Hmenu = LoadMenu(g_hIn, (LPCWSTR)IDR_MENU1);

SetMenu(hwnd, Hmenu);

}

LRESULT CALLBACK test(HWND hwnd, UINT msgID, WPARAM wParam, LPARAM lParam)

{

switch (msgID)

{

case WM_CREATE:

on_create(hwnd);

break;

case WM_SYSCOMMAND:

if (wParam == SC_CLOSE)

{

if (MessageBox(hwnd, L"是否关闭?", L"infor", MB_OKCANCEL | MB_ICONEXCLAMATION) == IDOK)

{

PostQuitMessage(0);

}

else

{

return 0;

}

}

break;

}

return DefWindowProc(hwnd, msgID, wParam, lParam);

}

int CALLBACK wWinMain(_In_ HINSTANCE hInstance,

_In_opt_ HINSTANCE hPrevInstance,

_In_ LPWSTR lpCmdLine,

_In_ int nCmdShow)

{

g_hIn = hInstance;

AllocConsole();//增加dos窗口

g_out = 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 = hInstance;//实例句柄

wc.lpfnWndProc = test;//窗口处理函数

wc.lpszClassName = (LPCWSTR)L"main";//窗口类名称

wc.lpszMenuName = NULL;//不要菜单

//wc.lpszMenuName = (LPCWSTR)IDR_MENU1;

wc.style = CS_HREDRAW | CS_VREDRAW;//窗口水平或竖直方向有变化就重绘窗口

RegisterClass(&wc);//将以上所有赋值写入操作系统

//在内存中创建窗口

//HMENU menu1 = LoadMenu(g_hIn, (LPCWSTR)IDR_MENU1);

//HWND hwnd = CreateWindow((LPCWSTR)L"main", (LPCWSTR)L"hello world", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, menu1, hInstance, NULL);

HWND hwnd = CreateWindow((LPCWSTR)L"main", (LPCWSTR)L"hello world", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hInstance, NULL);

//显示窗口

ShowWindow(hwnd, SW_SHOW);

UpdateWindow(hwnd);

//消息循环

MSG nMSG = { 0 };

while (GetMessage(&nMSG, NULL, 0, 0))

{

TranslateMessage(&nMSG);

DispatchMessage(&nMSG);//派发消息,将消息交给窗口处理函数处理

}

return 0;

}

4.命令消息处理

只要点击菜单项就会发送WM_COMMAND消息

WM_COMMAND: 附带信息: wPARAM: HIWORD - 对于菜单为0 LOWORD - 菜单项的ID IPARAM - 对于菜单为0

利用WM_COMMAND消息完成,尝试点退出弹出提示框

case WM_COMMAND:

ON_COM(hwnd, wParam);

break;

void ON_COM(HWND hwnd, WPARAM wParam)

{

if (LOWORD(wParam) == ID_OUT&&MessageBox(hwnd, L"是否关闭?", L"infor", MB_OKCANCEL | MB_ICONEXCLAMATION) == IDOK)

{

PostQuitMessage(0);

}

}

完整代码:

#include

#include

#include "resource.h"

void ON_COM(HWND hwnd, WPARAM wParam)

{

if (LOWORD(wParam) == ID_OUT&&MessageBox(hwnd, L"是否关闭?", L"infor", MB_OKCANCEL | MB_ICONEXCLAMATION) == IDOK)

{

PostQuitMessage(0);

}

}

LRESULT CALLBACK test(HWND hwnd, UINT msgID, WPARAM wParam, LPARAM lParam)

{

switch (msgID)

{

case WM_COMMAND:

ON_COM(hwnd, wParam);

break;

}

return DefWindowProc(hwnd, msgID, wParam, lParam);

}

int CALLBACK wWinMain(_In_ HINSTANCE hInstance,

_In_opt_ HINSTANCE hPrevInstance,

_In_ LPWSTR lpCmdLine,

_In_ int nCmdShow)

{

//注册窗口类

WNDCLASS wc = { 0 };

wc.cbClsExtra = 0;//申请缓冲区

wc.cbWndExtra = 0;//申请缓冲区

wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);//窗口背景色

wc.hCursor = NULL;//默认光标

wc.hIcon = NULL;//默认图标

wc.hInstance = hInstance;//实例句柄

wc.lpfnWndProc = test;//窗口处理函数

wc.lpszClassName = (LPCWSTR)L"main";//窗口类名称

//wc.lpszMenuName = NULL;//不要菜单

wc.lpszMenuName = (LPCWSTR)IDR_MENU1;

wc.style = CS_HREDRAW | CS_VREDRAW;//窗口水平或竖直方向有变化就重绘窗口

RegisterClass(&wc);//将以上所有赋值写入操作系统

//在内存中创建窗口

//HMENU menu1 = LoadMenu(g_hIn, (LPCWSTR)IDR_MENU1);

//HWND hwnd = CreateWindow((LPCWSTR)L"main", (LPCWSTR)L"hello world", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, menu1, hInstance, NULL);

HWND hwnd = CreateWindow((LPCWSTR)L"main", (LPCWSTR)L"hello world", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hInstance, NULL);

//显示窗口

ShowWindow(hwnd, SW_SHOW);

UpdateWindow(hwnd);

//消息循环

MSG nMSG = { 0 };

while (GetMessage(&nMSG, NULL, 0, 0))

{

TranslateMessage(&nMSG);

DispatchMessage(&nMSG);//派发消息,将消息交给窗口处理函数处理

}

return 0;

}

5.上下文菜单

· 现实上下文菜单

BOOL TrackPopupMenu(

HMENU hMenu,//菜单句柄

UINT uFlags,//现实方式

int x,//水平位置,屏幕坐标系

int y,//垂直位置,屏幕坐标系

int nReserved,//保留,必须0

HWND hWnd,//处理菜单消息的窗口句柄

CONST RECT *prcRect//NULL,忽略

)//是阻塞函数

void ON_CONTEXT(HWND hwnd, LPARAM lParam)

{

HMENU MainMenu = LoadMenu(G_HINS, (LPCWSTR)IDR_MENU1);

HMENU HPop = GetSubMenu(MainMenu, 0);//获得自菜单函数

TrackPopupMenu(HPop, TPM_CENTERALIGN | TPM_VCENTERALIGN, LOWORD(lParam), HIWORD(lParam), 0, hwnd, NULL);

}

LRESULT CALLBACK test(HWND hwnd, UINT msgID, WPARAM wParam, LPARAM lParam)

{

switch (msgID)

{

case WM_COMMAND:

ON_COM(hwnd, wParam);

break;

case WM_CONTEXTMENU://上下文弹出菜单的专门消息

ON_CONTEXT(hwnd, lParam);

break;

}

return DefWindowProc(hwnd, msgID, wParam, lParam);

}

WM_CONTEXTMENU:

wPARAM:右键点击的窗口句柄 lPARAM:LOWORD X坐标,屏幕坐标系;HIWORD Y坐标,屏幕坐标系

WM_CONTEXTMENU消息是在WM_RBUTTONUP消息之后产生的

TPM_CENTERALIGN | TPM_VCENTERALIGN是鼠标在弹出菜单的位置,此时设置的是菜单正中心,一般是TPM_LEFTALIGN | TPM_TOPALIGN在菜单左上角

运行效果: 在这里插入图片描述