MFC永久窗口对象与临时窗口对象

这篇讲得很清楚,就转过来了,原文如下:

因项目需要,最近在学习MFC,下午在一篇教程中提到了临时窗口、永久窗口,作者让读者自行查阅MSDN,了解临时窗口与永久窗口的概念,出于好奇,出于方便,直接百度一下,看到了几篇题为解释临时窗口与永久窗口的文章,随后网友在论坛中附上了MSDN中的原文,仔细翻译一下,发现网上查到的几篇文章,对这个概念的解释是有问题和不足的。 
首先我要说明一点的就是窗口是没有临时与永久之分的,窗口是一种资源,随着CreateWindow的调用而产生,随着DestroyWindow的调用而被销毁(资源所占据的内存被回收),在windows程序设计中通过句柄(这里可以将句柄看成是C++中的指针)来标识资源,通过句柄来操作窗口,控制窗口,也就是说真正表示窗口的是窗口句柄HWND类型变量,为了方便开发、提高开发效率,MFC帮我们封装了与窗口有关的操作(就是对win32 API的间接调用而已),并将标识窗口的句柄的HWND的变量,封装到了CWnd类中,作为其数据成员,所以我们在调用MFC类中与Win32同名的成员函数的时候,就少去了句柄这一参数,是因为CWnd类维护了这一HWND类型的变量,归根结底MFC的成员函数还是调用了win32函数,说这么多的原因主要是想说明MFC 中的C++窗口对象只是我们操作窗口的一层封装,一种手段,MSDN中说的是临时窗口对象的概念,而不是临时窗口与永久窗口,因为根本就没有这两个概念(创建窗口之后,只要不直接、间接调用destroywindow那么窗口就一直占据内存资源)
如上所述,在MFC中,都是以C++对象来操作窗口,而窗口是用句柄来标识的,这样就需要将窗口和C++对象关联起来。通过C++对象的成员变量m_hWnd(HWND类型)来建立这种联系.
首先解释一下何为永久窗口对象:
在MFC中建立一个窗口的步骤:
CWnd win;
win.Create();(篇幅所限此处略去Create函数的参数,create函数负责创建窗口并将其关联到win这个对象上,说白了就是给m_hWnd这个成员变量赋值);
此时win这个对象就是永久窗口对象,接着调用这段代码 CWnd* pWnd = CWnd::FromHandle(win.m_hWnd)返回的就是指向win这个永久窗口对象的指针,如果我们接着做如下操作:HWND hwnd = win.Detach();
接着再调用上面的代码:pWnd = CWnd::FromHandle(hwnd),此时pWnd指向的对象就是临时窗口对象
以下是MSDN中对CWnd::FromHandle函数返回值的说明

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

对于临时窗口对象,windows程序会在线程出于空闲时间的时候(消息队列为空),自动调用CWinThread::DeleteTempMap()函数把临时对象从他关联的窗口句柄上卸载下来,取消这种关联,并删除这个临时窗口对象,但注意,这个窗口句柄还是存在的,因为窗口这个资源并没有销毁,销毁的只是封装窗口句柄的这个临时的C++对象,所以我们不能存储这个对象的指针,在其他地方调用,因为它随时会被回收,变成无效指针,同样在不同的线程中也是不能传递C++窗口对象的,此处 不管该C++窗口对象是不是临时的,如果我们要在其它地方操作这个窗口,应该存储代表窗口的句柄,而非C++对象。

以下是MSDN原文对临时窗口对象与永久窗口对象的说明:

TN003: Mapping of Windows Handles to Objects
This note describes the MFC routines that support mapping Windows object handles to C++ objects.

The Problem

Windows objects are normally represented by HANDLEs. The MFC classes wrap Windows object handles with C++ objects. The handle wrapping functions of the MFC class library provide a way to find the C++ object that is wrapping the Windows object with a particular handle. There are times when a Windows object does not have a C++ wrapper object, however, and at these times a temporary object is created to act as the C++ wrapper.

