03 发送消息自定义消息模态对话框

03 windows编程3 发送消息 自定义消息 模态对话框

课程内容

  • 发送消息
  • 自定义消息
  • 模态对话框

课程详情

发送消息
方法一:SendMessage
函数原型:
LRESULT WINAPI SendMessage(
  _In_  HWND hWnd,
  _In_  UINT Msg,
  _In_  WPARAM wParam,
  _In_  LPARAM lParam
);
参数说明:
参数名 参数类型 参数说明
hWnd HWND 窗口句柄,指明要发送的消息进入哪个窗口的消息队列
Msg UINT 消息的编号
wParam WPARAM 消息附加信息1
lParam LPARAM 消息附加信息2
返回值:

类型: LRESULT

含义:消息处的结果 即消息处理函数的返回值

注意: 该函数以阻塞的方式将消息发送到消息队列.

如果用此方法发送消息,会导致进程阻塞,只到消息处理完毕,才会继续下去.因此,此方法一般应用于同进程的消息发送

示例:

当我们按下鼠标右键的时候,发送一个WM_KEYDOWN消息, 附加消息等价于按了A键

//第一步: 处理右键消息
 case WM_RBUTTONDOWN:
{
    LRESULT n = SendMessage(hWnd, WM_KEYDOWN, 0x041, 0);
    wchar_t szResult[100];
    wsprintf(szResult, L"返回值为%d", n);
    MessageBox(hWnd, szResult, L"提示", MB_OK);
    break;
}
//第二步: 按键消息处理
case WM_KEYDOWN:
{
    switch (wParam)
    {
        case 0x041:
            SetWindowText(hWnd, L"字母a键消");
            return 10;
            break;
    }
    break;
}
运行效果:

img

方法二: PostMessage
函数原型
BOOL WINAPI PostMessage(
  _In_opt_  HWND hWnd,
  _In_      UINT Msg,
  _In_      WPARAM wParam,
  _In_      LPARAM lParam
);
参数说明:
参数名 参数类型 参数说明
hWnd HWND 窗口句柄,指明要发送的消息进入哪个窗口的消息队列
Msg UINT 消息的编号
wParam WPARAM 消息附加信息1
lParam LPARAM 消息附加信息2
返回值说明:

类型: BOOL

含义: 消息发送成功与否,成功为非0,否则为0

说明: 本函数发送消息不会阻塞消息队列,因此只关注消息有没有发送成功,不关注消息的处理结果

因此,一般此方法用于不同的进程间的消息发送

示例:

如果鼠标左键点击,则查找系统中有没有运行"记事本"软件,如果有,则关闭所有的记事本软件,并弹窗显示关闭的个数

如果没有个数为0

case WM_LBUTTONDOWN:   // 鼠标左键消息处理
{
    int nCount = 0;	   //初始化计数器
    HWND hNotePad = FindWindow(L"Notepad", NULL);  //用窗口类名查找"记事本"的窗口句柄
    while (hNotePad)
    {                                                     
        PostMessage(hNotePad, WM_CLOSE, 0, 0);  //如果句柄不为空,则向该窗口发送关闭窗口消息
        Sleep(100);								//暂停100ms,以免发送速度过快来不及关闭
        nCount ++;								
        hNotePad = FindWindow(L"Notepad", NULL);//再次查找窗口句柄
    }
    wchar_t szInfo[100];
    wsprintf(szInfo, L"关闭了%d个记事本窗口", nCount);
    MessageBox(hWnd, szInfo, L"关闭结果", MB_OK);
    break;
}

img

说明:

因为是非阻塞的,因此,在循环条件中,如果不加延时,会造成在窗口关闭前不停的发送消息,导致计数不准确的情况.

自定义消息

首先, 消息的本质是一个整数,因此,自定义消息本质是将一个事件(消息)与一个整数进行绑定,为了避免与其他消息造成冲突,我们需要将自定义消息所绑定的整数是与其他消息不同的,即一个整数绑定一个消息.

系统定义了自定义消息的基础整数宏:

因此,自定义消息的步骤如下:

  1. 定义一个宏来绑定消息整数.
#define UM_MESSAGE1 WM_UESR + 1
#define UM_MESSAGE2 UM_MESSAGE + 1

为了与系统的消息做区别,自定义消息的整数应该排在WM_USER之后.

这里选择了+1, 加多少随意,只要不重复就可了

多个消息,可以依次往下排

  1. 自定义附加消息的含义

即自定义wParam, lParam两个参数的意义

  1. 自定义消息发送的时机

应该有计划的理解什么时候可以发送消息,如果对返回值有要求,也要考虑用哪一种方式进行发送消息

示例一:

按下Ctrl + C 时发送一个复制的消息

消息名: UM_COPY

wParam参数作用: 起点索引

lParam参数作用: 终点过引

示例代码:

//第一步: 定义UM_COPY宏
#define UM_COPY WM_USER + 1
//第二步: 触发逻辑
case 0X41 + 2:    // Ctrl + C 消息处理
{
    BOOL  bCtrl = GetKeyState(VK_CONTROL)  < 0;
    if (bCtrl)
    {
        PostMessage(hWnd, UM_COPY, 0, 10);
    }
    break;
}

//第三步:自定义消息的处理
case UM_COPY:
{
    int nStart = (int)wParam;
    int nEnd = (int)lParam;
    //假装可以获到这个字符串内容
    WCHAR szText[100];
    wsprintf(szText, L"复制的内容从%d到%d", (int)wParam, (int)lParam);
    MessageBox(hWnd, szText, l"复制", MB_OK);
    break;
}

运行效果:

img

示例二:

