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();//防止在任务栏右键图标时窗口出现最大最小关闭}
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();//防止在任务栏右键图标时窗口出现最大最小关闭}
相关文章推荐
- VC 实现 自绘 窗体 标题栏 非客户区
- VC MFC 钩子 实现 自绘 窗体 标题栏 非客户区
- 界面编程:VC实现自绘窗体标题栏非客户区
- VC 实现 自绘 窗体 标题栏 非客户区
- VC 实现 自绘 窗体 标题栏 非客户区
- 【转】 VC MFC 钩子 实现 自绘 窗体 标题栏 非客户区
- VC MFC 钩子 实现 自绘 窗体 标题栏 非客户区(VER.2013-11-06)
- VC 实现 自绘 窗体 标题栏 非客户区
- VC 实现 自绘 窗体 标题栏 非客户区
- VC 实现自绘 窗体 标题栏 非客户区
- MFC对话框禁止移动 使标题栏不响应鼠标消息 通过客户区移动窗体 OnNcHitTest()的实现
- MFC对话框禁止移动 使标题栏不响应鼠标消息 通过客户区移动窗体 OnNcHitTest()的实现
- vc++如何将客户区存为bmp和VC实现自绘图形输出到bmp文件
- MFC 客户区 模拟标题栏 功能 ,实现窗体拖动
- VC环境中获取窗体标题栏的位置和高度
- VC++ WIN32 sdk实现按钮自绘详解.
- VC++调用UpdateLayeredWindow实现半透明窗体【转】
- 用VC++实现自绘按钮控制
- 修改窗体非客户区大小更改窗体标题栏高度
- VC实现自绘图形输出到bmp文件