Est-il possible de renommer la barre de titre de la fenêtre d'une application que j'ai lancée? C'est à dire. si j'ai lancé Notepad.exe, je pourrais renommer sa barre de titre de "Untitled - Notepad" à "New Notepad".C# - Comment renommer une fenêtre de processus que j'ai démarrée?
Répondre
Vous pouvez le faire en utilisant 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");
}
L'arrière-plan du hack laid dans l'exemple de code est qu'il semble que si vous appelez SetWindowText immédiatement après le démarrage du processus, le titre ne changera pas. Peut-être que le message se retrouve trop tôt dans la file d'attente des messages du Bloc-notes, de sorte que le bloc-notes définira à nouveau le titre par la suite.
Notez également qu'il s'agit d'un changement très bref; Si l'utilisateur sélectionne Fichier -> Nouveau (ou fait quoi que ce soit qui fera que le Bloc-notes mettra à jour le titre de la fenêtre), le titre original sera de retour ...
Comme je l'ai dit dans ma réponse et un commentaire sur la question, Notepad (et la plupart des autres applications) ne supporte pas cela. Forcer le titre à changer avec SetWindowText() n'est pas une vraie solution, car l'application va simplement le remettre à un moment de son choix. – RBerteig
C'est une solution à mon problème car l'application que j'utilise ne le remettra jamais en place. J'ai seulement utilisé le bloc-notes comme exemple. De plus, si vous le souhaitez, il est assez simple de créer votre propre événement pour gérer le changement de titre de la poignée de fenêtre, puis le réinitialiser à nouveau. – GenericTypeTea
Juste pour noter sur le «bidouillage laid», je n'ai pas exigé cela comme j'avais déjà le contrôle du processus et sachez qu'il fonctionne avec sa barre de titre visible. – GenericTypeTea
No.
Cela nécessiterait que l'application cible permettent au titre de la fenêtre à modifier du tout. De nombreux programmes utilisent leurs titres pour afficher des informations utiles (telles que le nom du fichier ouvert pour l'édition dans le Bloc-notes ou le <TITLE>
du document HTML ouvert dans Firefox).
Le cas dont je suis conscient qui permet à un utilisateur de définir le texte du titre avec peu de restrictions est CMD.EXE en cours d'exécution dans une fenêtre de console. CMD prend en charge la commande intégrée TITLE
qui définit le titre de la fenêtre en fonction de ses arguments. Mais cela ne peut pas être fait par une seconde fenêtre sans injecter des touches dans la fenêtre de la console, ce qui n'est généralement pas recommandé.
Edit:
Puisque l'idée est que SetWindowText()
flotte va le faire pour vous, laissez-moi de préciser.
Cette fonction API change en effet la barre de titre d'une fenêtre de niveau supérieur. C'est, en fait, l'appel qu'une application comme Notepad est susceptible d'utiliser pour définir son propre titre chaque fois qu'il pense que le titre a changé.
La raison pour laquelle je déclare que c'est pas une solution est que le bloc-notes change effectivement le titre quand il veut. Une application qui prend en charge des changements arbitraires à son titre aurait un mécanisme quelconque pour se rappeler que le titre a été changé et ne restaure pas arbitrairement sa chaîne de titre préférée.
SetWindowText est une solution au problème. Il effectue exactement ce que j'ai demandé, donc on ne peut nier que c'est une solution au problème. En fait, je n'ai pas demandé à ce que ce soit permanent, mais comme je l'ai signalé dans d'autres commentaires, il existe une solution de contournement facile pour le garder permanent de toute façon. – GenericTypeTea
Ce n'est pas une solution générale. Vous avez demandé une solution générale et utilisé une application qui conserve des informations dans le titre à titre d'exemple. – RBerteig
L'application Windows Forms est dessinée par GDI + au niveau inférieur, au sein des API C incluses de manière native dans Windows. Donc, personne ne peut vous empêcher d'appeler une méthode de ceux qui utilisent P/Invoke. Au moment où vous avez un handle cible, vous pouvez simplement appeler une méthode définissant le comportement souhaité (texte, couleur, etc.) passant ce handle et la valeur nécessaire (par exemple le texte lui-même). –
En fait, je l'ai moi-même trié et cela fonctionne parfaitement. Merci quand même.
[DllImport("user32.dll")]
static extern SetWindowText(IntPtr hWnd, string windowName);
IntPtr handle = p.MainWindowHandle;
SetWindowText(handle, "This is my new title");
Ne vous attendez pas à ce que votre titre survive à l'événement arbitraire dans l'autre application qui l'amène à mettre à jour son titre. Le Bloc-notes le fait lorsque l'utilisateur ouvre un document différent, choisit Fichier | Nouveau ou Fichier | Enregistrer sous par exemple. – RBerteig
Je viens de créer un événement pour gérer une telle possibilité, donc dès que le texte change, il est de nouveau en retrait. – GenericTypeTea
Vous ne pouvez pas le faire en C#, mais vous pouvez le faire il utilise API de bas niveau. Injectez un thread dans le processus, appelez le SetWindowText()
Toute application qui utilise le titre pour transmettre des informations remplacera ce texte par le sien à un moment donné, comme le fait le Bloc-notes. – RBerteig
Comme le pense @Fredrik Mörk, le problème est qu'il faut attendre que la fenêtre puisse recevoir des messages pour définir son titre. Attendre 100 millisecondes peut casser le boucleur de message interne du programme et c'est juste une solution de contournement. Pour recevoir un message, la fenêtre doit avoir un handle qui est utilisé pour faire référence à cette fenêtre, ainsi vous pouvez simplement attendre le handle de la fenêtre, qui au démarrage devrait être IntPtr.Zero
(un handle vide).
Voici un exemple de cette approche:
Process p = Process.Start("notepad.exe");
while (p.MainWindowHandle == IntPtr.Zero)
Application.DoEvents();
SetWindowText(p.MainWindowHandle, "My Notepad");
En utilisant Application.DoEvents()
le programme continuera à recevoir et messages système de traitement, de sorte qu'il ne bloque pas (ni accident), bien qu'il ne soit pas asynchrone.
Vous pouvez aussi penser à éviter les fuites de mémoire en remplaçant la déclaration while
avec un appel SpinWait.SpinUntil
(donc, vous aurez besoin d'importer System.Threading
):
Process p = Process.Start("notepad.exe");
SpinWait.SpinUntil(delegate
{
return p.MainWindowHandle != IntPtr.Zero;
});
SetWindowText(p.MainWindowHandle, "My Notepad");
Voulez-vous dire alors qu'il est en cours d'exécution? – Sev
Oui ... bien que si je pouvais spécifier la barre de titre avant de lancer le processus, ce serait également acceptable. – GenericTypeTea
Généralement, pas à moins que l'application ne le prenne en charge. Beaucoup ne le font pas. Le Bloc-notes inclut le nom du fichier actuellement ouvert dans sa barre de titre, par exemple, et ne prend en charge aucune autre modification du titre. D'autre part, CMD.EXE a la commande intégrée TITLE qui permet de contrôler le titre de la fenêtre de la console. – RBerteig