鱼C论坛

 找回密码
 立即注册
查看: 49|回复: 13

[已解决]字符宽度问题

[复制链接]
发表于 昨天 21:51 | 显示全部楼层 |阅读模式

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

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

x
case WM_CREATE:
                hdc = GetDC(hwnd);
                GetTextMetrics(hdc, &tm);
                cyChar = tm.tmHeight + tm.tmExternalLeading;
                cxChar = tm.tmAveCharWidth;
                cxCat = (tm.tmPitchAndFamily & 1) ? 3 : 2 / 2 * cxChar;

                ReleaseDC(hwnd, hdc);
                return 0;

        case WM_PAINT:
                hdc = BeginPaint(hwnd, &ps);
               
                for (i = 0; i < 100; i++)
                {
                        StringCchPrintf(szBuffer1, 128, TEXT("%d: %s"), i + 1, TEXT("I Love fish.com!"));
                        StringCchLength(szBuffer1, 128, &iTarget1);
                        TextOut(hdc, 0, i *cyChar, szBuffer1, iTarget1);

                        StringCchPrintf(szBuffer2, 128, TEXT("%s"), TEXT("My Fist Windows BianCheng Xue xi!"));
                        StringCchLength(szBuffer2, 128, &iTarget2);
                        TextOut(hdc, 30 * cxCat , i * cyChar, szBuffer2, iTarget2);
                }
               
                EndPaint(hwnd, &ps);

szBuffer1里总共才19个字符, 我第二列 用30 * cxCat 为什么还会重叠在一起
最佳答案
昨天 22:03
1006150804 发表于 2025-01-11 22:03
FishC 发表于 2025-1-11 22:00
在您的代码中,`cxCat ...


是的,在您的代码中,`cxChar` 和 `cxCat` 的计算都是基于单个字符的宽度,而不是整个文本的宽度。

具体来说:

- **`cxChar`:** 这是 `tm.tmAveCharWidth`,表示字体的平均字符宽度。这个值是单个字母的平均宽度,并不针对具体的某个字母,而是整个字体的一个平均值。

- **`cxCat`:** 您的计算方式(`3` 或 `2 / 2 * cxChar`)是在针对单个字符或一部分字符的宽度来决定 `cxCat`。默认情况下这个计算是基于单个字符的,如果使用 `cxChar` 计算,也是表示单个字符的宽度。

在您的应用场景中,如果要为特定的列计算位置(比如通过 `30 * cxCat`),通常意味着您在为每行的列之间预留足够的宽度,以便适应平均字符宽度情况下的字符排列。

如果您需要计算整个文本的宽度,应该使用如 `GetTextExtentPoint32` 这类函数来计算文本整体宽度。这将针对整段文本计算它实际需要的像素宽度。这样可以更好地处理文本中混合大小写和不同字符造成的宽度变化。

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

使用道具 举报

发表于 昨天 21:52 | 显示全部楼层
在您的代码中,`cxCat` 计算后用于确定第二列文本的起始位置。您提到使用 `30 * cxCat` 作为位移,但文本存在重叠问题。以下是导致重叠的可能原因:

1. **`cxCat`的计算问题:**  
   您的计算公式 `cxCat = (tm.tmPitchAndFamily & 1) ? 3 : 2 / 2 * cxChar;` 可能不符合预期逻辑。这个公式需要确认是否正确,如果希望 `cxCat` 表示平均字符宽度,可以直接使用 `cxChar`。

2. **字符总宽度与位移计算不符:**  
   如果 `30 * cxCat` 不足以容纳第一列的大部分字符宽度,那么文本可能会重叠。平均字符宽度乘以一个常量(例如30)应该保证能够完全避开第一列文本。

3. **`cxCat`乘数问题:**  
   您用 `30` 乘以 `cxCat`,确保30这个数足够避开第一列,您需要确保该值对于当前字体和内容是合适的。

以下是调整建议:
cxCat = cxChar;  // 直接使用平均字符宽度作为字符单位宽度

使用 `cxCat` 的时候可以考虑增加倍数,确保每行的文本之间有足够的间隔:
int columnOffset = 50;  // 选择一个较大的数确保不会重叠
TextOut(hdc, columnOffset * cxChar, i * cyChar, szBuffer2, iTarget2);

以上调整确保每一行的第二列有足够的空间来显示,避免重叠。您可以根据实际需求调节 `columnOffset` 的值。

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

使用道具 举报

 楼主| 发表于 昨天 21:56 | 显示全部楼层
FishC 发表于 2025-1-11 21:52
在您的代码中,`cxCat` 计算后用于确定第二列文本的起始位置。您提到使用 `30 * cxCat` 作为位移,但文本存 ...

如果我一段文本里既有大写又有小写,该怎么算字符宽度,以大写的为准吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 21:58 | 显示全部楼层
1006150804 发表于 2025-01-11 21:56
FishC 发表于 2025-1-11 21:52
在您的代码中,`cxCat ...


