Reputation: 3276
I want to prevent the user from moving the winform. How do you lock or freeze the winform's location? So, that no matter what they do, it can't be moved. I think, for win32 you have a frozen option for windows. When this option is set, you only see the outline of the windows being moved but the actual window is still in its original location. I am trying to do a similar thing with winform.
EDIT: Here is a procedure to capture window message for position change in 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;
That is a working procedure and that is what I am trying to do with the WinForm. So far you all posted a work around not really the solution I am looking.
Upvotes: 0
Views: 549
Reputation: 3276
Although some of you came close, it just didn't work for me. Your answers were more or less work around. I was looking for a straight forward solution.
I figured out my issue. Although my solution works flawlessly, it doesn't draw and drag an outline of the winform. I probably have to implement code similar to LarsTech to achieve that.
Here is my working code:
//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;
Thank you all for your answers.
Upvotes: 0
Reputation: 81655
You can try this in your form:
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);
}
}
}
It intercepts the non-client area left mousedown button, pops a transparent form up that draws a gray rectangle around the borders, and sends a message to move the form around as-if it was the form you clicked on.
Upvotes: 0
Reputation: 2701
Better answer in regards to your needs:
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
Should now be able to set the Me.Location = New Point(0,0) to your initial location (grabbed at MouseDown maybe?)
Upvotes: 0
Reputation: 263843
Try this:
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
Hope this solves your problem.
Upvotes: 3
Reputation: 2701
In the Move event of the form, just set the location back to where you want it to be.
Upvotes: 0