c# - 在双向文本中,点右侧的字符串宽度

标签 c# string winforms right-to-left left-to-right

*如果标题不是很好,请见谅。我不确定如何用几句话来概括这个问题。


我有一个 DataGridView和一个搜索框。当用户键入查询时,所有匹配结果都在 DataGridView 中单元格,突出显示。为此,我使用 CellPainting DataGridView的事件并在结果后面画一个矩形。

一些单元格的方向是从右到左:

enter image description here

有些是从左到右的:

enter image description here

当方向为RTL时,我使用以下公式计算高亮矩形的X坐标:

e.CellBounds.Right - queryWidth - stringBeforeQueryWidth;

stringBeforeQueryWidth指的是这个:

enter image description here

当方向为LTR时,我使用以下公式:

e.CellBounds.Left + stringBeforeQueryWidth;

stringBeforeQueryWidth指的是这个:

enter image description here

我的计算方式stringBeforeQueryWidth如下:

var stringBeforeQuery = cellValue.Substring(0, cellValue.IndexOf(query));
var stringBeforeQueryWidth =
    e.Graphics.MeasureString(stringBeforeQuery, font, e.CellBounds.Width, format).Width;

因此,当方向为 RTL 时,我使用的事实是查询本身之前的所有字符都将绘制到它的右侧,而当方向为 LTR 时,我使用的事实是所有出现在查询本身之前的字符在查询本身将被绘制到它的左侧之前。

当单元格包含一个组合了 LTR 和 RTL 文本的字符串时,问题就开始了。例如: enter image description here

假设查询是 13 .计算stringBeforeQueryWidth我需要 רחוב ישראל ישראלי 的宽度和 /5 的宽度.我不能使用 cellValue.Substring(0, cellValue.IndexOf(query))检索它们,就像我在只有一个方向时所做的那样,因为 רחוב ישראל ישראלי出现在查询之前,/5出现在查询之后。

enter image description here

那么如何获取位于查询右侧的字符串部分的宽度?

最佳答案

Note: This is not a direct answer to the question. It's an alternative.

作为一个选项,您可以在 HTML 表格中显示搜索结果并将其显示在 WebBrowser 控件中,并使用 javascript 突出显示搜索文本。

要将搜索结果显示为 HTML,我将使用 T4 运行时文本模板。这样我就可以将数据传递给 html 模板,并通过将模板的输出字符串分配给 WebBrowser 控件的 DocumentText 属性来轻松呈现报告。我已经使用这个想法来创建简单快速的打印文档,例如看看 this post

要突出显示文本,您可以使用一些javascript 代码或插件。例如,您可以查看 this post

这是我将在本文中分享的示例的结果:

enter image description here

示例

  1. 创建一个 Form 并在其上放置一个 WebBrowser 控件和一个 ToolStrip 控件,如上图所示。

  2. 将以下.cs文件添加到项目中,并在文件中粘贴以下代码:

    namespace Sample
    {
        public class ReportModel
        {
            public string RTL { get; set; }
            public string LTR { get; set; }
        }
    }
    
  3. 向项目中添加一个新的RunTime Text Template 项并将其命名为ReportTemplate.tt。打开文件并粘贴以下内容。在这里,我使用 this plugin 来突出显示文本。并将模型传递给 t4 模板以轻松生成 HTML:

    <#@ template language="C#"#>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ parameter name="Model" type="System.Collections.Generic.List<Sample.ReportModel>"#>
    <!DOCTYPE html>
    <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=11" />
        <title></title>
        <style type="text/css">
            body { font-family: Calibri;}
            table { text-align:center; border-collapse: collapse;}
            table, th, td { border: 1px solid black; }
            th {background-color: #EEEEEE;}
            th , td {padding: 2px;}
            .container { width:100%; height:100%; }
            .highlight { background: yellow; }
            .rtl {direction: rtl; text-align: right;}
            .ltr {direction: ltr; text-align: left;}
        </style>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        <script src="https://johannburkard.de/resources/Johann/jquery.highlight-5.js"></script>
        <script>
        function highlight(text) {
            $('#container').highlight(text);
        }
        </script>
    </head>
    <body>
    <div id ="container" class="container">
    <table style="width:100%">
        <tr>
            <th style="width:50%">LTR</th>
            <th style="width:50%">RTL</th>
        </tr>
        <#
        foreach(var item in Model) 
        {
        #>
        <tr>
            <td class="ltr"><#=item.LTR#></td>
            <td class="rtl"><#=item.RTL#></td>
        </tr>
        <#
        }
        #>
    </table>
    <div>
    </body>
    </html>
    
  4. 处理表单的 Load 事件并关闭脚本错误并初始化示例数据:

    List<ReportModel> list;
    private void Form1_Load(object sender, EventArgs e)
    {
        webBrowser1.ScriptErrorsSuppressed = true;
        list = new List<ReportModel>()
        {
            new ReportModel(){ LTR = "Text 123 text", RTL = "متن 123 متن" }  ,
            new ReportModel(){ LTR = "Text 123 text", RTL = "متن 123 متن" }  ,
            new ReportModel(){ LTR = "Text 456 text", RTL = "متن 456 متن" }  ,
            new ReportModel(){ LTR = "Text 456 text", RTL = "متن 456 متن" }  ,
            new ReportModel(){ LTR = "Text 456 text", RTL = "متن 456 متن" }  ,
            new ReportModel(){ LTR = "Text 456 text", RTL = "متن 456 متن" }  ,
        };
    }
    
  5. 处理搜索按钮和搜索的Click事件,并将搜索结果传递给模板并运行模板并将结果显示在WebBrowser控件中:

    private void searchButton_Click(object sender, EventArgs e)
    {
        var txt = searchTextBox.Text;
        var rpt = new ReportTemplate();
        rpt.Session = new Dictionary<string, object>();
        rpt.Session["Model"] = list.Where(x => x.LTR.Contains(txt) ||
            x.RTL.Contains(txt)).ToList();
        rpt.Initialize();
        webBrowser1.DocumentText = rpt.TransformText();
    }
    
  6. 处理WebBrowserDocumentCompleted事件,调用Document对象的InvokeScript方法,调用highlight 我们已经在 html 中创建的 javascript 函数:

    private void webBrowser1_DocumentCompleted(object sender,
        WebBrowserDocumentCompletedEventArgs e)
    {
        var txt = searchTextBox.Text;
        if (!string.IsNullOrEmpty(txt))
            webBrowser1.Document.InvokeScript("highlight",
                new object[] { txt });
    }
    
  7. 运行应用程序并在文本框中键入 123,然后按搜索按钮查看结果。

关于c# - 在双向文本中,点右侧的字符串宽度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54574412/

相关文章:

vb.net - Winforms:获取发布版本号?

c# - 在 .Net Core 3.1 中使用 NetFwTypeLib 时发生内存泄漏

c# - 需要一些帮助来破译来自 .NET JITted 代码的一行汇编代码

c# - 为什么这种扩展方法不起作用?

c++ - 将输入字符串转换为 float / double C++

c# winform cool colordialog 收藏

c# - 从 Toast 通知激活时应用程序在启动时崩溃

javascript - 将单词(字符串)数组转换为正则表达式并使用它来匹配字符串

string - 软件/操作系统中存储的字母表顺序是什么级别?

c# - 如何在没有边框的情况下移动和调整窗体大小?