I am creating a form which has a Multiline TextBox to enter an URL. Expected URLs will be very long.
User will paste the URL and move to next box.
Right now, TextBox shows ending part of the URL when user moves to next TextBox. I want such that it will show starting of URL (Domain name) instead of trailing part.
Current:
Expected:
And this should happen when user leaves the TextBox.
I tried various methods of Selection in textBox_Leave() event but I guess, these methods won't work if focus is lost.
I am using .Net framework 3.5.
Update: Textbox I am using is Multiline. Answers suggested by #S.Akbari and #Szer are perfect if the Mutliline property is set to False. I realized it late that Multiline will play such a significant role. Hence updating the question!
Use SelectionStart in the Leave event should works:
private void textBox1_Leave(object sender, EventArgs e)
{
textBox1.SelectionStart = 0;
}
Before:
After leaving TextBox:
Tried it and it works. Proof
public Form1()
{
InitializeComponent();
textBox1.LostFocus += TextBox1_LostFocus;
}
private void TextBox1_LostFocus(object sender, EventArgs e)
{
textBox1.SelectionStart = 0;
textBox1.SelectionLength = 0;
}
I can see how it doesn't work with the Multiline property set to true.
A simple API call can make this work:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
private const int WM_VSCROLL = 0x115;
private const int SB_TOP = 6;
void textBox1_Leave(object sender, EventArgs e) {
SendMessage(textBox1.Handle, WM_VSCROLL, (IntPtr)SB_TOP, IntPtr.Zero);
}
Related
i have use until now a methods for click button after i have click another button. (i click button "A" and it actives the button "B")
buttonDeleteFields.PerformClick();
Now, because I innovated design, i have replace this button with a icon (picturebox), but the method PerformClick, with a PictureBox, doesn't work. Can you give me a method that will resolve this problem?
( I click button "A" and it active the picturebox "B")
To fully emulate the Click event (as if the user has clicked the picture box),
Add these to your form class:
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
private int WM_LBUTTONDOWN = 0x0201;
private int WM_LBUTTONUP = 0x0202;
And call like this inside your button click event:
private void button1_Click(object sender, EventArgs e)
{
// OLD CODE: Used to perform click on button 2,
// before it was changed to a picture box
// buttonDeleteFields.PerformClick();
// new code, emulating picture box click:
SendMessage(pictureBoxDeleteFields.Handle, WM_LBUTTONDOWN, 0, 1);
SendMessage(pictureBoxDeleteFields.Handle, WM_LBUTTONUP, 0, 0);
}
You just need to call the method bound to the PictureBox.Click event in method button1_Click.
private void pictureBox1_Click(object sender, EventArgs e)
{
MessageBox.Show("123");
}
private void button1_Click(object sender, EventArgs e)
{
pictureBox1_Click(this.pictureBox1, e);
}
Let's say I have the same form opened multiple times but I want to control just one of them (one that f.e has "hello" as window title (text) <- to identify)
How do I manage to do that?
EDIT:
Here is an example of what I want to do (it's a bit complicated, im not good at explaining what I want)
private void openthesecformfirst_Click(object sender, EventArgs e)
{
Form2 sec = new Form2();
sec.Text = "Hi";
sec.Show();
//The second form is now opened
}
private void openthesecformsecond_Click(object sender, EventArgs e)
{
Form2 sec = new Form2();
sec.Text = "Hello";
sec.Show();
//the second form is now opened twice
}
private void changelabelinfirst_Click(object sender, EventArgs e)
{
//Identified by the title the first opened form2 is supposed to change a label text
//How do I get this one specifically?
}
private void changelabelinsecond_Click(object sender, EventArgs e)
{
//Identified by the title the second opened form2 is supposed to change a label text
//How do I get this one specifically?
}
For find window in OS Windows you can use FindWindowEx from the Win32 Api, for example:
Because this is original unsafe code you should import functions from user32.dll:
[DllImport("user32.dll", SetLastError = true)] static extern IntPtr
FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,
string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr
childAfter,
string className, string windowTitle);
After import you can use function like that:
var CaptionTextForLooking = "hello"; // or "Hi"
var foundWindowPtr =
FindWindowEx(IntPtr.Zero,IntPtr.Zero,CaptionTextForLooking
,IntPtr.Zero);
More you can find here
You can use the Application.OpenForms property.
I have a listview control on my WinForms application.
here, on click of separate button, i do change couple of listview items backcolor and reload the whole grid as there are certain changes into database so, reloading from database on each click of button.
Now, problem is, once the grid is reloaded then lastly added items are scrolled so, need to scroll all items and find so, it makes hard to end user.
Is there any way to ,scroll the lastly added items or updated items into listview automatically (I mean, programmatically so, it could be view to user directly without being manually scrolled).
listView1.EnsureVisible(X);
where X is the item index.
This snippet can be used to scroll the ListView automatically to a particular index in the listView.
Consider the code: with this you can automatically scroll to the index 8 on button click
private void button2_Click(object sender, EventArgs e)
{
listView1.EnsureVisible(8);
}
Despite #user3711357 correct answer, I spent too much time trying to understand why it is not working for me.
I found that trying to call EnsureVisible in the constructor of the form will not work.
public class MyForm
{
public MyForm()
{
InitializeComponent();
listView1.EnsureVisible(8); // will not work !!!
}
private void MyForm_Load(object sender, EventArgs e)
{
listView1.EnsureVisible(8); // Works fine
}
}
Before you refresh the list, store the currently focussed or selected item (depending on how your interaction code works) into a variable, then you can restore the selected item afterwards. For example;
Dim selectedObjectName = listview.SelectedItems(0).Name
...
' refresh your list
...
Dim vItem as ListViewItem
If listview.SelectedItem.ContainsKey(selectedObjectName) Then
vItem = listview.Items(selectedObjectName)
Else
vItem = listview.Items(0)
End If
vItem.Selected = True
vItem.Focus
Can send messages directly.
public partial class Form1 : Form
{
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
public Form1()
{
InitializeComponent();
c_scroll.ScrollSlide += C_scroll_ScrollSlide;
}
private void C_vScrollBar_Scroll(object sender, ScrollEventArgs e)
{
const int LVM_SCROLL = (0x1000 + 20);
SendMessage(c_listView_show.Handle, LVM_SCROLL, 0, e.NewValue - e.OldValue);
}
}
Firstly, I apologize if the title does not make much sense, as I did not know the best way to explain it.
Now to really explain it. What I have done is created a control in a Class Library project in Visual Studio 2013. This control is supposed to act as the caption bar for form that is set with the "FormBorderStyle" as "None". This imitation caption bar control is supposed to move the form, just like a normal forms' caption bar would.
I have achieved this, but only in the forms code. This is the code I use:
private int mouseStartX, mouseStartY;
private int formStartX, formStartY;
private bool FormDragging = false;
private void titleBar_MouseDown(object sender, MouseEventArgs e)
{
this.mouseStartX = MousePosition.X;
this.mouseStartY = MousePosition.Y;
this.formStartX = this.Location.X;
this.formStartY = this.Location.Y;
FormDragging = true;
}
private void titleBar_MouseMove(object sender, MouseEventArgs e)
{
if (FormDragging)
{
this.Location = new Point(
this.formStartX + MousePosition.X - this.mouseStartX,
this.formStartY + MousePosition.Y - this.mouseStartY
);
}
}
private void titleBar_MouseUp(object sender, MouseEventArgs e)
{
FormDragging = false;
}
"this.*" is obviously referring to the form, when in the forms code. So of course, if I were to simply put this into the controls code, it'd obviously be referring to the control, and thus the control would be the one moving around on the form.
I've also created a control in the Class Library that acts as a close button. All I had to do was:
Form.ActiveForm.Close();
Same for minimize being:
Form.ActiveForm.WindowState = FormWindowState.Minimized;
And maximize being:
Form.ActiveForm.WindowState = FormWindowState.Maximized;
On the controls' click events.
When I try to replace "this." with "Form.ActiveForm.", in the first code posted - it returns this error:
'System.Windows.Forms.Form' does not contain a definition for 'mouseStarX' and no extension method 'mousStartX' accepting a first argument of type 'System.Windows.Forms.Form' could be found (are you missing a using directive or an assembly reference?)
That's about it, I don't know how else to go about this.
There is a simple pinvoke you can use to move the form via your control.
Adapted from C# - Make a borderless form movable?, instead of using Form.ActiveForm, you would use this.FindForm() to get the parent form of the control. It's used here to pass the form's handle value:
public class MyHeader : Control {
private const int WM_NCLBUTTONDOWN = 0xA1;
private const int HT_CAPTION = 0x2;
[DllImportAttribute("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, int Msg,
int wParam, int lParam);
[DllImportAttribute("user32.dll")]
private static extern bool ReleaseCapture();
protected override void OnMouseDown(MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
ReleaseCapture();
SendMessage(this.FindForm().Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
base.OnMouseDown(e);
}
}
For closing the form, you would use the same method:
this.FindForm().Close();
I am subclassing TextBox:
class Editor : TextBox
I have overridden OnKeyDown, because I want tabs to be replaced by four spaces:
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab) {
SelectedText = " ";
e.SuppressKeyPress = true;
}
}
This works, but unfortunately it also clears the undo buffer. The end result is that when the user presses tab, Ctrl+Z doesn't work and 'Undo' on the right-click menu becomes disabled. The problem appears to be the "e.SuppressKeyPress = true;" part.
Does anyone have any idea of how to get around this?
For more info, I am creating a fairly simple text editor, and I'm handling not only the Tab key (as above), but also the Enter key. So I have this problem with Tab and Enter. I am aware that this problem doesn't exist with RichTextBox, but for various reasons I want to use TextBox instead.
Any help would be much appreciated, as this is a show-stopping problem in my project.
Thanks,
Tom
This isn't a result of overriding OnKeyDown, it's that you're setting SelectedText (any text modification will have the same effect). You can see this by commenting out your code that sets the SelectedText while leaving everything else. Obviously you won't get a tab or four characters, but the undo buffer will be preserved.
According to this blog post, you should be able to use the Paste(string) function rather than setting the SelectedText property and preserve the undo buffer:
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab)
{
Paste(" ");
e.SuppressKeyPress = true;
}
}
I've finally found the solution, which is to use the Windows API as follows:
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab) {
WinApi.SendMessage(Handle, WinApi.WmChar, WinApi.VkSpace, (IntPtr)4);
e.SuppressKeyPress = true;
}
base.OnKeyDown(e);
}
Here is my WinApi class:
using System;
using System.Runtime.InteropServices;
class WinApi
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
public const UInt32 WmChar = 0x102;
public static readonly IntPtr VkSpace = (IntPtr)0x20;
}