日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

窗口类、窗口类对象与窗口 三者之间关系

發(fā)布時間:2023/12/18 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 窗口类、窗口类对象与窗口 三者之间关系 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文摘自孫鑫<VC++深入詳解3.3.1>

3.3.1??三者之間關系

很多開發(fā)人員都將窗口類、窗口類的對象和窗口之間的關系弄混淆了。為了使讀者能更好地理解它們之間的關系,下面我們將模擬CWnd類的封裝過程。首先新建一個Win32?Application類型的工程,取名為“WinMain”。在隨后的向導窗口中選擇創(chuàng)建一個空工程(即選擇an empty project選項)。接著為該工程新建一個源文件WinMain.cpp。在該文件中,首先新建一個類CWnd,然后為其定義創(chuàng)建窗口函數(CreateEx)、顯示窗口函數(ShowWindow)和更新窗口函數(UpdateWindow)三個函數,并定義一個成員變量(m_hWnd)。具體代碼如例3-18所示。

例3-18

class CWnd

{

public:

??? BOOL CreateEx(DWORD dwExStyle,????? // extended window style

??????????????? LPCTSTR lpClassName,? // registered class name

??????????????? LPCTSTR lpWindowName, // window name

??????????????? DWORD dwStyle,??????? // window style

??????????????? int x,??????????????? // horizontal position of window

??????????????? int y,??????????????? // vertical position of window

??????????????? int nWidth,?????????? // window width

??????????????? int nHeight,????????? // window height

??????????????? HWND hWndParent,????? // handle to parent or owner window

??????????????? HMENU hMenu,????????? // menu handle or child identifier

??????????????? HINSTANCE hInstance,? // handle to application instance

??????????????? LPVOID lpParam);??????? // window-creation data

??? BOOL ShowWindow(int nCmdShow);

??? BOOL UpdateWindow();

public:

??? HWND m_hWnd;

};

?

小技巧:這些函數的參數可以參照MSDN中相應MFC函數的定義,然后直接復制這些參數即可。

?

提示:因為SDK函數數量很多,程序員記憶負擔很重。MFC中使用的大部分函數名與相應的SDK函數名相同,這樣做的目的就是為了方便程序員,減輕記憶負擔。程序員只需要記憶兩者中的一個就可以了。

接下來完成這三個函數的定義,代碼如例3-19所示。

例3-19

BOOL CWnd::CreateEx(DWORD dwExStyle,????? // extended window style

??????????????? LPCTSTR lpClassName,? // registered class name

??????????????? LPCTSTR lpWindowName, // window name

??????????????? DWORD dwStyle,??????? // window style

??????????????? int x,??????????????? // horizontal position of window

??????????????? int y,??????????????? // vertical position of window

??????????????? int nWidth,?????????? // window width

??????????????? int nHeight,????????? // window height

??????????????? HWND hWndParent,????? // handle to parent or owner window

??????????????? HMENU hMenu,????????? // menu handle or child identifier

??????????????? HINSTANCE hInstance,? // handle to application instance

??????????????? LPVOID lpParam)??????? // window-creation data

{

??? m_hWnd=::CreateWindowEx(dwExStyle,lpClassName,dwStyle,x,y,

??????????????????? nWidth,nHeight,hWndParent,hMenu,hInstance,

??????????????????? lpParam);

??? if(m_hWnd!=NULL)

??????? return TRUE;

??? else

??????? return FALSE;

}

?

BOOL CWnd::ShowWindow(int nCmdShow)

{

??? return ::ShowWindow(m_hWnd,nCmdShow);

}

?

BOOL CWnd::UpdateWindow()

{

??? return ::UpdateWindow(m_hWnd);

}

其中,我們定義的CWnd類的CreateEx函數需要完成創(chuàng)建窗口的工作,這可以利用Win32提供的SDK函數:CreateWindowEx函數來實現。該函數返回一個句柄,標識它所創(chuàng)建的窗口。這里,我們就可以利用已定義的CWnd類的成員變量m_hWnd來保存這個窗口句柄。因為我們定義的CreateEx函數返回值是個BOOL型,所以應該判斷一下這個窗口句柄。根據其值是否為空來決定函數是返回TRUE值,還是FALSE值。

讀者應注意的是,在實際開發(fā)時,應該初始化m_hWnd變量,這可以在構造函數中實現,給它賦一個初值NULL。這里我們只是為了演示CWnd類是如何與窗口關聯(lián)起來的,因此就不進行初始化工作了。

接下來定義ShowWindow函數的實現。同樣,需要調用Platform SDK函數,即ShowWindow來完成窗口的顯示。為了區(qū)分這兩個同名函數,在調用這個Platform SDK函數時,前面加上作用域標識符(即::)。這種以“::”開始的表示方法表明該函數是一個全局函數,這里表示調用的ShowWindow函數是Platform SDK函數。因為CreateEx函數已經獲取了窗口句柄并保存到m_hWnd成員變量中,所以,ShowWindow函數可以直接把這個句柄變量作為參數來使用。

提示:讀者在定義自己的成員函數時,如果調用的API函數名與自己的函數名不同,那么該API函數名前可以加也可以不加“::”符號,編譯器會自動識別API函數。但是如果當前定義的成員函數與內部調用的API函數名相同,那么后者前面必須加“::”符號,否則程序在編譯或運行時就會出錯。

我們自己定義的UpdateWindow函數的實現比較簡單,直接調用SDK函數:UpdateWindow完成更新窗口的工作。

