<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    MFC永久窗口對象與臨時窗口對象

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    這篇講得很清楚,就轉過來了,原文如下:

    因項目需要,最近在學習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

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全