在计算字符宽度时,通常使用字体的平均字符宽度来确保兼顾各种字符的显示效果。如果需要确保文本不会因为包含宽度不同的字符(如大写字母)而导致布局问题,你可以考虑以下方法:

1. **使用最大字符宽度:**  
   获取字体中常用大写字母的宽度作为基准,因为大写字母通常比小写字母宽。

2. **计算具体字符的宽度:**  
   如果你的文本包含特定字符,可以使用 `GetTextExtentPoint32` 函数计算整个字符串的总宽度,这样无论大写还是小写,都会得到精确的宽度。

3. **以平均宽度为基准:**  
   简单情况下,继续使用 `tm.tmAveCharWidth` 可以适用于大多数文本显示,特别是在设计支持可变字符宽度时。

以下是调整字符宽度的代码示例:
SIZE size;
GetTextExtentPoint32(hdc, TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52, &size);
int maxCharWidth = size.cx / 52;

这样你就可以根据实际情况选择合适的方法来计算字符宽度,以便文本的展示不发生重叠或显示问题。

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

使用道具 举报

 楼主| 发表于 昨天 22:00 | 显示全部楼层
FishC 发表于 2025-1-11 21:52
在您的代码中,`cxCat` 计算后用于确定第二列文本的起始位置。您提到使用 `30 * cxCat` 作为位移,但文本存 ...

不对呀,还是没搞懂,我这里cxCat 计算出来算是什么
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 22:00 | 显示全部楼层
1006150804 发表于 2025-01-11 22:00
FishC 发表于 2025-1-11 21:52
在您的代码中,`cxCat ...


在您的代码中,`cxCat` 的计算涉及到如下语句:
cxCat = (tm.tmPitchAndFamily & 1) ? 3 : 2 / 2 * cxChar;
这个语句试图根据 `tm.tmPitchAndFamily` 的值来确定 `cxCat`,但公式本身可能会引起困惑。让我们来分析一下:

1. **`tm.tmPitchAndFamily & 1`:**  
   这个操作用于检查字体是否是可变宽度字体。如果结果为1,表示是可变宽度字体,否则是固定宽度字体。

2. **计算宽度:**  
   - (`tm.tmPitchAndFamily & 1)`的结果是 1 时,`cxCat` 被赋值 `3`。
   - 结果为 0 时,`cxCat` 似乎依赖于一个不完整的表达式 `2 / 2 * cxChar`,实际上这相当于 `cxChar`,因为 `2 / 2` 是 `1`。

**问题所在:**
- 对于固定宽度字体,仅用了 `cxChar`。
- 对于可变宽度字体,简单设为 `3` 可能没有意义或者不符合实际需求。

**解决办法:**
如果您希望 `cxCat` 考虑到大写字母的宽度或者平均字符宽度,建议如下修改:

- 使用平均字符宽度 `cxChar` 更为合适:
cxCat = cxChar;

如果文本有重叠问题,`cxCat` 的值可能需要是一个结合大写字母宽度和其它特定要求的值。可以参考上一个回复中关于获取具体文本宽度的方法。在 GUI 应用程序中,确定适当的列间距更为重要,因为每个字体和字符串的表现都会有所不同。

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

使用道具 举报

 楼主| 发表于 昨天 22:03 | 显示全部楼层
FishC 发表于 2025-1-11 22:00
在您的代码中,`cxCat` 的计算涉及到如下语句:

这个语句试图根据 `tm.tmPitchAndFamily` 的值来确 ...

那个我懂,我的意思是,这里的计算都是针对的单个字母,不是整个文本吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 22:03 | 显示全部楼层    本楼为最佳答案   
1006150804 发表于 2025-01-11 22:03
FishC 发表于 2025-1-11 22:00
在您的代码中,`cxCat ...


是的,在您的代码中,`cxChar` 和 `cxCat` 的计算都是基于单个字符的宽度,而不是整个文本的宽度。

具体来说:

- **`cxChar`:** 这是 `tm.tmAveCharWidth`,表示字体的平均字符宽度。这个值是单个字母的平均宽度,并不针对具体的某个字母,而是整个字体的一个平均值。

- **`cxCat`:** 您的计算方式(`3` 或 `2 / 2 * cxChar`)是在针对单个字符或一部分字符的宽度来决定 `cxCat`。默认情况下这个计算是基于单个字符的,如果使用 `cxChar` 计算,也是表示单个字符的宽度。

在您的应用场景中,如果要为特定的列计算位置(比如通过 `30 * cxCat`),通常意味着您在为每行的列之间预留足够的宽度,以便适应平均字符宽度情况下的字符排列。

如果您需要计算整个文本的宽度,应该使用如 `GetTextExtentPoint32` 这类函数来计算文本整体宽度。这将针对整段文本计算它实际需要的像素宽度。这样可以更好地处理文本中混合大小写和不同字符造成的宽度变化。

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

使用道具 举报

 楼主| 发表于 昨天 22:19 | 显示全部楼层
