开发者

Rich Text Box padding between text and border

I开发者_运维问答s it possible to add padding into a Rich Text Box control between the text and the border?

I tried docking a rich text box inside of a panel, with its padding for all four side set to 10 and that accomplished what I wanted. Except once the vertical scroll bar for the rich text box is needed that gets padded as well.


There are EM_GETRECT and EM_SETRECT.

Combining those two together, you can make this:

Rich Text Box padding between text and border

…look like this:

Rich Text Box padding between text and border

I've written a small C# extension class to wrap this all up.

Usage example:

const int dist = 24;
richTextBox1.SetInnerMargins(dist, dist, dist, 0);

This sets the inner margins left, top and right to 24, leaving the bottom as zero.

Please note that when scrolling, the top margin stays as being set, giving something like this:

Rich Text Box padding between text and border

Personally, this looks "unnatural" to me. I would prefer that when scrolling the top margin becomes zero, too.

Maybe there is a workaround for that…

Full source code

As of request:

public static class RichTextBoxExtensions
{
    public static void SetInnerMargins(this TextBoxBase textBox, int left, int top, int right, int bottom)
    {
        var rect = textBox.GetFormattingRect();

        var newRect = new Rectangle(left, top, rect.Width - left - right, rect.Height - top - bottom);
        textBox.SetFormattingRect(newRect);
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct RECT
    {
        public readonly int Left;
        public readonly int Top;
        public readonly int Right;
        public readonly int Bottom;

        private RECT(int left, int top, int right, int bottom)
        {
            Left = left;
            Top = top;
            Right = right;
            Bottom = bottom;
        }

        public RECT(Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom)
        {
        }
    }

    [DllImport(@"User32.dll", EntryPoint = @"SendMessage", CharSet = CharSet.Auto)]
    private static extern int SendMessageRefRect(IntPtr hWnd, uint msg, int wParam, ref RECT rect);

    [DllImport(@"user32.dll", EntryPoint = @"SendMessage", CharSet = CharSet.Auto)]
    private static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, ref Rectangle lParam);

    private const int EmGetrect = 0xB2;
    private const int EmSetrect = 0xB3;

    private static void SetFormattingRect(this TextBoxBase textbox, Rectangle rect)
    {
        var rc = new RECT(rect);
        SendMessageRefRect(textbox.Handle, EmSetrect, 0, ref rc);
    }

    private static Rectangle GetFormattingRect(this TextBoxBase textbox)
    {
        var rect = new Rectangle();
        SendMessage(textbox.Handle, EmGetrect, (IntPtr) 0, ref rect);
        return rect;
    }
}


The RichTextBox has no padding property.

Quick and dirty padding can be achieved by putting the RichTextBox in a Panel, which has the same BackColor property as the RichTextBox (usually Color.White).

Then, set the Dock property of the RichTextBox to Fill, and play with the Padding properties of the Panel control.


I had this same problem and the answer described didn't help me, this worked for me so i'll share it if it helps.

richTextBox1.SelectAll();
richTextBox1.SelectionIndent += 15;//play with this values to match yours
richTextBox1.SelectionRightIndent += 15;//this too
richTextBox1.SelectionLength = 0;
//this is a little hack because without this
//i've got the first line of my richTB selected anyway.
richTextBox1.SelectionBackColor = richTextBox1.BackColor;


A quick and easy way is to offset text from vertical scroll, by calling this example method at form load and at form/control resize events:

private void AdjustTextBoxRMargin()
{
    richTextBox1.RightMargin = richTextBox1.Size.Width - 35;
}

The value of 35 seems to work for Win7, but may differ on other versions of Windows.


Since RichTextBox has no padding property. You can create your own RichTextBoxSubclass like the one in this article:

http://www.codeproject.com/Articles/21437/A-Padded-Rich-Text-Box-Subclass


In the controltemplate the contentpart is this:

<ScrollViewer x:Name="PART_ContentHost" 
              Style="{StaticResource ScrollViewerTextBox}"
              VerticalAlignment="Top"/>`

Create a style (and controltemplate) for the scrollviewer; Set the MinWidth on the Grid column similar to the width of your scrollbar and adjust the margin to your preference on the ScrollContentPresenter.

<Style x:Key="ScrollViewerTextBox" TargetType="{x:Type ScrollViewer}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ScrollViewer}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition Width="Auto" MinWidth="18"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <ScrollContentPresenter Grid.Column="0" Margin="3 3 3 0" CanVerticallyScroll="True" CanContentScroll="True"/>
                    <ScrollBar x:Name="PART_VerticalScrollBar" 
                               Grid.Row="0" 
                               Grid.Column="1"
                               Value="{TemplateBinding VerticalOffset}" 
                               Maximum="{TemplateBinding ScrollableHeight}" 
                               ViewportSize="{TemplateBinding ViewportHeight}" 
                               Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}">
                        <ScrollBar.ContextMenu>
                            <ContextMenu Visibility="Hidden" />
                        </ScrollBar.ContextMenu>
                    </ScrollBar>
                    <ScrollBar x:Name="PART_HorizontalScrollBar" 
                               Orientation="Horizontal" 
                               Grid.Row="1" 
                               Grid.Column="0" 
                               Value="{TemplateBinding HorizontalOffset}" 
                               Maximum="{TemplateBinding ScrollableWidth}" 
                               ViewportSize="{TemplateBinding ViewportWidth}" 
                               Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}">
                        <ScrollBar.ContextMenu>
                            <ContextMenu Visibility="Hidden" />
                        </ScrollBar.ContextMenu>
                    </ScrollBar>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>


Maybe this is what you need?

richTextBox.SelectionIndent += 20;


Here's an even easier answer. It's not customizable, but it will put a small padding around the entire text -- top, bottom, left and right.

At design time, set the ShowSelectionMargin property of the RichTextBox to True. When you run, you might notice the margin being applied (from no margin to margin), which looks a little "jerkey". If so, put a Me.SuspendLayout in front of loading the RichTextBox, and put a Me.ResumeLayout after.


Here is a simple solution for setting the left and right margins of a RichTextBox that worked well for me in a C# Windows app. It sets both the right and left margins to 4 pixels.

[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hWnd, uint wMsg, UIntPtr wParam, IntPtr lParam);

// both left and right margins set to 4 pixels with the last parm: 0x00040004
SendMessage(richtextbox1.Handle, 0xd3, (UIntPtr)0x3, (IntPtr)0x00040004);

I tried to make the SendMessage more proper below:

const int EM_SETMARGINS = 0xd3;
const int EC_LEFTMARGIN = 0x1;
const int EC_RIGHTMARGIN = 0x2;

SendMessage(richtextbox1.Handle, EM_SETMARGINS,
 (UIntPtr)(EC_LEFTMARGIN | EC_RIGHTMARGIN), (IntPtr)0x00040004);

I figure this solution was not possible when the question was originally posted.


Perhaps you are looking to indent text? Like left and right indent? If so, then you could just use ReGEtIndent and ReSetIndent methods of the rtf object.

Here what I do:

//first I find the length of the active window

nLen := REGEtIndent( ::oActive:hWnd )    
//now resetIndents of the rtf control    
RESetIndent( ::oActive:hWnd, nLen[ 1 ] + 100, nLen[ 2 ] + 100, -25 )

Hope that helps.


Set the padding on the right to 0, and then set the RightMargin of the RichTextBox to 10. Not tested, but should work.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