TCTextBox –自制文本框支持透明背景

This article introduced a TextBox that supports transparent background.

本文介绍了一个支持透明背景的TextBox。

TCTextBox demo

介绍 (Introduction)

TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the urge for it. TextBox is among one of them, but unfortunately, once in a while people want it to be transparent (such as this typical question in EE: Transparent TextBox in C#).

TextBox是GUI设计中使用最广泛的控件组件。 大多数GUI控件不支持透明背景,或多或少没有这种要求。 TextBox就是其中之一,但是不幸的是,有时人们希望它是透明的(例如EE中的一个典型问题: C#中的Transparent TextBox )。

If you search on the internet for a solution, you will come across advices like subclassing TextBox and add the support to transparent background color, or, drawing your own background in the OnPaint event. It is rational theoretically but unfeasible practically, as revealed in the following analysis.

如果在Internet上搜索解决方案,则会遇到一些建议,例如将TextBox继承为子类并为透明背景色添加支持,或者在OnPaint事件中绘制自己的背景。 如以下分析所示,它在理论上是合理的,但在实践中是不可行的。

(For those who like fast food, you can skip the literature sections and jump to the “Using the Code” section to grab and eat. Actually I also get my hands wet immediately after a short hunting with no luck. After a couple of days working, when I decide to present this home-made component to public, I have to head back to the anatomization part to make the article complete. It costs me much more time than doing the simply coding stuff along.)

(对于那些喜欢快餐的人,您可以跳过文献部分,而跳到“使用代码”部分以获取和吃东西。实际上,经过短暂的狩猎,我也很快就被手弄湿了。工作时,当我决定向公众展示此自制组件时,我必须回到解剖部分以使文章完整(这比花一些简单的代码来花费我更多的时间。)

传统的TextBox只是拒绝进行调整 (The traditional TextBox just refused to be tweaked)

To verify the above common suggestions, I build a phantom class TestTextBox derived from TextBox. Again, test cases are flagged in the source code for users who like to practise by themselves.

为了验证上述常见建议,我构建了一个从TextBox派生的幻影类TestTextBox。 同样,测试用例在源代码中标记为喜欢自己练习的用户。

Set background color as Color.transparent (Test Case 1)

将背景色设置为Color.transparent(测试用例1)

The visual designer does not allow you to set the transparent color to the original TextBox. After subclassing it, you can enable it by adding:

视觉设计器不允许您将透明颜色设置为原始TextBox。 对其进行子类化后,可以通过添加以下内容来启用它:

this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);

When you run the program, you would be glad to see the TextBox showing the background image on the form. The image will stay there if you do not touch it. Once you start typing, the background returns back to normal color along with the text. When you refresh it, the TextBox becomes transparent again but the text is “gone”.

当您运行该程序时,您将很高兴看到TextBox在窗体上显示背景图像。 如果您不触摸它,图像将停留在那里。 开始输入后,背景和文本一起恢复为正常颜色。 刷新时,TextBox再次变为透明,但文本已消失。

Redraw background in OnPaint (Test Case 2)

重绘OnPaint中的背景(测试用例2)

The original TextBox does not even open the OnPaint event for users to subscribe it. After you subclass it, you’d better override the event handlers rather than to subscribe the events (even when it’s available). We leave out the part on how to compose an image, simply draw a pseudo image in OnPaint.

原始TextBox甚至没有打开OnPaint事件供用户订阅。 子类化之后,最好重写事件处理程序,而不要订阅事件(即使可用)。 我们省略了有关如何构成图像的部分,只需在OnPaint中绘制伪图像即可。

protected override void OnPaint(PaintEventArgs e)
        {
            if (backgroundImage == null)
            {
                backgroundImage = this.Parent.BackgroundImage; //Pretended that you have captured the background as image.
            }
            if (backgroundImage != null)
            {
                #region Test Case 2: 
                e.Graphics.DrawImage(backgroundImage, 0,0);   //Uncomment to view the effect.
                #endregion
            }
            base.OnPaint(e);
        }

Don’t forget to add another SetStyle to trigger the OnPaint event:

不要忘记添加另一个SetStyle来触发OnPaint事件:

SetStyle(ControlStyles.UserPaint, true);

When you run the program, you can see the image is drawn in the TextBox. But again, you cannot get the image and text shown at the same time.

当您运行该程序时,您可以看到在TextBox中绘制了图像。 但是同样,您无法同时显示图像和文本。

在WndProc中破解WM_PAINT消息(测试案例3) (Hack the WM_PAINT  message in WndProc (Test Case 3))

We can play a lot of magic by hacking the message loop, but not this one. We put here basically the same code as those in OnPaint. The runtime performance is even worse. If you do not add a “return” after drawing the image, the base TextBox will always draw itself on top of whatever you have done. The background image will never get a chance to show up on surface. If you add the “return” to block the WM_PAINT message passing on to base, the text will never appear.

通过破解消息循环,我们可以发挥很多魔力,但不能做到这一点。 我们在这里放置的代码与OnPaint中的代码基本相同。 运行时性能甚至更差。 如果在绘制图像后未添加“返回”,则基本TextBox将始终将其自身绘制在所做的一切之上。 背景图像永远不会有机会出现在表面上。 如果添加“ return”以阻止WM_PAINT消息传递给基本消息,则文本将永远不会出现。

All in all, the build-in control is competing with user-drawn image on the stage.

总而言之,内置控件正在与用户在舞台上绘制的图像竞争。

鲍勃·布拉德利的AlphaBlendTextBox (Bob Bradley’s AlphaBlendTextBox)

In the late 1990s, I was once working on an automation software for a kiosk project. It would monitor all the processes and applications running in the system. Sometimes it needed to send a mouse click or keyboard input to a certain control within a windows interface to perform actions in behalf of user, so that the user would not be confused by the system messages and focus on the internet surfing. I noticed that many GUI components actually contain more handles than they appear to be, what is so called “comprised control”. It is difficult to dissemble them apart.

在1990年代后期,我曾经为一个自助服务终端项目开发自动化软件。 它将监视系统中运行的所有进程和应用程序。 有时,它需要将鼠标单击或键盘输入发送到Windows界面内的某个控件以代表用户执行操作,以便使用户不会被系统消息所迷惑并专注于Internet浏览。 我注意到,许多GUI组件实际上包含的句柄比看起来更多,即所谓的“包含控件”。 很难将它们拆开。

So the solution of AlphaBlendTextBox is actually using a PictureBox fully covering up the TextBox. Flooding all the keyboard and mouse to the underlying TextBox, so that the TextBox could be working as normal in the behind, then the PictureBox displays an image containing the appearance of the TextBox with Alpha blending. It’s a really smart solution and not quite so arduous as described by himself. I might simply use his diea if I had spent more time on reading his code in the beginning. So far, with my limited search on the internet resources, I guess the AlphaBlendTextBox is the only one that succeeded through the drawing approach. I may do some optimization on his code later on – if there are demands.

因此, AlphaBlendTextBox的解决方案实际上是使用完全覆盖TextBox的PictureBox。 将所有键盘和鼠标泛洪到基础的TextBox,以便TextBox可以在后面正常工作,然后PictureBox显示包含Alpha混合的TextBox外观的图像。 这是一个非常聪明的解决方案,并不像他自己描述的那么艰巨。 如果我一开始花了更多时间阅读他的代码,我可能会简单地使用他的命令。 到目前为止,由于我对互联网资源的搜索有限,我猜想AlphaBlendTextBox是唯一通过绘制方法成功的工具。 如有需要,我稍后可能会对他的代码进行一些优化。

我的自制TCTextBox (My Homemade TCTextBox)

When developing my tiny drawing tool TCPaint, I want to support in-place text input so that users can see what they will get while typing. Since both transparent and opaque background is supported for other parts of the drawing, I would like text editing support both as well. So I write my own text box.

在开发微型绘图工具TCPaint时,我想支持就地文本输入,以便用户可以看到键入时得到的信息。 由于绘图的其他部分都支持透明和不透明背景,因此我希望文本编辑也同时支持。 所以我写了我自己的文本框。

It is derived directly from Control:

它直接来自

class TCTextBox : Control
{
        public TCTextBox()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.Cursor = System.Windows.Forms.Cursors.IBeam;
            this.ImeMode = System.Windows.Forms.ImeMode.On;
        }
}  

The first three SetStyle is to eliminate the possible flickering effect while redrawing itself. The forth SetStyle is to enable the transparent background. Then the cursor is set to IBeam as a visual indication that you can type in this control. And finally turn on the ImeMode to support multi-language input.

前三个SetStyle是为了消除重绘自身时可能出现的闪烁效果。 第四个SetStyle用于启用透明背景。 然后,将光标设置为IBeam,作为可以在此控件中键入的视觉指示。 最后打开ImeMode以支持多语言输入。

Now you have a transparent control looks like you can type in it. But if you are really typing, nothing will show up in the box, because the control does not process any key strike yet. There are a bunch of methods related to keyboard input:

现在您有了一个透明控件,看起来像您可以键入它。 但是,如果您真的在打字,则该框内将不会显示任何内容,因为该控件尚未处理任何按键。 有许多与键盘输入有关的方法:

protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)

