I am designing a word processor, my main mission is to emulate the functionality of a IntelliSense
but used for another purpose. To compose it I use a control Datagridview
and a Richtextbox
.
The pseudointellisense function appears when I open a bracket ( '[' ) and ends if I click on some of the filtered data in the datagridview or if I close the bracket ( ']' ). What I need is to create a hyperlink once I click on one of the options that are shown to me and when I make a key to a function.
What is the problem with all this?. The control richtextbox
has keywords to create links but these only work if the content is formatted as a link such as ...
And what I need to do is something like this
To be able to enter the text that I want and that is a hyperlink
Then I found the control's own RTF language (Rich Text Format). I didn't know it and from what I read it works like a kind of HTML. When trying to implement it, I don't end up using part of myself either because I lack knowledge of its use and because of the way I have coded the program.
Function that is called when writing on the Richtextbox
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (verificarDeCorchete)
{
char[] corchetes = new char[] { '[', ']' };
string where_buscador = VALOR_WHERE.TrimStart(corchetes);
textBox3.Text = where_buscador;
dt_gv.DataSource = connections.conn_database.SELECT($"SELECT * FROM tabla_de_nombres WHERE Descripcion LIKE '{textBox3.Text}%'");
if (dt_gv.Rows.Count > 0)
{
//Muestra el intellicense
dt_gv.Visible = true;
//Este codigo sirve para seguirle el rastro al carrete y
//asi el intellicense este donde se pueda ver
var o = Utility.GetCaretPoint(richTextBox1);
xpos = o.X;
ypos = o.Y;
textBox2.Text = Convert.ToString(xpos + "," + ypos);
dt_gv.BringToFront();
dt_gv.Location = new Point(xpos + 15, ypos + 30);
richTextBox1.Focus();
}
else
{
dt_gv.Visible = false;
}
}
}
Function that validates which character is being entered (to know when it is opening and closing brackets)
private void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
//Si es inicio de corchete activa el boleano
if (e.KeyChar.ToString() == "[")
{
verificarDeCorchete = true;
}
//Si es el final de corchete lo desactiva
else if (e.KeyChar.ToString() == "]")
{
verificarDeCorchete = false;
}
//Si el boleano esta activado o es el final de un corchete entra al if
//Se agrego la condicion del corchete cerrado para que lo pinte de rojo tambien.
if (verificarDeCorchete || e.KeyChar.ToString() == "]")
{
//Desactiva la vista del "Intellicense"
dt_gv.Visible = false;
//Pinta de rojo los colores dentro
richTextBox1.SelectionColor = Color.Red;
/*Si el valor del string es nulo agrega el caracter
* (esto pasa solo si es el primer caracter)*/
if (VALOR_WHERE == null)
{
VALOR_WHERE = e.KeyChar.ToString();
}
else
{
//Si el string es distinto a 0
if (VALOR_WHERE.Length != 0)
{
/*Esta condicion sirve para los backspace
al tocar esta tecla el programa lo leia como un caracter
(aunque no lo fuera) y rompia la logica y dejaba un string
mal escrito. Al hacer esto se borra el caracter (como pasa exactamente)*/
if (e.KeyChar.ToString() == "\b")
{
VALOR_WHERE = VALOR_WHERE.Remove(VALOR_WHERE.Length - 1);
}
else
{
VALOR_WHERE = VALOR_WHERE.Replace(VALOR_WHERE, VALOR_WHERE + e.KeyChar);
}
}
else
{
//Si es 0 copia el valor como pasa cuando es nulo.
VALOR_WHERE = e.KeyChar.ToString();
}
}
//Copia el valor en el textbox para pruebas. esto tiene que borrarse.
textBox1.Text = VALOR_WHERE;
}
else
{
//Cambia el color de la fuente si no es una busqueda especial.
richTextBox1.SelectionColor = Color.Black;
//Lo lleva a vacio para volver a usarse en otro momento.-
VALOR_WHERE = "";
}
}
With this function when clicking on any of the datagridview options it pastes it in the richtextbox. In this part the code that creates the link should be implemented. (In hyperlink I need it to call a function, not to enter a web page.)
private void dt_gv_CellClick(object sender, DataGridViewCellEventArgs e)
{
dt_gv.Visible = false;
verificarDeCorchete = false;
//Obtiene la posicion del carrete en ese momento
int caret_position = richTextBox1.GetCharIndexFromPosition(Utility.GetCaretPoint(richTextBox1));
int start_index = caret_position - VALOR_WHERE.Length;
int length = VALOR_WHERE.Length;
richTextBox1.Text = richTextBox1.Text.Remove(start_index, length);
string valor_seleccionado = dt_gv.CurrentCell.Value.ToString();
richTextBox1.Text = richTextBox1.Text.Insert(start_index, " " + valor_seleccionado + " ");
richTextBox1.Text = richTextBox1.Text.Replace("[", "");
richTextBox1.Text = richTextBox1.Text.Replace("]", "");
richTextBox1.SelectionStart = start_index + length + valor_seleccionado.Length;
}
When opening brackets
When clicking on some option (This should be a hyperlink)
Any ideas?
I found the solution to your question:
https://www.codeproject.com/Articles/9196/Links-with-arbitrary-text-in-a-RichTextBox
Whoever published that post seems to have modified the file that defines the DetectUrls property of the RichTextBox so that you can make any word a "hyperlink" capable of firing an event upon receiving a click.
If you download the source code for their project and use their "extended" RichTextBox, you'll be able to move on.
As a possible solution you can create a LinkLabel with the text you want and place it just above where you wanted to place the original hyperlink. Below is the approximate code to follow.
After finishing your code in the event
dt_gv_CellClick
we first need the location of the text we just inserted. We extract it as follows:Once this is done, the LinkLabel should be created, adjusted to the font of the RitchTextBox and placed just above the text you just added. Then we will control its method
LinkClicked
, which is the one that will be executed when clicking on itLinkLabel
:After this we will add the code of the method
LinkClicked
, here instead of calling a process to open the link, you can add the call to the function that you say:As a final note to say that yes, this solution is a bit "sloppy" and it is not optimal, in fact it would also be necessary to check that there is no more repeated text to locate the position correctly. Make sure you add the LinkLabel to the parent control of the correct RichTextBox, etc. But I think it is a solution that can work well, does not overload in terms of performance and gives the result you are looking for.