2024年4月28日发(作者:)

关于在模态对话框中获取父窗口对象的方法研究

姚君

/************************************************

*******************************/ 测试方法

/************************************************

*******************************/ 首先,新建一个默认

的单文档应用程序。 然后添加对话框资源,并为该对话框资源

关联一个类,例如:CSl;为添加菜单,如Test; 为view 类

添加成员变量: public: COLORREF m_clr; 在view 类下添加

菜单命令函数: void CColrView::OnTest() { // TODO: Add

your command handler code here Csl dlg(this);//指定当前

view 类窗口为模态对话框父窗口 l(); } 在CSl

类中添加消息响应函数(WM_PAINT): void Csl::OnPaint()

{ CPaintDC dc(this); // device context for painting // TODO:

Add your message handler code here CColrView *

cp=(CColrView *)GetParent();//不能正确的获取父窗口view

类对象指针 CWnd *cw=GetParent(); m_clr=((CColrView

*)m_pParentWnd)->m_clr;//可以通过断点debug,发现m_clr

是我们要 的值。 // Do not call CDialog::OnPaint() for painting

messages } 注意:m_pParentWnd 是在CDialog 类中定义的,

该类的头文件是"AFXWIN.H ”; protected: CWnd*

m_pParentWnd; 为什么调用CWnd 类的GetParent 方法不能

正确的获取到父窗口类对象指针的问题留待有 时间认真阅读

该函数源代码后再予以说明。

[-------------------------------------------------------------------------

--------------------------------------------

---------------------------------------------------] 关于GetParent

方法不能正确获取父窗口类对象指针的问题已得到解决, 先将

研究结果放置于下方

[-------------------------------------------------------------------------

--------------------------------------------

---------------------------------------------------] 首先,来看MFC

的源代码,这儿找到的是CWnd* CWnd::GetParentOwner(),

该函数源 码位于 中。 CWnd*

CWnd::GetParentOwner() const { if (GetSafeHwnd() ==

NULL) // no Window attached return NULL;

ASSERT_VALID(this); HWND hWndParent = m_hWnd;

HWND hWndT; while ((::GetWindowLong(hWndParent,

GWL_STYLE) & WS_CHILD) && (hWndT

= ::GetParent(hWndParent)) != NULL) { hWndParent =

hWndT; } return CWnd::FromHandle(hWndParent); } 首先,

调用了WIN32API 函数GetWindowLong来获取Windows

Styles,然后与WS_CHILD 进行&运算,之后又调用全局API 函

数GetParent 获取父窗口句柄.注意,这儿是一个While 循环,

所以最终找到的将是the most immediate parent or owner

window that is not a child window (does not have the

WS_CHILD style)的句柄。最后将句柄传给CWnd::FromHandle

函数并将返回的CWnd 指针作为函数的返回值。 因为没有找

到GetParent 函数源码,那么就MSDN 一下,在MSDN 中是

这样介绍的: Remarks Call this function to get a pointer to a

child window’s parent window (if any). The GetParent

function returns a pointer the immediate parent. In contrast,

the GetParentOwner function returns a pointer to the most

immediate parent or owner window that is not a child window

(does not have the WS_CHILD style). If you have a child

window within a child window GetParent and GetParentOwner

return different results. 现在让我们回到上边的程序中断点调

试。在CMainFrame 类的OnCreate 函数中有一个this 调用,

我们就在这儿设置第一个断点;在view 类OnTest 函数设置

第二个断点;在CSl 类 OnPaint 函数中设置第三个断点。然

后调试运行。 我们会发现指针cp、cw 的值其实就是this 指

针的值,也就是指向了框架类窗口对象。所以 我们想要调用

m_clr 就会出错。 CWnd::GetParent()函数在view 类方法中

调用时可以正确的找到父窗口。

[-------------------------------------------------------------------------

--------------------------------------------

---------------------------------------------------] 最后再介绍一种

方法来解决本题:

[-------------------------------------------------------------------------

--------------------------------------------

---------------------------------------------------] 首先,介绍一个函

数: CWnd::FromHandle static CWnd* PASCAL

FromHandle( HWND hWnd ); Return Value Returns a pointer

to a CWnd object when given a handle to a window. If a

CWnd object is not attached to the handle, a temporary CWnd

object is created and attached. The pointer may be temporary

and should not be stored for later use. Parameters hWnd An

HWND of a Windows window. 这是一个静态函数,可以通过

窗口句柄返回相关的CWnd 类对象的指针。 好,下面我们来

修改下 void Csl::OnPaint() { CPaintDC dc(this); // device

context for painting // TODO: Add your message handler code

here ((CColrView

*)FromHandle(m_pParentWnd->m_hWnd))->m_clr; // Do

not call CDialog::OnPaint() for painting messages } 目的同样

得到了实现。 这儿主要是想讲下FromHandle 函数,所以这

种方法无谓的绕了绕。 写在文末:此外还有好些方法可以实现,

本文主要是想从模态对话框内部直接查找父窗口。