使用VC實現可拖動視窗
阿新 • • 發佈:2018-12-05
有很多漂亮的小程式,它們的視窗都是可以拖動的。滑鼠在視窗的任意位置按下,即可把視窗拖動到其它位置。通常標準的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