2010-07-18 4 views
8

J'ai une fenêtre principale moins fenêtre WPF. J'essaie de faire en sorte que l'utilisateur final puisse faire glisser la fenêtre.Façon de faire glisser une fenêtre WPF sans fenêtre sans obtenir InvalidOperationException

J'ai ajouté ce qui suit au constructeur de la fenêtre:

this.MouseLeftButtonDown += delegate { DragMove(); }; 

Le problème est, j'ai une boîte de dialogue qui ouvre avec deux boutons. Lorsque je clique sur l'un de ces boutons, je reçois une exception InvalidOperationException non traitée avec le message "Impossible d'appeler DragMove lorsque le bouton principal de la souris est enfoncé". Cela pose quelques questions: Pourquoi un événement mousedown dans un dialogue aurait-il quelque chose à voir avec cela? Comment puis-je faire cela sans cette exception?

Merci!

+0

J'ai aussi des fenêtres avec des boutons et laisse l'utilisateur glisser en appuyant sur le bouton gauche de la souris et ça marche bien. Veuillez fournir un exemple de code minimal mais complet montrant ce comportement. –

Répondre

7

La 'bonne' manière de rendre une fenêtre sans bordure mobile est de retourner HTCAPTION dans le message WM_NCHITTEST. Le code suivant montre comment faire cela. Notez que vous voudrez renvoyer HTCLIENT si le curseur est sur certains éléments visuels de votre fenêtre, donc ce code est juste pour vous aider à démarrer.

http://msdn.microsoft.com/en-us/library/ms645618(VS.85).aspx

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     InitializeComponent(); 
    } 

    protected override void OnSourceInitialized(EventArgs e) 
    { 
     HwndSource hwndSource = (HwndSource)HwndSource.FromVisual(this); 
     hwndSource.AddHook(WndProcHook); 
     base.OnSourceInitialized(e); 
    } 

    private static IntPtr WndProcHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handeled) 
    { 
     if (msg == 0x0084) // WM_NCHITTEST 
     { 
      handeled = true; 
      return (IntPtr)2; // HTCAPTION 
     } 
     return IntPtr.Zero; 
    } 
} 
+0

Si vous essayez de "renvoyer HTCAPTION dans le message WM_NCHITTEST" comme le suggère Tergiver, les boutons ne seront pas cliquables, c'est-à-dire que l'événement click ne fonctionnera pas pour les boutons. Quelqu'un at-il une solution de contournement pour cela? –

+0

Notez que j'ai indiqué que ce code n'était qu'un point de départ. Vous ne pouvez pas retourner HTCAPTION pour tout le rectangle de votre fenêtre comme le code ci-dessus. Vous devez décider quelle (s) zone (s) de votre fenêtre ne doit pas être des zones 'légende'. Cela peut être aussi simple qu'un rectangle dans votre zone de contrôle, ou aussi complexe que de marcher dans l'arbre visuel et de chercher des contrôles. – Tergiver

0

Il y a un projet Microsoft qui gère tout le style « sans fenêtre » et bien plus encore, et il est opensource, vous voudrez peut-être jeter un oeil à http://code.msdn.microsoft.com/WPFShell. J'utilise sur une application financière commerciale, et n'a pas encore rencontré de problèmes sur une version de Windows.

1

Régler le attribuiez MouseDown de la fenêtre ou tout autre contrôle que vous souhaitez utiliser:

<TextBlock Grid.Column="0" HorizontalAlignment="Stretch" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" >Handy Dandy</TextBlock> 

et mettre en œuvre dans le code derrière comme celui-ci:

private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
{ 
    this.DragMove(); 
} 

De: http://www2.suddenelfilio.net/2007/01/19/wpf-draggable-windowless-windows/

0

vous pouvez remplacer la méthode d'origine:

public new void DragMove() 
    { 
     if (this.WindowState == WindowState.Normal) 
     { 
      SendMessage(hs.Handle, WM_SYSCOMMAND, (IntPtr)0xf012, IntPtr.Zero); 
      SendMessage(hs.Handle, WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero); 
     } 
    } 
Questions connexes