1. 程式人生 > >使用VC實現可拖動視窗

使用VC實現可拖動視窗

有很多漂亮的小程式,它們的視窗都是可以拖動的。滑鼠在視窗的任意位置按下,即可把視窗拖動到其它位置。通常標準的Windows視窗只有在標題欄上按下滑鼠才可以拖動,那麼如何實現視窗的任意位置都可以拖動呢? 稍有經驗的程式設計師會立刻想到:響應滑鼠按下訊息,然後在滑鼠移動時移動視窗。對於程式基礎好的程式設計師,可以按這個思維很快實現,對於初學者,可能就要多除錯一會兒了。有沒有其它方法呢? 仔細瞭解一下MFC的實現,就能找到更簡單的方法。 MFC把視窗分成兩個部分,一部分是Client區,也叫客戶區,就是我們可以在上面畫畫、放置子視窗等地方的區域,程式設計師負責這個區域的操作;另一部分叫NC區,也就是Not Client區,稱為非客戶區,標題欄、邊框、視窗選單等都屬於非客戶區。在非客戶區的操作都由MFC負責。而MFC並沒有獨攬視窗非客戶區的操作大權,程式設計師可以使用虛擬函式、視窗訊息等方式影響非客戶區的操作。 當滑鼠在非客戶區按下的時候,MFC通過傳送 WM_NCHITTEST 訊息來確定位置,並依據WM_NCHITTEST訊息的響應函式返回的位置資訊確定應該執行的操作。在標題欄上按下滑鼠將執行拖動視窗操作。 現在我們有了另一個實現拖動視窗的方法了:響應WM_NCHITTEST訊息,無論滑鼠在什麼位置,都返回HTCAPTION(標題欄),騙過MFC,讓它來實現視窗拖動。 如果IDE好使的話,可以使用增加訊息響應嚮導簡化程式設計。也可以按以下方法手動新增WM_NCHITTEST的響應函式。 1) 在視窗類定義中新增響應函式的宣告: afx_msg UINT OnNcHitTest(CPoint point);
2) 在訊息響應入口表中登記響應入口,也就是在EGIN_MESSAGE_MAP和END_MESSAGE_MAP之間增加以下內容: ON_WM_NCHITTEST() 3) 實現OnNcHitTest的函式體,假設類名為CXxx: UINT CXxx::OnNcHitTest(CPoint point) {            return HTCAPTION; }
經過這三步,視窗應該可以拖動了,實在是有點太容易。 喜歡研究問題的朋友一定會在HTCAPTION上按一下F12,也就是去看一下HTCAPTION的定義。如果您這樣做了,您一定會看到在HTCAPTION旁邊還定義著很多其它的東西,向下面這樣: /*  * WM_NCHITTEST and MOUSEHOOKSTRUCT Mouse Position Codes  */ #define HTERROR             (-2)
#define HTTRANSPARENT       (-1) #define HTNOWHERE           0 #define HTCLIENT            1 #define HTCAPTION           2 // 我們返回的那個(蘇林注) #define HTSYSMENU           3 #define HTGROWBOX           4 #define HTSIZE              HTGROWBOX #define HTMENU              5 #define HTHSCROLL           6 #define HTVSCROLL           7 #define HTMINBUTTON         8 #define HTMAXBUTTON         9 #define HTLEFT              10 #define HTRIGHT             11 #define HTTOP               12 #define HTTOPLEFT           13 #define HTTOPRIGHT          14 #define HTBOTTOM            15 #define HTBOTTOMLEFT        16 #define HTBOTTOMRIGHT       17 #define HTBORDER            18 #define HTREDUCE            HTMINBUTTON #define HTZOOM              HTMAXBUTTON #define HTSIZEFIRST         HTLEFT #define HTSIZELAST          HTBOTTOMRIGHT #if (WINVER >= 0x0400) #define HTOBJECT            19 #define HTCLOSE             20 #define HTHELP              21 #endif /* WINVER >= 0x0400 */ 如果您的響應函式中,在適當地方返回這些值,可以得到很多其它效果,如最大化、改變大小、啟動幫助、關閉視窗等,有興趣的話可以自己去研究。 作者:蘇林 2007-12-24   有很多漂亮的小程式,它們的視窗都是可以拖動的。滑鼠在視窗的任意位置按下,即可把視窗拖動到其它位置。通常標準的Windows視窗只有在標題欄上按下滑鼠才可以拖動,那麼如何實現視窗的任意位置都可以拖動呢? 稍有經驗的程式設計師會立刻想到:響應滑鼠按下訊息,然後在滑鼠移動時移動視窗。對於程式基礎好的程式設計師,可以按這個思維很快實現,對於初學者,可能就要多除錯一會兒了。有沒有其它方法呢? 仔細瞭解一下MFC的實現,就能找到更簡單的方法。 MFC把視窗分成兩個部分,一部分是Client區,也叫客戶區,就是我們可以在上面畫畫、放置子視窗等地方的區域,程式設計師負責這個區域的操作;另一部分叫NC區,也就是Not Client區,稱為非客戶區,標題欄、邊框、視窗選單等都屬於非客戶區。在非客戶區的操作都由MFC負責。而MFC並沒有獨攬視窗非客戶區的操作大權,程式設計師可以使用虛擬函式、視窗訊息等方式影響非客戶區的操作。 當滑鼠在非客戶區按下的時候,MFC通過傳送 WM_NCHITTEST 訊息來確定位置,並依據WM_NCHITTEST訊息的響應函式返回的位置資訊確定應該執行的操作。在標題欄上按下滑鼠將執行拖動視窗操作。 現在我們有了另一個實現拖動視窗的方法了:響應WM_NCHITTEST訊息,無論滑鼠在什麼位置,都返回HTCAPTION(標題欄),騙過MFC,讓它來實現視窗拖動。 如果IDE好使的話,可以使用增加訊息響應嚮導簡化程式設計。也可以按以下方法手動新增WM_NCHITTEST的響應函式。 1) 在視窗類定義中新增響應函式的宣告: afx_msg UINT OnNcHitTest(CPoint point); 2) 在訊息響應入口表中登記響應入口,也就是在EGIN_MESSAGE_MAP和END_MESSAGE_MAP之間增加以下內容: ON_WM_NCHITTEST() 3) 實現OnNcHitTest的函式體,假設類名為CXxx: UINT CXxx::OnNcHitTest(CPoint point) {            return HTCAPTION; } 經過這三步,視窗應該可以拖動了,實在是有點太容易。 喜歡研究問題的朋友一定會在HTCAPTION上按一下F12,也就是去看一下HTCAPTION的定義。如果您這樣做了,您一定會看到在HTCAPTION旁邊還定義著很多其它的東西,向下面這樣: /*  * WM_NCHITTEST and MOUSEHOOKSTRUCT Mouse Position Codes  */ #define HTERROR             (-2) #define HTTRANSPARENT       (-1) #define HTNOWHERE           0 #define HTCLIENT            1 #define HTCAPTION           2 // 我們返回的那個(蘇林注) #define HTSYSMENU           3 #define HTGROWBOX           4 #define HTSIZE              HTGROWBOX #define HTMENU              5 #define HTHSCROLL           6 #define HTVSCROLL           7 #define HTMINBUTTON         8 #define HTMAXBUTTON         9 #define HTLEFT              10 #define HTRIGHT             11 #define HTTOP               12 #define HTTOPLEFT           13 #define HTTOPRIGHT          14 #define HTBOTTOM            15 #define HTBOTTOMLEFT        16 #define HTBOTTOMRIGHT       17 #define HTBORDER            18 #define HTREDUCE            HTMINBUTTON #define HTZOOM              HTMAXBUTTON #define HTSIZEFIRST         HTLEFT #define HTSIZELAST          HTBOTTOMRIGHT #if (WINVER >= 0x0400) #define HTOBJECT            19 #define HTCLOSE             20 #define HTHELP              21 #endif /* WINVER >= 0x0400 */ 如果您的響應函式中,在適當地方返回這些值,可以得到很多其它效果,如最大化、改變大小、啟動幫助、關閉視窗等,有興趣的話可以自己去研究。 作者:蘇林 2007-12-24