欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MFC窗口子类化

程序员文章站 2022-05-24 18:22:58
...

我写东西很少婆婆妈妈,可能是比较懒散,如果2个字能说完,绝对不会说三个字以上,有朋友开玩笑说“言语珍贵”,因为简单,很多人不理解,所以也有“跳跃性思维”的说法。

对一个问题,我喜欢”自悟“,一定要知道所以然,即使有一些细节不知,但是整个过程是不应该出现错误,对于问题,我喜欢“心神领会”,只有领会了,才可以游刃有余,

在使用的时候方可如鱼得水,其次领会一个问题,可以让大脑轻松,而不被宿主在大脑中的问题所困扰,这也是所谓的快乐学习,但是弄懂一个问题,是要以时间为代价的,生命如此短暂,我又能弄懂几个问题?

蹉跎的岁月让人一天天变老,让人一天天憔悴,让人的脑细胞在生与死的斗争中,终于死的越来越多,这就是所谓的规律。哀叹时光的流逝,自己却无能无力,只能反省,反省……。

时间在让我们老去的同时,让我们越来越聪明,越来越有智慧,人就因为有太多的不明白,所以才活着,如果都明白了,估计也就是在死亡的那一刻吧!

过于追去完美,过于追求,为什么,让自己在和时间的赛跑中成了一个失败者,无心留恋逝去的光阴,无心幻想剩下的岁月,只有无力的哀叹!

 08年的时候,机缘巧合看了《深入浅出MFC》,也许是因为有一门课程就是VC++开发的,但是当时看那本书,很是晦涩难懂,而因为一些原因,VC++开发的课程也夭折了,一晃,

已经5年过去了,凭借自己的坚持,终于将《深入浅出MFC》看完了,也了解了很多以前觉得晦涩难懂的东西,可能真是自己当时的知识不够而已,也许是自己天资愚笨。用时间去战胜问题是我最大的总结。

言归正传,MFC窗口对象和窗口句柄是两个完全不同的东西,前者是一个C++对象,而后者是一个window对象或者window控件或者windows的一种资源,后者其实就类似一个身份证的东西,唯一标识了它的身份,而这个身份又是前者的一个成员变量,这可能是我们最初的认识吧。

但是当遇到子类化这个概念的时候,懵了,一头雾水,丈二的和尚摸不着头脑?子类化,简单地说就是替换了window窗口句柄的处理过程,书上都这么说,我也就这么说,其实这个还是要从前面的一句话说起,这个所谓的C++对象是如何和window句柄关联起来的?

create函数,这个不应该陌生,在create函数中调用了createx函数等一系列相关的函数,而这些函数做了大概以下事情,注册一个窗口,创建一个窗口返回一个句柄,这个时候这个句柄就放在了m_hWnd成员变量中,在《深入浅出MFC》中,在主窗体创建的时候还有一个偷天换日的动作,那就是将默认的处理函数替换成了我afxwndproc,而这个就对应了所在类的消息映射函数,其实这个就是一个子类化过程,暂且就这么理解吧。所以create函数已经帮我们子类化了,如果细细跟踪下去,会遇到setwindowlong等函数,这些可以自己动手去跟踪下,我点到为止。create函数因为将句柄和C++对象关联起来了,我们当然就可以用C++对象对窗口进行操作了,其实里面调用的还是win32 api,只是这些都被封装在了这个C++对象中,现在应该有豁然开朗和柳暗花明又一村的感觉了吧,当然句柄和C++也就是这个MFC对象关联不仅仅是create函数这一种方式,subclasswindow和DDX也是可以的,跟踪下去这些包含create都是调用了attach和setwindowlong这个函数,源码面前无秘密,大家可以去源码中看看。

 

 

这里我只是写了一个字符串而已:
void CMFCTestDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); //DDX_Control(pDX, IDC_EDIT1, m_edit); m_edit.SubclassWindow(GetDlgItem(IDC_Test)->m_hWnd); m_edit.SetWindowTextW(L"liuyu"); } CWnd* CWnd::GetDlgItem(int nID) const { ASSERT(::IsWindow(m_hWnd)); if (m_pCtrlCont == NULL) return CWnd::FromHandle(::GetDlgItem(m_hWnd, nID)); else return m_pCtrlCont->GetDlgItem(nID); }

 

 

如果向我上面的这种写法,是实现不了子类化的,为什么?因为我这个操作只是将控件和类关联起来了?这可以从头文件中看出来:

 

CEdit m_edit;

通俗来讲子类化就是用自己的窗口处理函数来处理特定消息,并将自己其他消息还给标准(默认)窗口处理函数,而CEdit是微软定义的基类,里面定义了对EDIT控件默认的消息处理函数.

 

看到这个CEdit,我们似乎应该知道原因,这个是一个基类,或者说是从CWnd派生的一个窗口对象。在子类化介绍的时候,往往会用一个对输入的字符做判断这个例子,如果我们没有在CEdit这个类做特殊处理,我们就无法实现对输入字符的判断?那我们可以不可以在CEdit中添加,其实理论上是可行的,但是不这么做,你想下,这样将基类都破坏了,微软的人看了,还不会被气死,所以我们可以这么做,从CEdit派生一个类,回想主窗体创建的那个过程?这两个就类似,当然可以在这个派生类中添加消息处理函数了。

 

一般在使用子类化的时候,从基类中派生一个子类,这样我们就会自己去定制想要的功能!一旦有了子类,我们就可以在子类中添加要处理的函数,并且采用自己熟悉的方式进行句柄关联……,这算是我对子类化的一点个人看法,如果有什么想法,可以跟我探讨!下面附上我的一些操作代码:

 

 

 

头文件
CEdit m_edit;
CmyEdit m_edit1;

 

 

所谓的子类化
void CMFCTestDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	//DDX_Control(pDX, IDC_EDIT1, m_edit);
	m_edit1.SubclassWindow(GetDlgItem(IDC_Test)->m_hWnd);
	//m_edit.SetWindowTextW(L"ss");
}

 

 

 

派生类中对OnChar的处理,这里我将第一个输入的字母A改成了B,不要注释掉CEdit::OnChar(nChar, nRepCnt, nFlags),但是可以注释下看看效果。

void CmyEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) {  // TODO: 在此添加消息处理程序代码和/或调用默认值

 CString ch;

 GetWindowText(ch);  // 获得已输入的字符序列

 if(strlen(ch)==0&&nChar == 'A')  {         SetWindowTextW(this->m_hWnd,L"B");

  return ;  }

  

   CEdit::OnChar(nChar, nRepCnt, nFlags);

}

 前面我们说到过create这函数,这个函数其实就是创建一个window的句柄对象或者说window对象(区别C++对象)

那么如果我们有了一个子类,不是通过拖放控件的方式,我们可以自己用create函数去做这个子类化,代码如下:

 

BOOL CMFCTestDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码


	CRect r(20,10,300,500); 
	//GetClientRect(&r);


	m_edit1.Create(WS_VISIBLE|WS_CHILD,r,this,10003);

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

 

 

 

转载于:https://www.cnblogs.com/zuiyirenjian/archive/2013/05/27/3102564.html