zoukankan      html  css  js  c++  java
  • 学习:MFC子类化

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

    简单说来,子类化是靠拦截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;
    	}
    }
    
    
  • 相关阅读:
    等额本息还款法、等额本金
    数学集合:N Z Q R C
    Xshell配置SSH免密码登录
    【转】Microsoft .Net Remoting之Marshal、Disconnect与生命周期以及跟踪服务
    【转】Microsoft .Net Remoting 之.Net Remoting基础篇
    【转】C#调用WebService实例和开发
    【MYSQL】存储过程示例
    【转】【C++】C++ 中的线程、锁和条件变量
    【C++】线程_beginthreadex参数说明
    【转】【c++】指针参数是如何传递内存的
  • 原文地址:https://www.cnblogs.com/zpchcbd/p/12300069.html
Copyright © 2011-2022 走看看