Implementing "Find Next" in web browser control in C# - c#

I have a web browser control embedded in a form. Upon form load it loads a locally stored HTML file. I have implemented a find text functionality to find a particular text in the HTML document loaded in the web browser control. It is working for finding the first occurrence of the word specified.But I want to highlight all the occurrences of the specified word all at once or still better implementing something analogous to "Find Next" function found in various applications. Is it possible to do that for web browser control???
Here's the current code:
private void toolStripButton1_Click(object sender, EventArgs e)
{
string TextToFind;
TextToFind = toolStripTextBox1.Text;
if (webBrowser1.Document != null)
{
IHTMLDocument2 doc = webBrowser1.Document.DomDocument as IHTMLDocument2;
if (doc != null)
{
IHTMLSelectionObject currentSelection = doc.selection;
IHTMLTxtRange range = currentSelection.createRange() as IHTMLTxtRange;
if (range != null)
{
String search = TextToFind.ToString();
if (range.findText(search, search.Length, 2))
{
range.select();
}
}
}
}
}
Thanks.

You will find the the code sample for your question here MSDN Forums: WebBrowser Find Dialog
Hope that is exactly what you are looking for.

Just take input from the user in a textbox [here txtNoteSearch] and then follow the following code to implement the search. Following code demonstrates the search and highlight.
private void WebBrowser_DocumentCompleted(object sender, System.Windows.Forms.WebBrowserDocumentCompletedEventArgs e)
{
mshtml.IHTMLDocument2 doc2 = WebBrowser.Document.DomDocument;
string ReplacementTag = "<span style='background-color: rgb(255, 255, 0);'>";
StringBuilder strBuilder = new StringBuilder(doc2.body.outerHTML);
string HTMLString = strBuilder.ToString();
if (this.m_NoteType == ExtractionNoteType.SearchResult)
{
List<string> SearchWords = new List<string>();
SearchWords.AddRange(this.txtNoteSearch.Text.Trim.Split(" "));
foreach (string item in SearchWords)
{
int index = HTMLString.IndexOf(item, 0, StringComparison.InvariantCultureIgnoreCase);
// 'If index > 0 Then
while ((index > 0 && index < HTMLString.Length))
{
HTMLString = HTMLString.Insert(index, ReplacementTag);
HTMLString = HTMLString.Insert(index + item.Length + ReplacementTag.Length, "</span>");
index = HTMLString.IndexOf(item, index + item.Length + ReplacementTag.Length + 7, StringComparison.InvariantCultureIgnoreCase);
}
}
}
else
{
}
doc2.body.innerHTML = HTMLString;
}

Related

How to make interactive labels?

