MFC-更换窗口过程

本文介绍了如何在MFC中通过子类化技术更换窗口过程以拦截消息,以编辑框为例,详细阐述了从创建新类到实现消息处理的步骤,并提及了恢复原窗口过程的方法,包括在析构函数和WM_DESTROY消息中进行恢复。
摘要由CSDN通过智能技术生成

更换窗口过程就是拦截消息,专业术语叫做窗口”子类化”技术.

下面用编辑框做例子.如图:

1.添加一个C++类
右键单击项目->添加->C++类,如图所示:

2.在新建类的头文件中添加相关变量和函数

protected:
    //新的窗口过程,格式一定得这样写.
    static LRESULT APIENTRY NewEditProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

protected:
    HWND m_hOldEdit;//保存旧的窗口句柄
    LONG m_lOldProc;//旧的窗口过程
public:
    //更换窗口过程
    BOOL ChangeProc(HWND hOldEdit);
    //恢复窗口过程
    BOOL ReNewProc();``

3.在新建类cpp文件中实现函数体

BOOL CNewEdit::ChangeProc(HWND hOldEdit)
{
    BOOL bRet = FALSE;

    do 
    {
        if(hOldEdit == nullptr)
            break;
        //给Edit设置一个新的窗口属性(是一个字符串,随便写),
        //目的是为了获得指向CNewEdit的指针
        SetProp(hOldEdit, TEXT("NewEdit"), this);

        //把旧的窗口过程换成新的窗口过程,发回旧的窗口过程
        m_lOldProc = SetWindowLong(hOldEdit, GWL_WNDPROC, (LONG)NewEditProc);
        if(m_lOldProc == 0)
            break;
        bRet = TRUE;
    } while (FALSE);

    return bRet;
}

BOOL CNewEdit::ReNewProc()
{
    BOOL bRet = FALSE;

    do 
    {
        if(m_hOldEdit == nullptr)
            break;
        //恢复窗口过程
        SetWindowLong(m_hOldEdit, GWL_WNDPROC, m_lOldProc);
        m_lOldProc = 0;
        m_hOldEdit = nullptr;
        bRet = TRUE;
    } while (FALSE);

    return bRet;
}

LRESULT APIENTRY CNewEdit::NewEditProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    //获取新设置的窗口属性,就是获取CNewEdit的指针,方便后面访问m_lOldProc这个成员
    CNewEdit* pNewEdit = (CNewEdit*)GetProp(hwnd, TEXT("NewEdit"));

    if (message == WM_CHAR)
    {
        switch (wParam)
        {
        default:
            if (wParam > '9' || wParam < '0')
            {
                //return 0就是消息截止,不再调用旧的窗口过程,所以不能输入0-9以外的字符
                return 0;
            }
            break;
        }
    }
    //处理完需要截获(改变)的消息后接着返回旧的窗口过程
    return CallWindowProc((WNDPROC)pNewEdit->m_lOldProc,hwnd,message,wParam,lParam);
}

4.更换窗口过程

//更换窗口过程,传入的是需要更换的窗口句柄
    g_NewEdit.ChangeProc(GetDlgItem(IDC_EDIT)->GetSafeHwnd());
    //g_NewEdit是全局变量

5.恢复窗口过程

    //恢复窗口过程
    g_NewEdit.ReNewProc();

6.除了手动恢复,还可以在新建类的析构函数和对话框的WM_DESTROY消息函数中进行恢复.

现在就可以拦截不是0-9的消息了,钩子函数也可用实现消息拦截.这个以后讲.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值