MFC-更换窗口过程

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

下面用编辑框做例子.如图:
MFC-更换窗口过程_第1张图片
1.添加一个C++类
右键单击项目->添加->C++类,如图所示:
MFC-更换窗口过程_第2张图片
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的消息了,钩子函数也可用实现消息拦截.这个以后讲.

你可能感兴趣的:(mfc,子类化,拦截消息,更换窗口过程)