[MFC] 無邊框視窗的Resize拖動效果的實現(下):子視窗覆蓋,導致主視窗熱點區無法響應WM_NCHITTEST
阿新 • • 發佈:2019-01-10
這篇博文講解了如何實現無邊框視窗的Resize拖動效果,文中提到,需要響應主視窗的WM_NCHITTEST訊息,檢測滑鼠是否在resize熱點區並返回HTTOPLEFT、HTBOTTOM等相應的結果。
但是,如果子視窗覆蓋了主視窗的熱點區,當滑鼠在熱點區移動時,主視窗是無法收到WM_NCHITTEST訊息的。比如圖中所示的視窗,主視窗只有藍色的resize區域能響應WM_NCHITTEST,其他幾個resize區域的滑鼠訊息均會被分發到子視窗中:
有什麼解決辦法? 1、子視窗訊息分發 這種方法比較容易想到,在子視窗中響應到WM_NCHITTEST後,判斷自己是否處於主視窗的resize熱點區,是的話就把訊息通知給主視窗。 但是這種方法很麻煩,會覆蓋resize區的視窗型別太多了:CDialog,CWnd。既有視窗、也有控制元件。雖然都可以在基類中處理WM_NCHITTEST,但還是麻煩。 2、懸停Popup型別的半透明視窗
建立四個Popup型別的透明視窗,將四個視窗始終懸停在主視窗的四個邊上,並使其視窗Z序高於主視窗。在這四個視窗中處理游標的檢測(HTTOPLEFT、HTBOTTOM等對應的游標狀態)、滑鼠左鍵按下和resize的邏輯,如果使用者在半透明視窗中按下左鍵並移動,則在計算移動的尺寸後,更新主視窗的桌面位置、寬高,即可實現主視窗的resize效果。四個視窗之所以使用半透明,是為了不讓使用者感受到其存在。但是注意,四個視窗不能完全透明,否則無法響應滑鼠事件(可以將其alpha設為1)。
如何建立四個半透明的Popup視窗?關鍵詞:WS_EX_LAYERED + SetLayeredWindowAttributes。如果還不懂WS_EX_LAYERED屬性,可以參考 這篇博文
如上所述,方法2中,實際上提出了一種新的實現無邊框視窗的Resize方法。
有什麼解決辦法? 1、子視窗訊息分發 這種方法比較容易想到,在子視窗中響應到WM_NCHITTEST後,判斷自己是否處於主視窗的resize熱點區,是的話就把訊息通知給主視窗。 但是這種方法很麻煩,會覆蓋resize區的視窗型別太多了:CDialog,CWnd。既有視窗、也有控制元件。雖然都可以在基類中處理WM_NCHITTEST,但還是麻煩。 2、懸停Popup型別的半透明視窗