鱼C论坛

 找回密码
 立即注册
查看: 98|回复: 9

[技术交流] 学习课程

[复制链接]
发表于 2025-1-14 21:28:47 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
SDK编程讲课时写的windows窗口边框的红色是怎么设置的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2025-1-14 21:28:56 | 显示全部楼层
在Windows SDK编程中,要设置窗口边框的颜色为红色,需要自定义窗口的边框绘制。这通常可以通过拦截`WM_NCPAINT`消息来实现。

以下是实现的简单步骤:
1. 拦截`WM_NCPAINT`消息。
2. 获取窗口的边框区域(非客户区)。
3. 使用`GetDCEx`函数获取边框的绘图设备上下文(DC)。
4. 使用GDI函数,如`Rectangle`结合`SelectObject`设置颜色并绘制红色边框。

以下为代码示例:
case WM_NCPAINT:
{
    HDC hdc = GetWindowDC(hwnd);
    if (hdc)
    {
        RECT rect;
        GetWindowRect(hwnd, &rect);
        OffsetRect(&rect, -rect.left, -rect.top);

        HBRUSH hBrush = CreateSolidBrush(RGB(255, 0, 0)); // 设置红色画刷
        FrameRect(hdc, &rect, hBrush);

        DeleteObject(hBrush);
        ReleaseDC(hwnd, hdc);
    }
    return 0; // 消息已处理
}

这样就可以实现窗口边框显示为红色。


以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-1-14 21:46:00 | 显示全部楼层
FishC 发表于 2025-1-14 21:28
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

这里的GetWindowRect(hwnd, &rect); 获取到的是整个非客户区的区域吗,这个OffsetRect(&rect, -rect.left, -rect.top)又是什么意义
        
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-1-14 21:46:20 | 显示全部楼层
1006150804 发表于 2025-01-14 21:46
FishC 发表于 2025-1-14 21:28
以上回复来自 FishC A ...


解答:

1. `GetWindowRect(hwnd, &rect);`  
   这个函数获取的是整个窗口在屏幕上的矩形范围,包括窗口的非客户区(标题栏、边框等)和客户区。

2. `OffsetRect(&rect, -rect.left, -rect.top);`  
   这个函数的作用是将 `rect` 的左上角位置(rect.left, rect.top)移动到 (0, 0)。  
   换句话说,就是把窗口的位置标准化为以窗口本身左上角为原点的坐标系。  
   这样处理后,`rect` 的各个值就表示窗口在其自身坐标系下的大小,而不再受到屏幕坐标系的影响。

总结:  
用 `GetWindowRect` 获取的范围是屏幕坐标下的整个窗口区域,而 `OffsetRect` 的操作可以将窗口的坐标标准化,方便进一步计算和使用。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-1-14 21:55:26 | 显示全部楼层
FishC 发表于 2025-1-14 21:46
解答:

1. `GetWindowRect(hwnd, &rect);`  

如果我把这里的 FrameRect函数,换成Rectangle函数,那是不是客户区和非客户区都变成红色了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-1-14 21:55:38 | 显示全部楼层
1006150804 发表于 2025-01-14 21:55
FishC 发表于 2025-1-14 21:46
解答:

