Windows forms - catch pressed key in main form - c#

I have this:
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
private void Form1_Load(object sender, EventArgs e)
{
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "notepad";
info.UseShellExecute = true;
var process = Process.Start(info);
Thread.Sleep(2000);
SetParent(process.MainWindowHandle, this.Handle);
}
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
MessageBox.Show("asd");
}
Now, whenever I press a key while Form1 has focus, it detects it just fine. But when I start typing text in notepad - Form1 doesn't see the keys I press. How can I make that Form1 can catch the keys I press?

What you need is a keylogger kind of software. It works even if the form is not focused. Check this link out. It should be able to help you.
http://null-byte.wonderhowto.com/how-to/create-simple-hidden-console-keylogger-c-sharp-0132757/

Related

Control one form that is opened multiple times

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.

SetParent not Working InvalidOperationException

I recently tried to work on an old project I had an i am not able to get the setparent to work it keeps giving me the "InvalidOperationException" error, here is the code:
private void button1_Click(object sender, EventArgs e)
{
Process proc = Process.Start("calc.exe");
proc.WaitForInputIdle();
Thread.Sleep(500);
SetParent(proc.MainWindowHandle, this.Handle);
}
Its being called with a button and when it tries to set the parent it errors out. Everything i can find online say that my code is right.
This code below is working fine on my side (Please check the declaration of your Windows API function SetParent):
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
private void button1_Click(object sender, EventArgs e)
{
Process proc = Process.Start("calc.exe");
proc.WaitForInputIdle();
Thread.Sleep(500);
SetParent(proc.MainWindowHandle, this.Handle);
}
Result:
Hope that helps :)

Showing starting text of Mulitline TextBox when focus is changed

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);
}

Hotkey not working on form load

I have one class to register/unregister hotkey. It works perfectly when application start with Form Load event.
private Hotkey myHotKey;
private IntPtr thisWindow;
private void Form1_Load(object sender, EventArgs e)
{
thisWindow = FindWindow(null, "Form1");
myHotKey = new Hotkey(thisWindow);
myHotKey.RegisterHotKeys();
}
Now problem is I want to hide application in system tray at start but its not registering my host key , When I run below code it is displaying me successfully Notify() and other things except my hotkey have no effect.:
public Form1()
{
InitializeComponent();
notifyIcon1.ContextMenuStrip = contextMenuStrip1;
notifyIcon1.Click += notifyIcon1_Click;
notifyIcon1.DoubleClick += notifyIcon1_DoubleClick;
openToolStripMenuItem.Click += openToolStripMenuItem_Click;
exitToolStripMenuItem.Click += exitToolStripMenuItem_Click;
Notify("Application Name", "Application Started...", 1000);
thisWindow = FindWindow(null, "Form1");
myHotKey = new Hotkey(thisWindow);
myHotKey.RegisterHotKeys();
}
Can you please guide me what I am doing wrong. Thank you
Thanks guys for help, I came across this example which explained everything in better way:
http://www.pinvoke.net/default.aspx/user32/RegisterHotKey.html
hotkey = new GlobalHotkeys();
hotkey.RegisterGlobalHotKey( (int) Keys.F11, GlobalHotkeys.MOD_CONTROL, this.Handle);

Minimizing the application form causes a modal form to close, but not a MessageBox

If I programatically minimize the application's form while a modal dialog is open, that modal dialog gets closed.
However, if I programatically minimize the application's form while a MessageBox is open, the MessageBox is not closed (i.e. when I restore the application to normal window state, the message box is still showing).
Here's my sample code demonstrating the difference:
public partial class Form1 : Form
{
// ...
private void showMessageBoxBtn_Click(object sender, EventArgs e)
{
timer1.Start();
// This MessageBox does *not* get closed when the WindowState of Form1 is set to minimized in timer1_Tick
MessageBox.Show(this, "MessageBox");
}
private void formShowDialogBtn_Click(object sender, EventArgs e)
{
timer1.Start();
// This form gets closed when the WindowState of Form1 is set to minimized in timer1_Tick
Form2 form2 = new Form2();
form2.ShowDialog();
}
private void timer1_Tick(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
timer1.Stop();
}
}
Question:
Is there a way to get the Form to behave like the MessageBox?
What you are seeing is the side-effect of countermeasures built in to Winforms to deal with dialog usability problems, countermeasures that the MessageBox() function doesn't have. They were probably more relevant to Windows 98, originally an important target operating system for Winforms, too long ago for me to remember accurately.
An important usability problem is what happens when you show a dialog and it gets minimized. A dialog disables all other windows in the app so you can no longer activate them. The dialog should have its ShowInTaskbar property set to false. The user now has a problem, there is no simple way to get back to the dialog. Nothing to click on.
Winforms avoids this trap by automatically closing the dialog. As you can tell, MessageBox doesn't do this. It can not reasonably do this either, it doesn't have a good way to return a "dialog was canceled" status code.
Notable is that this trap still partially exists. On my Win8 machine, I can click the disabled form's taskbar button and get it to move back in the foreground. But that activates the disabled form instead of the message box. Major UI blooper there and nasty if the message box is behind that form.
So to answer your question: no. Feature, not a bug.
First, declare the Form2 form variable outside the method's scope, so it could be reachable from the timer1_tick method. Then, when the Timer ticks, minimize the main form, but show the modal dialog and then minimize it.
Try this:
Form2 form2;
private void timer1_Tick(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
form2.Show();
form2.WindowState = FormWindowState.Minimized;
timer1.Stop();
}
Matt,
Try changing:
form2.ShowDialog();
to
form2.Show(this);
Is this the behavior you are looking for?
You can try something like this:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication37
{
public partial class Form1 : Form
{
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern IntPtr GetParent(IntPtr hWnd);
Form2 form2 = null;
IntPtr parent = IntPtr.Zero;
public Form1()
{
InitializeComponent();
}
private void formShowDialogBtn_Click(object sender, EventArgs e)
{
timer1.Start();
// This form gets closed when the WindowState of Form1 is set to minimized in timer1_Tick
form2 = new Form2();
form2.ShowDialog();
}
private void timer1_Tick(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
timer1.Stop();
}
private void Form1_Resize(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
this.parent = GetParent(form2.Handle);
SetParent(form2.Handle, IntPtr.Zero);
form2.Hide();
}
else
{
SetParent(form2.Handle, this.parent);
form2.ShowDialog();
}
}
}
}
Please note that this is somewhat an hack, I'm not totally sure about consequences. Criticism is acceptable :)
If you set
Visible = true;
on the modal form immediately after programmatically minimizing the owner from, the modal form does not get killed by the OS.
So
ownerForm.WindowState = FormWindowState.Minimized;
will kill the modal form. But
ownerForm.WindowState = FormWindowState.Minimized;
modalForm.Visible = true;
will not kill it.

Categories