问题
*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
Form
and drop aWebBrowser
control and aToolStrip
control on it, like what you see in above image.Add the following
.cs
file 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 Template
item 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
Load
event 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
Click
event of the search button and seach, and pass the search result to template and run the template and show the result inWebBrowser
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(); }
Handle
DocumentCompleted
event of theWebBrowser
and callInvokeScript
method ofDocument
object and callhighlight
javascript 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
123
in 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