C# compare window title - c#

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).

Related

Detect new app and run it in panel

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

SendKeys.Send("hello"); continuously sending string how can i send only once

This code is continuously sending a string. I need a solution which can send the supplied string only once by clicking a button in the window which has the focus.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
SendKeys.Send("This is a test...");
}
}
The issue seems to be the fact that the button1 control has the focus, and when you send certain keys to it (like the space in your example), it triggers the Click event, and you end up in an infinite loop.
Try adding a TextBox to your form and then set focus to that first (or if you already know the thing that should receive the text, ensure that it has the focus before you call SendKeys):
private void button1_Click(object sender, EventArgs e)
{
textBox1.Focus();
SendKeys.Send("This is a test...");
}

how to show a window only one time?

I want display a window only one time. When the user click on this button:
private void Notification_Click(object sender, RoutedEventArgs e)
{
NotificationSettings notifications = new NotificationSettings();
notifications.ShowDialog();
}
this will create a new window, I want that if there is already a window opened the user can't open a new one. There is an option in xaml for tell to compiler this? I remember the vb.net with windows form that allow to set the option to show only one windows at time.
Thanks.
Just hold a reference to your window in a field/property and check if it's Visisble already.
well I am not sure what is NotificationSettings exactly but for a window you can create a bool flag to mark when the window is opened and closed, check this code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
bool WindowFlag = false;
private void button_Click_1(object sender, RoutedEventArgs e)
{
Window TestWindows = new Window();
TestWindows.Closing += TestWindows_Closing;
if (WindowFlag == true)
{
MessageBox.Show("The Window is already opened");
}
else
{
TestWindows.Show();
WindowFlag = true;
}
}
private void TestWindows_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
WindowFlag = false;
}
}

MouseDown event on new Window does not DragMove MainWindow

I have a WPF application that I have removed the border and default controls by doing the following:
WindowStyle="None" AllowsTransparency="True"
Now I added a MouseDown handler MouseDown="Window_MouseDown" and added the following code to allow me to move my Window around:
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
try
{
if (e.ChangedButton == MouseButton.Left)
DragMove();
}
catch (Exception ex) { }
}
But now I have a UserControl that I want to resize to the full size of my Application so to achieve this I created a new Window that is the same size as my MainWindow and placed the UserControl onto it. I create this new Window and set its parent to be my main application like so:
public MyFullScreenWindow()
{
InitializeComponent();
this.Owner = App.Current.MainWindow;
}
I launch this window like so:
MyFullScreenWindow fullScreen = new MyFullScreenWindow();
fullScreenVideo.ShowDialog();
My problem is that I want to still move my whole application around whenever the user clicks and moves this new window. To achieve this I have added an Event to MyFullScreenWindow:
public partial class MyFullScreenWindow: Window
{
static public event EventHandler MouseDownEvent;
public MyFullScreenWindow()
{
InitializeComponent();
this.Owner = App.Current.MainWindow;
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (MouseDownEvent != null)
{
MouseDownEvent(sender, e);
}
}
}
And I handle this event in my MainWindow like so:
MyFullScreenWindow.MouseDownEvent += new EventHandler(MyFullScreenMouseDownHandler);
private void MyFullScreenMouseDownHandler(object sender, EventArgs e)
{
DragMove();
}
But when I click and drag I see that the event is fired off but my whole application does not move like it should. Why is this??
Simply add the following function code only
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
// Begin dragging the window
this.DragMove();
}
move your window where ever you want.
I don't know the context of your problem, but why would you create a new window, "place" it inside the parent one? You can use controls without creating a new window.
It's possible that you are doing this because you need AllowTransparency=false functionality, while showing it in AllowTransparency=true window. (I had this case when working with DirectShow). If you're doing this for custom window chrome, then don't use AllowTransparency - it decreases performance greatly. It's creating picture of every frame and disables GPU acceleration, after all! Instead, you can adapt to CustomChromeWindow project(found on Internets).
Note that you can enable the main window so that it would process messages from underlying window:
public class WindowSecond : Window
{
public WindowSecond()
{
Owner = Application.Current.MainWindow;
MouseDown += delegate
{
// maybe cache it.
IntPtr handle = new WindowInteropHelper(Owner).Handle;
EnableWindow(handle, true);
Application.Current.MainWindow.DragMove();
EnableWindow(handle, false);
};
}
[DllImport("user32")]
internal static extern bool EnableWindow(IntPtr hwnd, bool bEnable);
}

Close a form from an external thread using the Invoke method

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.

Categories