Как заблокировать или заморозить местоположение winform? - PullRequest
0 голосов
/ 04 января 2012

Я хочу запретить пользователю перемещать winform.Как вы можете заблокировать или заморозить местоположение winform?Так что, что бы они ни делали, его нельзя двигать.Я думаю, для win32 у вас есть замороженный вариант для Windows.Когда эта опция установлена, вы видите только контур перемещаемых окон, но фактическое окно все еще находится в своем первоначальном положении.Я пытаюсь сделать то же самое с winform.

EDIT: Вот процедура захвата сообщения окна для изменения позиции в win32:

//Frozen is a user-defined boolean variable
procedure TVIewFrm.WMPosChanging(var Msg: TMessage);
var
  wp:PWINDOWPOS;
begin
  if Frozen then
  begin
    wp := PWINDOWPOS(Msg.lParam);
    wp^.flags := wp^.flags or SWP_NOMOVE;
  end;
  inherited;
end;

То естьрабочая процедура, и это то, что я пытаюсь сделать с WinForm.Пока что вы все опубликовали работу, которая не является решением, которое я ищу.

Ответы [ 5 ]

3 голосов
/ 04 января 2012

Попробуйте:

Public Class UnmovableForm

    Protected Overrides Sub OnHandleCreated(ByVal e As System.EventArgs)
        '' Remove the Move command from the system menu so the window becomes unmovable
        Call RemoveMenu(GetSystemMenu(Me.Handle, False), SC_MOVE, MF_BYCOMMAND)
        MyBase.OnHandleCreated(e)
    End Sub

    Private Declare Function RemoveMenu Lib "user32" (ByVal hMenu As IntPtr, ByVal nPosition As Integer, ByVal wFlags As Integer) As Integer
    Private Declare Function GetSystemMenu Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal bRevert As Boolean) As IntPtr
    Private Const MF_DISABLED As Integer = 2
    Private Const MF_BYCOMMAND As Integer = 0
    Private Const SC_MOVE As Integer = &HF010
End Class

Надеюсь, это решит вашу проблему.

0 голосов
/ 04 января 2012

Хотя некоторые из вас подошли близко, это просто не сработало для меня. Ваши ответы были более или менее обойти. Я искал прямое решение.

Я понял свою проблему. Хотя мое решение работает безупречно, оно не рисует и не перетаскивает контур формы. Я, вероятно, должен реализовать код, похожий на LarsTech, чтобы добиться этого.

Вот мой рабочий код:

//declared within a form class under protected
method WndProc(var m:Message); override;

//and is defined as follows.
method MainForm.WndProc(var m: Message);
const WM_NCLBUTTONDOWN = 161;
const WM_SYSCOMMAND = 274;
const HTCAPTION = 2;
const SC_MOVE = 61456;
begin
    if ((m.Msg = WM_SYSCOMMAND) and (m.WParam.ToInt32 = SC_MOVE)) then
    begin
        exit;
    end;

    if ((m.Msg = WM_NCLBUTTONDOWN) and (m.WParam.ToInt32 = HTCAPTION)) then
    begin
        exit;
    end;
    inherited WndProc(var m);
end;

Спасибо всем за ваши ответы.

0 голосов
/ 04 января 2012

Вы можете попробовать это в вашей форме:

public partial class TestForm : Form {

  private const int HT_CAPTION = 0x2;
  private const int WM_NCLBUTTONDOWN = 0xA1;

  [DllImportAttribute("user32.dll")]
  public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

  public TestForm() {
    InitializeComponent();
    this.ControlBox = false;
  }

  protected override void WndProc(ref Message m) {
    if (m.Msg == Win32.WM_NCLBUTTONDOWN) {
      Form moveForm = new Form();
      moveForm.FormBorderStyle = FormBorderStyle.None;
      moveForm.StartPosition = FormStartPosition.Manual;
      moveForm.ShowInTaskbar = false;
      moveForm.TransparencyKey = Color.Lime;
      moveForm.BackColor = Color.Lime;
      moveForm.SetBounds(this.Left, this.Top, this.Width, this.Height);
      moveForm.Paint += moveForm_Paint;        
      moveForm.Show();
      SendMessage(moveForm.Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
      moveForm.Paint -= moveForm_Paint;
      moveForm.Close();
    } else {
      base.WndProc(ref m);
    }
  }

  void moveForm_Paint(object sender, PaintEventArgs e) {
    using (Pen p = new Pen(Color.Gray, 7)) {
      p.Alignment = System.Drawing.Drawing2D.PenAlignment.Center;
      e.Graphics.DrawRectangle(p, ((Form)sender).ClientRectangle);
    }
  }
}

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

0 голосов
/ 04 января 2012

Лучший ответ в зависимости от ваших потребностей:

Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Integer, ByVal uParam As Integer, ByRef lpvParam As String, ByVal fuWinIni As Integer) As Integer

Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Integer, ByVal uParam As Integer, ByRef lpvParam As Long, ByVal fuWinIni As Integer) As Integer

Private Const SPI_GETDRAGFULLWINDOWS = 38
Private Const SPI_SETDRAGFULLWINDOWS = 37
Private Const SPIF_SENDWININICHANGE = 2

Private Sub frmMain_Move(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Move
Dim result As Long
result = SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, 1&, vbNullString, SPIF_SENDWININICHANGE)
Me.Location = New Point(0, 0)
result = SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, 0&, vbNullString, SPIF_SENDWININICHANGE)

End Sub

Должна ли теперь быть возможность установить Me.Location = New Point (0,0) для вашего начального местоположения (возможно, захваченного в MouseDown?)

0 голосов
/ 04 января 2012

В событии Move формы просто установите местоположение обратно туда, где вы хотите, чтобы оно было.

...