Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# - How can I rename a process window that I started?

Is there any way I can rename the window titlebar of an application that I've launched? I.e. if I launched Notepad.exe, I could rename its title bar from "Untitled - Notepad" to "New Notepad Name".

like image 882
djdd87 Avatar asked Jun 19 '09 07:06

djdd87


3 Answers

You can do it using P/Invoke:

[DllImport("user32.dll")]
static extern int SetWindowText(IntPtr hWnd, string text);



private void StartMyNotepad()
{
    Process p = Process.Start("notepad.exe");
    Thread.Sleep(100);  // <-- ugly hack
    SetWindowText(p.MainWindowHandle, "My Notepad");
}

The background of the ugly hack in the code sample is that it seems as if you call SetWindowText immediately after starting the process, the title will not change. Perhaps the message ends up too early in the message queue of Notepad, so that notepad will set the title again afterwards.

Also note that this is a very brief change; if the user selects File -> New (or does anything else that will cause Notepad to update the window title), the original title will be back...

like image 125
Fredrik Mörk Avatar answered Sep 24 '22 14:09

Fredrik Mörk


Actually, I sorted it myself and it works perfectly. Thanks anyway.

[DllImport("user32.dll")]
static extern SetWindowText(IntPtr hWnd, string windowName);

IntPtr handle = p.MainWindowHandle;
SetWindowText(handle, "This is my new title");
like image 42
djdd87 Avatar answered Sep 26 '22 14:09

djdd87


As @Fredrik Mörk thinks, the problem is that there's need to wait for the window to be able to receive messages, before its title can be set. Waiting 100 milliseconds can break the internal message looper of the program and it's just a workaround. To receive a message, the window must have a handle that's used for referencing that window, thus you can simply wait for the window to have a handle, like this:

Process p = Process.Start("notepad.exe");
while (p.MainWindowHandle == IntPtr.Zero)
    Application.DoEvents();
SetWindowText(p.MainWindowHandle, "My Notepad");

Using Application.DoEvents() the program will continue to receive and process system messages, so it won't block (nor crash), although it isn't asynchronous.

You can also think to avoid CPU overhead by replacing the while statement with a SpinWait.SpinUntil call (from System.Threading):

Process p = Process.Start("notepad.exe");
SpinWait.SpinUntil(() => p.MainWindowHandle != IntPtr.Zero);
SetWindowText(p.MainWindowHandle, "My Notepad");
like image 44
Davide Cannizzo Avatar answered Sep 24 '22 14:09

Davide Cannizzo