Window核心编程笔记(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 <windows.h>
#include <stdio.h>
#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 <windows.h>
#include <stdio.h>
#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在菜单左上角

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

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值