问题
*Sorry if the title is not great. I am not sure how to summarize this question into a few words.
I have a DataGridView and a search box. When the user types a query, any matching result in the DataGridView cells, is highlighted. To achieve this I use the CellPainting event of DataGridView and draw a rectangle behind the results.
Some of the cells are oriented Right-To-Left:
And some are oriented Left-To-Right:
When the orientation is RTL, I use the following formula to calculate the highlight rectangle X-coordinate:
e.CellBounds.Right - queryWidth - stringBeforeQueryWidth;
and stringBeforeQueryWidth refers to this:
When the orientation is LTR, I use the following formula:
e.CellBounds.Left + stringBeforeQueryWidth;
and stringBeforeQueryWidth refers to this:
The way I calculate stringBeforeQueryWidth is as follows:
var stringBeforeQuery = cellValue.Substring(0, cellValue.IndexOf(query));
var stringBeforeQueryWidth =
e.Graphics.MeasureString(stringBeforeQuery, font, e.CellBounds.Width, format).Width;
So when the orientation is RTL, I use the fact that all the characters that come before the query itself will be drawn to the right of it, and when the orientation is LTR, I use the fact that all the characters that come before the query itself will be drawn to the left of it.
The problem starts when the cell contains a string that combines LTR and RTL texts. For example:
Let's say the query is 13. To calculate stringBeforeQueryWidth I need the width of רחוב ישראל ישראלי and the width of /5. I cannot use cellValue.Substring(0, cellValue.IndexOf(query)) to retrieve them, like I did when there was only one orientation, because רחוב ישראל ישראלי comes before the query, and /5 comes after the query.
So how can I get the width of the part of the string that is located to the right of the query?
回答1:
Note: This is not a direct answer to the question. It's an alternative.
As an option, you can show the search result in a HTML table and display it in WebBrowser control and highlight the search text using javascript.
To show search result as HTML, I'll use use T4 Run-time Text Templates. This way I can pass data to the html template and render the report easily by assigning output string of the template to a DocumentText property of the WebBrowser control. I've used this idea for creating simple and fast print document, for example take a look at this post.
TO highlight the text, you can use some javascript code or plugins. For example you can take a look at this post.
Here is result of the example which I will share in this post:
Example
Create a
Formand drop aWebBrowsercontrol and aToolStripcontrol on it, like what you see in above image.Add the following
.csfile to the project and paste the following code in the file:namespace Sample { public class ReportModel { public string RTL { get; set; } public string LTR { get; set; } } }Add a new
RunTime Text Templateitem to the project and name itReportTemplate.tt. Open the file and paste the following content. Here I've used this plugin to highlight the text. And passed a model to the t4 template to easily generate 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>Handle
Loadevent of the form and turn off script errors and initialize sample data: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 متن" } , }; }Handle
Clickevent of the search button and seach, and pass the search result to template and run the template and show the result inWebBrowsercontrol: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(); }Handle
DocumentCompletedevent of theWebBrowserand callInvokeScriptmethod ofDocumentobject and callhighlightjavascript function which we have already created in the html:private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { var txt = searchTextBox.Text; if (!string.IsNullOrEmpty(txt)) webBrowser1.Document.InvokeScript("highlight", new object[] { txt }); }Run the application and type
123in the text box and press search button to see the result.
来源:https://stackoverflow.com/questions/54574412/width-of-string-to-the-right-of-a-point-in-a-bi-directional-text