SubclassWindow和SubclassDlgItem

来源:互联网 发布:淘宝开店阿里巴巴专栏 编辑:程序博客网 时间:2024/05/24 01:41

问题缘起

通常如果在对话框中将一个控件映射到一个变量,有三种方法:

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)中调用两个主要操作:AttachhWnd)和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指针。

SubclassDlgItemGetDlgItem二者的区别

   如果只是想调用一个控件对应类的方法,差别不大。只是前者会生成一个类对象,而后者得到指向对象的指针。

   但如果跟消息有关,则前者会相应消息。例如:

   比如我自己写了一个类叫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 CWndobject. 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’sWndProc and AfxWndProc functions. The function stores a pointer to the old WndProc in the CWndobject.

参考资料(来自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 namedScrollProc; 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.



http://www.newsmth.net/pc/pccon.php?id=1363&nid=81054

0 0