65.9K
CodeProject 正在变化。 阅读更多。
Home

控件中的控件:带行号的编辑框

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (22投票s)

2004年3月10日

公共领域

5分钟阅读

viewsIcon

141560

downloadIcon

6368

带行号的编辑控件

Sample Image - linenumberedit.gif

引言

CLineNumberEdit 是一个从 CEdit 派生的类,具有自动在左边距添加行号的功能。边栏的颜色和行号的格式都可以编辑。这个子类化是对在编辑框内包含控件的一次实验,即使我已经添加了足够的功能使其具有一定的实用性,主要目标还是为了探索这种包含(也可参阅 www.codeproject.com/editctrl/editwithicon.asp)。

使用代码

将 cpp 和 h 文件添加到项目中。CLineNumberEdit 可以动态创建,通过调用 Create,或者从对话框模板创建。在后一种情况下,可以使用类向导创建并绑定控件变量,或者使用 SubclassDlgItem

此类公共成员

要设置行号字段的背景颜色,请调用 SetMarginBackgroundColor。默认值为 RGB( 255, 255, 248 )(参见图片)。

SetMarginForegroundColor 用于设置文本颜色。默认值为黑色。

SetLineNumberFormat 用于设置格式字符串,该字符串稍后将与 CString::Format 一起使用,因此它遵循该调用的规则。格式字符串必须包含一个(且仅一个)数字类型。默认值为 "%05i",生成一个右对齐、零填充的 5 位字符串。

PreSubclassWindow 中,会检查编辑框的样式。如果它不包含 ES_MULTILINE,则类会 ASSERT。除了在最少的情况下可能与非多行编辑框有些不相关之外,用于为行号腾出空间的 SetRect 调用对于单行编辑框将无法正常工作。

边距在 Prepare 中设置。在此,计算行号字段所需的宽度。这通过创建一个字符串来完成,使用控件的格式字符串,并使用控件的最大字符数(调用 CEdit::GetLimitText)对其进行格式化。这假设每行只有一个字符,因此我们知道这将是我们的最大行数。测量字符串,然后添加一个小边距。

最后,创建一个具有所需尺寸的 CLineNumberStatic(一个从 CStatic 派生的控件)。编辑框的顶部和底部行会发送给此控件。顶部边距也已设置。

CLineNumberStatic 是一个简单的从 CStatic 派生的类,通过 OnPaint 管理行号的绘制。绘制到内存 CDC 并将其blit 到屏幕,并且会处理 WM_ERASEBKGND 以避免闪烁。

通过设置新的顶部和底部行值,CLineNumberStaticCLineNumberEdit 同步。这必须在控件滚动和/或内容更改时完成。幸运的是,这很简单——通过处理 EN_CHANGEWM_SETTEXT 消息来实现修改,以及处理 EN_VSCROLLWM_VSCROLL 实现滚动。EN_VSCROLL 负责编辑框“内部”的滚动(例如使用箭头键移动),WM_VSCROLL 在移动滑块时更新行号。

会处理 WM_SIZE,以重新建立行号字段的大小和编辑矩形。最后,还会处理 WM_SETFONT 以重新建立编辑矩形——因为它在控件接收到此消息时会被重置。WM_SETFONT 还会使行号控件重绘。

关注点

此控件带来了一些问题。编辑控件和行号静态控件必须同步。编辑矩形必须在被销毁后立即重新建立。主要问题在于找到发送给控件的消息,以便完成这两项任务。一个模糊的区域是编辑矩形何时被销毁,后来我发现 SetWindowPlacement 也会这样做——没有解决方案,只能“改用 MoveWindow”。

获取第一个可见行很简单——只需调用 GetFirstVisibleLine。然而,获取最后一行比较棘手。我最初尝试使用一个非常巧妙的方法,通过混合调用 GetLineGetPosFromChar 来获取两行之间的差异,但控件的内容没有以一种使其可靠的方式重新格式化。现在,我只需使用控件字体中一行的高度,以及 GetRect 父项的顶部边距。

历史

远古时代

第一版

14/4 2004

来自 **Keith Bowes** 的一些非常好的补充;可以使用系统颜色来绘制行号部分,以及处理起始值和最大值。

可以调用 UseSystemColours( BOOL bUseEnabled = TRUE, BOOL bUseDisabled = TRUE ); 分别为启用和禁用状态使用当前系统颜色。

可以使用 SetLineNumberRange( UINT nMin, UINT nMax = 0 ); 来设置起始行号和要编号的最大行数。请注意,这不是一个最小值-最大值范围,例如,最小值 100 和最大值 10 会将行号从 100、101、102 等编号到 109。

nMax 设置为零表示没有上限。最大值以上的行将不被编号,尽管它们仍然会显示。

22/4 2004

来自 **Keith Bowes** 的一项新补充——处理 WM_LINESCROLL 消息。这是社区精神!

为了不甘落后,我添加了代码,可以通过单击行号来选择整行。通过注册消息和行号控件的点击处理来实现。

添加了一个小型演示程序。我意识到有些人可能只是想看一看——为此创建一个项目可能有点太过了 :-)

© . All rights reserved.