RichTextBox CreateCaret 宽度测量 [英] RichTextBox CreateCaret Width Measurement

查看:48
本文介绍了RichTextBox CreateCaret 宽度测量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过为插入和覆盖模式创建插入符号来扩展富文本框.问题是测量的宽度太宽了.这在较大的字体大小上最为明显.

I'm extending the richtextbox by creating a caret for the insert and overwrite modes. The issue is that the width measured is too wide. This is most noticeable on larger font sizes.

SelectionFont.Height 返回的高度是正确的.有没有类似的 Width 属性?

The height returned from SelectionFont.Height is correct. Is there no similiar Width property?

如何准确测量指定字符ch的宽度?谁能举个例子?

How can I measure the width of the specified character ch accurately? Can anyone provide an example?

下面是转换成C#的代码,下面是VB.NET中的代码:

Below is the code converted to C#, and below that in VB.NET:

using System;

public class RichTextBoxCaret : RichTextBox
{
    [DllImport("user32.dll", CharSet=CharSet.Auto)]
    private extern static void CreateCaret(IntPtr hWnd, IntPtr hBitmap, int nWidth, int nHeight);

    [DllImport("user32.dll", CharSet=CharSet.Auto)]
    private extern static void ShowCaret(IntPtr hWnd);

    private bool mInsertKeyState = true;

    protected override void OnKeyDown(System.Windows.Forms.KeyEventArgs e)
    {
        base.OnKeyDown(e);

        if (e.KeyCode == Keys.Insert)
        {
            mInsertKeyState = !mInsertKeyState;
        }

        this.DrawCaret();
    }

    protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs mevent)
    {
        base.OnMouseUp(mevent);

        this.DrawCaret();
    }

    public void DrawCaret()
    {
        Size sz = new Size(0, 0);

        if (this.SelectionFont != null)
        {
            if (!mInsertKeyState && this.SelectionStart < this.TextLength)
            {
                using (Graphics g = this.CreateGraphics)
                {
                    using (Font f = new Font(this.SelectionFont.FontFamily, this.SelectionFont.Size, this.SelectionFont.Style, GraphicsUnit.Pixel, Convert.ToByte(0), false))
                    {
                        char ch = this.Text[this.SelectionStart];
                        sz.Width = Convert.ToInt32(g.MeasureString(ch, f).Width * this.ZoomFactor);
                    }
                }
            }

            sz.Height = Convert.ToInt32(this.SelectionFont.Height * this.ZoomFactor);
        }

        if (!sz.IsEmpty)
        {
            CreateCaret(this.Handle, IntPtr.Zero, sz.Width, sz.Height);
            ShowCaret(this.Handle);
        }
    }
}

对于 VB.NET:

Public Class RichTextBoxCaret
    Inherits RichTextBox

    <DllImport("user32.dll", CharSet:=CharSet.Auto)> _
    Private Shared Sub CreateCaret(ByVal hWnd As IntPtr, ByVal hBitmap As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer)
    End Sub

    <DllImport("user32.dll", CharSet:=CharSet.Auto)> _
    Private Shared Sub ShowCaret(ByVal hWnd As IntPtr)
    End Sub

    Private mInsertKeyState As Boolean = True

    Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
        MyBase.OnKeyDown(e)

        If e.KeyCode = Keys.Insert Then
            mInsertKeyState = Not mInsertKeyState
        End If

        Me.DrawCaret()
    End Sub

    Protected Overrides Sub OnMouseUp(ByVal mevent As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseUp(mevent)

        Me.DrawCaret()
    End Sub

    Public Sub DrawCaret()
        Dim sz As New Size(0, 0)

        If Me.SelectionFont IsNot Nothing Then
            If Not mInsertKeyState AndAlso Me.SelectionStart < Me.TextLength Then
                Using g As Graphics = Me.CreateGraphics
                    Using f As New Font(Me.SelectionFont.FontFamily, Me.SelectionFont.Size, Me.SelectionFont.Style, GraphicsUnit.Pixel, CByte(0), False)
                        Dim ch As Char = Me.Text.Chars(Me.SelectionStart)
                        sz.Width = CInt(g.MeasureString(ch, f).Width * Me.ZoomFactor)
                    End Using
                End Using
            End If

            sz.Height = CInt(Me.SelectionFont.Height * Me.ZoomFactor)
        End If

        If Not sz.IsEmpty Then
            CreateCaret(Me.Handle, IntPtr.Zero, sz.Width, sz.Height)
            ShowCaret(Me.Handle)
        End If
    End Sub
End Class

推荐答案

测量宽度已通过使用 GetPositionFromCharIndex 解决.

Measuring the width was resolved by using GetPositionFromCharIndex.

最终实现:

<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Private Shared Sub CreateCaret(ByVal hWnd As IntPtr, ByVal hBitmap As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer)
End Sub

<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Private Shared Sub ShowCaret(ByVal hWnd As IntPtr)
End Sub

Private mInsertKeyState As Boolean = True

Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
    MyBase.OnKeyDown(e)

    If e.KeyCode = Keys.Insert Then
        mInsertKeyState = Not mInsertKeyState
    End If

    Me.DrawCaret()
End Sub

Protected Overrides Sub OnMouseUp(ByVal mevent As System.Windows.Forms.MouseEventArgs)
    MyBase.OnMouseUp(mevent)

    Me.DrawCaret()
End Sub

Public Sub DrawCaret()
    Dim nHeight As Integer = 0
    Dim nWidth As Integer = 0

    If Me.SelectionFont IsNot Nothing Then
        nHeight = CInt(Me.SelectionFont.Height * Me.ZoomFactor)
    Else
        nHeight = CInt(Me.Font.Height * Me.ZoomFactor)
    End If

    If Not mInsertKeyState AndAlso Me.SelectionStart < Me.TextLength Then
        Dim p1 As Point = MyBase.GetPositionFromCharIndex(Me.SelectionStart)
        Dim p2 As Point = MyBase.GetPositionFromCharIndex(Me.SelectionStart + 1)

        nWidth = p2.X - p1.X
    End If

    CreateCaret(Me.Handle, IntPtr.Zero, nWidth, nHeight)
    ShowCaret(Me.Handle)
End Sub

这篇关于RichTextBox CreateCaret 宽度测量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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