我已经实现了Tab Control拖放。当我点击Tab Control并拖动时,会打开一个带有Tabpage数据的新表单。
问题是如果我保持form.Show()。表单显示拖动外观并随鼠标移动。 但是,如果我使用form.ShowDialog(),那么表单只是打开并且不会发生拖动效果。
在这种情况下,我只能在单击表单标题并再次拖动时才能拖动。 我在下面写了相同的代码。
protected override void WndProc(ref Message m)
{
if (m.Msg == NativeMethods.WM_MOVING)
{
DockUndockTabpage(m);
}
base.WndProc(ref m);
switch (m.Msg)
{
case NativeMethods.WM_MOUSEMOVE:
if (m.WParam.ToInt32() == 1)
{
if (!captured)
{
Point pt = tabControl.PointToScreen((Cursor.Position));
Point newPosition = new Point(pt.X - dragOffset.X, pt.Y - dragOffset.Y);
this.Location = newPosition;
}
NativeMethods.RECT rc = new NativeMethods.RECT(this.Bounds);
IntPtr lParam = Marshal.AllocHGlobal(Marshal.SizeOf(rc));
Marshal.StructureToPtr(rc, lParam, true);
NativeMethods.SendMessage(this.Handle, NativeMethods.WM_MOVING, IntPtr.Zero, lParam);
Marshal.FreeHGlobal(lParam);
}
break;
case NativeMethods.WM_SETCURSOR:
captured = true;
break;
default:
break;
}
}
有两种方法可以分别进行对接和取消,分别来往原始形式。
private void DockToTab()
{
if (!tabControl.TabPages.Contains(tabPageToInsert))
{
tabControl.TabPages.Insert(tabID, tabPageToInsert);
tabControl.SelectedTab = tabPageToInsert;
tabControl.Capture = true;
this.Close();
}
}
private static void UnDockFromTab()
{
if (formToShow.Visible || formToShow.IsDisposed)
return;
formToShow.tabControl.TabPages.Remove(formToShow.tabPageToInsert);
formToShow.Capture = true;
formToShow.ShowDialog();
}
Kinldy帮助。
答案 0 :(得分:1)
我注意到我对这种用户界面的反对意见,这是非常难以发现的。一些代码使其无论如何都能正常工作。您需要做的基本事情是检测用户开始在TabControl上拖动鼠标。一旦检测到,您就可以即时创建表单。将它放在与选项卡相同的位置,使其看起来像是从选项卡本身拖动的。然后,您需要一个技巧来说服表单被其标题栏拖动,您可以通过发布WM_NCLBUTTONDOWN消息来执行此操作。这很有效:
private Point TabMouseDownPos;
private void tabControl1_MouseDown(object sender, MouseEventArgs e) {
TabMouseDownPos = e.Location;
}
private void tabControl1_MouseMove(object sender, MouseEventArgs e) {
// Detect start of drag
if (e.Button != System.Windows.Forms.MouseButtons.Left) return;
int dx = e.X - TabMouseDownPos.X;
int dy = e.Y - TabMouseDownPos.Y;
if (Math.Abs(dx) >= SystemInformation.DoubleClickSize.Width ||
Math.Abs(dy) >= SystemInformation.DoubleClickSize.Height) {
// Start drag, create the form at the same position as the tab
Form form = CreateTabForm();
form.StartPosition = FormStartPosition.Manual;
var tabpos = tabControl1.GetTabRect(tabControl1.SelectedIndex);
form.Location = tabControl1.PointToScreen(new Point(tabpos.Left + dx, tabpos.Top + dy));
// Juggle the mouse so it now starts dragging the form
tabControl1.Capture = false;
PostMessage(form.Handle, WM_NCLBUTTONDOWN, (IntPtr)2, IntPtr.Zero);
form.ShowDialog();
}
}
private Form CreateTabForm() {
// Return form object that matches tabControl1.SelectedIndex
//...
return new Form2();
}
private const int WM_NCLBUTTONDOWN = 0x00a1;
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr PostMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
使用CreateTabForm()方法创建与tabControl.SelectedIndex属性值匹配的表单实例。