I'm trying to make a small application what will be used as a Template Manager. I would like to ask that how to do that in one user form it will show the data in the following way. Will check .xml file and what is inside tags will be shown one under the other. So lets say I have 5 items with this tag, so all 5 will be listed one under another.
I have something like this, but this is opening a new new MessageBox and showing them one by one.
private void button1_Click(object sender, EventArgs e)
{
string Username = System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString();
var str = Username;
var result = str.Length <= 4 ? "" : str.Substring(4);
string path = $"C:\\Users\\{result}\\Documents
XmlDocument doc = new XmlDocument();
doc.Load(path);
XmlTextReader xtr = new XmlTextReader(path);
while (xtr.Read())
{
if (xtr.NodeType == XmlNodeType.Element && xtr.Name == "name")
{
string string_title = xtr.ReadElementString();
// Console.WriteLine("Name = "+ s1);
MessageBox.Show("Title: " + Environment.NewLine + string_title);
}
}
I have a second from called Form2 for now, I can refer in this way as an example new Form2().Show(); but how do I make the lables on the form change according to what is in the xml file between specific tags?
Try this.
string string_title;
while (xtr.Read())
{
if (xtr.NodeType == XmlNodeType.Element && xtr.Name == "name")
{
string_title += xtr.ReadElementString() + Environment.NewLine;
// Console.WriteLine("Name = "+ s1);
}
}
MessageBox.Show("Title: " + string_title);
Guessing if you are calling form 2 from form 1 on the button click. You can do as below.
Inside button click.
var form2 = new Form2(string_title);
form2.show();
Inside form 2.
string dataFromForm1;
public Form2(string data) {
dataFromForm1 = data;
}
Inside form 2 show method.
public void show(){
MessageBox.Show("Title: " + dataFromForm1);
}

parsing an element in a div with html agility pack [C#]

I'm using Html Agility Pack on a website to extract some data. Parsing some of the HTML I need is easy but I am having trouble with this (slightly complex?) piece of HTML.
<tr>
<td>
<div onmouseover="toggle('clue_J_1_1', 'clue_J_1_1_stuck', '<em class="correct_response">Obama</em><br /><br /><table width="100%"><tr><td class="right">Kailyn</td></tr></table>')" onmouseout="toggle('clue_J_1_1', 'clue_J_1_1_stuck', 'Michelle LaVaughn Robinson')" onclick="togglestick('clue_J_1_1_stuck')">
...
I need to get the value from the em class "correct_response" in the onmouseover div based on the clue_J_X_Y value. I really don't know how to go beyond this..
HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes("//tr//td/div[#onmouseover]");
Some help would be appreciated.
I don't know what you're supposed to get out from the em. But I will give you all the data you say you need to figure it out.
First we load the HTML.
string html = "<tr>" +
"<td>" +
"<div onmouseover = \"toggle('clue_J_1_1', 'clue_J_1_1_stuck', '<em class="correct_response">Obama</em><br/><br/><table width="100%"><tr><td class="right">Kailyn</td></tr></table>')\" onmouseout = \"toggle('clue_J_1_1', 'clue_J_1_1_stuck', 'Michelle LaVaughn Robinson')\" onclick = \"togglestick('clue_J_1_1_stuck')\"></div></td></tr>";
HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
//Console.WriteLine(doc.DocumentNode.OuterHtml);
Then we get the value of the attribute, onmouseover.
string toggle = doc.DocumentNode.SelectSingleNode("//tr//td/div[#onmouseover]").GetAttributeValue("onmouseover", "FAILED");
It will return FAILED if it failed to find an attribute named "onmouseover". Now we get the parameters of the toggle method where each are enclosed by two '(apostrophe).
//Get Variables from toggle()
List<string> toggleVariables = new List<string>();
bool flag = false; string temp = "";
for(int i=0; i<toggle.Length; i++)
{
if (toggle[i] == '\'' && flag== true)
{
toggleVariables.Add(temp);
temp = "";
flag = false;
}
else if (flag)
{
temp += toggle[i];
}
else if (toggle[i] == '\'')
{
flag = true;
}
}
After that we have a list with 3 entities. In this case it will contain the following.
clue_J_1_1
clue_J_1_1_stuck
<em class="correct_response">Obama</em><br/><br/><table width="100%"><tr><td class="right">Kailyn</td></tr></table>;
Now we can create a new HtmlDocument with the HTML code from the third parameter. But first we have to convert it into workable HTML since the third parameter contains escape characters from HTML.
//Make it into workable HTML
toggleVariables[2] = HttpUtility.HtmlDecode(toggleVariables[2]);
//New HtmlDocument
HtmlDocument htmlInsideToggle = new HtmlDocument();
htmlInsideToggle.LoadHtml(toggleVariables[2]);
Console.WriteLine(htmlInsideToggle.DocumentNode.OuterHtml);
And done. The code in it's entirety is below from here.
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using HtmlAgilityPack;
using System.Web;
namespace test
{
class Program
{
public static void Main(string[] args)
{
string html = "<tr>" +
"<td>" +
"<div onmouseover = \"toggle('clue_J_1_1', 'clue_J_1_1_stuck', '<em class="correct_response">Obama</em><br/><br/><table width="100%"><tr><td class="right">Kailyn</td></tr></table>')\" onmouseout = \"toggle('clue_J_1_1', 'clue_J_1_1_stuck', 'Michelle LaVaughn Robinson')\" onclick = \"togglestick('clue_J_1_1_stuck')\"></div></td></tr>";
HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
//Console.WriteLine(doc.DocumentNode.OuterHtml);
string toggle = doc.DocumentNode.SelectSingleNode("//tr//td/div[#onmouseover]").GetAttributeValue("onmouseover", "FAILED");
//Clean up string
//Console.WriteLine(toggle);
//Get Variables from toggle()
List<string> toggleVariables = new List<string>();
bool flag = false; string temp = "";
for(int i=0; i<toggle.Length; i++)
{
if (toggle[i] == '\'' && flag== true)
{
toggleVariables.Add(temp);
temp = "";
flag = false;
}
else if (flag)
{
temp += toggle[i];
}
else if (toggle[i] == '\'')
{
flag = true;
}
}
//Make it into workable HTML
toggleVariables[2] = HttpUtility.HtmlDecode(toggleVariables[2]);
//New HtmlDocument
HtmlDocument htmlInsideToggle = new HtmlDocument();
htmlInsideToggle.LoadHtml(toggleVariables[2]);
Console.WriteLine(htmlInsideToggle.DocumentNode.OuterHtml);
//You're on your own from here
Console.ReadKey();
}
}

(C# WebBrowser) Why does "WebBrowser.Document" always returns null when reading PDF?

It doesn't matter if it is in WPF or Winform, because I tried both and the results were the same.
I am making a PDF reader by using WebBrower.
First of all, I added the reference and the directive "using mshtml".
Then I loaded the PDf file like this:
OpenFileDialog dlg = new OpenFileDialog() { Filter = "*.pdf(PDF file)|*.pdf" }; ;
if (dlg.ShowDialog() == DialogResult.OK)
{
webBrowser1.Navigate(dlg.FileName);
}
Then I tried to search for a string in the WebBrowser, which did not work:
if (webBrowser1.Document != null)
{
IHTMLDocument2 document = webBrowser1.Document.DomDocument as IHTMLDocument2;
if (document != null)
{
IHTMLSelectionObject currentSelection = document.selection;
IHTMLTxtRange range = currentSelection.createRange() as IHTMLTxtRange;
if (range != null)
{
const string search = "Privacy";//This string is in the PDF file;
if (range.findText(search, search.Length, 2))
{
range.select();
}
}
}
}
I also set a breakpoint at this line:
IHTMLSelectionObject currentSelection = document.selection;
But the breakpoint was never triggered, which means the variable "document" is always null. Why is that? Do I have to set a document property for the WebBrowser? I can't figure out what causes the problem.
I want to search for a string and then highlight it.
Thanks a lot.

How to search for a file in DataGgridView which is without database

My search function is happening now in a listbox.. i am populating all the files from a folder to a listbox.. and i am able to search for a filename accordingly from the listbox. But my real ideaa is to search from a gridview. So i need your help to modify this and search within my gridview.. How can i do that.
Need to search on basis of my column name Drawing_Number
snapshot of my gridview, I need to search for these files
Codes for searching inside a listbox
Code Snippet:
private void SrchBtn_Click(object sender, EventArgs e)
{
DirectoryInfo di = new DirectoryInfo(#"C:\St\Fabrication\Draft");
FileInfo[] fi = di.GetFiles();
if (textBox1.Text != "")
{
string search = textBox1.Text;
lbxResults.Items.Clear();
foreach (FileInfo curFile in fi)
{
if (curFile.Name.ToUpper().IndexOf(search.ToUpper()) != -1)
{
lbxResults.Items.Add(curFile.Name);
}
textBox1.Clear();
textBox1.Focus();
}
}
}
Able to search from a listbox..
snapshot of searched files coming in listbox
I need to convert this search to my gridview. How can i do this!!!
Try this method on your button click event. This will check the file is exist in the specified folder path in folderPath variable. System.IO.Directory.GetFiles(string path, string patern) function will find the files from the folder if the string matched and assign the value in the Drawing cell.
string folderPath = #"C:\St\Fabrication\Draft";
for (int i = 0; dataGridView1.Rows.Count; i++)
{
string strSearch = string.Format("*{0}*", dataGridView1.Rows[i].Cells["Drawing_Number"].Value);
string[] arrFiles = System.IO.Directory.GetFiles(folderPath, strSearch);
if (arrFiles.Length > 0)
{
dataGridView1.Rows[i].Cells["Drawing"].Value = arrFiles[0];
}
}
I found the answer..
it was a simple thing!!!
Here is the code:
(dataGridView1.DataSource as DataTable).DefaultView.RowFilter
= string.Format(#"`Drawing Number` LIKE '%{0}%' OR `Release Path` LIKE '%{0}%'", textBox1.Text);
dataGridView1.Focus();
textBox1.Focus();
int rowCount = dataGridView1.BindingContext[dt].Count;
if (rowCount == 0)
{
MessageBox.Show("No results");
}
I found the help from this link: Filtering DataGridView without changing datasource
Here is a sample that checks for a match and selects all rows that match.
Notes:
Your column name does not include a space as you wrote.
I show the number of matches in a Label.
The matches can be done with a few options. Pick what you need or give the user checkboxes..
private void textBox1_TextChanged(object sender, EventArgs e)
{
string columnName = "filename";
bool partial = false; // full comparison or only a substring is searched
bool includeExtensions = true; // include the file extension in the search
bool ignoreCase = true; // make the search case-(in)sensitive
string search = textBox1.Text;
if (ignoreCase) search = search.ToLowerInvariant();
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
string v = dataGridView1.Rows[i].Cells[columnName].Value.ToString();
if (ignoreCase) v = v.ToLowerInvariant();
string f = includeExtensions ?
Path.GetFileName(v) : Path.GetFileNameWithoutExtension(v);
if (partial) dataGridView1.Rows[i].Selected = (f.IndexOf(search) >= 0);
else dataGridView1.Rows[i].Selected = (f == search);
}
label1.Text = dataGridView1.SelectedRows.Count.ToString() + " files found.";
}

Gedcom Reader for C#

Does anyone know of a good class to read in .ged files
Gedcom is a file format that is used to store genealogical information.
My goal is to write something that would let me import a ged file and export a .dot file for graphviz so that I can make a visual representation of a family tree
thanks if you can help
Heres my best attempt so far.
It seems to be working for what i need though its defiently not full proof ( then again my family tree is rather large and that adds some complexity)
please let me know if you think i could make anything more elequient
struct INDI
{
public string ID;
public string Name;
public string Sex;
public string BirthDay;
public bool Dead;
}
struct FAM
{
public string FamID;
public string type;
public string IndiID;
}
List<INDI> Individuals = new List<INDI>();
List<FAM> Family = new List<FAM>();
private void button1_Click(object sender, EventArgs e)
{
string path = #"C:\mostrecent.ged";
ParseGedcom(path);
}
private void ParseGedcom(string path)
{
//Open path to GED file
StreamReader SR = new StreamReader(path);
//Read entire block and then plit on 0 # for individuals and familys (no other info is needed for this instance)
string[] Holder = SR.ReadToEnd().Replace("0 #", "\u0646").Split('\u0646');
//For each new cell in the holder array look for Individuals and familys
foreach (string Node in Holder)
{
//Sub Split the string on the returns to get a true block of info
string[] SubNode = Node.Replace("\r\n", "\r").Split('\r');
//If a individual is found
if (SubNode[0].Contains("INDI"))
{
//Create new Structure
INDI I = new INDI();
//Add the ID number and remove extra formating
I.ID = SubNode[0].Replace("#", "").Replace(" INDI", "").Trim();
//Find the name remove extra formating for last name
I.Name = SubNode[FindIndexinArray(SubNode, "NAME")].Replace("1 NAME", "").Replace("/", "").Trim();
//Find Sex and remove extra formating
I.Sex = SubNode[FindIndexinArray(SubNode, "SEX")].Replace("1 SEX ", "").Trim();
//Deterine if there is a brithday -1 means no
if (FindIndexinArray(SubNode, "1 BIRT ") != -1)
{
// add birthday to Struct
I.BirthDay = SubNode[FindIndexinArray(SubNode, "1 BIRT ") + 1].Replace("2 DATE ", "").Trim();
}
// deterimin if there is a death tag will return -1 if not found
if (FindIndexinArray(SubNode, "1 DEAT ") != -1)
{
//convert Y or N to true or false ( defaults to False so no need to change unless Y is found.
if (SubNode[FindIndexinArray(SubNode, "1 DEAT ")].Replace("1 DEAT ", "").Trim() == "Y")
{
//set death
I.Dead = true;
}
}
//add the Struct to the list for later use
Individuals.Add(I);
}
// Start Family section
else if (SubNode[0].Contains("FAM"))
{
//grab Fam id from node early on to keep from doing it over and over
string FamID = SubNode[0].Replace("# FAM", "");
// Multiple children can exist for each family so this section had to be a bit more dynaimic
// Look at each line of node
foreach (string Line in SubNode)
{
// If node is HUSB
if (Line.Contains("1 HUSB "))
{
FAM F = new FAM();
F.FamID = FamID;
F.type = "PAR";
F.IndiID = Line.Replace("1 HUSB ", "").Replace("#","").Trim();
Family.Add(F);
}
//If node for Wife
else if (Line.Contains("1 WIFE "))
{
FAM F = new FAM();
F.FamID = FamID;
F.type = "PAR";
F.IndiID = Line.Replace("1 WIFE ", "").Replace("#", "").Trim();
Family.Add(F);
}
//if node for multi children
else if (Line.Contains("1 CHIL "))
{
FAM F = new FAM();
F.FamID = FamID;
F.type = "CHIL";
F.IndiID = Line.Replace("1 CHIL ", "").Replace("#", "");
Family.Add(F);
}
}
}
}
}
private int FindIndexinArray(string[] Arr, string search)
{
int Val = -1;
for (int i = 0; i < Arr.Length; i++)
{
if (Arr[i].Contains(search))
{
Val = i;
}
}
return Val;
}
There is a very pretty one at Codeplex: FamilyShow (a WPF showcase). It imports/exports GEDCOM 5.5 and there is source.
I would actually have been surprised if there wasn't at least the beginnings of one. I found Gedcom.NET (sourceforge) quite easily
I'd be fairly surprised if there was a C# reader for this format available on the web, given that it's a fairly specialized format. On the upside, the format looks to be pretty straightforward to read if you need to create your own reader. I would suggest going down that path and coming back to SO if you have specific questions about the implementation. Take a look at the System.IO.StreamReader class; it's trivial to read in a file line-by-line that way, and parsing the individual lines should be simple as well.
Good luck!
I found a fresh project GedcomParser.

Categories

Resources