The Windows objects that use handle maps are: 
HWND (CWnd and CWnd-derived classes)
HDC (CDC and CDC-derived classes)
HMENU (CMenu)
HPEN (CGdiObject)
HBRUSH (CGdiObject)
HFONT (CGdiObject)
HBITMAP (CGdiObject)
HPALETTE (CGdiObject)
HRGN (CGdiObject)
 HIMAGELIST (CImageList)
SOCKET (CSocket)  
Given a handle to any of these objects, you can find the MFC object that wraps the handle by calling the static member function FromHandle. For example, given an HWND called hWnd:

CWnd::FromHandle(hWnd)

will return a pointer to the CWnd that wraps the hWnd. If that hWnd does not have a specific wrapper object, then a temporary CWnd is created to wrap the hWnd. This makes it possible to get a valid C++ object from any handle.

Once you have a wrapper object, you can get to its handle through a public member variable. In the case of an CWnd, m_hWnd contains the HWND for that object.

Attaching Handles to MFC Objects

Given a newly created handle-wrapper object and a handle to a Windows object, you can associate the two by calling Attach. For example:

CWnd myWnd;
myWnd.Attach(hWnd);

This makes an entry in the permanent map associating myWnd and hWnd. Calling CWnd::FromHandle(hWnd) will now return a pointer to myWnd. When myWnd is deleted, the destructor will automatically destroy the hWnd by calling the Windows DestroyWindow function. If this is not desired, the hWnd must be detached from myWnd before the myWnd object is destroyed (normally when leaving the scope at which myWnd was defined). The Detach member function does this.

myWnd.Detach();

More About Temporary Objects

Temporary objects are created whenever FromHandle is given a handle that does not already have a wrapper object. These temporary objects are detached from their handle and deleted by the DeleteTempMap functions. The default OnIdle processing in CWinThread automatically calls DeleteTempMap for each class that supports temporary handle maps. This means that you cannot assume a pointer to a temporary object will be valid past the point of exit from the function where the pointer was obtained, as the temporary object will be deleted during the Windows message-loop idle time.

Wrapper Objects and Multiple Threads

Both temporary and permanent objects are maintained on a per-thread basis. That is, one thread cannot access another threads C++ wrapper objects, regardless of whether it is temporary or permanent. As stated above, temporary objects are deleted when the thread which that temporary object belongs enters OnIdle.

To pass these objects from one thread to another, always send them as their native HANDLE type. Passing a C++ wrapper object from one thread to another will often result in unexpected results

时间: 2024-11-08 19:25:30

MFC永久窗口对象与临时窗口对象的相关文章

winapi-C# winfrom项目,怎么样实现通过WINAPI 关闭对象的句柄窗口后,还能再次获取该句柄窗口

问题描述 C# winfrom项目,怎么样实现通过WINAPI 关闭对象的句柄窗口后,还能再次获取该句柄窗口 在C# Winfrom项目中,from窗体中,有一个Panel控件. 目前已经实现将对象的窗口通过winAPI获取到句柄窗口放到了Panel控件中. 请问怎么样实现关闭from窗体后,下次再进入from窗体后,还通过winAPI获取到句柄窗口放到了Panel控件中. 关闭from窗体的事情需要怎么样写,才能实现通过winAPI获取到句柄窗口放到了Panel控件中. 附上代码(通过winA

mfc-PPT 自动化开发,PPT嵌入MFC对话框后,按下ESC,幻灯片播放的窗口退出,PPT窗口也同时退出

问题描述 PPT 自动化开发,PPT嵌入MFC对话框后,按下ESC,幻灯片播放的窗口退出,PPT窗口也同时退出 Alert me | Edit | Delete | Change type Question You cannot vote on your own post 0 我自己创建了一个atl控件,用来实现PPT的播放.保存的功能(office 2013版本):然后将该控件嵌入MFC对话框程序里面,但是播放PPT的出现了问题:播放幻灯片的时候,能够正常播放,但是按下ESC按钮结束幻灯片播放

c++-小弟请教在MFC中子窗口如何获取父窗口的句柄啊

