重新回来这里,纪念下吧

已经几年没回来了,过程中有相回来看下以前写的文章,后面发现竟然百度不出来了。 然后也懒得弄。

几年过去默然回首,还是多写文章多研究,好点。

<think>由于用户指出上一个回答可能丢失了部分内容,需要重新回答。但根据历史记录,上一个回答是完整的,因此这里将重新组织并确保完整性。 问题:MFC MDI多文档框架默认的绘制的客户区会有一圈边框,这个是在哪边绘制的,如何修改呢? 回答: 在MFC的MDI(多文档界面)框架中,子窗口(即文档窗口)默认会带有一圈边框。这个边框实际上是MDI子窗口的窗口边框,由Windows系统绘制,属于非客户区(Non-Client Area)的一部分。 ### 边框绘制的位置 边框的绘制是在MDI子窗口的非客户区,由Windows系统在绘制窗口框架时自动完成。具体来说: - 当MDI子窗口创建时,它通常会使用`WS_OVERLAPPEDWINDOW`样式,该样式包含`WS_BORDER`、`WS_THICKFRAME`、`WS_CAPTION`等。 - 边框的绘制发生在系统消息`WM_NCPAINT`的处理过程中,由系统负责绘制。 ### 修改边框的方法 要修改或移除这个边框,可以通过修改窗口样式来实现。以下是几种常见方法: #### 方法1:在`PreCreateWindow`中修改样式(推荐) 在自定义的MDI子窗口类(通常是`CChildFrame`)中重写`PreCreateWindow`函数,修改`CREATESTRUCT`中的样式。 ```cpp BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs) { if (!CMDIChildWnd::PreCreateWindow(cs)) return FALSE; // 移除边框样式(例如,移除WS_THICKFRAME和WS_BORDER) cs.style &= ~(WS_THICKFRAME | WS_BORDER); // 可以添加其他样式,比如对话框边框样式 // cs.style |= WS_DLGFRAME; return TRUE; } ``` #### 方法2:在`OnCreate`中修改样式 在窗口创建过程中,可以在`OnCreate`函数中使用`ModifyStyle`来改变样式。注意需要调用`SetWindowPos`来应用更改。 ```cpp int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1) return -1; // 移除边框样式 ModifyStyle(WS_THICKFRAME | WS_BORDER, 0); // 刷新窗口框架 SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); return 0; } ``` #### 方法3:自定义非客户区绘制(高级) 如果需要自定义边框的绘制,可以处理`WM_NCPAINT`消息。但注意,这需要自己绘制整个非客户区(包括边框和标题栏等)。 ```cpp void CChildFrame::OnNcPaint() { // 如果需要完全自定义非客户区,可以在这里绘制 // 但通常不推荐,因为需要处理很多细节(如窗口按钮等) // 如果只是想改变边框颜色,可以绘制一个简单的边框 CWindowDC dc(this); CRect rect; GetWindowRect(&rect); rect.OffsetRect(-rect.left, -rect.top); // 绘制一个红色边框 dc.Draw3dRect(rect, RGB(255,0,0), RGB(255,0,0)); // 注意:如果处理了WM_NCPAINT,则不会调用默认处理,因此需要绘制所有非客户区内容 // 或者可以选择调用基类的OnNcPaint,但那样又会绘制默认边框,所以通常不调用。 } ``` 在消息映射中添加: ```cpp BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd) ON_WM_NCPAINT() END_MESSAGE_MAP() ``` ### 注意事项 - 修改边框样式可能会影响窗口的调整大小功能(如果移除了`WS_THICKFRAME`,则无法调整大小)。 - 如果移除了标题栏(`WS_CAPTION`),那么窗口的标题和系统菜单也会消失。 - 修改样式后,需要刷新非客户区,使用`SetWindowPos`并指定`SWP_FRAMECHANGED`标志可以强制更新。 如果需要更复杂的边框效果(如圆角边框、自定义颜色等),可能需要结合使用自定义绘制和窗口样式修改。 §§相关问题§§ 1. 如何移除MFC MDI子窗口的标题栏? 2. 修改窗口样式后边框未更新,如何强制刷新? 3. 在自定义非客户区绘制时,如何正确处理窗口的最大化/最小化按钮? 4. 除了修改窗口样式,还有哪些方法可以改变MDI子窗口的边框? 5. 如何为MDI子窗口添加自定义边框颜色和宽度?</think>在MFC MDI多文档框架中,默认的客户区边框是系统级绘制的非客户区元素。以下是完整解答: ### 边框绘制位置和机制 1. **绘制位置** 边框由`CMDIChildWnd`类在**非客户区**绘制,具体在: - Windows系统级绘制(`WM_NCPAINT`消息处理期间) - MFC框架的`CWnd::OnNcPaint`默认实现中 - 通过`WS_OVERLAPPEDWINDOW`样式集(包含`WS_BORDER | WS_THICKFRAME`)控制 2. **核心代码位置** 在MFC源码中(`winmdi.cpp`): ```cpp // CMDIChildWnd::Create() 内部样式设置 dwStyle = WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW; // WS_OVERLAPPEDWINDOW = // WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | // WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX ``` ### 修改边框的三种方法 #### 方法1:重写`PreCreateWindow`(最佳实践) ```cpp BOOL CMyChildFrame::PreCreateWindow(CREATESTRUCT& cs) { if(!CMDIChildWnd::PreCreateWindow(cs)) return FALSE; // 移除粗边框和单线边框 cs.style &= ~(WS_THICKFRAME | WS_BORDER); // 可选:添加细边框(对话框样式) // cs.style |= WS_DLGFRAME; return TRUE; } ``` #### 方法2:动态修改样式(`OnCreate`中) ```cpp int CMyChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if(CMDIChildWnd::OnCreate(lpCreateStruct) == -1) return -1; // 移除边框并刷新窗口 ModifyStyle(WS_THICKFRAME | WS_BORDER, 0); SetWindowPos(NULL,0,0,0,0, SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED); return 0; } ``` #### 方法3:自定义绘制(高级) ```cpp // 头文件声明 afx_msg void OnNcPaint(); // 实现文件 BEGIN_MESSAGE_MAP(CMyChildFrame, CMDIChildWnd) ON_WM_NCPAINT() END_MESSAGE_MAP() void CMyChildFrame::OnNcPaint() { CWindowDC dc(this); CRect rc; GetWindowRect(&rc); rc.OffsetRect(-rc.TopLeft()); // 转换到窗口坐标 // 绘制红色2px边框 CPen pen(PS_SOLID, 2, RGB(255,0,0)); dc.SelectObject(&pen); dc.SelectStockObject(NULL_BRUSH); dc.Rectangle(rc); } ``` ### 关键注意事项 1. **样式标志含义**: - `WS_THICKFRAME`:可调整大小的边框(默认3px) - `WS_BORDER`:单线固定边框(1px) - `WS_DLGFRAME`:对话框样式边框(不可调整大小) 2. **刷新机制**: - 修改样式后必须调用`SetWindowPos(..., SWP_FRAMECHANGED)` - 否则需要最小化/最大化窗口才能生效 3. **功能影响**: - 移除`WS_THICKFRAME`将禁用窗口大小调整 - 移除`WS_BORDER`可能影响窗口激活状态视觉反馈
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值