加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

SubclassWindow和SubclassDlgItem

(2013-10-17 14:20:39)
标签:

c

分类: c

问题缘起

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

1.       DDX的方法

2.       GetDlgItem的方法,例如CEdit pEdt = (CEdit *)GetDlgItem(IDC_EDIT1);

3.       SubclassWindow的方法(或者其扩展SubclassDlgItem),例如CEdit m_editm_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 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.



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

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有