從例3-19所示代碼可知,我們定義的CWnd類的后兩個函數(ShowWindow和UpdateWindow)內部都需要一個窗口句柄,即需要知道對哪個窗口進行操作。

現在我們就實現了一個窗口類:CWnd。但我們知道如果要以類的方式來完成窗口的創(chuàng)建、顯示和更新操作,那么首先還需要編寫一個WinMain函數。讀者并不需要記憶這個函數的寫法,只要機器上有MSDN就可以了,在MSDN中找到該函數的幫助文檔,直接復制其定義即可。這里,我們只是想講解在這個函數內部所做的工作,并不是真正的實現,因此只是寫出其主要的代碼,如例3-20所示。

例3-20

int WINAPI WinMain(

? HINSTANCE hInstance,????? // handle to current instance

? HINSTANCE hPrevInstance,? // handle to previous instance

? LPSTR lpCmdLine,????????? // command line

? int nCmdShow????????????? // show state

)

{

??? //首先是設計窗口類,即定義一個WNDCLASS,并為相應字段賦值。

??? WNDCLASS wndcls;

??? wndcls.cbClsExtra=0;

??? wndcls.cbWndExtra=0;

??? ......

//注冊窗口類

RegisterClass(&wndcls);

?

//創(chuàng)建窗口

CWnd wnd;

wnd.CreateEx(...);

?

//顯示窗口

wnd.ShowWindow(SW_SHOWNORMAL);

???

//更新窗口

wnd.UpdateWindow();

//接下來就是消息循環(huán),此處省略

......

return 0;

}

請讀者回想一下第1章中我們利用SDK編程時為創(chuàng)建窗口、顯示窗口和更新窗口所編寫的代碼(如例3-21所示),并比較例3-20和例3-21這兩段代碼的區(qū)別。

例3-21

??? HWND hwnd;

??? hwnd=CreateWindowEx();

??? ::ShowWindow(hwnd,SW_SHOWNORMAL);

??? ::UpdateWindow(hwnd);

我們可以發(fā)現,SDK程序中多了一個HWND類型的變量hwnd。該變量用來保存由CreateWindowEx函數創(chuàng)建的窗口句柄,并將其作為參數傳遞給隨后的顯示窗口操作(ShowWindow函數)和更新窗口操作(UpdateWindow函數)。而我們自定義的實現代碼中,CWnd類定義了一個HWND類型的成員變量:m_hWnd,用于保存這個窗口句柄。首先CWnd類的CreateEx函數創(chuàng)建窗口,并將該窗口句柄保存到這個成員變量,接著調用CWnd類的ShowWindow函數顯示窗口時,就不需要再傳遞這個句柄了,因為它已經是成員變量,該函數可以直接使用它。CWnd類的UpdateWindow函數也是一樣的道理。

許多程序員在進行MFC程序開發(fā)時,容易混淆一點:認為這里的CWnd類型的wnd這個C++對象所代表的就是一個窗口。因為在實踐中,他們看到的現象是:當C++窗口類對象銷毀時,相應的窗口也就沒了。有時正好巧合,當窗口銷毀時,C++窗口類對象的生命周期也到了,從而也銷毀了。正因為如此,許多程序員感覺C++窗口類對象就是窗口,窗口就是這個C++窗口類對象。事實并非如此。讀者可以想像一下,如果我們關閉了一個窗口,這個窗口就銷毀了,那么該窗口對應的C++窗口類對象銷毀了沒有呢?當然沒有。當一個窗口銷毀時,它會調用CWnd類的DestroyWindow函數,該函數銷毀窗口后,將CWnd成員變量:m_hWnd設為NULL。

C++窗口類對象的生命周期和窗口的生命周期不是一致的。當一個窗口銷毀時,與C++窗口類對象沒有關系,它們之間的紐帶僅僅在于這個C++窗口類內部的成員變量:m_hWnd,該變量保存了與這個C++窗口類對象相關的那個窗口的句柄。

另一方面,當我們設計的這個C++窗口類對象銷毀的時候,與之相關的窗口是應該銷毀的,因為它們之間的紐帶(m_hWnd)已經斷了。另外,窗口也是一種資源,它也占據內存。這樣,在C++窗口類對象析構時,也需要回收相關的窗口資源,即銷毀這個窗口。

因此,讀者一定要注意:C++窗口類對象與窗口并不是一回事,它們之間惟一的關系是C++窗口類對象內部定義了一個窗口句柄變量,保存了與這個C++窗口類對象相關的那個窗口的句柄。窗口銷毀時,與之對應的C++窗口類對象銷毀與否,要看其生命周期是否結束。但C++窗口類對象銷毀時,與之相關的窗口也將銷毀。在我們定義的這個WinMain程序(例3-20所示代碼)中,當程序運行到WinMain函數的右大括號(})時,該函數內部定義的Wnd窗口類對象的生命周期也就結束了。

這是我們自已定義的CWnd類,那么MFC提供的CWnd類是不是這樣實現的呢?讀者在MSDN中查看MFC提供的CWnd類,將會發(fā)現該類確實定義了一個數據成員:m_hwnd,用來保存與之相關的窗口的句柄。因為MFC中所有的窗口類都是由CWnd類派生的,于是,所有的窗口類(包括子類)內部都有這樣的一個成員用來保存與之相關的窗口句柄。所以,讀者不能認為我們前面創(chuàng)建的MFC程序Test中的CMainFrame類和CTestView類的對象就是一個窗口。

總結

以上是生活随笔為你收集整理的窗口类、窗口类对象与窗口 三者之间关系的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。