2009-05-31 6 views
3

Existe-t-il un moyen de contrôler où vous pouvez déplacer un formulaire? Donc, si je déplace un formulaire, il ne peut être déplacé que sur l'axe vertical et quand j'essaie de le déplacer horizontalement, rien ne se passe.Déplacement de contrôle de formulaire C#

Je ne veux pas d'une implémentation buggée comme locationchanged ou déplacer un événement et le remonter en ligne. Je ne suis pas un moyen d'utiliser quelque chose comme un override WndProc mais après avoir cherché pendant un moment, je ne pouvais rien trouver. Aidez-nous

Répondre

2

Vous souhaiterez très certainement remplacer WndProc et gérer le message WM_MOVING. According to MSDN:

Le message d'WM_MOVING est envoyé à une fenêtre que l'utilisateur se déplace. Par traitant ce message, une application peut surveiller la position du rectangle de traînée et, au besoin, changer sa position.

Ce serait une façon de le faire, cependant, vous évidemment besoin de Tweek pour vos besoins:

using System.Diagnostics; 
using System.Runtime.InteropServices; 
using System.Windows.Forms; 

namespace VerticalMovingForm 
{ 
    public partial class Form1 : Form 
    { 
     private const int WM_MOVING = 0x0216; 
     private readonly int positionX; 
     private readonly int positionR; 

     public Form1() 
     { 
      Left = 400; 
      Width = 500;        
      positionX = Left; 
      positionR = Left + Width; 
     } 
     protected override void WndProc(ref Message m) 
     { 
      if (m.Msg == WM_MOVING) 
      { 
       var r = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT)); 
       r.Left = positionX; 
       r.Right = positionR; 
       Marshal.StructureToPtr(r, m.LParam, false); 
      } 
      base.WndProc(ref m);     
     } 

     [StructLayout(LayoutKind.Sequential)] 
     private struct RECT 
     { 
      public int Left; 
      public int Top; 
      public int Right; 
      public int Bottom; 
     } 
    } 
} 
3

Par exemple:

using System.Runtime.InteropServices; 

protected override void WndProc(ref Message m) 
{ 
    if (m.Msg == 0x216) // WM_MOVING = 0x216 
    { 
     Rectangle rect = 
      (Rectangle) Marshal.PtrToStructure(m.LParam, typeof (Rectangle)); 
     if (rect.Left < 100) 
     { 
      // compensates for right side drift 
      rect.Width = rect.Width + (100 - rect.Left); 
      // force left side to 100 
      rect.X = 100; 
      Marshal.StructureToPtr(rect, m.LParam, true); 
     } 
    } 
    base.WndProc(ref m); 
} 

Le code ci-dessus définit une position minimum à gauche de 100.

Il n'y a pas besoin de recréer la structure RECT, comme le fait driis, le Rectangle .NET natif fonctionne bien . Cependant, vous devez définir l'emplacement via la propriété X, puisque Left est une propriété Get Only.

+0

+1 pour utiliser le plus code CLR natif possible. –

+0

Vous devrez également gérer d'autres messages, car WM_MOVING n'est pas appelé lors de la création de la fenêtre. Soit vous ne définissez pas explicitement la position de vos fenêtres lors de la création, soit vous devez vous assurer que, lorsqu'il est créé, il est dans les limites que vous désirez. –

1

VB.NET Version:

Protected Overloads Overrides Sub WndProc(ByRef m As Message) 
    If m.Msg = &H216 Then 
     ' WM_MOVING = 0x216 
     Dim rect As Rectangle = DirectCast(Marshal.PtrToStructure(m.LParam, GetType(Rectangle)), Rectangle) 
     If rect.Left < 100 Then 
      ' compensates for right side drift 
      rect.Width = rect.Width + (100 - rect.Left) 
      ' force left side to 100 
      rect.X = 100 
      Marshal.StructureToPtr(rect, m.LParam, True) 
     End If 
    End If 
    MyBase.WndProc(m) 
End Sub 
Questions connexes