Ширина строки справа от точки в двунаправленном тексте - PullRequest
0 голосов
/ 07 февраля 2019

* Извините, если название не велико.Я не уверен, как можно обобщить этот вопрос в несколько слов.


У меня есть 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, я использую тот факт, что все символы, которые предшествуют самому запросу, будут нарисованы слева от него.

Проблема начинается, когда ячейка cсодержит строку, которая объединяет тексты LTR и RTL.Например: enter image description here

Скажем, запрос 13.Для вычисления stringBeforeQueryWidth мне нужна ширина רחוב ישראל ישראלי и ширина /5.Я не могу использовать cellValue.Substring(0, cellValue.IndexOf(query)) для их извлечения, как я делал, когда была только одна ориентация, потому что רחוב ישראל ישראלי предшествует запросу, а /5 идет после запроса.

enter image description here

Так, как я могу получить ширину части строки, которая расположена справа от запроса?

1 Ответ

0 голосов
/ 13 февраля 2019

Примечание: Это не прямой ответ на вопрос.Это альтернатива.

Как вариант, вы можете отобразить результат поиска в таблице HTML, отобразить его в элементе управления WebBrowser и выделить текст поиска с помощью JavaScript.

Комупоказывать результат поиска как HTML, я буду использовать T4 текстовые шаблоны времени выполнения .Таким образом, я могу передать данные в шаблон html и легко отобразить отчет, назначив выходную строку шаблона свойству DocumentText элемента управления WebBrowser.Я использовал эту идею для создания простого и быстрого документа для печати, например, взгляните на этот пост .

Чтобы выделить текст, вы можете использовать некоторый код JavaScript или плагины.Например, вы можете взглянуть на этот пост .

Вот результат примера, которым я поделюсь в этом посте:

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.Откройте файл и вставьте следующий контент.Здесь я использовал этот плагин , чтобы выделить текст.И передал модель в шаблон 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 control:

    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. Обработка DocumentCompleted события WebBrowser и вызова InvokeScript метода Document объекта и вызова highlight функции JavaScript, которую мы уже создали в html:

    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 в текстовое поле и нажмите кнопку поиска, чтобы увидеть результат.

...