MFC无边框对话框实现拖动
解決無標題欄窗口的拖動問題有兩種方案,一種方案是使用常規思路來處理鼠標拖拽事件,當窗口獲得WM_LBUTTONDOWN(OnLButtonDown)時,通過設置標志并調用CWnd::SetCapture()函數來讓當前窗口捕捉鼠標消息,應用程序進入移動模式,此時只要有WM_MOUSEMOVE消息過來,就可以據此移動框架窗口,最后當用戶釋放鼠標按鈕,則WM_LBUTTONUP消息處理例程清除標志并調用CWnd::ReleaseCapture()函數將鼠標控制返還給Windows。
這種方法比較繁瑣,首先要決定窗口準備移到哪?然后要想好如何重繪窗口等等,而且根據屏幕顯示屬性對話框"效果"頁中"視覺效果"項的"拖動時顯示窗口中內容"復選框是不是選中,拖動效果是不同的。那么你怎么知道設置的信息呢?方法是調用SystemParametersInfo(SPI_GETDRAGFULLWINDOWS)。
Windows要程序員來事無巨細地處理這些繁瑣的事情真是太糟了。
由于Windows本身知道通過鼠標點住標題欄可以移動窗口,那么能不能將鼠標在窗口客戶區任何地方的點擊拖動行為都模仿成好像是在標題欄中一樣呢?答案是肯定的,這樣就產生了第二種拖動窗口移動的方法。實際上,用鼠標點住對話框背景進行拖動操作并不難,但是你必須了解在標題欄里拖動窗口的原理。
Windows首先確定鼠標點中了哪個窗口,然后向那個窗口發送一個WM_NCHITTEST消息找出此窗口的哪個"非客戶區"(如邊界、最大化/最小化按鈕、菜單、標題等等)擁有鼠標光標。
接著默認的窗口過程響應消息并返回一個特定的代碼。如果鼠標指針落在標題欄中,那么這個特定代碼就是HTCAPTION,此時Windows便進入拖拽模式,以便用戶能夠對窗口進行移動操作。所以要想在客戶區里用鼠標拖動對話框,那么只要在客戶區里模仿標題欄里的鼠標拖動行為即可。
下面的代碼通過處理WM_NCHITTEST消息實現了對話框的拖動操作:
UINT CMyDialog::OnNcHitTest(CPoint pt) { CRect rc; GetClientRect(&rc);ClientToScreen(&rc);return rc.PtInRect(pt) ? HTCAPTION : CDialog::OnNcHitTest(pt); }上面這個代碼很容易理解,當鼠標落在客戶區內,函數返回HTCAPTION。對于一個簡單的對話框來說,僅僅用這個代碼就完全可以實現在對話框背景內的拖動操作。
因為Windows使用z-order坐標來確定鼠標下是哪個窗口,所以對話框中其它的所有對象照常工作。如果用戶單擊某個控制,只要這個控制不是靜態位圖圖像或者文本,那么Windows都將鼠標事件發送到該控制上,而不是對話框。
由于靜態位圖圖像或者文本對于對話框是透明的,所以鼠標在上面的拖動同樣實現移動,而對于對話框中的編輯框、按鈕、組合框等其它非靜態控制則按通常的行為方式運行。
如果應用不是一個純粹的對話框程序,而是是包含CFormView或其它非對話框視圖,處理方法幾乎是一樣的,只需在視圖代碼中做一點小小的改動即可,因為Windows在發送WM_NCHITTEST消息時,是將它發送到鼠標光標下的框架/視圖最頂層非透明窗口,由于視圖首先獲得WM_NCHITTEST消息。
所以只要在視圖的WM_NCHITTEST消息處理例程中返回HTTRANSPARENT,讓視圖對鼠標點擊"透明"即可。注意是在視圖中,而不是在框架中加入下面代碼:
UINT CMyView::OnNcHitTest(CPoint pt) { return HTTRANSPARENT; }這樣做以后,Windows將忽略視圖并繼續搜索能接收WM_NCHITTEST的窗口。如果順利的話,將找到父窗口,這時用與對話框相同的WM_NCHITTEST處理代碼即可,即在客戶區中的點擊返回HTCAPTION。你甚至可以通過鼠標坐標的象素計算,在規定的局部范圍內實現視圖透明。
總結
以上是生活随笔為你收集整理的MFC无边框对话框实现拖动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高企备案是什么意思(高企备案)
- 下一篇: 【黑客帝国数字雨屏保】基于Win32的黑