《自绘边框窗口.doc》由会员分享,可在线阅读,更多相关《自绘边框窗口.doc(9页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、【精品文档】如有侵权,请联系网站删除,仅供学习与交流自绘边框窗口.精品文档.自绘边框窗口自绘窗口需要响应如下的几个消息: 1、WM_NCCALCSIZE 这个是用来返回NC区域的。windows系统根据这个消息的返回,决定矩形区域中,NC区域在哪里。如下的代码是我的一个实现: void CSIPanel:OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) RECT r; / TODO: Add your message handler code here and/or call default if (m_psi)
2、 if (m_psi-m_bCustomWindow) memcpy(&r,&lpncsp-rgrc0,sizeof(RECT); r.top = r.top+m_psi-m_NcRect.top; r.bottom = r.bottom - m_psi-m_NcRect.bottom; r.left = r.left+m_psi-m_NcRect.left; r.right = r.right-m_psi-m_NcRect.right; memcpy(&lpncsp-rgrc0,&r,sizeof(RECT); return; CWnd:OnNcCalcSize(bCalcValidRect
3、s, lpncsp); 在这个代码中,m_psi-m_bCustomWindow是用来标志是否是自绘窗口的。如果不是自绘窗口,才需要调整大小。至于bCalcValidRects这个参数,说老实话我也不知道它的用处。我查过很多的代码,都没有使用这个参数(比如BCGPRO的代码等),而实际情况下也是不使用也没有问题的。完全只需要更改lpncsp-rgrc0就可以了。 2、需要响应NCPAINT消息。 (如果在窗口非active的情况下,并不绘制ncpaint或者调用原来的ncpaint,那么系统就会画出以前的难看的窗口边框和标题)很简单,这个是我的代码: void CSIPanel:OnNcPai
4、nt() CWindowDC dc(this); if (m_psi = NULL) return; if (m_psi-m_bCustomWindow = FALSE) return; p_PaintCorners(&dc); p_PaintIcons(&dc); p_PaintPushedIcons(&dc); p_PaintTitleLine(&dc); 3、还需要响应CREATE消息 为何响应Create消息?因为我的窗口是不规则的(不是直角矩形而是园角矩形的) int CSIPanel:OnCreate(LPCREATESTRUCT lpCreateStruct) if (CWnd:
5、OnCreate(lpCreateStruct) = -1) return -1; / TODO: Add your specialized creation code here ResetWindowRgn(); SetWindowPos(NULL,0,0,0,0,SWP_FRAMECHANGED|SWP_NOOWNERZORDER| SWP_NOMOVE|SWP_NOSIZE); return 0; SetWindowPos是强制让Window重新计算大小(NCCALCSIZE)和绘制。 / / CSIPanel message handlers void CSIPanel:ResetWi
6、ndowRgn() int iRet; BOOL bRet; CRgn m_rgn1,m_rgn2,m_rgn3; RECT r; GetWindowRect(&r); OffsetRect(&r,-r.left,-r.top); bRet = m_rgn1.CreateRoundRectRgn(r.left,r.top,r.right+1,r.top+45,12,12); m_rgn2.CreateRoundRectRgn(r.left,r.top+18,r.right+1,r.bottom+2,12,12); iRet = m_rgn2.CombineRgn(&m_rgn1,&m_rgn2
7、,RGN_OR); iRet = SetWindowRgn(m_rgn2,TRUE); 4、还需要响应WM_SIZE void CSIPanel:OnSize(UINT nType, int cx, int cy) CWnd:OnSize(nType, cx, cy); / TODO: Add your message handler code here ResetWindowRgn(); Invalidate(); 5、响应ACTIVE 用于绘制不同情况下的标题。 void CSIPanel:OnActivate(UINT nState, CWnd* pWndOther, BOOL bMin
8、imized) CWnd:OnActivate(nState, pWndOther, bMinimized); if (nState = WA_INACTIVE) if (m_bTraceFlag) ReleaseCapture(); m_bTraceFlag = FALSE; m_bActive = FALSE; else m_bActive = TRUE; SetWindowPos(NULL,0,0,0,0,SWP_FRAMECHANGED|SWP_NOOWNERZORDER| SWP_NOMOVE|SWP_NOSIZE); 这里为何要检测一个鼠标的情况呢?因为如果在标题行上有自绘的小按钮
9、,那么,我们需要跟踪鼠标才行(响应NCMOUSELCLICK是不行的)所以,如果本窗口失去焦点,应该RelaseCapture。 6、响应NCLBUTTONDOWN 为了能够在标题行绘制自己的最大最小按钮,并且能够响应它,就绪要响应在标题行上的鼠标左键。但是为了能够像window操作一样,鼠标左键按下的时候不触发,而是鼠标左键抬起的时候触发,这就需要在NCLBUTTONDOWN的时候做SetCapture. void CSIPanel:OnNcLButtonDown(UINT nHitTest, CPoint point) / TODO: Add your message handler co
10、de here and/or call default RECT r; RECT r1; BOOL bRet; int iSizeX,iSizeY; if (m_bTraceFlag = TRUE) return; m_bMinPushed = FALSE; m_bMaxPushed = FALSE; m_bClosePushed = FALSE; m_bSysPushed = FALSE; GetWindowRect(&r); if (m_bActive = FALSE) goto L_DEFAULT; r.bottom = r.top + (m_psi-m_rLT.bottom - m_p
11、si-m_rLT.top); bRet = PtInRect(&r,point); if (bRet = FALSE) goto L_DEFAULT; /* - * 判定是否在按钮上按下的. * - */ if (m_bIconSys) r1.left = r.left + 5; r1.top = r.top + 5; r1.right = m_psi-m_rSYS.right - m_psi-m_rSYS.left + r1.left; r1.bottom = m_psi-m_rSYS.bottom- m_psi-m_rSYS.top + r1.top; bRet = PtInRect(&r
12、1,point); if (bRet = TRUE) m_bSysPushed = TRUE; goto L_FOUND; if (m_bIconMin) iSizeX = m_psi-m_rCLOSE.right - m_psi-m_rCLOSE.left; iSizeY = m_psi-m_rCLOSE.bottom - m_psi-m_rCLOSE.top; r1.left = r.right - 6 - 3 * iSizeX - 3 * 2; r1.top = r.top+5; r1.right = r1.left + iSizeX; r1.bottom = r1.top + iSiz
13、eY; bRet = PtInRect(&r1,point); if (bRet = TRUE) m_bMinPushed= TRUE; goto L_FOUND; if (m_bIconMax) iSizeX = m_psi-m_rCLOSE.right - m_psi-m_rCLOSE.left; iSizeY = m_psi-m_rCLOSE.bottom - m_psi-m_rCLOSE.top; r1.left = r.right - 6 - 2 * iSizeX - 2 * 2; r1.top = r.top+5; r1.right = r1.left + iSizeX; r1.b
14、ottom = r1.top + iSizeY; bRet = PtInRect(&r1,point); if (bRet = TRUE) m_bMaxPushed= TRUE; goto L_FOUND; if (m_bIconClose) iSizeX = m_psi-m_rCLOSE.right - m_psi-m_rCLOSE.left; iSizeY = m_psi-m_rCLOSE.bottom - m_psi-m_rCLOSE.top; r1.left = r.right - 6 - iSizeX - 2; r1.top = r.top+5; r1.right = r1.left
15、 + iSizeX; r1.bottom = r1.top + iSizeY; bRet = PtInRect(&r1,point); if (bRet = TRUE) m_bClosePushed= TRUE; goto L_FOUND; L_DEFAULT: CWnd:OnNcLButtonDown(nHitTest, point); return; L_FOUND: m_bTraceFlag = TRUE; SetCapture(); RepaintIcons(); return; 7、当然要响应LBUTTONUP消息。 为何是LBUTTONUP而不是NCLBUTTONUP?因为在NCL
16、BUTTONDOWN的时候SetCapture之后,就是LBUTTONUP消息了。(应该不会有NCLBUTTONUP消息的)。 void CSIPanel:OnLButtonUp(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/or call default RECT r; CWnd:OnLButtonUp(nFlags, point); if (m_bTraceFlag = FALSE) return; ReleaseCapture(); GetWindowRect(&r); m_bTrace
17、Flag = FALSE; if (m_bSysPushed = TRUE) / PostMessage(WM_SYSCOMMAND,SC_MOUSEMENU,r.left16|r.top); PostMessage(WM_SYSCOMMAND,SC_KEYMENU,r.left16|r.top); else if (m_bMinPushed = TRUE) PostMessage(WM_SYSCOMMAND,SC_MINIMIZE,r.left16|r.top); else if (m_bMaxPushed = TRUE) PostMessage(WM_SYSCOMMAND,SC_MAXIM
18、IZE,r.left16|r.top); else if (m_bClosePushed = TRUE) PostMessage(WM_SYSCOMMAND,SC_CLOSE,r.leftm_rSYS.right - m_psi-m_rSYS.left + r1.left; r1.bottom = m_psi-m_rSYS.bottom- m_psi-m_rSYS.top + r1.top; bRet = PtInRect(&r1,point); if (bRet = TRUE) m_bSysPushed = TRUE; goto L_FOUND; if (m_bIconMin) iSizeX
19、 = m_psi-m_rCLOSE.right - m_psi-m_rCLOSE.left; iSizeY = m_psi-m_rCLOSE.bottom - m_psi-m_rCLOSE.top; r1.left = r.right - 6 - 3 * iSizeX - 3 * 2; r1.top = r.top+5; r1.right = r1.left + iSizeX; r1.bottom = r1.top + iSizeY; bRet = PtInRect(&r1,point); if (bRet = TRUE) m_bMinPushed= TRUE; goto L_FOUND; i
20、f (m_bIconMax) iSizeX = m_psi-m_rCLOSE.right - m_psi-m_rCLOSE.left; iSizeY = m_psi-m_rCLOSE.bottom - m_psi-m_rCLOSE.top; r1.left = r.right - 6 - 2 * iSizeX - 2 * 2; r1.top = r.top+5; r1.right = r1.left + iSizeX; r1.bottom = r1.top + iSizeY; bRet = PtInRect(&r1,point); if (bRet = TRUE) m_bMaxPushed=
21、TRUE; goto L_FOUND; if (m_bIconClose) iSizeX = m_psi-m_rCLOSE.right - m_psi-m_rCLOSE.left; iSizeY = m_psi-m_rCLOSE.bottom - m_psi-m_rCLOSE.top; r1.left = r.right - 6 - iSizeX - 2; r1.top = r.top+5; r1.right = r1.left + iSizeX; r1.bottom = r1.top + iSizeY; bRet = PtInRect(&r1,point); if (bRet = TRUE) m_bClosePushed= TRUE; goto L_FOUND; m_bMinPushed = FALSE; m_bMaxPushed = FALSE; m_bClosePushed = FALSE; m_bSysPushed = FALSE; L_FOUND: RepaintIcons(); return; 恩。到这里,自绘边框的窗口就ok了。
限制150内