受保护的重写void OnPreviewKeyDown(PreviewKe yDownEvent 精氨酸e)

protected override void OnKeyDown(KeyEventArgs e)

受保护的重写void OnKeyDown(KeyEventArgs e)

protected override void OnKeyUp(KeyEventArgs e)

受保护的重写void OnKeyUp(KeyEventArgs e)

protected override void OnKeyPress(KeyPressEventArgs e)

受保护的重写void OnKeyPress(KeyPressEventAr gs e)

protected override bool IsInputKey(Keys keyData)

受保护的覆盖布尔IsInputKey(Keys keyData)

protected override bool IsInputChar(char charCode)

受保护的重写bool IsInputChar(char charCode)

protected override bool PreProcessMessage(ref Message msg)

受保护的覆盖布尔PreProcessMessage(参考消息msg)

protected override bool ProcessKeyEventArgs(ref Message m)

受保护的重写bool ProcessKeyEventArgs(参考消息m)

protected override bool ProcessDialogKey(Keys keyData)

受保护的重写bool ProcessDialogKey(Keys keyData)

protected override bool ProcessDialogChar(char charCode)

受保护的重写bool ProcessDialogChar(char charCode)

They are invented for different purposes. You can read MSDN for details. ProcessDialogChar is the proper one to intercept char input and the only one to enable multiple language IME tool. (Here is a nice guidance if you do not know what is multiple language input:How to Set Up & Use Multiple Language Input Options on Your Computer)

