RichTextBox的:如何确定文本超出了控制范围延伸? - 水平滚动条出现时,它不应该发送EM_SETTARGETDEVICE,然后调整控制后, [英] RichTextBox: How to determine if text extends beyond the control bounds? - Horizontal Scrollbar appearing when it shouldn't after sending EM_SETTARGETDEVICE and then resizing the control

查看:616
本文介绍了RichTextBox的:如何确定文本超出了控制范围延伸? - 水平滚动条出现时,它不应该发送EM_SETTARGETDEVICE,然后调整控制后,的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经扩展了RichTextBox控件来实现许多在本地的RichEdit类提供缺少的功能。

I have extended the RichTextBox control to implement much of the missing functionality provided in the native RichEdit class.

我运行到哪里,如果控制设置换行到窗口或换行到打印机,即使它不应该当控制调整大小,水平滚动条出现的问题。

I'm running into an issue where if the control is set to wrap to the window or to wrap to printer the horizontal scrollbar appears even though it shouldn't when the control is resized.

骑自行车的换行来无回,并似乎解决了问题,但包装到打印机时,可以相对慢(即:速度过慢对每一个Resize事件调用)。

Cycling the wordwrap to none and back seems to resolve the problem but can be relatively slow when wrapping to a printer (ie: much too slow to call on every Resize event).

下面是我的换行code:

Here's my wordwrap code:

    private void ChangeWordWrap(WordWrap wordWrap)
    {   
        switch (wordWrap)
        {
            case WordWrap.NoWrap:
                {
                    User32.SendMessage(_RichTextBox.Handle, ApiConstants.EM_SETTARGETDEVICE, 0, 1);
                    break;                        
                }
            case WordWrap.WrapToPrintDocument:
                {
                    using (Graphics g = PrintDocument.PrinterSettings.CreateMeasurementGraphics(PrintDocument.DefaultPageSettings))
                    {
                        int lParam = ConvertEx.HundredthInchToTwips((PrintDocument.DefaultPageSettings.Bounds.Width - PrintDocument.DefaultPageSettings.Margins.Left - PrintDocument.DefaultPageSettings.Margins.Right));
                        IntPtr wParam = g.GetHdc();
                        User32.SendMessage(_RichTextBox.Handle, ApiConstants.EM_SETTARGETDEVICE, wParam, lParam);
                        g.ReleaseHdc();
                    }
                    break;                                                
                }
            case WordWrap.WrapToControl:
                {
                    User32.SendMessage(_RichTextBox.Handle, ApiConstants.EM_SETTARGETDEVICE, 0, 0);
                    break;
                }
        }
    }

Originially我想这个问题可能与这样的事实,我释放了图形处理,但问题还当我包装的控制和无柄是必要的发生。

Originially I thought the problem might be related to the fact I'm releasing the graphics handle but the issue also occurs when I'm wrapping to the control and no handle is needed.

添加截图:

正确的行为:

替代文字

不正确的行为(调整表格的之后的非常略):

Incorrect behavior (after resizing the form VERY slightly):

替代文字

环绕到窗口/无包code来自评论的的 http://msdn.microsoft.com/en-us/library/bb774282%28VS.85%29.aspx

The wrap to window/no wrap code came from a comment at http://msdn.microsoft.com/en-us/library/bb774282%28VS.85%29.aspx

*调用:: SendMessage消息(HWND,EM_SETTARGETDEVICE,NULL,0),将自动换行到窗口,并:: SendMessage消息(HWND,EM_SETTARGETDEVICE,NULL,1)将禁用自动换行完全。我不知道这是记录在其他地方。*

*Calling ::SendMessage(hwnd, EM_SETTARGETDEVICE, NULL, 0) will wrap text to the window, and ::SendMessage(hwnd, EM_SETTARGETDEVICE, NULL, 1) will disable word-wrap entirely. I'm not sure this is documented anywhere else.*

我的P / Invoke:

My p/invoke:

    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);

相关常量:

    public const int WM_USER = 0x400;
    public const int EM_SETTARGETDEVICE = (WM_USER + 72);

编辑:

我一直在研究这个更多,我相信.NET RichTextBox控件可能是发送SetScrollRange()与不正确的值时,控制调整大小。这将使意义,因为它不一定了解EM_SETTARGETDEVICE消息。

