I am creating application that runs another app inside panel.
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
public Form3() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
Process p = Process.Start(#"path\app.exe");
Thread.Sleep(200); // Allow the process to open it's window
SetParent(p.MainWindowHandle, panel1.Handle);
}
But the problem is, that app.exe sometimes (I know when) creates new window as a new app. I want to add this new window into new panel.
private Process GetProcess() {
//do some magic stuff and find actually running app
return NewAppProcess;
}
private void button2_Click(object sender, EventArgs e) {
Process p = GetProcess();
SetParent(p.MainWindowHandle, panel2.Handle);
}
Thanks for everything that can push me to right way
Using ManagementEventWatcher, you can watch Win32_ProcessStartTrace to receive an event when a new process starts.
Example
In this example, I shows how you can watch starting of mspaint.exe and adding it as child of a Panel in your form. To so add a reference to System.Management dll to your project and then use the following code.
Note 1: The watcher is not super fast and you probably see the the window opens in desktop and then sits in the panel.
Note 2: It's an example and showing hot to do it with mspaint.exe. If you have any problem applying the solution on your real app.exe, you need to specifically ask about the solution for your app.exe.
Note 3: Make sure you run your as administrator.
using System.Management;
using System.Runtime.InteropServices;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
ManagementEventWatcher watcher;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
watcher = new ManagementEventWatcher(
"Select * From Win32_ProcessStartTrace Where ProcessName = 'mspaint.exe'");
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcher.Start();
}
void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
var id = (UInt32)e.NewEvent["ProcessID"];
var process = System.Diagnostics.Process.GetProcessById((int)id);
this.Invoke(new MethodInvoker(() => {
SetParent(process.MainWindowHandle, panel1.Handle);
}));
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
watcher.Stop();
watcher.Dispose();
base.OnFormClosed(e);
}
}
Related
I have found many pages describing how to prevent the blinking caret. Looks simple enough.
[DllImport("user32")]
public static extern bool HideCaret(IntPtr hWnd);
private void OnFocusEnterSpecificTextbox(object sender, EventArgs e)
{ HideCaret(SpecificTextbox.Handle); }
It's not working. When I click on the Textbox, there's the caret. I can breakpoint and see that I am hitting that code.
What boneheaded mistake am I making?
This works (VS 2008 on Windows 7):
public partial class Form1 : Form
{
[DllImport("user32")]
public static extern bool HideCaret(IntPtr hWnd);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
textBox1.GotFocus += new EventHandler(textBox1_GotFocus);
}
void textBox1_GotFocus(object sender, EventArgs e)
{
HideCaret(textBox1.Handle);
}
}
Here's another way to stop blinking cursor in TextBox:
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern bool HideCaret(IntPtr hWnd);
public Form1()
{
InitializeComponent();
textBox1.GotFocus += (s1, e1) => { HideCaret(textBox1.Handle); };
}
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have 3 form: A, B, C
Form1 A;
Form2 B, C;
A is parent of B and C
public partial class Form1 : Form
{
Form2 formB = null;
Form2 formC = null;
public Form1()
{
InitializeComponent();
formB = new Form2();
formB.Owner = this;
formC = new Form2();
formC.Owner = this;
}
private void showBC_Click(object sender, EventArgs e)
{
formB.Visible = true;
formC.Visible = true;
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void hide_Click(object sender, EventArgs e)
{
this.Hide();
}
}
When application start, form A is show.
I open another program (ex: cmd), to active cmd window
I click on form A, to active form A
I click on button ShowBC -> showBC_Click
Form B and C is shown
I click button hide on C then B is actived
I click button hide on B and I hope A is active (you think so?)
cmd window is active
// ==============================================
#Sinatr
I have same problem with only A and B form
public partial class Form1 : Form
{
Form2 formB = null;
public Form1()
{
InitializeComponent();
formB = new Form2();
formB.Owner = this;
}
private void showB_Click(object sender, EventArgs e)
{
formB.Visible = true;
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void hide_Click(object sender, EventArgs e)
{
this.Hide();
}
private void MsgBox_Click(object sender, EventArgs e)
{
MessageBox.Show("Test");
}
}
When application start, form A is show.
I open another program (ex: cmd), to active cmd window
I click on form A, to active form A
I click on button ShowB -> showB_Click
Form B is shown
I click button MsgBox on form B
MessageBox "Test" is shown
I click button OK on MessageBox
Messagebox is closed
I click button hide on B and I hope A is active (you think so?)
cmd window is active
I expect A is active in the final step
Solution:
Because some child window is not form, like SelectColor Dialog, .. so I need to use win32 api to list child window to active them.
In every child form I need to do that:
[DllImport("user32.dll")]
private static extern IntPtr GetTopWindow(IntPtr parentHandle);
private static uint GW_HWNDNEXT = 2;
[DllImport("user32.dll")]
private static extern IntPtr GetWindow(IntPtr hWnd, uint wCmd);
[DllImport("user32.dll")]
private static extern int IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr SetFocus(IntPtr parentHandle);
[DllImport("user32.dll")]
private static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
public static void SetAppFocus()
{
IntPtr topWindowHandle = GetTopWindow(IntPtr.Zero);
while (topWindowHandle != null)
{
if (IsWindowVisible(topWindowHandle) != 0)
{
int currentProcessId = Process.GetCurrentProcess().Id;
int processId = 0;
GetWindowThreadProcessId(topWindowHandle, out processId);
if (processId == currentProcessId)
{
SetFocus(topWindowHandle);
break;
}
}
// goto next window
topWindowHandle = GetWindow(topWindowHandle, GW_HWNDNEXT);
}
}
I was able to reproduce the issue.
It should be something related to activating Owner when more than one forms has same owner, because it works correctly with just one Form2.
Bug here is that another Form2 is activated if either one is closed.
Try to
void showBC_Click(object sender, EventArgs e)
{
B.Visible = C.Visible = true;
Activate();
}
Now everything work "properly": closing either Form2 will activate the owner.
If you want to keep original behavior, then here is a workaround:
public Form1()
{
InitializeComponent();
formB = new Form2 { Owner = this };
formC = new Form2 { Owner = this };
formB.VisibleChanged += Child_VisibleChanged;
formC.VisibleChanged += Child_VisibleChanged;
}
void Child_VisibleChanged(object sender, EventArgs e)
{
if (!Application.OpenForms.Cast<Form>().OfType<Form2>().Any(o => o.Visible))
Activate();
}
You are leaving it up the OS to figure out which window should be activated when the one with the focus disappears. What it does here certainly doesn't win any prizes. Also a pretty big problem with WPF dialogs btw. Exactly why it does this is hard to guess, it just doesn't seem to pay enough attention to the window owner. Do note that it works just fine when you minimize the window instead of hiding it, why that acts differently is, well, weird. Let's not hesitate calling it a bug.
The workaround is pretty straight-forward, just don't force it to find another window by itself:
if (this.Owner != null) this.Owner.Activate();
this.Hide();
Also the solution in a WPF app.
How can I compare if my active application/window title is equal to something? For example, I want my WinForms application to only execute its functions when a certain application is in focus.
I tried using GetForegroundWindow() but it's not working.
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (GetForegroundWindow().ToString() == "Test123")
{
MessageBox.Show("right");
}
else
MessageBox.Show("wrong");
}
So my timer was going to check if the current window title is called "Test123" (note: not the process name, just the window title text), and tell me if it's right or wrong.
GetForegroundWindow() just returns you an IntPtr. This is your window handle (hWnd) for other calls to get information.
In this case, to get the window text you need to use GetWindowText. Implement that and pass in your newly acquired IntPtr (hWnd).
What I want to happen is that when a textbox is clicked a pop up keyboard will show and whatever i type on the keyboard will be putt in the textbox, but nothing happen but when I use notepad, it works. How can I fix this?
Here is my main form code:
private void textBox1_MouseClick(object sender, MouseEventArgs e)
{
Form1 frm1 = new Form1();
frm1.ShowDialog();
}
And here is my code for pop up keyboard
public partial class Form1 : Form
{
const int WS_EX_NOACTIVATE = 0x08000000;
//this line of code fixed the issue
[DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
public static extern IntPtr GetDesktopWindow();
public Form1()
{
InitializeComponent();
}
protected override CreateParams CreateParams
{
get
{
CreateParams param = base.CreateParams;
param.ExStyle |= WS_EX_NOACTIVATE;
//This line of code fix the issues
param.Style = 0x40000000 | 0x4000000;
param.Parent = GetDesktopWindow();
return param;
}
}
private void button1_Click(object sender, EventArgs e)
{
SendKeys.Send("1");
}
private void button3_Click(object sender, EventArgs e)
{
SendKeys.Send("2");
}
private void button4_Click(object sender, EventArgs e)
{
SendKeys.Send("3");
}
private void button2_Click(object sender, EventArgs e)
{
}
}
Use form1.Show() ... not ShowDialog()
If you manually added the testbox make sure you hook into the MouseEventHandler like so:
this.textBox1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.textBox1_MouseClick);
when your form loads.
I fixed the issue by just adding this line of code
[DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
public static extern IntPtr GetDesktopWindow();
And
param.Style = 0x40000000 | 0x4000000;
param.Parent = GetDesktopWindow();
I have to close a Form from a thread and I am using the Invoke method of the Form for calling the Close() method.
The problem is that when closing, the form is disposed and I get an InvalidOperationExecption wit the message "Invoke or BeginInvoke cannot be called on a control until the window handle has been created.".
I have got this exception only when debugging with a "Step Into" in the Close method but I don't want to risk with a possible error on normal running.
This is an example code to reproduce it:
private void Form1_Load(object sender, EventArgs e)
{
Thread thread = new Thread(CloseForm);
thread.Start();
}
private void CloseForm()
{
this.Invoke(new EventHandler(
delegate
{
Close(); // Entering with a "Step Into" here it crashes.
}
));
}
The form is disposed in the automatic generated code for the form (which I would like not to modify):
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
I would appreciate it if someone could give me a solution for this or another way to close a form from another thread.
Use this method :
// Inspired from: http://stackoverflow.com/a/12179408/1529139
public static void InvokeIfRequired(Control control, MethodInvoker action)
{
if (control.IsDisposed)
{
return;
}
if (control.InvokeRequired)
{
try
{
control.Invoke(action);
}
catch (ObjectDisposedException) { }
catch (InvalidOperationException e)
{
// Intercept only invokation errors (a bit tricky)
if (!e.Message.Contains("Invoke"))
{
throw e;
}
}
}
else
{
action();
}
}
Usage example:
Functions.InvokeIfRequired(anyControl, (MethodInvoker)delegate()
{
// UI stuffs
});
So far the best solution for this case has been to use the SynchronizationContext mechanism. I had the tip in Should I use Invoke or SynchronizationContext to update form controls from another thread?.
The example code would be like this:
private void Form1_Load(object sender, EventArgs e)
{
Thread thread = new Thread(MethodThread);
thread.Start(SynchronizationContext.Current);
}
private void MethodThread(Object syncronizationContext)
{
((SynchronizationContext)syncronizationContext).Send(CloseForm,null);
}
private void CloseForm(Object state)
{
Close();
}
The most obvious comment is - there's no apparent reason why you would need to close a form before it has even completed loading. There are other, better ways to handle whatever the reason is.
However since you asked...
The error gives you the answer - do not close until it has been constructed. Setup a Forms Timer - who's WM_TIMER message won't be processed until all other form creation messages are.
private System.Windows.Forms.Timer _timer;
protected override void OnLoad(EventArgs args)
{
_timer = new Timer { Interval = 1 };
_timer.Tick += (s, e) => new Thread(CloseForm).Start();
_timer.Start();
base.OnLoad(args);
}
While I feel that there must be a clean way to do this without platform interop, I can't think what it is. In the meantime, here's some code showing an approach that certainly works, assuming you don't mind the p/invoke...
public partial class Form1 : Form
{
private const uint WM_CLOSE = 0x0010;
private IntPtr _myHandle;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var t = new Thread(ThreadProc);
t.Start();
}
protected override void OnHandleCreated(EventArgs e)
{
_myHandle = this.Handle;
base.OnHandleCreated(e);
}
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
private void ThreadProc(object o)
{
Thread.Sleep(5000);
PostMessage(_myHandle, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}
}
I ran into a similar situation this morning where I was calling Close in an Invoke call and getting the InvalidOperationException when the Close method tried to return. The Invoke method is not able to return a value to the caller since it has been disposed. To sole this problem, I used BeginInvoke instead which allowed my thread to return before the form was closed.