窗口子类化:是创建一个新的窗口函数代替原来的窗口函数。
简单说来,子类化是靠拦截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; } }
来源:https://www.cnblogs.com/zpchcbd/p/12300069.html