在控制之外处理 DragDrop - DragEnd 事件?
Handle DragDrop outside of control - DragEnd event?
我正在尝试在 WinForm 应用程序中模仿 Web 浏览器的行为,您可以在其中将选项卡拖入和拖出浏览器,并在将选项卡放到不存在的某个位置时创建它的另一个实例选项卡。
目前 WinForm 应用程序只有一个主要 TabControl
,我正在查看 DoDragDrop()
相关事件,但它们似乎只有在您有两个 TabControls
和移动 TabPages
围绕那两个。
有没有办法让它只与一个 TabControl
一起工作?意思是,如果你从 TabControl
中 Drop
一个 TabPage
那么它会创建一个新的 TabControl
其中包含 TabPage
?
我只能想到使用:
private void TabControl_DragLeave(object sender, EventArgs e)
{
Form newInstance = new Form();
TabControl newTabControl = new TabControl();
newInstance.Controls.Add(newTabControl);
newTabControl.TabPages.Add(sender as TabPage);
newInstance.Show();
}
但这很粗糙,每次离开 TabControl 时都会创建新选项卡。
看来您正在寻找一个在放置结束时引发的事件,无论是在您的控制范围内还是在您的控制范围之外。
您可以依赖 QueryContinueDrag
并检查操作是否为 Drop
,然后检查鼠标位置,例如,如果它不在您的控制范围内,则只需创建另一个 window 并将所选选项卡添加到新 window.
内的选项卡控件中
private void tabControl1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
tabControl1.DoDragDrop(tabControl1.SelectedTab, DragDropEffects.All);
}
}
private void tabControl1_DragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(TabPage)))
e.Effect = DragDropEffects.Move;
}
private void tabControl1_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
{
if (e.Action == DragAction.Drop)
{
var tabPage = tabControl1.SelectedTab;
if (!tabControl1.RectangleToScreen(tabControl1.Bounds).Contains(Cursor.Position))
{
var form = new Form();
form.Text = tabPage.Text;
var tabControl = new TabControl();
tabControl.TabPages.Add(tabPage);
tabControl.Dock = DockStyle.Fill;
form.Controls.Add(tabControl);
form.FormBorderStyle = FormBorderStyle.SizableToolWindow;
form.StartPosition = FormStartPosition.Manual;
form.Location = new Point(Cursor.Position.X - form.Width / 2,
Cursor.Position.Y - SystemInformation.CaptionHeight / 2);
form.Show();
e.Action = DragAction.Cancel;
//You can comment tabControl.TabPages.Add
//Then set e.Action = DragAction.Continue
//Then the DragDrop event will raise and add the tab there.
}
}
}
private void tabControl1_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(TabPage)))
{
var tabPage = (TabPage)e.Data.GetData(typeof(TabPage));
tabControl1.TabPages.Remove(tabPage);
tabControl1.TabPages.Add(tabPage);
}
}
对于更高级的场景和增强代码:
开始拖动时,鼠标至少拖动到指定的点数,例如16个点数,即可开始拖动。这很容易计算。将 p1 作为鼠标按下点,将 p2 作为鼠标移动点,将 d 作为拖动阈值。开始拖动以防万一 (p1.X-p2.X)*(p1.X-p2.X) + (p1.Y-p2.Y)*(p1.Y-p2.Y) > d*d
.
您可以使用 GiveFeedback
事件禁用鼠标的默认光标,而是在拖动时显示更合适的光标,很容易通过 e.UseDefaultCursors = false;
和设置 Cursor.Current = Cursors.SizeAll;
例如。
您可以封装逻辑并将其放在派生的TabControl
中。然后在 DragEnter
和 DragLeave
事件中设置静态 属性 用于跟踪放置目标。如果 drop-target 有值,则表示您正在派生的选项卡控件上放置,否则意味着您正在放置在外部。然后可以轻松地为所有自定义选项卡控件启用拖放功能。
您可以在拖放后关闭工具表单,以防表单不包含任何其他选项卡。
添加标签时,可以将其插入before/after选中的标签或目标光标下的标签。
我正在尝试在 WinForm 应用程序中模仿 Web 浏览器的行为,您可以在其中将选项卡拖入和拖出浏览器,并在将选项卡放到不存在的某个位置时创建它的另一个实例选项卡。
目前 WinForm 应用程序只有一个主要 TabControl
,我正在查看 DoDragDrop()
相关事件,但它们似乎只有在您有两个 TabControls
和移动 TabPages
围绕那两个。
有没有办法让它只与一个 TabControl
一起工作?意思是,如果你从 TabControl
中 Drop
一个 TabPage
那么它会创建一个新的 TabControl
其中包含 TabPage
?
我只能想到使用:
private void TabControl_DragLeave(object sender, EventArgs e)
{
Form newInstance = new Form();
TabControl newTabControl = new TabControl();
newInstance.Controls.Add(newTabControl);
newTabControl.TabPages.Add(sender as TabPage);
newInstance.Show();
}
但这很粗糙,每次离开 TabControl 时都会创建新选项卡。
看来您正在寻找一个在放置结束时引发的事件,无论是在您的控制范围内还是在您的控制范围之外。
您可以依赖 QueryContinueDrag
并检查操作是否为 Drop
,然后检查鼠标位置,例如,如果它不在您的控制范围内,则只需创建另一个 window 并将所选选项卡添加到新 window.
private void tabControl1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
tabControl1.DoDragDrop(tabControl1.SelectedTab, DragDropEffects.All);
}
}
private void tabControl1_DragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(TabPage)))
e.Effect = DragDropEffects.Move;
}
private void tabControl1_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
{
if (e.Action == DragAction.Drop)
{
var tabPage = tabControl1.SelectedTab;
if (!tabControl1.RectangleToScreen(tabControl1.Bounds).Contains(Cursor.Position))
{
var form = new Form();
form.Text = tabPage.Text;
var tabControl = new TabControl();
tabControl.TabPages.Add(tabPage);
tabControl.Dock = DockStyle.Fill;
form.Controls.Add(tabControl);
form.FormBorderStyle = FormBorderStyle.SizableToolWindow;
form.StartPosition = FormStartPosition.Manual;
form.Location = new Point(Cursor.Position.X - form.Width / 2,
Cursor.Position.Y - SystemInformation.CaptionHeight / 2);
form.Show();
e.Action = DragAction.Cancel;
//You can comment tabControl.TabPages.Add
//Then set e.Action = DragAction.Continue
//Then the DragDrop event will raise and add the tab there.
}
}
}
private void tabControl1_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(TabPage)))
{
var tabPage = (TabPage)e.Data.GetData(typeof(TabPage));
tabControl1.TabPages.Remove(tabPage);
tabControl1.TabPages.Add(tabPage);
}
}
对于更高级的场景和增强代码:
开始拖动时,鼠标至少拖动到指定的点数,例如16个点数,即可开始拖动。这很容易计算。将 p1 作为鼠标按下点,将 p2 作为鼠标移动点,将 d 作为拖动阈值。开始拖动以防万一
(p1.X-p2.X)*(p1.X-p2.X) + (p1.Y-p2.Y)*(p1.Y-p2.Y) > d*d
.您可以使用
GiveFeedback
事件禁用鼠标的默认光标,而是在拖动时显示更合适的光标,很容易通过e.UseDefaultCursors = false;
和设置Cursor.Current = Cursors.SizeAll;
例如。您可以封装逻辑并将其放在派生的
TabControl
中。然后在DragEnter
和DragLeave
事件中设置静态 属性 用于跟踪放置目标。如果 drop-target 有值,则表示您正在派生的选项卡控件上放置,否则意味着您正在放置在外部。然后可以轻松地为所有自定义选项卡控件启用拖放功能。您可以在拖放后关闭工具表单,以防表单不包含任何其他选项卡。
添加标签时,可以将其插入before/after选中的标签或目标光标下的标签。