如何使RichTextBox呈现扁平化外观?

22

我正在开发一个WinForms智能客户端应用程序,其中使用了许多RichTextBox控件 - 由于各种原因,有些替代了常规的文本框。不幸的是,RichTextBox会绘制丑陋的Win95 3D边框,而不是主题化的XP或Vista风格边框。

请问是否有方法可以将主题化的边框应用到RichTextBox?我不介意为此目的子类化它们。

谢谢!

6个回答

42

这确实是一个技巧,但是你可以在页面上放置一个面板控件。将其BorderStyle设置为FixedSingle(默认情况下为None)。

将RichTextBox放入面板中,并将BorderStyle设置为无。然后将RichTextBox的Dock属性设置为Fill。

这将给您一个带有平坦边框的RichTextBox。


我遵循了这个建议,只是我使用了一个分组框。+1 - contactmatt

2

以前我必须使用一个面板来解决这个问题,其中文本框是组件内部的,设置了3或4像素的DockPadding。然后我会将该面板样式设置为单个像素。

我一直觉得这很烦人!


2
这真的很恼人,必须有更好的方法,因为这样做并不能真正呈现文本框的主题。 - grover
1
有时候我会想,为什么他们没有把BorderStyle叫做“TextBox”呢? :D - Momoro

1

这里是VB.NET代码,它将非客户区充气为-1,然后填充非客户区与淡蓝色。可以使用SharpDevelop 4.4将其转换为C#。我从这篇文章中得出了该代码:

http://www.codeproject.com/Articles/13723/Themed-RichTextBox-A-RichTextBox-with-XP-styled-bo

Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports System.Windows.Forms.VisualStyles
Imports System.Drawing
Imports System.Diagnostics

Public Class FlatRichTextBox
    Inherits RichTextBox

    Private BorderRect As RECT

    Sub New()
        If VisualStyleInformation.IsEnabledByUser Then
            BorderStyle = BorderStyle.None
        End If
    End Sub

    Protected Overrides Sub WndProc(ByRef m As Message)
        Const WM_NCPAINT = &H85
        Const WM_NCCALCSIZE = &H83
        Const WM_THEMECHANGED = &H31A

        Select Case m.Msg
            Case WM_NCPAINT
                WmNcpaint(m)
            Case WM_NCCALCSIZE
                WmNccalcsize(m)
            Case WM_THEMECHANGED
                UpdateStyles()
            Case Else
                MyBase.WndProc(m)
        End Select
    End Sub

    Private Sub WmNccalcsize(ByRef m As Message)
        MyBase.WndProc(m)

        If Not VisualStyleInformation.IsEnabledByUser Then Return

        Dim par As New NCCALCSIZE_PARAMS()
        Dim windowRect As RECT

        If m.WParam <> IntPtr.Zero Then
            par = CType(Marshal.PtrToStructure(m.LParam, GetType(NCCALCSIZE_PARAMS)), NCCALCSIZE_PARAMS)
            windowRect = par.rgrc0
        End If

        Dim clientRect = windowRect

        clientRect.Left += 1
        clientRect.Top += 1
        clientRect.Right -= 1
        clientRect.Bottom -= 1

        BorderRect = New RECT(clientRect.Left - windowRect.Left,
                              clientRect.Top - windowRect.Top,
                              windowRect.Right - clientRect.Right,
                              windowRect.Bottom - clientRect.Bottom)

        If m.WParam = IntPtr.Zero Then
            Marshal.StructureToPtr(clientRect, m.LParam, False)
        Else
            par.rgrc0 = clientRect
            Marshal.StructureToPtr(par, m.LParam, False)
        End If

        Const WVR_HREDRAW = &H100
        Const WVR_VREDRAW = &H200
        Const WVR_REDRAW = (WVR_HREDRAW Or WVR_VREDRAW)

        m.Result = New IntPtr(WVR_REDRAW)
    End Sub

    Private Sub WmNcpaint(ByRef m As Message)
        MyBase.WndProc(m)

        If Not VisualStyleInformation.IsEnabledByUser Then Return

        Dim r As RECT
        GetWindowRect(Handle, r)

        r.Right -= r.Left
        r.Bottom -= r.Top
        r.Top = 0
        r.Left = 0

        r.Left += BorderRect.Left
        r.Top += BorderRect.Top
        r.Right -= BorderRect.Right
        r.Bottom -= BorderRect.Bottom

        Dim hDC = GetWindowDC(Handle)
        ExcludeClipRect(hDC, r.Left, r.Top, r.Right, r.Bottom)

        Using g = Graphics.FromHdc(hDC)
            g.Clear(Color.CadetBlue)
        End Using

        ReleaseDC(Handle, hDC)
        m.Result = IntPtr.Zero
    End Sub

    <DllImport("user32.dll")>
    Public Shared Function GetWindowRect(hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
    End Function

    <DllImport("user32.dll")>
    Public Shared Function GetWindowDC(hWnd As IntPtr) As IntPtr
    End Function

    <DllImport("user32.dll")>
    Public Shared Function ReleaseDC(hWnd As IntPtr, hDC As IntPtr) As Integer
    End Function

    <DllImport("gdi32.dll")>
    Public Shared Function ExcludeClipRect(hdc As IntPtr, nLeftRect As Integer, nTopRect As Integer, nRightRect As Integer, nBottomRect As Integer) As Integer
    End Function

    <StructLayout(LayoutKind.Sequential)>
    Public Structure NCCALCSIZE_PARAMS
        Public rgrc0, rgrc1, rgrc2 As RECT
        Public lppos As IntPtr
    End Structure

    <StructLayout(LayoutKind.Sequential)>
    Public Structure RECT
        Public Left As Integer
        Public Top As Integer
        Public Right As Integer
        Public Bottom As Integer

        Public Sub New(left As Integer, top As Integer, right As Integer, bottom As Integer)
            Me.Left = left
            Me.Top = top
            Me.Right = right
            Me.Bottom = bottom
        End Sub
    End Structure
End Class

0

0
[另一个黑客(VB.NET)] 创建一个标签并添加代码:
Label backcolor = System.Drawing.Color.Transparent 
Label.BorderStyle = BorderStyle.FixedSingle
myRichTextBox.BringToFront
Label.Width=  myRichTextbox.Width + 4
Label.Height = myRichTextbox.Height + 4 
Label.left = myRichTextBox.left -2
Label.Top = myRichTextboxTop -2

希望能有所帮助 Vincenzo

-4
最简单的去除3D边框的方法是设置另一个边框:
richTextBox.BorderStyle = BorderStyle.FixedSingle;

FixedSingle 边框样式是最接近例如按钮的 FlatStyle 的样式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接