Dans des applications comme Windows Explorer et Internet Explorer, on peut saisir les zones de cadre étendues sous la barre de titre et faire glisser Windows.
Pour les applications WinForms, les formulaires et les contrôles sont aussi proches des API Win32 natives qu'il est possible de l'être ; il suffit de remplacer la balise WndProc()
dans leur formulaire, traitent le WM_NCHITTEST
et faire croire au système qu'un clic sur la zone du cadre est en réalité un clic sur la barre de titre en renvoyant le message suivant HTCAPTION
. Je l'ai fait dans mes propres applications WinForms avec un effet délicieux.
Dans WPF, je peux également mettre en œuvre un système similaire de WndProc()
et l'accrocher au handle de ma fenêtre WPF tout en étendant le cadre de la fenêtre dans la zone client, comme ceci :
// In MainWindow
// For use with window frame extensions
private IntPtr hwnd;
private HwndSource hsource;
private void Window_SourceInitialized(object sender, EventArgs e)
{
try
{
if ((hwnd = new WindowInteropHelper(this).Handle) == IntPtr.Zero)
{
throw new InvalidOperationException("Could not get window handle for the main window.");
}
hsource = HwndSource.FromHwnd(hwnd);
hsource.AddHook(WndProc);
AdjustWindowFrame();
}
catch (InvalidOperationException)
{
FallbackPaint();
}
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case DwmApiInterop.WM_NCHITTEST:
handled = true;
return new IntPtr(DwmApiInterop.HTCAPTION);
default:
return IntPtr.Zero;
}
}
Le problème est que, puisque je règle aveuglément handled = true
et renvoyant HTCAPTION
en cliquant partout mais l'icône de la fenêtre ou les boutons de contrôle provoquent le déplacement de la fenêtre. En d'autres termes, tout ce qui est mis en évidence en rouge ci-dessous provoque un glissement. Cela inclut même les poignées de redimensionnement situées sur les côtés de la fenêtre (la zone non cliente). Mes contrôles WPF, à savoir les zones de texte et le contrôle de tabulation, cessent également de recevoir des clics en conséquence :
Ce que je veux c'est pour seulement
- la barre de titre, et
- les régions de l'espace client...
- ... qui ne sont pas occupées par mes commandes.
pour qu'il soit possible de le faire glisser. En d'autres termes, je veux que seules ces régions rouges puissent être déplacées (zone client + barre de titre) :
Comment puis-je modifier mon WndProc()
et le reste du code XAML/code-behind de ma fenêtre, pour déterminer quelles zones doivent renvoyer HTCAPTION
et lesquels ne devraient pas l'être ? Je pense à quelque chose du genre de l'utilisation de Point
pour vérifier l'emplacement du clic par rapport à l'emplacement de mes contrôles, mais je ne suis pas sûr de la façon de procéder dans le monde WPF.
EDIT [4/24] : Une façon simple d'y parvenir est de faire en sorte qu'un contrôle invisible, ou même la fenêtre elle-même, réponde aux questions suivantes MouseLeftButtonDown
en invoquant DragMove()
sur la fenêtre (voir Réponse de Ross ). Le problème est que pour une raison quelconque DragMove()
ne fonctionne pas si la fenêtre est agrandie, ce qui ne convient pas à Windows 7 Aero Snap. Comme j'opte pour l'intégration de Windows 7, ce n'est pas une solution acceptable dans mon cas.
10 votes
Cette question comprend un bref tutoriel sur la gestion des messages Windows en C#, elle comporte des illustrations bien conçues qui indiquent exactement ce qui est demandé, et il n'y a pas de fautes de frappe évidentes. +1, bébé !
0 votes
@Jeffrey L Whitledge : Mince, merci (+1 à vous) ! La seule chose que j'ai dû modifier à la fin était le titre de la question... Je jure que le titre précédent n'était pas ce que j'avais écrit avant de le poster.