Windows程序设计/win32:让编辑框响应鼠标/键盘消息

本文介绍了在编写聊天程序时遇到的编辑框(edit)控件无法响应WM_KEYDOWN消息的问题。解决方案是为编辑框设置单独的回调函数,使用SetWindowLong函数更改窗口过程。在WM_SIZE消息中,获取并保存原有的回调函数,然后用新的EditProc回调函数替换。EditProc回调函数中处理WM_KEYDOWN消息,如回车键,实现了通过回车发送消息的功能。

一、问题描述

在写聊天程序的时候,想要通过回车结束输入,进行消息发送,结果发现编辑框(edit)在编辑时,无法响应WM_KEYDOWN的消息。

二、解决方案

编辑框(edit)子窗口控件无法响应同等消息循环下的WM_KEYDWON以及按键消息,需要给子窗口控件设置单独的回调函数。

2.1 函数介绍

这里我们使用SetWindowLong函数帮助我们完成设置。先来看函数原型。

Long SetWindowLong(HWND hWnd,int nIndex,LONG dwNewLong)
#ifdef UNICODE
#define SetWindowLong  SetWindowLongW
#else
#define SetWindowLong  SetWindowLongA
#endif // !UNICODE

MSDN上的解释:https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowlonga

百度百科上的解释:https://baike.baidu.com/item/SetWindowLong

第一个参数HWND是: 窗口句柄及间接给出的窗口所属的类。

第二个参数int是:指定将设定的大于等于0的偏移值。有效值的范围从0到额外类的存储空间的字节数减4:例如若指定了12或多于12个字节的额外窗口存储空间,则应设索引位8来访问第三个4字节,同样设置0访问第一个4字节,4访问第二个4字节。要设置其他任何值,可以指定下面值之一:

                                                                (来自百度百科)

第三个参数LONG是:指定的替换值。

如果函数成功,返回值是指定的32位整数的原来的值。如果函数失败,返回值为0。若想获得更多错误信息,请调用GetLastError函数。

如果指定32位整数的原来的值为0,并且函数成功,则返回值为0,但是函数并不清除最后的错误信息,这就很难判断函数是否成功。这时,就应在调用SetWindowLong之前调用SetLastError(0)函数来清除最后的错误信息。这样,如果函数失败就会返回0,并且GetLastError。也返回一个非零值。

三、代码实现(只罗列了关键部分!)

#include<Windows.h>

//只罗列代码框架

//原始的回调函数,即edit子窗口所在父窗口的回调函数
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);

//想要为edit编辑框设置的回调函数
LRESULT CALLBACK EditProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR szCmdLine,
                   int iCmdShow) {
    ......
    wndClass.lpfnWndProc = WinProc;//主回调函数
    ......



    ......
}
LRESULT CALLBACK WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
    static HWND hwndEdit;//编辑框句柄
    static LONG OldProc;//保存老的WNDPROC
    switch(msg){
    case WM_CREATE:{//在WM_CREATE中创建窗口
        //调用CreateWindow函数创建子窗口控件,接收子窗口句柄
        hwndEdit = CreateWindow(L"edit", L"",
			WS_CHILD | WS_VISIBLE | ES_LEFT | ES_MULTILINE,
			0, 0, 0, 0, hWnd, (HMENU)1, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
        return 0;
    }
    case WM_SIZE:{//在WM_SIZE中构筑窗口
        //调用MoveWindow函数重绘窗口
        MoveWindow(hwndEdit, x坐标, y坐标, 长, 宽, TRUE);

        //在窗口绘制完成后,使用SetWindowLong函数设置自己的回调函数
        //并将老的回调函数保存下来
        OldProc = SetWindowLong(hwndEdit, GWL_WNDPROC, (LONG)EditProc);
        return 0;
    }



    ......




    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}
LRESULT CALLBACK EditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	switch (msg) {
	case WM_KEYDOWN: {
		if (wParam == VK_RETURN) {//以回车消息为例
			MessageBox(NULL, L"回车键按下", L"提示", MB_OK);
		}
		return 0;
	}
	}
    //这里一定要注意,我们只处理我们想要处理的消息,我们不需要处理的消息放给原来的回调函数处理
	return CallWindowProc((WNDPROC)OldProc, hWnd, msg, wParam, lParam);
}

 

 

 

 

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

return 1010

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

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

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

打赏作者

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

抵扣说明:

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

余额充值