当按下Ctrl + V时,弹出对话框,输出一个结构体的中的字段

结构体

struct STU
{
    wchar_t name[20]; //姓名
    int age; //年龄
};

消息名:UM_PAST

wParam: 一个STU结构体指针

lParam: 无

返回值: 无

示例代码:

//第一步: 绑定消息整数
#define UM_PAST UM_COPY + 1
//第二步: 发送UM_PAST消息
 case 0x41 + 'v' - 'a':
{
    BOOL bCtrl = GetKeyState(VK_CONTROL) < 0;
    if (bCtrl)
    {
        STU * stu = new STU;
        wsprintf(stu->name, L"张三");
        stu->age = 20;
        PostMessage(hWnd, UM_PAST, (WPARAM)stu, 0);
    }
    break;
}
//第三步: 处理消息
case UM_PAST:
{
    WCHAR szStuInfo[200];
    STU *stu = (STU *)wParam;
    wsprintf(szStuInfo, L"姓名%s, 年龄%d", stu->name, stu->age);
    MessageBox(hWnd, szStuInfo, L"粘贴结果", MB_OK);
    break;
}

运行效果:

<think>嗯,用户想了解Excel中的VLOOKUP函数的用法和参数含义。首先,我需要回忆一下VLOOKUP的基本结构。VLOOKUP是垂直查找函数,用于在表格的首列查找指定的值,然后返回该行中指定列的数据。它的四个参数分别是查找值、表格范围、列索引号和匹配模式。 接下来,我得确认每个参数的具体作用。第一个参数是lookup_value,也就是用户要查找的值,比如产品ID或者姓名。第二个参数是table_array,即查找的范围,这里要注意的是,查找值必须位于这个范围的第一列,否则函数无法正确工作。第三个参数是col_index_num,也就是用户想要返回的数据在表格范围中的第几列,这个列数是从表格范围的第一列开始算起的,不是整个工作表的列。第四个参数是range_lookup,决定是精确匹配还是近似匹配,通常用FALSE或0来指定精确匹配,避免错误。 然后,用户可能需要一个具体的例子来理解如何使用。比如,假设有一个产品价格表,用户想根据产品ID查找对应的价格。这时候,VLOOKUP就可以在ID列查找,然后返回价格列的数据。同时,要提醒用户注意表格范围最好使用绝对引用,比如$A$2:$C$100,这样在拖动公式时范围不会变化。 可能遇到的问题也需要考虑。比如,如果查找值不在表格的第一列,或者列索引号超过了表格的列数,函数会返回错误。此外,数据格式不一致也可能导致问题,比如查找值是数字,而表格中是文本格式的数字,这时候需要统一格式。还有,当出现#N/A错误时,可能是查找值不存在,或者匹配模式设置不正确,需要检查参数是否正确。 用户可能还会问到如何避免常见的错误,比如部分数据匹配出错的情况。这时候需要检查是否有多余的空格,或者数据格式不一致,或者表格范围没有锁定导致拖动时偏移。此外,XLOOKUP作为VLOOKUP的升级版,可能在某些情况下更方便,比如可以向左查找或者返回多列数据,这也是可以提及的内容。 最后,整理步骤,从基础语法到参数说明,再到具体案例,逐步引导用户理解如何使用VLOOKUP函数。同时,提供常见错误和解决方法,帮助用户在实际应用中避免问题。如果有必要,还可以比较VLOOKUP和其他查找函数的区别,比如HLOOKUP或XLOOKUP,但根据用户的问题,主要集中在VLOOKUP本身即可。</think>### Excel VLOOKUP函数详解 #### 一、基础语法与参数说明 VLOOKUP函数的语法为: $$=VLOOKUP(lookup\_value, table\_array, col\_index\_num, [range\_lookup])$$ 包含4个参数: 1. **lookup_value**(必填):要查找的值(如单元格引用或具体值) 2. **table_array**(必填):包含数据的表格范围(必须包含查找列和返回列) 3. **col_index_num**(必填):返回值所在列的序号(从table_array第一列开始计数) 4. **range_lookup**(可选):匹配类型 - `TRUE`/`1`:近似匹配(默认值,需数据升序排列) - `FALSE`/`0`:精确匹配(常用选项) [^1][^2] #### 二、使用步骤演示(工资表查询案例) 假设需要根据员工编号查询工资: 1. 建立查询单元格(如`B12`) 2. 输入公式: ```excel =VLOOKUP(A12, $A$2:$D$100, 4, 0) ``` - `A12`:待查询的员工编号 - `$A$2:$D$100`:锁定数据区域(绝对引用) - `4`:返回第4列(工资列) - `0`:精确匹配 [^2][^3] #### 三、常见错误与解决方法 | 错误现象 | 原因 | 解决方案 | |---------|------|---------| | #N/A | 查找值不存在 | 检查数据源或改用`IFERROR`容错 | | #REF! | 列序号超出范围 | 确认col_index_num ≤ 表格列数 | | 部分匹配失败 | 数据格式不一致 | 统一数值/文本格式 | | 结果错位 | 表格未锁定 | 使用`$`符号固定区域引用 | [^3][^4] #### 四、进阶技巧 1. **多条件查询**: 使用辅助列合并多个条件字段 ```excel =VLOOKUP(A2&B2, $D$2:$F$100, 3, 0) ``` 2. **通配符匹配**: `"*"`匹配任意字符,`"?"`匹配单个字符 ```excel =VLOOKUP("张*", $A$2:$C$100, 3, 0) ``` 3. **跨表查询**: 引用其他工作表数据 ```excel =VLOOKUP(A2, Sheet2!$A$2:$D$100, 4, 0) ``` [^1][^4]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱编程的章老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值