Subclassdlgitem

来源:互联网 发布:纹理算法 编辑:程序博客网 时间:2024/06/05 15:13
subclassdlgitem 

Call this member function to "dynamically subclass" a control created from a dialog template and attach it to thisCWnd object.

该函数用来子类化一个控件.
Subclass(子类化)是MFC中最常用的窗体技术之一。子类化完成两个工作:一是把窗体类对象attach到一个windows窗体实体中(即把一个窗体的hwnd赋给该类)。另外就是把该类对象的消息加入到消息路由中,使得该类可以捕获消息。
SubclassDlgItem可以把对话框中已有的控件与某个窗口对象动态连接起来,该窗口对象将接管控件的消息处理,从而使控件具有新的特性.SubclassDlgItem函数的声明为
BOOL SubclassDlgItem( UINT nID, CWnd* pParent );
参数nID是控件的ID,pParent是指向父窗口的指针.若连接成功则函数返回TRUE,否则返回FALSE.
综上所述,要在程序中使用派生控件,应该按下面两步进行:
在对话框模板中放置好基类控件.
在对话框类中嵌入派生控件类的对象.

在OnInitDialog中调用SubclassDlgItem将派生类的控件对象与对话框中的基类控件相连接,则这个基类控件对象变成了派生控件对象

问题缘起


通常如果在对话框中将一个控件映射到一个变量,有三种方法:
1.       DDX的方法
2.       GetDlgItem的方法,例如CEdit pEdt = (CEdit *)GetDlgItem(IDC_EDIT1);
3.       SubclassWindow的方法(或者其扩展SubclassDlgItem),例如CEdit m_edit;m_edit.SubclassDlgItem(IDC_EDIT1);
SubclassWindow


      CWnd::SubclassWindow(HWND hWnd)中调用两个主要操作:Attach(hWnd)和WNDPROC oldWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)AfxGetAfxWndProc());
    前者的作用是把CWnd中的m_hWnd设置为hWnd,后者的作用是改变该窗口的窗口函数为AfxGetAfxWndProc()的返回.
AfxGetAfxWndProc返回了AfxWndProc的函数指针,即窗口函数的指针,AfxWndProc包裹了AfxCallWndProc,后者又调用了pWnd->WindowProc(nMsg, wParam, lParam);。
可见SubclassWindow完成了两项功能:
1.       我们对该窗体实例调用成员函数将会直接改变相关窗体句柄对应的窗体(Attach)
2.       系统传给相关窗体句柄的消息会先经过该窗体实例的消息映射(SetWindowLong)。
SubclassDlgItem


      调用了SubclassWindow,但之前调用了::GetDlgItem获取一个控件ID对应的窗口句柄。
GetDlgItem


      只是调用::GetDlgItem获得控件ID对应的窗口句柄,然后使用FromHandle将句柄转换为CWnd指针。
SubclassDlgItem和GetDlgItem二者的区别


      如果只是想调用一个控件对应类的方法,差别不大。只是前者会生成一个类对象,而后者得到指向对象的指针。
      但如果跟消息有关,则前者会相应消息。例如:
      比如我自己写了一个类叫CSuperEdit(父类为CEdit),在该类中我声明了void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);并在消息循环里添加了ON_WM_CHAR 一行。现在我只要在对话框CProg1Dlg 中声明CSuperEdit m_edit;然后在CProg1Dlg::OnInitDialog中,添加以下代码,就完成了“超类化”:
HWND hWndControl = ::GetDlgItem(pParent->m_hWnd, IDC_EDIT1);
m_edit.SubclassWindow (hWndControl);
      通过这种方式,可以动态改变一个控件的消息处理流程,使得CsuperEdit中重载的消息可以被执行。如果不使用子类型化,则无法执行。
参考资料(MSDN):


      Call this member function to "dynamically subclass" a window and attach it to this CWnd object. When a window is dynamically subclassed, windows messages will route through the CWnd’s message map and call message handlers in the CWnd’s class first. Messages that are passed to the base class will be passed to the default message handler in the window.
This member function attaches the Windows control to a CWnd object and replaces the window’s WndProc and AfxWndProc functions. The function stores a pointer to the old WndProc in the CWnd object.
参考资料(来自CSDN)


http://dev.csdn.net/Develop/article/16/16045.shtm
参考资料(来自Programming Windows)


The window procedure for the scroll bar controls is somewhere inside Windows. However, you can obtain the address of this window procedure by a call to GetWindowLong using the GWL_WNDPROC identifier as a parameter. Moreover, you can set a new window procedure for the scroll bars by calling SetWindowLong. This technique, which is called "window subclassing," is very powerful. It lets you hook into existing window procedures, process some messages within your own program, and pass all other messages to the old window procedure.
The window procedure that does preliminary scroll bar message processing in COLORS1 is named ScrollProc; it is toward the end of the COLORS1.C listing. Because ScrollProc is a function within COLORS1 that is called by Windows, it must be defined as a CALLBACK.
For each of the three scroll bars, COLORS1 uses SetWindowLong to set the address of the new scroll bar window procedure and also obtain the address of the existing scroll bar window procedure:
OldScroll[i] = (WNDPROC) SetWindowLong (hwndScroll[i], GWL_WNDPROC,
                                       (LONG) ScrollProc)) ;
Now the function ScrollProc gets all messages that Windows sends to the scroll bar window procedure for the three scroll bars in COLORS1 (but not, of course, for scroll bars in other programs). The ScrollProc window procedure simply changes the input focus to the next (or previous) scroll bar when it receives a Tab or Shift-Tab keystroke. It calls the old scroll bar window procedure using CallWindowProc.

0 0
原创粉丝点击