1.如果需要加高标题栏(用于贴图等),就要调用OnNcCalcSize追加部分空间(非客户区间):
[cpp] view plain copy void CMy2011082302Dlg::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) { lpncsp->rgrc[0].top += 25;//尺度自己把握 //lpncsp->rgrc[0].bottom -= 100;//类似增加底边栏,此例无用 CDialog::OnNcCalcSize(bCalcValidRects, lpncsp); }2.添加绘制标题栏函数DrawTitleBar():
[cpp] view plain copy void CMy2011082302Dlg::DrawTitleBar(CDC *pDC) { if (m_hWnd) { CBrush Brush(RGB(0,100,255)); CBrush* pOldBrush = pDC->SelectObject(&Brush); CRect rtWnd, rtTitle, rtButtons; GetWindowRect(&rtWnd); //取得标题栏的位置 rtTitle.left = GetSystemMetrics(SM_CXFRAME); rtTitle.top = GetSystemMetrics(SM_CYFRAME); rtTitle.right = rtWnd.right - rtWnd.left - GetSystemMetrics(SM_CXFRAME); rtTitle.bottom = rtTitle.top + GetSystemMetrics(SM_CYSIZE); CPoint point; //填充顶部框架 point.x = rtWnd.Width(); point.y = GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYFRAME)+20; pDC->PatBlt(0, 0, point.x, point.y, PATCOPY); //填充左侧框架 point.x = GetSystemMetrics(SM_CXFRAME) + 1; point.y = rtWnd.Height(); pDC->PatBlt(0, 0, point.x, point.y, PATCOPY); //填充底部框架 point.x = rtWnd.Width(); point.y = GetSystemMetrics(SM_CYFRAME) + 1; pDC->PatBlt(0, rtWnd.Height()-point.y, point.x, point.y, PATCOPY); //填充右侧框架 point.x = GetSystemMetrics(SM_CXFRAME) + 1; point.y = rtWnd.Height(); pDC->PatBlt(rtWnd.Width()-point.x, 0, point.x, point.y, PATCOPY); pDC->SelectObject(pOldBrush); //重画图标 m_rtIcon.left = rtWnd.Width() - 135; m_rtIcon.top = GetSystemMetrics(SM_CYFRAME); m_rtIcon.right = m_rtIcon.left + 32; m_rtIcon.bottom = m_rtIcon.top + 32; ::DrawIconEx(pDC->m_hDC, m_rtIcon.left, m_rtIcon.top, m_hIcon, m_rtIcon.Width(), m_rtIcon.Height(), 0, NULL, DI_NORMAL); m_rtIcon.OffsetRect(rtWnd.TopLeft()); //准备画XP风格按钮 CBitmap* pBitmap = new CBitmap; CBitmap* pOldBitmap; CDC* pDisplayMemDC=new CDC; pDisplayMemDC->CreateCompatibleDC(pDC); //重画关闭button rtButtons.left = rtTitle.right - 19; rtButtons.top = rtTitle.top; rtButtons.right = rtButtons.left + 19; rtButtons.bottom = rtButtons.top + 19; pBitmap->LoadBitmap(IDB_EXIT_NORMAL); pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap); pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 0, 0, SRCCOPY); pDisplayMemDC->SelectObject(pOldBitmap); m_rtButtExit = rtButtons; m_rtButtExit.OffsetRect(rtWnd.TopLeft()); pBitmap->DeleteObject(); //重画最大化/恢复button rtButtons.right = rtButtons.left - 3; rtButtons.left = rtButtons.right - 19; if (IsZoomed()) pBitmap->LoadBitmap(IDB_RESTORE_NORMAL); else pBitmap->LoadBitmap(IDB_MAX_NORMAL); pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap); pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 0, 0, SRCCOPY); pDisplayMemDC->SelectObject(pOldBitmap); m_rtButtMax = rtButtons; m_rtButtMax.OffsetRect(rtWnd.TopLeft()); pBitmap->DeleteObject(); //重画最小化button rtButtons.right = rtButtons.left - 3; rtButtons.left = rtButtons.right - 19; pBitmap->LoadBitmap(IDB_MIN_NORMAL); pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap); pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 0, 0, SRCCOPY); pDisplayMemDC->SelectObject(pOldBitmap); m_rtButtMin = rtButtons; m_rtButtMin.OffsetRect(rtWnd.TopLeft()); pBitmap->DeleteObject(); //重画帮助button rtButtons.right = rtButtons.left - 3; rtButtons.left = rtButtons.right - 19; pBitmap->LoadBitmap(IDB_HELP_NORMAL); pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap); pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 0, 0, SRCCOPY); pDisplayMemDC->SelectObject(pOldBitmap); m_rtButtHelp = rtButtons; m_rtButtHelp.OffsetRect(rtWnd.TopLeft()); pBitmap->DeleteObject(); //贴图 point.x = rtWnd.Width(); point.y = GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYFRAME)+20; pBitmap->LoadBitmap(IDB_BITMAP1); pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap); pDC->BitBlt(0, 0, point.x, point.y, pDisplayMemDC, 0, 0, SRCCOPY); pDisplayMemDC->SelectObject(pOldBitmap); pBitmap->DeleteObject(); //拉伸图片 //pDC->StretchBlt(x,y, nW, nH ,&memDc,0,0, //bm.bmWidth,bm.bmHeight,SRCCOPY); //重写标题文字 int nOldMode = pDC->SetBkMode(TRANSPARENT); COLORREF clOldText=pDC->SetTextColor(RGB(255, 255, 255)); pDC->SelectStockObject(SYSTEM_FIXED_FONT); rtTitle.left += 2; rtTitle.top += GetSystemMetrics(SM_CYSIZE); rtTitle.bottom = rtTitle.top + 30; CString m_strTitle; GetWindowText(m_strTitle); pDC->DrawText(m_strTitle, &rtTitle, DT_LEFT); pDC->SetBkMode(nOldMode); pDC->SetTextColor(clOldText); ReleaseDC(pDisplayMemDC); delete pDisplayMemDC; delete pBitmap; } }3.按钮响应,消息发送/拦截等(系统消息函数)
[cpp] view plain copy LRESULT CMy2011082302Dlg::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 CMy2011082302Dlg::OnNcLButtonDown(UINT nHitTest, CPoint point) { //检测各按钮是否按到 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(); } void CMy2011082302Dlg::OnNcMouseMove(UINT nHitTest, CPoint point) { CDC* pDC = GetWindowDC(); CDC* pDisplayMemDC=new CDC; pDisplayMemDC->CreateCompatibleDC(pDC); CBitmap* pBitmap = new CBitmap; CBitmap* pOldBitmap; CRect rtWnd, rtButton; if (pDC) { GetWindowRect(&rtWnd); //关闭button if (m_rtButtExit.PtInRect(point)) pBitmap->LoadBitmap(IDB_EXIT_FOCUS); else pBitmap->LoadBitmap(IDB_EXIT_NORMAL); rtButton = m_rtButtExit; rtButton.OffsetRect(-rtWnd.left, -rtWnd.top); pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap); pDC->BitBlt(rtButton.left, rtButton.top, rtButton.Width(), rtButton.Height(), pDisplayMemDC, 0, 0, SRCCOPY); pDisplayMemDC->SelectObject(pOldBitmap); pBitmap->DeleteObject(); //最大化/恢复button if (m_rtButtMax.PtInRect(point)) { if (IsZoomed()) pBitmap->LoadBitmap(IDB_RESTORE_FOCUS); else pBitmap->LoadBitmap(IDB_MAX_FOCUS); } else { if (IsZoomed()) pBitmap->LoadBitmap(IDB_RESTORE_NORMAL); else pBitmap->LoadBitmap(IDB_MAX_NORMAL); } rtButton = m_rtButtMax; rtButton.OffsetRect(-rtWnd.left, -rtWnd.top); pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap); pDC->BitBlt(rtButton.left, rtButton.top, rtButton.Width(), rtButton.Height(), pDisplayMemDC, 0, 0, SRCCOPY); pDisplayMemDC->SelectObject(pOldBitmap); pBitmap->DeleteObject(); //最小化button if (m_rtButtMin.PtInRect(point)) pBitmap->LoadBitmap(IDB_MIN_FOCUS); else pBitmap->LoadBitmap(IDB_MIN_NORMAL); rtButton = m_rtButtMin; rtButton.OffsetRect(-rtWnd.left, -rtWnd.top); pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap); pDC->BitBlt(rtButton.left, rtButton.top, rtButton.Width(), rtButton.Height(), pDisplayMemDC, 0, 0, SRCCOPY); pDisplayMemDC->SelectObject(pOldBitmap); pBitmap->DeleteObject(); //帮助button if (m_rtButtHelp.PtInRect(point)) pBitmap->LoadBitmap(IDB_HELP_FOCUS); else pBitmap->LoadBitmap(IDB_HELP_NORMAL); rtButton = m_rtButtHelp; rtButton.OffsetRect(-rtWnd.left, -rtWnd.top); pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap); pDC->BitBlt(rtButton.left, rtButton.top, rtButton.Width(), rtButton.Height(), pDisplayMemDC, 0, 0, SRCCOPY); pDisplayMemDC->SelectObject(pOldBitmap); pBitmap->DeleteObject(); } ReleaseDC(pDisplayMemDC); ReleaseDC(pDC); delete pDisplayMemDC; delete pBitmap; CDialog::OnNcMouseMove(nHitTest, point); }
1.去除窗口标题风格
2.添加响应按钮(最大化、最小化等)
3.贴图(可借助众所周知的BitButtonNL类 )处理
4.添加可供窗口拖移消息欺骗:
[cpp] view plain copy void CMy2011082302Dlg::OnLButtonDown(UINT nFlags, CPoint point) { //处理移动 if (point.y < 26) PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x,point.y)); CDialog::OnLButtonDown(nFlags, point); }方法同1.1
问题:1) 禁用cs.style&=~WS_SYSMENU;(为了去除原标题栏按钮) ,但这导致邮件菜单不可用。
2) 不名操作闪烁(个别特殊操作,基本不会)
3) 1.1中的第1步如果单/多文档绘制了菜单,会出现菜单夹中问题。如需菜单建议菜单重绘或bcg界面库工程
由于2.1中的问题1和2,再加上去除标题栏所导致的非客户区自绘按钮消息无法响应以及窗口无法拖动等情况,我们必须用OnNcHitTest改变新增加空间(1.1中第1步)为HTCAPTION属性。
1.去除标题栏 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){} 添加:
[cpp] view plain copy ModifyStyle(WS_CAPTION,WS_DLGFRAME,SWP_FRAMECHANGED);2.同1.1中1.2.3步。1步不可缺省哦。
3. OnNcHitTest返回HTCAPTION:
[cpp] view plain copy UINT CMainFrame::OnNcHitTest(CPoint point) { RECT rectWindows, rectClient; this->GetWindowRect(&rectWindows); this->GetClientRect(&rectClient); if (point.y > rectWindows.top && point.y < rectWindows.top + 25) { return HTCAPTION;//标题栏形式 } else { return CFrameWnd::OnNcHitTest(point); } }