更换窗口过程就是拦截消息,专业术语叫做窗口”子类化”技术.
下面用编辑框做例子.如图:
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的消息了,钩子函数也可用实现消息拦截.这个以后讲.