学习:MFC子类化

删除回忆录丶 提交于 2020-02-12 19:10:16

窗口子类化:是创建一个新的窗口函数代替原来的窗口函数。

简单说来,子类化是靠拦截Windows系统中的某些消息来自己进行处理。

自己实现的是子类化一个编辑框,对编辑框输入的内容进行限制 只允许0~9、空格、一个点

定义一个CEditDemo头文件

/*
逻辑顺序:
1、在窗口的初始化函数中得到想要子类化的窗口句柄
2、Attach函数中利用SetWindowLong替换自己要的窗口函数,并且再定义一个指针来保存SetWindowLong返回来的初始的窗口函数
3、定义自己想要的窗口函数NewProc,先判断uMsg是否WM_CHAR,为想要子类化的消息事件,再利用传过来的wParam和lParam来进行详细的字符判断,在进行操作
4、在窗口函数中进行处理完,还需要重新调用初始的窗口函数,其他的默认操作还需要交给初始的窗口函数进行处理
5、最后还需要重写恢复窗口函数

*/
#pragma once
class CEditDemo
{
public:
    CEditDemo();
    ~CEditDemo();
    bool Attach(HWND hWnd);
    bool Detach(HWND hWnd);
    long OldProc;
protected:

    static LRESULT  APIENTRY NewProc(
        HWND hwnd,      // handle to window
        UINT uMsg,      // message identifier
        WPARAM wParam,  // first message parameter
        LPARAM lParam   // second message parameter
    );

protected:
    HWND m_hWnd;
};

CEditDemo的源文件:

#include "stdafx.h"
#include "CEditDemo.h"


CEditDemo::CEditDemo()
{
}


CEditDemo::~CEditDemo()
{
}

bool CEditDemo::Attach(HWND hWnd) {
    if (hWnd == NULL) {
        return false;
    }

    m_hWnd = hWnd; //保存 旧的Edit句柄

    SetProp(hWnd, _T("NewProp"), this);
    OldProc = SetWindowLong(hWnd, GWL_WNDPROC, (long)NewProc); //替换窗口函数
    if (OldProc == 0) {
        return false;
    }
    else {
        return true;
    }
}

LRESULT APIENTRY CEditDemo::NewProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    CEditDemo *theDemo = (CEditDemo*)GetProp(hwnd, _T("NewProp"));

    if (theDemo == NULL)
    {
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }

    bool ret = false;
    wchar_t szbuffer[16];

    if (uMsg == WM_CHAR) {
        //获取当前文本内容
        
        GetWindowText(hwnd, szbuffer, 16);
        switch (wParam) {

        case '.':
            if (wcschr(szbuffer, '.')) { //只能匹配一个点
                ret = true;
            }
            break;
        default:
            if ((wParam < '0' || wParam > '9') && wParam != VK_BACK) { //只能在0~9、空格之间
                ret = true;
            }
            break;
        }

        if (ret) { //如果进去的话 那么输入的字符则不是0~9之间
            MessageBeep(-1);
            return 0;
        }
    }
    return CallWindowProc((WNDPROC)theDemo->OldProc, hwnd, uMsg, wParam, lParam);
}

bool CEditDemo::Detach(HWND hWnd) {
    //恢复窗口函数
    if (hWnd == NULL) {
        return true;
    }
    if (SetWindowLong(hWnd, GWL_WNDPROC,(long)OldProc)) {
        return true;
    }
    else {
        return false;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!