///<summary>Fills a memory address to quickly get the point of the char index within the RichTextBox from the Windows API wrapper. ///This is MUCH faster than using RichTextBox.GetPositionFromCharIndex().</summary> private Point GetPosFromCharIndex(int index) { int rawPointSize = Marshal.SizeOf(typeof(Point)); IntPtr wParam = Marshal.AllocHGlobal(rawPointSize); WindowsApiWrapper.SendMessage(this.Handle, (int)WindowsApiWrapper.EM_Rich.EM_POSFROMCHAR, (int)wParam, index); Point position = (Point)Marshal.PtrToStructure(wParam, typeof(Point)); Marshal.FreeHGlobal(wParam); return(position); }
private void PaintLineNumbers(Graphics g) { int lineNumberWidth = LineNumberWidth; //If the line number width has changed, we need to grow or shrink the left margin and repaint. if (lineNumberWidth != _lastLineWidth) { SetLeftMargin(lineNumberWidth + Margin.Left); _lastLineWidth = lineNumberWidth; WindowsApiWrapper.SendMessage(Handle, (int)WindowsApiWrapper.WinMessagesOther.WM_PAINT, 0, 0); return; } //Figure out how many total lines can be shown on the screen. int visibleLineCount = (int)Math.Ceiling((double)this.Bounds.Height / _lineNumberSize.ToSize().Height); int minLineCount = Math.Min(visibleLineCount, ListIndicesOfNewLines.Count); int firstLineNumber = ListIndicesOfNewLines.Count; int firstCharIndex = this.GetCharIndexFromPosition(new Point(1, 1)); int idx = 0; foreach (int index in ListIndicesOfNewLines) { idx++; if (firstCharIndex <= index) { firstLineNumber = idx; break; } } using (Bitmap doubleBufferer = new Bitmap(lineNumberWidth, this.Bounds.Height)) using (Graphics gDoubleBuffer = Graphics.FromImage(doubleBufferer)) { Rectangle rect = new Rectangle(0, 0, lineNumberWidth, this.Bounds.Height); gDoubleBuffer.FillRectangle(SystemBrushes.ControlLight, rect); int curNumberWidth = lineNumberWidth; for (int i = firstLineNumber; i <= ListIndicesOfNewLines.Count; i++) { int curPointY = 0; if (firstLineNumber != 1) { //Get the Y position of the character after the new line character of the previous line. curPointY = GetPosFromCharIndex(ListIndicesOfNewLines[i - 2] + 1).Y; //2 because we want the previous line and the list is 0 based } if (this.Bounds.Height <= curPointY) { break; } Rectangle rectDraw = new Rectangle(0, curPointY, curNumberWidth, _lineNumberSize.ToSize().Height); gDoubleBuffer.DrawString(firstLineNumber.ToString(), _lineNumberFont, _brushOlive, rectDraw, _stringFormatForDrawingNumbers); firstLineNumber++; } g.DrawImage(doubleBufferer, new Point(0, 0)); } }
///<summary>Nulls out variables so that the text boxes recalculate their contents on paint.</summary> private void LineNumberRecalculate() { _listIndicesOfNewLines = null; _lineNumberWidth = -1; WindowsApiWrapper.SendMessage(this.Handle, (int)WindowsApiWrapper.WinMessagesOther.WM_PAINT, 0, 0); }
public void SetScroll(int delta) { WindowsApiWrapper.SendMessage(this.Handle, (int)WindowsApiWrapper.EM_Rich.EM_LINESCROLL, 0, delta); }
private void SetLeftMargin(int widthInPixels) { WindowsApiWrapper.SendMessage(this.Handle, (int)WindowsApiWrapper.EM_Rich.EM_SETMARGINS, WindowsApiWrapper.EC_LEFTMARGIN, widthInPixels); }