MFC創(chuàng)建一個可通過鼠標(biāo)點(diǎn)擊客戶區(qū)拖動窗口位置的方法

通過添加消息響應(yīng)函數(shù)
afx_msg UINT OnNcHitTest(CPoint point);
添加宏
ON_WM_NCHITTEST()

然后, 定義OnNcHitTest的行為即可, OnNcHitTest的代碼如下:
UINT CTimerDlg::OnNcHitTest(CPoint point)
{
    CRect rect;
    GetClientRect(rect);
    ClientToScreen(rect);

    
if(rect.PtInRect(point))
        
return HTCAPTION;
    
return CDialog::OnNcHitTest(point);
}

首先, 發(fā)生WM_NCHITTEST消息的時(shí)候, 程序先取得客戶區(qū)的窗口矩形, 這里用到GetClientRect方法得到, 由于GetClientRect取得的是相對于窗口坐標(biāo)系統(tǒng), 但OnNcHitTest的參數(shù)point卻是相對于屏幕的坐標(biāo)系統(tǒng), 所以這里用到了ClientToScreen把取到的客戶區(qū)矩形轉(zhuǎn)成相對于屏幕的坐標(biāo), 然后用CRect類的PtInRect方法判斷point是否落在這個矩形里面, 如果是, 則返回HTCAPTION(就相當(dāng)于這次點(diǎn)擊是點(diǎn)擊標(biāo)題欄), 所以, 就可以這樣來拖動窗口了. 如果, OnNcHitTest直接返回HTCAPTION的話, 那么, 但用戶點(diǎn)擊非客戶區(qū)的時(shí)候, 有些功能會失效, 比如點(diǎn)擊系統(tǒng)的關(guān)閉按鈕, 試一下就會發(fā)現(xiàn)這個按鈕無效了; ok, 如果點(diǎn)擊的是非客戶端, 者直接返回CDialog::OnNcHitTest(point), 這就是按默認(rèn)處理了.

以上的這個方法比較麻煩, 其實(shí)可以更簡單一點(diǎn), 只要先調(diào)用父類的OnNcHitTest(point), 取得返回值, 在判斷是不是HTCLIENT, 如果是, 則返回HTCAPTION, 否則直接返回父類OnNcHitTest(point)的返回值就ok了, 修改后如下:
UINT CTimerDlg::OnNcHitTest(CPoint point)
{
    UINT uRet 
= CDialog::OnNcHitTest(point);
    
if(HTCLIENT == uRet)
        
return HTCAPTION;
    
return uRet;
}

再簡化一下, 就成這樣子:
UINT CTimerDlg::OnNcHitTest(CPoint point)
{
    UINT uRet 
= CDialog::OnNcHitTest(point);
    
return (HTCLIENT == uRet) ? HTCAPTION : uRet;
}