很多时候,自带的控件并不能满足我们的需求
我们就需要对自带的控件进行扩展
比如需要一个只能输入字母和输入的编辑框
这个时候我们就需要使用子类化 替换掉原本的过程函数
// SUBCLASS.cpp : 定义应用程序的入口点。
//
#include "framework.h"
#include "SUBCLASS.h"
BOOL CALLBACK DiaLogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK NewEdtProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);
WNDPROC g_pfnOldEdtProc = NULL; // 保存回调函数的全局函数指针
int APIENTRY wWinMain( HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
/*
创建对话框 传入当前应用的实例 对话框id 父窗口句柄 和 回调函数
*/
return DialogBox(hInstance, MAKEINTRESOURCE(DLG_SUB_CLASS),NULL, DiaLogProc);
}
/*
自定义EditCtroller 回调函数
*/
LRESULT CALLBACK NewEdtProc(HWND hwnEdit, UINT message, WPARAM wParam, LPARAM lParam){
switch (message)
{
/*
wParam 虚拟码
*/
case WM_CHAR:{ // 键盘消息 如果是数字或者 字母我们就调用正常的显示 其他的我们直接return
if(('0' <= wParam && wParam <= '9') ||
('a' <= wParam && wParam <= 'z') ||
('A' <= wParam && wParam <= 'Z')) {
// 如果是我们想要的字母或数字 正常显示 否则的话 不处理
return g_pfnOldEdtProc(hwnEdit,message, wParam, lParam);
}else{
return (LRESULT)TRUE;
}
}
}
return g_pfnOldEdtProc(hwnEdit, message, wParam, lParam);
}
BOOL CALLBACK DiaLogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
WORD wId;
switch (message)
{
case WM_COMMAND:
wId = LOWORD(wParam);
switch (wId)
{
case BTN_SUB_CLASS:{ // 子类化的按钮点击
/*
LONG SetWindowLong(
HWND hWnd, // handle to window
int nIndex, // offset of value to set
LONG dwNewLong // new value);
窗口句柄 索引 新的值
GWL_WNDPROC 替换过程函数的索引
新的值 我们填我们的过程函数地址
*/
HWND edtHwnd = GetDlgItem(hwndDlg, EDT_SUB_CLASS);
// 点击的时候替换文本框的过程函数为我们自定义的函数
if(!g_pfnOldEdtProc){
// 防止多次替换 造成递归
// 修改EditCtroller 的过程函数为我们自定义的过程函数
g_pfnOldEdtProc = (WNDPROC)SetWindowLong(edtHwnd, GWL_WNDPROC, (LONG)&NewEdtProc); // 返回原本的编辑框的回调函数指针
}
return TRUE;
}
case WM_CLOSE:
case IDOK:
case IDCANCEL:
// 关闭对话框
EndDialog(hwndDlg, wParam);
return TRUE;
}
}
return FALSE;
}