2010年9月27日 星期一

client area 與 WM_NCHITTEST

在 MFC 中若要製作不同於 Windows 風格的視窗時,
往往會將 Dialog 的 Border 屬性設為 None,
然後利用自己畫背景的方式製作美美的視窗、對話框。

這樣做會讓視窗失去標準的外框,
而 Window 有個功能即是當滑鼠移至右下角時會改變為可縮放狀態,
沒有標準外框的 Window 就會失去這個功能,
這是因為 Window 被分為 client area 與 non client area(NC)
外面一圈外框和標題列屬於 non client area
裡面屬於 client area,而使用 ::SetWindowPos() 時,
會根據你的視窗是否有邊框來設定 NC 的大小或 Client 的大小,
而在有 Dialog Frame 的視窗下要取得整個視窗的大小,
使用 GetWindowRect() 即可,若要取得 Client area 的大小,
則要使用 GetClientRect() 來取得,
而讓視窗可以縮放的功能必須要在 MOUSE ON NC 的狀況下才有用。

要讓沒有外框的視窗具備縮放、移動功能,必須在接獲 WM_NCHITTEST 時動手腳,
簡單的範例如下


LRESULT CDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
  if(message == WM_NCHITTEST)
  {
    CPoint pt;
    CRect rcTemp(m_rcClient);
    GetCursorPos(&pt);
    ScreenToClient(&pt);
    rcTemp.DeflateRect(m_rcClient.Width() - 16,
                       m_rcClient.Height() - 16, 0, 0);
    // left 移動 width - 16,top 移動 height - 16
    return rcTemp.PtInRect(pt) ? HTBOTTOMRIGHT : HTCAPTION;
  }
}


當滑鼠在視窗上滑動時都會定期的收到 WM_NCHITTEST 訊息,
這時只要計算滑鼠的位置相對於視窗的哪一部份即可指定我們想做的事,
上例是寫當滑鼠在視窗的右下角 16*16px 這個範圍內就可縮放,
其餘區域就讓視窗可利用滑鼠按著拖拉移動,
常用到的有下面三種,其餘可以再到 WinUser.h 查看。

HTBOTTOMRIGHT:右下角,可縮放視窗
HTCAPTION:標題區,可移動視窗
HTCLIENT:client area

PS:若是 CDialog 除了送 HTBOOTOMRIGHT 之外,對話框屬性的 System Menu 記得改成 False

沒有留言:

張貼留言