【问题标题】:Can I get TComboBoxEx to be the same Height as TComboBox?我可以让 TComboBoxEx 与 TComboBox 的高度相同吗?
【发布时间】:2009-08-24 21:55:32
【问题描述】:

在 Delphi 中,所有的 TEdit 和 TComboBox 控件默认都是 21 像素高。在 TComboBox 的情况下,这个大小是绝对的,试图将它拉伸到更大的东西是行不通的。但是,在 TComboBoxEx 的情况下,默认高度是 22 像素,这使它在您使用它的任何形式上都显得有点突出。现在根据Microsoft docs 的说法,ComboBoxEx 本质上是一个 ComboBox,它处理了所有者绘制的功能以允许图像和缩进。

那么可以让我的 TComboBoxEx 控件高 21 像素吗?这取决于什么?

更新:根据 Roddy 的建议,我在该问题上添加了 Quality Central report。另外,我找到了解决方法。显然,大小取决于组合框中项目 -1 的大小。因此,您将该大小设置为 15(或比默认大小小 1 个像素),然后框会缩小到更熟悉的 21 个像素。

【问题讨论】:

  • 哇 - 巧妙的修复!我建议您将其添加为您自己问题的“已接受答案”。值得一票!
  • 添加了答案,但我只能在一两天内接受。还有一个涉及图像显示的警告 - 请参阅下面的答案。

标签: delphi height


【解决方案1】:

我找到了解决办法。 Delphi 似乎有几个与此相关的错误:

  1. 发布的 ItemHeight 属性的值被强制为 16,因为 TComboBoxEx 类将 GetItemHt 函数覆盖为硬编码的 16。不考虑项目的实际大小 - 奇怪,因为这在组合框。我不知道他们为什么决定采用这种策略。可能是为了确保图像始终适合。
  2. Delphi 实际上并没有调用 CB_SETITEMHEIGHT 消息,因此即使您覆盖此函数,也不会发生任何变化。

更新:

正如 mghie 所指出的,我最初使用硬编码值 15 调用消息的想法在不同的 DPI 设置下效果不佳。所以我现在使用对 GetTextMetrics 的调用来确定高度。 GetSystemMetrics(SM_CYBORDER) 的值添加到字体的高度。

这是基于 VCL 确定 TEdit 大小的方式。我认为这不太对,但由于目标是使 ComboBoxEx 的大小与 TEdit 相同,因此它可能与我们将得到的一样接近。它适用于 96、120、144 和 192 的 DPI 设置。

ComboBoxEx 的高度由项目-1 的高度决定。所以项目 0 到 count-1 是实际的列表项目,但项目 -1 是用于编辑器的高度。如果您将该高度设置为 15,则控件的高度会更正为 21 像素(有关缩放问题,请参阅上面的更新)。我认为 Mason 可能是正确的,字体大小在这里起作用(可能会调整项目的大小),但您可以通过调整项目大小使其正常工作。

它似乎引入了一个新的(在我看来,更小)问题,即在 96 DPI 16 像素高的图像在编辑器部分显示时最底线松动,但这几乎不引人注意。

那么解决方法就是调用这段代码:

GetTextMetrics(Canvas.Handle, TM);
SendMessage(Handle, CB_SETITEMHEIGHT, -1, 
  GetSystemMetrics(SM_CYBORDER) * 2 + TM.tmHeight);

【讨论】:

  • 我笔记本电脑上 DPI 设置为 124 的 TEdit 肯定不是 21 像素高。硬编码的高度是错误的,不管它们是否适合你,返回 15 并不比返回 16 更好。不同的字体或 DPI 设置怎么样?真正的解决方法是获取字体高度并据此计算项目高度。
  • 关于 DPI 设置的要点。所以现在我需要知道编辑框的高度是如何计算的。我查看了根据字体​​高度计算项目高度,但我不明白这是如何让它们首先达到 16 - 我实际上认为选择它是为了适合 16x16 字形。似乎在 96 DPI 和 120 上都有效的是调用 GetTextMetric 并使用 tmHeight + 2。我认为使用 tmHeight + tmInternalLeading 是正确的,但这仅适用于 120 DPI。我可以从 15 开始,然后将其从 96 扩展到 120,但这似乎也不正确。有什么想法吗?
  • TEdit.AdjustHeight 方法也做出了明显的假设,我明白了。它使用 tmHeight + I,其中 I 是 GetSystemMetrics(SM_CYBORDER) * 6 或 8,具体取决于控件是否设置了 Ctl3D。似乎 6 或 8 应该是边框的宽度加上编辑控件的内部间距。因此,如果我这样做,我将用一个幻数替换另一个。那么如何确定内部间距呢?请记住,目标是使 TComboBoxEx 高度与 TEdit 的默认高度相同。
  • +1,感谢您跟进此事并找到更好的解决方案。
【解决方案2】:

TComboBox 的高度不是绝对的;它与您使用的字体的高度相关。 TComboBoxEx 的工作方式相同,但正如您所指出的,它似乎有一个额外的“开销”像素,并且似乎没有任何简单的方法可以改变它。如果这是内置 Windows 控件的包装器,则可能无法在 Delphi 级别更改它。

【讨论】:

  • 除非您想创建自己的版本,但我认为这不是一个有效的选择;-)。
【解决方案3】:

改变 TComboBoxEx 高度的两种方法,不幸的是,这两种方法都不是你想要的。

  • 将 font.size 属性设置得更小 - 框会缩小。 (但是,您的文字更小)

  • 设置 StyleEx.csExNoSizeLimit := false,然后根据需要设置 Height := 21。不幸的是,这只会导致您的盒子被剪裁,因此底部边框消失了。

我可能会用 TComboBoxEx 替换所有 TComboBoxes - GExperts 有一个出色的“替换组件”向导来执行此操作。

这看起来像一个 Delphi 错误。您是否通过 QC 报告过?

【讨论】:

  • 添加了质控报告。链接已添加到问题。
猜你喜欢
  • 2017-09-12
  • 2016-05-13
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 2012-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多