它们是出于不同目的而发明的。 您可以阅读MSDN以获得详细信息。 ProcessDialogChar是截获char输入的正确方法,并且是启用多语言IME工具的唯一方法。 (如果您不知道什么是多语言输入,那么这里是一个很好的指导: 如何在计算机上设置和使用多语言输入选项

protected override bool ProcessDialogChar(char charCode)
        {
base.Text += charCode;
return true;
}

Then display the input in OnPaint:

然后在OnPaint中显示输入:

protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            e.Graphics.DrawString(Text, Font, new SolidBrush(this.ForeColor), 
                new RectangleF(0, 0, this.Width, this.Height), StringFormat.GenericDefault);
        }

Now you have a control in which you can type something and it will display what you have hit. Writing a textbox is not so terrifying at all:)

现在,您可以在其中输入内容的控件,它将显示您所点击的内容。 编写文本框一点也不可怕:)

You can subclass and override the above methods from any kind of control. Then the control will be enabled to accept text input and display it. Of course you need to think about why you would do that.

您可以从任何控件中继承并覆盖上述方法。 然后,将启用该控件以接受文本输入并显示它。 当然,您需要考虑为什么要这么做。

I would not bore you out by the technical details. The TCTextBox currently supports:

我不会因技术细节而烦您。 TCTextBox当前支持:

Caret: I use Win32 functions to display a caret. You can draw a customized one if you like.

插入符号:我使用Win32函数显示插入符号。 如果愿意,可以绘制定制的图片。

Caret position: It will go up/down, left/right when an arrow key is pressed.

插入位置:按下箭头键时,它将向上/向下,向左/向右移动。

AutoScroll: If the text is longer than the height of the display window, it will automatically scroll up or down to put the current position in the viewport.

自动滚动:如果文本长于显示窗口的高度,它将自动向上或向下滚动以将当前位置放置在视口中。

Selection: You can select any length of text using mouse click and drag. The three properties: SelectionStart, SelectionLength, SelectionText, are supported.

选择:您可以使用鼠标单击和拖动来选择任意长度的文本。 支持三个属性:SelectionStart,SelectionLength,SelectionText。

Copy & Paste: You can either use short cut keys or context menu to interact with the system clipboard.

复制和粘贴:您可以使用快捷键或上下文菜单与系统剪贴板进行交互。

Background image: You can set an image in a TCTextBox as background. You can of course set your own BackColor, ForeColor, Font, Size to it. They are supported natively by the base class already.

背景图像:您可以将TCTextBox中的图像设置为背景。 当然,您可以为其设置BackColor,ForeColor,Font,Size。 它们已经由基类本地支持。

That’s all. The remaining features of the original TextBox have not been implemented. And the supported features have not been fully tested. Use it at your own risk.

就这样。 原始TextBox的其余功能尚未实现。 并且支持的功能尚未经过全面测试。 需要您自担风险使用它。

使用代码 (Using the Code)

After adding the source file TCText.cs into your project, you should be able to see a new component in toolbox. Then you can select and use it as normal controls in Visual Designer.

将源文件TCText.cs添加到项目中之后,您应该能够在工具箱中看到一个新组件。 然后,您可以选择它并将其用作Visual Designer中的常规控件。

The source code and a demo project can be downloaded from here:    TCTextBoxDemo.zip

可以从此处下载源代码和演示项目: TCTextBoxDemo.zip

And the simple drawing tool demonstrates the in-place editing:    TCPaint.exe

并且简单的绘图工具演示了就地编辑: TCPaint.exe

翻译自: https://www.experts-exchange.com/articles/4331/TCTextBox-A-Homemade-Textbox-supports-transparent-background.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值