FishC 发表于 2025-1-11 22:03
是的,在您的代码中,`cxChar` 和 `cxCat` 的计算都是基于单个字符的宽度,而不是整个文本的宽度。

...

GetTextMetrics(hdc, &tm)这玩意获取的是系统的信息,跟我输入输出的文本大小写不搭噶对吧,那为什么不直接定义一个cxChar,  一个cxCat = 1.5 * cxChar呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 22:19 | 显示全部楼层
1006150804 发表于 2025-01-11 22:19
FishC 发表于 2025-1-11 22:03
是的,在您的代码中, ...


确实,`GetTextMetrics(hdc, &tm)`获取的是指定字体的度量信息,其中包括字符平均宽度、高度等属性。它和具体输入的文本内容(比如大写或小写字母)没有直接关系。但是,它为您展示文本时提供了一种基于当前字体的合理默认度量。

### 关于您的疑问:
1. **定义固定的`cxChar`:**
   您完全可以根据设计需求直接定义一个固定的`cxChar`值。这样做通常是为了简化程序开发,尤其是在您明确知道需要多少空间来展示字符时。

2. **计算`cxCat`:**
   如果您希望严格控制每行的列间距,例如让每个字符占用1.5倍的平均宽度,那么定义`cxCat`为`1.5 * cxChar`是一个合适的方式。这样可以确保每个字符有更多的宽度空间,便于显示混合大小写字母。

### 实际情况:
- **灵活性:** 使用系统`GetTextMetrics`的目的是为不同字体提供兼容性保证,在字体或字体大小更改时自动调整布局。
- **静态定义:** 如果您确定应用中字体和字号不会变化,也理解具体内容的宽度需求,自行定义常量是可以的。

所以,最终选择取决于您的应用场景:动态适配系统字体变化和要求还是定制设计以符合具体布局。

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

使用道具 举报

 楼主| 发表于 昨天 22:32 | 显示全部楼层
FishC 发表于 2025-1-11 22:19
确实,`GetTextMetrics(hdc, &tm)`获取的是指定字体的度量信息,其中包括字符平均宽度、高度等属性。它 ...

我刚刚试了一下  TextOut(hdc, 30 * cxCat , i * cyChar, szBuffer2, iTarget2);这里把cxCat  换成cxChar行间距会更大,这是为什么, 按这个cxCat = (tm.tmPitchAndFamily & 1) ? 3 : 2 / 2 * cxChar;计算,cxCat要大于等于cxChar才对呀
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 22:32 | 显示全部楼层
1006150804 发表于 2025-01-11 22:32
FishC 发表于 2025-1-11 22:19
确实,`GetTextMetric ...


看起来您遇到了一个关于逻辑运算的误解。让我们仔细看一下您提供的 cxCat 计算公式:
cxCat = (tm.tmPitchAndFamily & 1) ? 3 : 2 / 2 * cxChar;

首先,这里的 `(tm.tmPitchAndFamily & 1)` 是在检查字体是否是可变间距(TrueType)。在可变间距字体的情况下,`cxCat` 被设为 `3`,否则它被设为 `2 / 2 * cxChar`。

问题可能出现在 `2 / 2 * cxChar` 的计算上。这里 `2 / 2` 的结果是 `1`,所以这个情况实际上将 `cxCat` 设置为 `cxChar`,即:
cxCat = cxChar;

这意味着在 (tm.tmPitchAndFamily & 1) 结果为0的情况下,`cxCat` 就等于 `cxChar`。

### 为什么 `TextOut(hdc, 30 * cxChar, ...)` 显得行间距会更大?

1. **固定值比较:**
   - 当 `tm.tmPitchAndFamily & 1` 为真时,`cxCat` 被静态设定为 `3`,这是一个非常小的距离。
   - 当公式执行计算为 `cxChar` 时,`cxChar` 通常是字体的平均字符宽度,通常大于 `3`。

2. **数值差异:**
   - 所以,当您使用 `30 * cxChar` 时,乘积结果往往大于 `30 * cxCat`(如果 `cxCat` 被设为 `3`),因此行间距会显得更大。

为了更好理解,不妨试试打印 `cxCat` 和 `cxChar` 的值,以便在执行时确定它们的具体数值,这样有助于解释实际间距变化。

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

使用道具 举报

 楼主| 发表于 昨天 22:36 | 显示全部楼层
FishC 发表于 2025-1-11 22:32
看起来您遇到了一个关于逻辑运算的误解。让我们仔细看一下您提供的 cxCat 计算公式:

找到原因所在了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 22:36 | 显示全部楼层
1006150804 发表于 2025-01-11 22:36
FishC 发表于 2025-1-11 22:32
看起来您遇到了一个关 ...


很好!解决问题的过程本身就是学习的一个重要部分。如果有更多问题或需要进一步的帮助,随时可以继续询问。祝您在编码之路上一帆风顺!

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-12 09:44

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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