问题描述 小弟请教在MFC中子窗口如何获取父窗口的句柄啊 比如我有个父类的Dialog类为A,还有一个子类的Dialog类为B,然后在A类的头文件中包含了B的头文件,然后在A类中生命一个B类的成员变量,类似下面那样,然后我通过一个button调用DoModal();B类的STYLE改为CHILD了: 然后我希望在子窗口中处理一些数据,然后传给父窗口:比如A中有个IDC_text1 有个IDD_BUTTON1,B中有个IDC_text2,有个IDD_BUTTON2: 我就希望在B中的IDC_tex

360极速浏览器临时窗口那些事儿

临时窗口 您可以使用临时窗口完成实现如下功能: 多开QQ空间.论坛.游戏等网站的小号. 浏览不想让人知道的私密网站,即隐身浏览. 临时窗口的特性 在临时窗口中打开的网页和下载的文件不会记录到您的浏览历史记录以及下载历史记录中. 临时窗口中对360极速浏览器收藏夹和常规设置所做的更改以及下载的文件都会保存下来. 每个临时窗口下的登录的网站帐号彼此独立(即Cookie独立),不会串号. 在您关闭一个临时窗口后,系统会删除对应的临时窗口里产生的新的 Cookie. 为了避免扩展导致泄密,临时窗口下已默

动画窗口重绘-MFC动画窗口的重绘 窗口重绘

问题描述 MFC动画窗口的重绘 窗口重绘 10C 动画窗口重绘 在窗口的显示过程中有动画效果 但是这个窗口是无边框 又贴了一些控件的窗口 请问此窗口如何重绘??? 解决方案 在刷新窗口时经常要调用重绘函数MFC提供了三个函数用于窗口重绘InvalidateRect(&Rect)Invalidate()UpdateWindow()当需要更新或者重绘窗口时,一般系统会发出两个消息WM_PAINT(通知客户区有变化)和WM_NCPAINT(通知非客户区有变化)–WM_NVPAINT系统会自己搞定–WM

c++-C++函数返回的临时匿名对象的生命周期

问题描述 C++函数返回的临时匿名对象的生命周期 C++函数返回的临时匿名对象什么时候被释放内存 #include using namespace std; class A { public: int x; A(int a){cout<<"creating"<<endl;x=a;} A(const A& a){cout<<"copy"<<endl;x=a.x;} void operator=(A& a)

mfc-我用MFC做的聊天软件刚刚点击完发送就弹出每个MFC都会弹出的普通窗口,然后聊天的对话框就不见了

问题描述 我用MFC做的聊天软件刚刚点击完发送就弹出每个MFC都会弹出的普通窗口,然后聊天的对话框就不见了 我用MFC做的聊天软件刚刚点击完发送就弹出每个MFC都会弹出的普通窗口,然后聊天的对话框就不见了,求解释?? 我是照着书上做的,我在创建服务器后会有个对话框,然后有发送按钮,预想点击发送后是会像聊天窗口一样的显示,但是实际上却是: 关闭了对话框,然后打开MFC最开始的基本窗口: 我的 窗口函数在这里,然后OnSend是处理"发送"按钮的 // CChat 消息处理程序 #incl

背景图片-MFC中对话框中图片适应窗口的问题

问题描述 MFC中对话框中图片适应窗口的问题 我自己建的窗口,当从文件加载背景图片时消失在对话框中的图片太大没有显示完全?这个该如何解决呢!? 解决方案 什么意思,能说清除一点吗

mfc窗口,父窗口parentwindow,所有者窗口ownerwindow 区别

一. parent:创建者,owner:所有者 小玉的父母生下小玉,养到8岁,卖给贾府当丫头小玉的父母是parent,贾府是owner 二. 1.Pop-up窗口: 一个弹出窗口是必须具有WS_POPUP属性的窗口,弹出窗口只能是一个Top-Level窗口,不能是子窗口,弹出窗口多用于对话框和消              息框,也可以用于应用程序的主窗口, 弹出窗口可以不必具有标题栏 2.Overlapped窗口: 一个重叠窗口是一个必须具有WS_OVERLAPPED属性的窗口,也就是一个重叠窗