2009-05-31 11 views
3

Gibt es trotzdem zu steuern, wo Sie ein Formular verschieben können?C# Form Control Move

Also wenn ich ein Formular verschiebe, kann es nur auf der vertikalen Achse bewegt werden und wenn ich versuche, es horizontal zu bewegen, passiert nichts.

Ich möchte keine Buggy-Implementierung wie locationchanged oder move-Ereignis und wieder inline einfügen. Nein, es gibt einen Weg, der etwas wie einen WndProc-Override verwendet, aber nachdem ich eine Weile gesucht habe, konnte ich nichts finden. Bitte helfen Sie

Antwort

2

Sie würden höchstwahrscheinlich WndProc überschreiben und die WM_MOVING Nachricht behandeln. According to MSDN:

Die WM_MOVING Nachricht an ein Fenster gesendet wird, dass der Benutzer sich bewegt. Durch Verarbeitung dieser Nachricht kann eine Anwendung die Position des Ziehen Rechteck überwachen und, falls erforderlich, ändern Sie ihre Position.

Dies wäre ein Weg, es zu tun, würden Sie aber offensichtlich ist es für Ihre Bedürfnisse tweek benötigen:

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

Zum Beispiel:

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

Der obige Code eines Set minimale linke Position von 100.

Es ist nicht notwendig, die RECT-Struktur neu zu erstellen, wie es driis getan hat, das .NET-native Rectangle funktioniert gut . Sie müssen den Speicherort jedoch über die X-Eigenschaft festlegen, da Left eine Nur-Get-Eigenschaft ist.

+0

+1 für so viel nativen CLR-Code wie möglich zu verwenden. –

+0

Sie müssen auch andere Nachrichten behandeln, da WM_MOVING nicht aufgerufen wird, wenn das Fenster zum ersten Mal erstellt wird. Entweder müssen Sie Ihre Windows-Position bei der Erstellung explizit festlegen, oder Sie müssen sicherstellen, dass sie bei der Erstellung innerhalb der von Ihnen gewünschten Grenzen liegt. –

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