Windows 預設標題列、邊框風格千篇一律。本文教學如何在對話框應用程式中完全接管非客戶區繪製,自繪標題列背景、圖示、系統按鈕(關閉、最大化、最小化、說明)並處理滑鼠互動與點擊邏輯,打造獨特視覺風格。
DefWindowProc、WM_NCMOUSEMOVE、WM_NCLBUTTONDOWNCRect m_rtButtExit; // 關閉按鈕區域
CRect m_rtButtMax; // 最大化按鈕區域
CRect m_rtButtMin; // 最小化按鈕區域
CRect m_rtButtHelp; // 說明按鈕區域
CRect m_rtIcon; // 圖示區域
void CTitleBarDlg::DrawTitleBar(CDC* pDC) {
if (!m_hWnd) return;
CBrush Brush(RGB(0,100,255)); // 自訂標題列背景色
CBrush* pOldBrush = pDC->SelectObject(&Brush);
CRect rtWnd, rtTitle, rtButtons;
GetWindowRect(&rtWnd);
// ... 計算各區域矩形、繪製背景、按鈕位圖、圖示、標題文字 ...
// 程式碼較長,完整版請參考原始碼附件
pDC->SelectObject(pOldBrush);
}
LRESULT CTitleBarDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
LRESULT lrst = CDialog::DefWindowProc(message, wParam, lParam);
if (!::IsWindow(m_hWnd)) return lrst;
// 影響非客戶區外觀的訊息觸發重繪
if (message == WM_MOVE || message == WM_PAINT || message == WM_NCPAINT ||
message == WM_NCACTIVATE || message == WM_NOTIFY) {
CDC* pWinDC = GetWindowDC();
if (pWinDC) {
DrawTitleBar(pWinDC);
ReleaseDC(pWinDC);
}
}
return lrst;
}
void CTitleBarDlg::OnNcMouseMove(UINT nHitTest, CPoint point) {
CDC* pDC = GetWindowDC();
if (pDC) {
// 根據 point 判斷滑鼠在哪個按鈕區域
// 切換對應按鈕位圖為焦點狀態並重繪
// ...
}
ReleaseDC(pDC);
CDialog::OnNcMouseMove(nHitTest, point);
}
void CTitleBarDlg::OnNcLButtonDown(UINT nHitTest, CPoint point) {
if (m_rtIcon.PtInRect(point))
AfxMessageBox("歡迎訪問 FlySnowStdio 主頁");
else if (m_rtButtHelp.PtInRect(point))
SendMessage(WM_HELP);
else if (m_rtButtExit.PtInRect(point))
SendMessage(WM_CLOSE);
else if (m_rtButtMin.PtInRect(point))
SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, MAKELPARAM(point.x, point.y));
else if (m_rtButtMax.PtInRect(point)) {
if (IsZoomed())
SendMessage(WM_SYSCOMMAND, SC_RESTORE, MAKELPARAM(point.x, point.y));
else {
SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, MAKELPARAM(point.x, point.y));
Invalidate();
}
}
else if (!IsZoomed())
Default(); // 標題列拖曳移動視窗
}
Owner Draw Menu) 實現整體視覺風格一致自繪非客戶區是打造獨特視覺風格的終極手段。本文提供完整的訊息處理架構與繪製邏輯框架,開發者可在此基礎上發揮創意,設計專屬的視窗外觀。注意:此技術繞過系統標準繪製機制,需仔細處理相容性與無障礙存取問題。