Question

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

Was it helpful?

Solution

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

OTHER TIPS

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

You can't do it in C#, but you can do it using low level API. Inject a thread into the process, call SetWindowText() from it

As @Fredrik Mörk thinks, the problem is that there's need to wait for the window can receive messages to set its title. 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 to that window, thus you can simply wait for the handle of the window, which at the startup should be IntPtr.Zero (an empty handle).

Here's an example of this approach:

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 (so, you'll need to import System.Threading):

Process p = Process.Start("notepad.exe");
SpinWait.SpinUntil(delegate
{
    return p.MainWindowHandle != IntPtr.Zero;
});
SetWindowText(p.MainWindowHandle, "My Notepad");

No.

This would require that the target application allow the window title to be modified at all. Many programs use their titles to show useful information (such as the name of the file open for editing in Notepad, or the <TITLE> of the HTML document open in Firefox).

The one case I am aware of that lets a user set the title text with few restrictions is CMD.EXE running in a console window. CMD supports the TITLE built-in command that sets the window title based on its arguments. But that can't be done by a second window without injecting key strokes into the particular console window, which is generally not recommended.

Edit:

Since the idea is floating that SetWindowText() will do this for you, let me clarify.

That API function does indeed change the title bar of a top level window. It is, in fact, the call that an application like Notepad is likely using to set its own title any time it thinks that the title has changed.

The reason I claim that this is not a solution is that Notepad does indeed change the title when it wants to. An application that supported arbitrary changes to its title would have a mechanism of some kind to remember that the title was changed and not arbitrarily restore its preferred title string.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top