I've been researching this more and I believe the .NET RichTextBox control is probably sending a SetScrollRange() with incorrect values when the control is resized. Which would make sense since it doesn't necessarily know about the EM_SETTARGETDEVICE message.

我大概可以执行SetScrollRange()或东西调整大小后similiar但我的问题是,我不知道什么是正确的价值观会或者我怎么能去搞清楚了这一点。

I could probably execute SetScrollRange() or something similiar after a resize but my problem is that I have no idea what the correct values would be or how I could go about figuring that out.

另一件事我注意到的是,当这个问题是存在的,我可以调整控制,将实际包装中的文本大小。在这一点上的滚动条返回到正常状态,我可以调整,直到自动换行循环到无人能及了。

Another thing I've noticed is that when the problem is occuring I can resize the control to a size that would actually wrap the text. At this point the scrollbar goes back to a functional state and I can resize until the word wrap is cycled to none and back.

编辑:(同样是在我下面的非功能性的回答一些更详细)

(Also some more detail in my non-functional answer below)

看起来EM_GETRECT是不是因为它的大小改变控件大小改变时,我真正想要的。这里的MSDN说明:

It looks like EM_GETRECT is not what I actually want since it's size changes when the control size changes. Here's the MSDN description:

EM_GETRECT信息 获取编辑控件的格式化矩形。格式化矩形是限制矩形成控制绘制的文本。限制矩形是独立的编辑控制窗口的大小的。您可以发送该消息到任何一个编辑控件或丰富的编辑控件。

我最初的理解是,这是对整个文本的矩形,并从它我将能够确定客户端窗口较小的格式矩形,因此滚动条应该显示

My initial understanding was that this was the rectangle for the entire text and from it I would be able to determine if the client window was smaller that the formatting rectangle and thus a scrollbar should be shown.

看起来这格式化矩形的真正目的是为了使文本显示在一个面积比编辑控制小。(如:边距)

Looks like the real purpose of this formatting rectangle is to make the text display in an area smaller than the Edit Control (ie: margins).

新的问题:

那么,有没有一个矩形,这就是我想EM_GETRECT会给我吗?一个矩形,它会告诉我,有多宽的文字(包括跑出画面的一部分)是?举例来说,如果我有一个400像素的控制和文本行是800px长时间,我想要得到的800px值,这样我就可以把它比作控制宽度和显示/不显示滚动条。

So, is there a rectangle that is what I thought EM_GETRECT would give me? A rectangle that will tell me how wide the text (including the part that runs off the screen) is? For instance if I had a 400px control and a line of text that was 800px long I want to get the 800px value so I can compare it to control width and show/not show the scrollbar.

其实我不在乎关闭控制文本的长度这么多,因为我在乎知道如果文本超出控制的范围。

Actually I don't care about the length of the off-control text so much as I care about know IF text extends beyond the bounds of the control.

感谢所有帮助迄今。

推荐答案

我有什么样的工作,但它不是我真正想要的。

I've got something sort of working but it's not what I really want.

我真正想要的是让RichTextBox的做我想做的事情。相反,我让RichTextBox的做它想做什么,然后尝试在事后进行修复。这是一个健谈的解决方案,有时会导致滚动条闪烁。

What I really want is to make the RichTextBox do what I want it to do. Instead I am letting the RichTextBox do what it wants and then trying to fix it after the fact. It's a chatty solution and sometime results in the scrollbar flashing.

下面是我在做什么:

SCROLLINFO scrollinfo = new SCROLLINFO();
scrollinfo.cbSize = Marshal.SizeOf(scrollinfo);
scrollinfo.fMask = ApiConstants.SIF_ALL;
bool flag1 = User32.GetScrollInfo(_RichTextBox.Handle, ApiConstants.SB_HORZ, ref scrollinfo);

Logging.LogMessage("Resize - ScrollInfo: Max: " + scrollinfo.nMax + " Min: " + scrollinfo.nMin + " Page: " + scrollinfo.nPage + " Pos: " + scrollinfo.nPos + " TrackPos: " + scrollinfo.nTrackPos + " || RichtTextBox.RightMargin == " + _RichTextBox.RightMargin + " || RichTextBox.WordWrap == " + WordWrap + " / " + _RichTextBox.WordWrap + " Size: " + Size + " ClientRectangle: " + _RichTextBox.ClientSize);

