您的位置:首页 > 其它

VC 实现 自绘 窗体 标题栏 非客户区

2008-10-15 11:18 507 查看
VC 实现 自绘 窗体 标题栏 非客户区
1.准备工作。(1)得到文件夹中的位图句柄:首先要准备相应图片。HBITMAP bitmap;bitmap=(HBITMAP)::LoadImage(AfxGetInstanceHandle(),    "skin//Test.bmp",    IMAGE_BITMAP,    0,    0,    LR_DEFAULTSIZE|LR_LOADFROMFILE);
CBitmap cbmp;cbmp.Attach(bitmap);      其中,skin//Test.bmp为文件路径。
(2)关于非客户区的消息:ON_WM_NCPAINT()//绘非客户区时。ON_WM_NCACTIVATE()//非客户区有焦点和失去焦点时。ON_WM_NCCALCSIZE()//计算窗体尺寸时。
(3)改变标题栏尺寸:  重写ON_WM_NCCALCSIZE()消息响应函数。void CMYSkinDlg::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp){//重设标题栏高度。m_nCaptionHeight在PreSubclassWindow中计算。lpncsp->rgrc[0].top+=m_nCaptionHeight-GetSystemMetrics(SM_CYCAPTION);CDialog::OnNcCalcSize(bCalcValidRects, lpncsp);}
(4)非客户区的鼠标动作:  相关消息:ON_WM_NCLBUTTONDOWN()//鼠标下。ON_WM_NCLBUTTONUP()//鼠标上。ON_WM_NCMOUSEMOVE()//鼠标悬停。
(5)屏蔽最大最小关闭消息:在WindowProc中:LRESULT CMYSkinDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam){if (message == WM_NCHITTEST)    {     LRESULT lRet = CDialog::WindowProc(message, wParam, lParam);     //屏蔽最大最小关闭消息.     if (lRet==HTZOOM || lRet == HTMINBUTTON || lRet == HTCLOSE)      return HTCAPTION;//视为标题栏动作。     else      return lRet;    }...2.程序和注释:(1)用户变量和函数.protected:CBrush m_brBG;//对话框背景颜色,在OnInitDialog 中初始化,在OnCtlColor中作为返回值.CString m_strCaption;//标题.CRect m_rtWnd;//整个窗体Rect.int     m_nCaptionHeight;//标题栏高度.CRect m_rtButtons;//最大,最小,关闭按钮.CRect m_rtIcon;//图标.CRect m_rtButtMin;//最小.CRect m_rtButtMax;//最大.CRect m_rtButtExit;//关闭.CRect m_rtButtMaxM;CRect m_rtButtMinM;CRect m_rtButtExitM;CRect m_bmRt;//Bitmap所在的Rect.BOOL    m_bNCActive;//窗体活动.
bool FillRtWithBmp(CString bmpFileName,CDC *pDC,CRect rt);//用Bitmap添满整个rt.bool FillWithBmpRtUL(CString bmpFileName,CDC *pDC,CPoint pt);//pt为Bitmap的左上.bool FillWithBmpRtUR(CString bmpFileName,CDC *pDC, CPoint pt);//pt为Bitmap的右上.bool FillButton(CString bmpButtonName, CDC *pDC, CPoint pt,int intState);//void DrawNC(CDC* pDC);//画非客户区.(2)显示之前计算从图片计算标题栏高度:void CMYSkinDlg::PreSubclassWindow(){//得到标题栏图片高度。CString bmpFileName="C2";HBITMAP bitmap;bitmap=(HBITMAP)::LoadImage(AfxGetInstanceHandle(),    "skin//"+_T(bmpFileName)+".bmp",    IMAGE_BITMAP,    0,    0,    LR_DEFAULTSIZE|LR_LOADFROMFILE);
BITMAP bm;CBitmap cbmp;cbmp.Attach(bitmap);cbmp.GetBitmap(&bm);cbmp.DeleteObject();m_nCaptionHeight=bm.bmHeight-4;
CDialog::PreSubclassWindow();}(3)重写OnNcCalCsize:void CMYSkinDlg::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp){//重设标题栏高度。m_nCaptionHeight在PreSubclassWindow中计算。lpncsp->rgrc[0].top+=m_nCaptionHeight-GetSystemMetrics(SM_CYCAPTION);CDialog::OnNcCalcSize(bCalcValidRects, lpncsp);}(4)绘非客户区:void CMYSkinDlg::OnNcPaint(){CDC* pWinDC=GetWindowDC();if (pWinDC) DrawNC(pWinDC);//函数实现略。ReleaseDC(pWinDC);}(5)对非客户区焦点情况的处理:BOOL CMYSkinDlg::OnNcActivate(BOOL bActive){m_bNCActive=bActive;//在DrawNC中有体现。//初始时设NC区为活动.//防止在任务栏右键图标时出现最大最小关闭OnNcPaint();//实际源程序中有细节的考虑。return true;}(6)响应鼠标在非客户区的事件:鼠标在非客户区按下:void CMYSkinDlg::OnNcLButtonDown(UINT nHitTest, CPoint point){//检测最小,最大和关闭按钮是否按下,然后更换图片....if(!IsZoomed())//防止在最大化后能拖动.    CDialog::OnNcLButtonDown(nHitTest,point);}//OnNcLButtonUp中触发最大最小关闭:void CMYSkinDlg::OnNcLButtonUp(UINT nHitTest, CPoint point){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) );}}//鼠标在非客户区悬停:void CMYSkinDlg::OnNcMouseMove(UINT nHitTest, CPoint point){//检测最小,最大和关闭按钮是否有鼠标悬停,然后更换相应图片....}
(7)屏蔽单击程序非客户系统原有图标矩形时出现的系统菜单或动作:UINT CMYSkinDlg::OnNcHitTest(CPoint point){CRect tst(2,2,m_nCaptionHeight+4,m_nCaptionHeight+4);tst.OffsetRect(m_rtWnd.TopLeft());//原图标屏幕位置if(tst.PtInRect(point))//最大最小关闭按钮位置.    return HTCAPTION;else if(m_rtButtMin.PtInRect(point)||     m_rtButtMax.PtInRect(point)||     m_rtButtExit.PtInRect(point))    return HTSYSMENU;//使此区域能够响应OnNcLButtonUpelse    return CDialog::OnNcHitTest(point);}
(8)系统菜单的显示和隐藏:为了使重绘工作顺利进行而不影响程序外在表现,要对系统菜单显示和隐藏, 如在OnNcActivate中有这样的程序片段:...if(bActive){    ModifyStyle(0, WS_SYSMENU);    OnNcPaint();}else{    ModifyStyle(WS_SYSMENU, 0);    OnNcPaint();}...又如,在OnCreate中:...this->ModifyStyle(WS_SYSMENU, 0);//防止在任务栏右单击时出现最大最小关闭....
(9)对系统最大最小关闭图标依然出现的处理:  虽然用户取消了NC区系统的重绘,但是系统仍然对最大最小关闭图标重绘(主要表现在用户右单击任务栏图标时),这里的处理方法如下:void CMYSkinDlg::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu){//CDialog::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);if (bSysMenu) OnNcPaint();//防止在任务栏右键图标时窗口出现最大最小关闭}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: