我有一个无边框 #if
,其中Form
停靠在顶部(就好像它是标题栏)。到目前为止一切正常,除了我自己无法弄清楚的一个问题。
我必须在Panel
的{{1}}事件中关注代码才能移动MouseDown
:
Panel
当然导入外部API后:
Form
我还覆盖了SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
的{{1}}方法,以便能够像Windows中的任何其他常规格式一样调整[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
的大小(取自SO帖子,找不到)现在的链接):
WndProc
现在上面的代码工作正常,唯一的问题是上边框,因为Form
的上半部分被Form
覆盖。所以我认为我可以在窗格的protected override void WndProc(ref Message m)
{
if (!_resizable)
{
base.WndProc(ref m);
return;
}
const UInt32 WM_NCHITTEST = 0x0084;
const UInt32 WM_MOUSEMOVE = 0x0200;
const UInt32 HTLEFT = 10;
const UInt32 HTRIGHT = 11;
const UInt32 HTBOTTOMRIGHT = 17;
const UInt32 HTBOTTOM = 15;
const UInt32 HTBOTTOMLEFT = 16;
const UInt32 HTTOP = 12;
const UInt32 HTTOPLEFT = 13;
const UInt32 HTTOPRIGHT = 14;
const int RESIZE_HANDLE_SIZE = 10;
bool handled = false;
if (m.Msg == WM_NCHITTEST || m.Msg == WM_MOUSEMOVE)
{
Size formSize = this.Size;
Point screenPoint = new Point(m.LParam.ToInt32());
Point clientPoint = this.PointToClient(screenPoint);
Dictionary<UInt32, Rectangle> boxes = new Dictionary<UInt32, Rectangle>()
{
{HTBOTTOMLEFT, new Rectangle(0, formSize.Height - RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE)},
{HTBOTTOM, new Rectangle(RESIZE_HANDLE_SIZE, formSize.Height - RESIZE_HANDLE_SIZE, formSize.Width - 2*RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE)},
{HTBOTTOMRIGHT, new Rectangle(formSize.Width - RESIZE_HANDLE_SIZE, formSize.Height - RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE)},
{HTRIGHT, new Rectangle(formSize.Width - RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, formSize.Height - 2*RESIZE_HANDLE_SIZE)},
{HTTOPRIGHT, new Rectangle(formSize.Width - RESIZE_HANDLE_SIZE, 0, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE) },
{HTTOP, new Rectangle(RESIZE_HANDLE_SIZE, 0, formSize.Width - 2*RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE) },
{HTTOPLEFT, new Rectangle(0, 0, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE) },
{HTLEFT, new Rectangle(0, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, formSize.Height - 2*RESIZE_HANDLE_SIZE) }
};
foreach (KeyValuePair<UInt32, Rectangle> hitBox in boxes)
{
if (this.WindowState != FormWindowState.Maximized
&& hitBox.Value.Contains(clientPoint))
{
m.Result = (IntPtr)hitBox.Key;
handled = true;
break;
}
}
}
if (!handled)
base.WndProc(ref m);
else
this.Refresh();
}
和Form
事件中执行类似的操作,以使Windows认为事件来自表单。
在Panel
事件中:
MouseDown
在MouseMove
事件中:
MouseDown
这是const int WM_NCLBUTTONDOWN = 0xA1;
(sender as Control).Capture = false;
Int32 lparam = MakeLParam(e.X, e.Y);
Message msg = Message.Create(Handle, WM_NCLBUTTONDOWN, IntPtr.Zero, (IntPtr)lparam);
WndProc(ref msg);
方法:
MouseMove
无论如何,它只是不起作用。
如何让Windows相信鼠标移动/点击来自表单本身而不是来自面板?
答案 0 :(得分:0)
我在different forum找到了解决方案。这很简单。基本上,您将处理MouseMove
事件,然后手动发送调整大小消息,而不是传递所有子控件消息。秘诀在于发送WM_NCLBUTTONDOWN
消息以及方向。
这是一个示例代码(在VB.NET中,但我认为所有C#编码员都很容易理解它):
Private Sub Form1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
'Calculate which direction to resize based on mouse position
If e.Location.X < BorderWidth And e.Location.Y < BorderWidth Then
resizeDir = ResizeDirection.TopLeft
ElseIf e.Location.X < BorderWidth And e.Location.Y > Me.Height - BorderWidth Then
resizeDir = ResizeDirection.BottomLeft
ElseIf e.Location.X > Me.Width - BorderWidth And e.Location.Y > Me.Height - BorderWidth Then
resizeDir = ResizeDirection.BottomRight
ElseIf e.Location.X > Me.Width - BorderWidth And e.Location.Y < BorderWidth Then
resizeDir = ResizeDirection.TopRight
ElseIf e.Location.X < BorderWidth Then
resizeDir = ResizeDirection.Left
ElseIf e.Location.X > Me.Width - BorderWidth Then
resizeDir = ResizeDirection.Right
ElseIf e.Location.Y < BorderWidth Then
resizeDir = ResizeDirection.Top
ElseIf e.Location.Y > Me.Height - BorderWidth Then
resizeDir = ResizeDirection.Bottom
Else
resizeDir = ResizeDirection.None
End If
End Sub
Private Sub Form1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown
If e.Button = Windows.Forms.MouseButtons.Left And Me.WindowState <> FormWindowState.Maximized Then
ResizeForm(resizeDir)
End If
End Sub
Private Sub ResizeForm(ByVal direction As ResizeDirection)
Dim dir As Integer = -1
Select Case direction
Case ResizeDirection.Left
dir = HTLEFT
Case ResizeDirection.TopLeft
dir = HTTOPLEFT
Case ResizeDirection.Top
dir = HTTOP
Case ResizeDirection.TopRight
dir = HTTOPRIGHT
Case ResizeDirection.Right
dir = HTRIGHT
Case ResizeDirection.BottomRight
dir = HTBOTTOMRIGHT
Case ResizeDirection.Bottom
dir = HTBOTTOM
Case ResizeDirection.BottomLeft
dir = HTBOTTOMLEFT
End Select
If dir <> -1 Then
ReleaseCapture()
SendMessage(Me.Handle, WM_NCLBUTTONDOWN, dir, 0)
End If
End Sub