1. `GetWin ...


是的!

### 解答:
1. `FrameRect()`  
   - `FrameRect` 只会绘制一个矩形框的边框部分(用笔刷填充),不会影响矩形内部区域。
   - 默认情况下,你绘制的内容只会出现在客户区,而无论非客户区还是客户区,只绘制边框。

2. `Rectangle()`  
   - `Rectangle` 会直接绘制一个填充的矩形区域(包括边框和内部所有区域),只要涉及到的区域是可绘制的,它都会被填充。  

### 如果替换成 `Rectangle()`:
- 客户区会被红色填充。
- Non-client(非客户区,例如标题栏和边框本身)默认情况下不会直接被影响,因为程序通常只对客户区进行绘制。但窗口重绘时可能会有异常,建议不要这么做,以免影响非客户区的显示。

总结:  
`Rectangle()` 的主要影响是填充客户区,它不会直接影响非客户区。不过,非客户区绘制通常是由 Windows 系统负责的,自己要修改需要通过特定的 WM_NCPAINT 消息或其他技术来处理。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-1-15 19:25:21 | 显示全部楼层
FishC 发表于 2025-1-14 21:28
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

为什么我用这段代码显示出来的边框只是一条线
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-1-15 19:25:44 | 显示全部楼层
1006150804 发表于 2025-01-15 19:25
FishC 发表于 2025-1-14 21:28
以上回复来自 FishC A ...


### 解答

你看到的边框只有一条线,可能与 `FrameRect` 的工作原理和矩形的大小有关。下面是几个可能的原因:

---

1. **确认矩形区域的大小是否正确:**
   - `FrameRect` 仅绘制矩形的边框,而边框的宽度等于你使用的画刷(`hBrush`)的宽度。如果矩形太小,它的边框看起来就会像是一条线。
   - 如果在绘制之前使用了 `OffsetRect`,可能会改变矩形的实际区域导致可见部分被限制为一条线。

---

2. **检查矩形坐标是否正确:**
   - `GetWindowRect` 获取的矩形范围是屏幕坐标,但客户区坐标是基于窗口左上角(0, 0)的。如果你没有正确转换(例如使用 `OffsetRect`),绘图可能的位置不对。

   示例(无转换的错误情况,例如只是一条线):
rect: top=100, left=100, bottom=100, right=300
   这里的 `top` 和 `bottom` 相等,导致矩形塌缩为一条水平线,绘制出的边框自然只会是一条窄线。

---

3. **可能的画刷宽度影响:**
   - `FrameRect` 使用的是画刷来绘制边框,但画刷只能绘制宽度为 1 像素的边框。如果你希望更粗的边框,可以考虑用其他方法,例如 `Polygon` 或 `Rectangle` 函数手动绘制更粗的矩形。

---

### 解决方法

要确保你绘制的边框显示正确,可以参考以下步骤:
RECT rect;
GetWindowRect(hwnd, &rect);

// 缩小为客户区适当范围
OffsetRect(&rect, -rect.left, -rect.top);

// 缩小矩形以便更清晰显示边框
InflateRect(&rect, -10, -10); // 缩小 10 像素边框

// 绘制边框
FrameRect(hDC, &rect, hBrush);

- 确保 `InflateRect` 将矩形变小,让边框看起来更加明显。
- 检查传入的 `RECT` 的边界是否有问题(`top == bottom` 或 `left == right` 的情况会导致只画出一条线)。

---

### 总结

1. **只有一条线的情况**通常是因为矩形边界定义不正确(例如高度或宽度为 0)。
2. `FrameRect` 只能绘制宽度为 1 像素的边框,如果需求是更宽的边框,需要用其他函数代替(比如 `Rectangle` 或 `Polygon` 函数)。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-1-15 19:25:59 | 显示全部楼层
1006150804 发表于 2025-1-15 19:25
为什么我用这段代码显示出来的边框只是一条线

而且最大化最小化按钮也没了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-1-15 19:26:38 | 显示全部楼层
1006150804 发表于 2025-01-15 19:25
1006150804 发表于 2025-1-15 19:25
为什么我用这段 ...


### 解答

最大化、最小化按钮消失,是因为你在绘制或者设置窗口属性时,意外改变了非客户区(Non-Client Area)的显示行为。非客户区包括标题栏、边框、菜单栏等,默认由 Windows 系统管理。如果你的代码影响了它,可能会导致按钮消失甚至边框异常。

以下是一些可能的原因和解决方案:

---

#### 原因 1:使用了错误的绘制方式
- **问题现象:**
  如果你在客户区(Client Area)使用了类似 `Rectangle()` 或者其他涉及整个窗口范围的绘图函数,又没有正确避免覆盖非客户区,就可能把标题栏、边框等内容一并覆盖,导致最大化、最小化按钮不可见。

- **解决方法:**
  确保绘图操作仅限于客户区(通过 `BeginPaint` 或 `GetClientRect` 获取客户区范围),避免绘制到整个窗口区域。

RECT rect;
  GetClientRect(hwnd, &rect); // 仅获取客户区范围
  FrameRect(hDC, &rect, hBrush); // 确保只影响客户区

---

#### 原因 2:窗口样式被意外更改
- **问题现象:**
  窗口样式(`WS_SYSMENU`, `WS_MINIMIZEBOX`, `WS_MAXIMIZEBOX` 等)控制了标题栏、最小化、最大化按钮的显示。如果在某处修改了窗口属性,或者在 `CreateWindow` 时没有正确设置样式,就会导致按钮消失。

- **解决方法:**
  确保你的窗口样式包含以下标志:
WS_OVERLAPPEDWINDOW // 包括常见的标题栏、边框、最大化/最小化按钮
  如果你的窗口需要额外控制,可以用 `SetWindowLong` 动态修改窗口样式:
LONG style = GetWindowLong(hwnd, GWL_STYLE);
  SetWindowLong(hwnd, GWL_STYLE, style | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
  SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);

---

#### 原因 3:处理了 `WM_NCPAINT` 消息
- **问题现象:**
  重写 `WM_NCPAINT` 或 `WM_NCCALCSIZE`(非客户区大小计算)消息的处理逻辑时,如果没有正确调用默认处理函数,可能会导致非客户区(包括标题栏和按钮)不显示。

- **解决方法:**
  确保对 `WM_NCPAINT` 的处理正确,如无特殊需要,调用 `DefWindowProc`:
case WM_NCPAINT:
      return DefWindowProc(hwnd, uMsg, wParam, lParam);

---

#### 原因 4:窗口被设置为无边框样式
- **问题现象:**
  如果你在创建窗口时使用了 `WS_POPUP` 样式,或者意外移除了 `WS_CAPTION` 和 `WS_THICKFRAME`,会让窗口成为无边框样式,从而没有标题栏和按钮。

- **解决方法:**
  确保窗口样式正确,比如使用以下组合:
WS_OVERLAPPEDWINDOW // 标准窗口样式,包含标题栏、边框、最大化/最小化按钮

---

### 总结

- 如果最大化、最小化按钮消失,优先检查是否覆盖到了非客户区(比如用 `Rectangle` 绘图时没有限制范围)。
- 如果仍有问题,检查窗口样式是否正确设置(`WS_SYSMENU` 和 `WS_MINIMIZEBOX` 等必须保留)。
- 当重写 `WM_NCPAINT` 和 `WM_NCCALCSIZE` 时,确保调用了 `DefWindowProc` 进行默认处理。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-23 07:23

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表