下面是网上收集来的代码,实现炫彩自绘窗口非客户区,贴出来大家参考共享...
效果如下图所示:
关键代码如下:
在框架类中添加:
public:
afx_msg void OnNcLButtonDown(UINT nHitTest, CPoint point);
afx_msg void OnNcMouseMove(UINT nHitTest, CPoint point);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);
public:
CRect m_rtIcon; //程序图标位置
CRect m_rtButtMax; //最大化按钮位置
CRect m_rtButtMin; //最小化按钮位置
CRect m_rtButtExit; //关闭按钮位置
实现:
在OnCreate消息里添加:
CRect rtWnd;
GetWindowRect(&rtWnd);
CRgn rgn;
rgn.CreateRoundRectRgn(0,0,rtWnd.Width(),rtWnd.Height(),5,5);
SetWindowRgn((HRGN)rgn,true);
下面是消息部分:
void CMainFrame::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
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));
CRect rtWnd;
GetWindowRect(&rtWnd);
CRgn rgn;
rgn.CreateRoundRectRgn(0,0,rtWnd.Width(),rtWnd.Height(),5,5);
SetWindowRgn((HRGN)rgn,true);
Invalidate();
}
else
{
SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, MAKELPARAM(point.x, point.y));
CRect rtWnd;
GetWindowRect(&rtWnd);
CRgn rgn;
rgn.CreateRoundRectRgn(0,0,rtWnd.Width(),rtWnd.Height(),5,5);
SetWindowRgn((HRGN)rgn,true);
Invalidate();
}
}
else if (!IsZoomed())
Default();
//CFrameWndEx::OnNcLButtonDown(nHitTest, point);
}
void CMainFrame::OnNcMouseMove(UINT nHitTest, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CWindowDC dc(this);
CWindowDC* pDC = &dc;
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_BITMAP1);
else
pBitmap->LoadBitmap(IDB_BITMAP2);
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_BITMAP9);
else
pBitmap->LoadBitmap(IDB_BITMAP5);
}
else
{
if (IsZoomed())
pBitmap->LoadBitmap(IDB_BITMAP10);
else
pBitmap->LoadBitmap(IDB_BITMAP6);
}
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_BITMAP7);
else
pBitmap->LoadBitmap(IDB_BITMAP8);
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();
}
pDisplayMemDC->DeleteDC();
delete pDisplayMemDC;
delete pBitmap;
//CDialog::OnNcMouseMove(nHitTest, point);
CFrameWndEx::OnNcMouseMove(nHitTest, point);
}
BOOL CMainFrame::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
BOOL retValue= CWnd::OnEraseBkgnd(pDC);
CRect rc;
GetClientRect(&rc);
pDC->FillSolidRect(&rc,RGB(236,233,216));
return retValue;
}
BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
if(pMsg->message == WM_KEYDOWN){
switch(pMsg->wParam){
case VK_RETURN://截获回车
return TRUE;
case VK_ESCAPE://截获ESC
return TRUE;
break;
}
}
return CFrameWndEx::PreTranslateMessage(pMsg);
}
LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: 在此添加专用代码和/或调用基类
LRESULT lrst=CWnd::DefWindowProc(message, wParam, lParam);
/*
IsWindow()函数用法:
IsWindow()函数判断hwndDlg是否已经指向一个窗口,如果返回TRUE,表示对话框已经显示,
不需要再调用对话框,如果返回FALSE,调用CreateDialog()显示对话框。要注意一点,
hwndDlg必须声明为全局变量,而不是对话框函数的私有变量,否则每次对话框函数被调用都将重新初始化
该变量IsWindow(hwndDlg)总方会FALSE,上面的判断语句就形同虚设了。同时应在调用EndDialog()前设hwndDlg=NULL,
否则对话框关闭后IsWindow(hwndDlg)总返回TRUE,再也打不开了*/
if (!::IsWindow(m_hWnd))
return lrst;
if (message==WM_MOVE||message==WM_PAINT||message==WM_NCPAINT||message==WM_NCACTIVATE ||message == WM_NOTIFY)
{
try
{
CDC* pWinDC = GetWindowDC();
if (pWinDC)
DrawTitleBar(pWinDC);
ReleaseDC(pWinDC);
}
catch( CException* e )
{
e->Delete();
}
}
return lrst;
//return CFrameWndEx::DefWindowProc(message, wParam, lParam);
}
void CMainFrame::DrawTitleBar(CDC *pDC)
{
if (m_hWnd)
{
CBrush Brush(RGB(83,83,83));
CBrush* pOldBrush = pDC->SelectObject(&Brush);
CRect rtWnd, rtTitle, rtButtons;
GetWindowRect(&rtWnd);
//取得标题栏的位置
//SM_CXFRAME 窗口边框的边缘宽度
//SM_CYFRAME 窗口边框的边缘高度
//SM_CXSIZE 窗口标题栏宽度
//SM_CYSIZE 窗口标题栏高度
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) + 0;
pDC->PatBlt(0, 0, point.x, point.y, PATCOPY);
//填充左侧框架
point.x = GetSystemMetrics(SM_CXFRAME) -1;
point.y = rtWnd.Height()- 1;
pDC->PatBlt(0, 0, point.x, point.y, PATCOPY);
//填充底部框架
point.x = rtWnd.Width();
point.y = GetSystemMetrics(SM_CYFRAME);
pDC->PatBlt(0, rtWnd.Height()-point.y, point.x, point.y, PATCOPY);
//填充右侧框架
point.x = GetSystemMetrics(SM_CXFRAME);
point.y = rtWnd.Height();
pDC->PatBlt(rtWnd.Width()-point.x, 0, point.x, point.y, PATCOPY);
//重画标题栏图标
m_rtIcon.left = rtTitle.left ;
m_rtIcon.top = rtTitle.top;
m_rtIcon.right = m_rtIcon.left + 16;
m_rtIcon.bottom = m_rtIcon.top + 15;
::DrawIconEx(pDC->m_hDC, m_rtIcon.left, m_rtIcon.top, AfxGetApp()->LoadIcon(IDI_ICON1),
m_rtIcon.Width(), m_rtIcon.Height(), 0, NULL, DI_NORMAL);
m_rtIcon.OffsetRect(rtWnd.TopLeft());
CBitmap* pBitmap = new CBitmap;
CBitmap* pOldBitmap;
CDC* pDisplayMemDC=new CDC;
pDisplayMemDC->CreateCompatibleDC(pDC);
//重画关闭button
rtButtons.left = rtTitle.right - 16;
rtButtons.top = rtTitle.top - 1;
rtButtons.right = rtButtons.left + 16;
rtButtons.bottom = rtButtons.top + 15;
pBitmap->LoadBitmap(IDB_BITMAP1);
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 - 16;
if (IsZoomed())
pBitmap->LoadBitmap(IDB_BITMAP10);
else
pBitmap->LoadBitmap(IDB_BITMAP5);
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 - 16;
pBitmap->LoadBitmap(IDB_BITMAP7);
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();
//重画caption
int nOldMode = pDC->SetBkMode(TRANSPARENT);
COLORREF clOldText=pDC->SetTextColor(RGB(255, 255, 255));
CFont m_captionFont;
m_captionFont.CreateFont(
18, // 字体的高度
0, // 字体的宽度
0, // 字体显示的角度
0, // 字体的角度
FW_BOLD, // 字体的磅数
FALSE, // 斜体字体
FALSE, // 带下划线的字体
0, // 带删除线的字体
ANSI_CHARSET, // 所需的字符集
OUT_DEFAULT_PRECIS, // 输出的精度
CLIP_DEFAULT_PRECIS, // 裁减的精度
DEFAULT_QUALITY, // 逻辑字体与输出设备的实际字体之间的精度
DEFAULT_PITCH | FF_SWISS, // 字体间距和字体集
_T("Arial")); // 字体名称
CFont* pOldFont = NULL;
pOldFont = pDC->SelectObject(&m_captionFont);
rtTitle.left += m_rtIcon.Width ()+3;
rtTitle.top = rtTitle.top;
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;
}
}