简体   繁体   English

在RichTextBox中获取滚动条“位置”并禁用滚动条

[英]Obtain scroll bar 'position' in RichTextBox with scroll bars disabled

My earlier post here shows how to obtain the position of the horizontal or vertical scrollbars in a RichTextbox. 我之前的帖子显示了如何在RichTextbox中获取水平或垂直滚动​​条的位置。 However, these only work if scrollbars are enabled. 但是,这些仅在启用滚动条时有效。 If you set scrollbars to None (via richTextBox1.ScrollBars = RichTextBoxScrollBars.None; ), then you can still scroll down off the bottom of the box (and off to the right if you disable WordWrap). 如果将滚动条设置为无(通过richTextBox1.ScrollBars = RichTextBoxScrollBars.None; ),则仍然可以向下滚动框的底部(如果禁用WordWrap则向右滚动)。 However, the getVerticalScroll() and getHorizontalScroll() methods (as shown in the link I posted) only return 0 now. 但是, getVerticalScroll()getHorizontalScroll()方法(如我发布的链接中所示)现在只返回0。 They seem to need to 'see' the scrollbars to actually work. 他们似乎需要“看到”滚动条才能真正起作用。

So how can I get (and set) the 'scroll position' whilst scroll bars are disabled? 那么当滚动条被禁用时,如何获取(并设置)“滚动位置”?

The RichTextBox class has several helper methods that lets you discover the position of text inside the window. RichTextBox类有几个辅助方法,可以让您发现窗口内文本的位置。 Which is what you need to use here since you don't have a direct feedback from a scrollbar anymore. 这是您需要在此处使用的内容,因为您不再需要滚动条的直接反馈。

You can find which line is displayed as the first visible line with RichTextBox.GetCharIndexFromPosition() to find the first visible character, followed by GetLineFromCharIndex() to figure out the line that contains that character: 你可以找到哪一行显示为RichTextBox.GetCharIndexFromPosition()的第一个可见行,以找到第一个可见字符,然后是GetLineFromCharIndex()以找出包含该字符的行:

    public static double GetVerticalScrollPos(RichTextBox box) {
        int index = box.GetCharIndexFromPosition(new Point(1, 1));
        int topline = box.GetLineFromCharIndex(index);
        int lines = box.Lines.Length;
        return lines == 0 ? 0 : 100.0 * topline / lines; 
    }

The horizontal scroll position can be found by looking on which line the caret is currently located. 通过查看插入符当前所在的行可以找到水平滚动位置。 And mapping the start of the line back to a position: 并将行的开头映射回位置:

    public static double GetHorizontalScrollPos(RichTextBox box) {
        int index = box.SelectionStart;
        int line = box.GetLineFromCharIndex(index);
        int start = box.GetFirstCharIndexFromLine(line);
        Point pos = box.GetPositionFromCharIndex(start);
        return 100 * (1 - pos.X) / box.ClientSize.Width;
    }

You may want to redefine what 100% means, your original question didn't give any guidance. 您可能想要重新定义100%的含义,您的原始问题没有给出任何指导。

This question has the aspects of an XY Problem and it smells that what you really want to do is to replace the scrollbars with bigger ones. 这个问题涉及XY问题的各个方面,它说你真正想做的是用更大的滚动条替换滚动条。 Don't overlook the silly simple solution, you can just overlay the existing ones by placing yours correctly so they overlap and hide them. 不要忽视这个愚蠢的简单解决方案,你可以通过正确放置它们来覆盖现有的解决方案,使它们重叠并隐藏它们。 You just need to change the border so it isn't so obvious. 你只需要改变边框,这样就不那么明显了。

I think you will find something interesting here . 我想你会在这里找到一些有趣的东西 It's description of RichEdit used behind RichTextBox in .Net. 它是在.Net中RichTextBox背后使用的RichEdit的描述。

Also solution of your question: 还解决了你的问题:

var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(POINT)));
Marshal.StructureToPtr(new POINT(), ptr, false);
SendMessage(this.richTextBox1.Handle, EM_GETSCROLLPOS, IntPtr.Zero, ptr);
var point = (POINT)Marshal.PtrToStructure(ptr, typeof(POINT));
Marshal.FreeHGlobal(ptr);

Where: 哪里:

EM_GETSCROLLPOS = WM_USER + 221

And POINT structure from pinvoke.net . 来自pinvoke.net的 POINT结构。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM