2009-05-31 3 views
3

Есть ли способ контролировать, где вы можете перемещать форму?C# Form Control Move

Так что, если я перемещаю форму, ее можно перемещать только по вертикальной оси, и когда я пытаюсь переместить ее по горизонтали, ничего не происходит.

Я не хочу использовать багги, например, менять расположение или перемещать событие и вытаскивать его обратно. У меня нет способа использовать что-то вроде переопределения WndProc, но после некоторого поиска я ничего не смог найти. Пожалуйста, помогите

ответ

2

Вы, скорее всего, захотите переопределить WndProc и обработать сообщение WM_MOVING. According to MSDN:

Сообщение WM_MOVING отправляется в окне пользователь перемещается. К , обрабатывая это сообщение, приложение может отслеживать позицию прямоугольника перетаскивания и, при необходимости, изменить свое положение.

Это был бы способ сделать это, однако, вы, очевидно, нужно Твик это для ваших нужд:

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

Например:

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

Приведенный выше код устанавливает минимальное левое положение 100.

Нет необходимости воссоздавать структуру RECT, как, например, driis, родной Rectangle .NET работает отлично , Однако вы должны установить местоположение через свойство X, так как Left - свойство Get only.

+0

+1 для использования как много нативного кода CLR, как это возможно. –

+0

Вам также придется обрабатывать другие сообщения, потому что WM_MOVING не вызывается при первом создании окна. Либо вы можете явно установить позицию вашего окна при создании, либо вам нужно убедиться, что когда оно создано, оно находится в пределах, которые вы хотите. –

1

VB.NET Версия:

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