switch (WordWrap)
{
    case WordWrap.WrapToControl:
    {
        if (scrollinfo.nMax > _RichTextBox.ClientSize.Width)
        {
            User32.ShowScrollBar(_RichTextBox.Handle, ApiConstants.SB_HORZ, false);
        }
        break;
    }
    case WordWrap.WrapToPrintDocument:
    {
        if (scrollinfo.nMax > _PrintableWidth)
        {
            User32.ShowScrollBar(_RichTextBox.Handle, ApiConstants.SB_HORZ, false);
        }
        break;
    }
}

WordWrap.WrapToControl 条件的逻辑被打破,我不知道如何解决它。的问题是,当在错误条件的最大滚动比的ClientSize大。然而,当文本实际上跑出画面(考虑左缩进)最大滚动也比的ClientSize大。

The logic in the WordWrap.WrapToControl condition is broken and I'm not sure how to fix it. The problem is that when in the error condition the max scroll is larger than the ClientSize. However when the text actually runs off the screen (consider a left indent) the max scroll is also larger than the ClientSize.

我想我也许可以使用 EM_GETRECT 消息来解决,但我仍然需要做更多的测试。这有可能是在 EM_GETRECT 解决方案还将努力为WrapToPrintDocument条件,但如果这样做,为什么不RichTextBox的已经做到这一点?真希望我能找出RichTextBox的是得到它的距离,因为这样我可能会使得RichTextBox控件做我想做而不需要第二个修复消息SCROLLINFO参数。

I think I might be able to solve this by using the EM_GETRECT message but I still need to do more testing. It's possible that the EM_GETRECT solution will also work for the WrapToPrintDocument condition but if it does why doesn't the RichTextBox already do this? Really wish I could find out where the RichTextBox was getting it's SCROLLINFO parameters from because then I could possibly make the RichTextBox control do what I want without the need for a second "fix" message.

请注意:我并不需要的情况下,以显示滚动条,因为RichTextBox的处理这部分罚款后,我隐藏它(的叹息的)

Note: I don't need cases to show the scrollbar since the RichTextBox handles that part fine after I hide it (sigh)

编辑:

看起来EM_GETRECT是不是因为它的大小改变控件大小改变时,我真正想要的。这里的MSDN说明:

It looks like EM_GETRECT is not what I actually want since it's size changes when the control size changes. Here's the MSDN description:

EM_GETRECT信息 获取编辑控件的格式化矩形。格式化矩形是限制矩形成控制绘制的文本。限制矩形是独立的编辑控制窗口的大小的。您可以发送该消息到任何一个编辑控件或丰富的编辑控件。

我最初的理解是,这是对整个文本的矩形,并从它我将能够确定客户端窗口较小的格式矩形,因此滚动条应该显示

My initial understanding was that this was the rectangle for the entire text and from it I would be able to determine if the client window was smaller that the formatting rectangle and thus a scrollbar should be shown.

看起来这格式化矩形的真正目的是为了使文本显示在一个面积比编辑控制小。(如:边距)

Looks like the real purpose of this formatting rectangle is to make the text display in an area smaller than the Edit Control (ie: margins).

新的问题:

那么,有没有一个矩形,这就是我想EM_GETRECT会给我吗?一个矩形,它会告诉我,有多宽的文字(包括跑出画面的一部分)是?举例来说,如果我有一个400像素的控制和文本行是800px长时间,我想要得到的800px值,这样我就可以把它比作控制宽度和显示/不显示滚动条。

So, is there a rectangle that is what I thought EM_GETRECT would give me? A rectangle that will tell me how wide the text (including the part that runs off the screen) is? For instance if I had a 400px control and a line of text that was 800px long I want to get the 800px value so I can compare it to control width and show/not show the scrollbar.

感谢所有帮助迄今。

这篇关于RichTextBox的:如何确定文本超出了控制范围延伸? - 水平滚动条出现时,它不应该发送EM_SETTARGETDEVICE,然后调整控制后,的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