3

如何在用 C#/.NET 2.0 编写的 Windows 应用程序中实现复制菜单项?

我想让用户在控件中标记一些文本,然后从应用程序菜单栏中的编辑菜单中选择复制菜单项,然后在例如 Excel 中进行粘贴。

让我头晕目眩的是如何首先确定哪个子窗体处于活动状态,然后如何找到包含应复制到剪贴板的标记文本的控件。

请帮忙。

4

5 回答 5

5

在我和我的一位同事的一些重磅编程的帮助下,我想出了这个,请随意重构。

代码放在主窗体中。copyToolStripMenuItem_Click 方法处理编辑菜单中复制菜单项上的 Click 事件。

    /// <summary>
    /// Recursively traverse a tree of controls to find the control that has focus, if any
    /// </summary>
    /// <param name="c">The control to search, might be a control container</param>
    /// <returns>The control that either has focus or contains the control that has focus</returns>
    private Control FindFocus(Control c) 
    {
        foreach (Control k in c.Controls)
        {
            if (k.Focused)
            {
                return k;
            }
            else if (k.ContainsFocus)
            {
                return FindFocus(k);
            }
        }

        return null;
    }

    private void copyToolStripMenuItem_Click(object sender, EventArgs e)
    {
        Form f = this.ActiveMdiChild;

        // Find the control that has focus
        Control focusedControl = FindFocus(f.ActiveControl);

        // See if focusedControl is of a type that can select text/data
        if (focusedControl is TextBox)
        {
            TextBox tb = focusedControl as TextBox;
            Clipboard.SetDataObject(tb.SelectedText);
        }
        else if (focusedControl is DataGridView)
        {
            DataGridView dgv = focusedControl  as DataGridView;
            Clipboard.SetDataObject(dgv.GetClipboardContent());
        }
        else if (...more?...)
        {
        }
    }
于 2008-09-15T14:36:59.983 回答
1

要确定打开的窗口,您可以查询 Form.ActiveMDIChild 属性以获取对当前活动窗口的引用。从那里,您可以执行以下两项操作之一:

1)如果您创建自己的自定义表单类(例如 FormFoo),它具有新的公共成员函数 GetCopiedData(),然后从该类继承应用程序的所有子表单,您可以执行以下操作:

((FormFoo)this.ActiveMDIChild).GetCopiedData();

假设 GetCopiedData 函数将具有特定于表单的实现来检测应将哪些文本复制到剪贴板。

或者

2)您可以使用继承来检测处于活动状态的表单的类型,然后根据表单的类型做一些事情来获取复制的数据:

Form f = this.ActiveMDIChild;
if(f is FormGrid)
{
    ((FormGrid)f).GetGridCopiedData();
} else if(f is FormText) {
    ((FormText)f).GetTextCopiedData();
}

等等

这应该让您开始查找活动窗口以及如何实现复制功能。如果您在复制 GridView 时需要更多帮助,最好发布另一个问题。

于 2008-09-15T13:45:59.123 回答
0

为什么不扩展控件,所以控件本身提供了应该复制到剪贴板的数据。

查看ApplicationCommands文档。

于 2008-09-15T13:33:41.150 回答
0

如果窗体是选项卡式的并且目标控件是 DataGridView,则当右键单击 DataGridView 时,有时可以使用上述方法将窗体的 TabControl 作为活动控件返回。

我通过为我的 DataGridView 实现以下处理程序来解决这个问题:-

私人无效dataGridView_CellMouseDown(对象发送者,DataGridViewCellMouseEventArgs e)

{

 if (e.Button == MouseButtons.Right)
 {
      dataGridView.Focus();

      dataGridView.CurrentCell = dataGridView[e.ColumnIndex, e.RowIndex];
 }

}

于 2009-07-30T15:38:30.303 回答
-1

在我看来,您最好将其分解为较小的任务/问题。从听起来的方式来看,您遇到了一些问题。

您打开了多个“子”窗口。这是一个 MDI 应用程序吗?当在这些子窗口之一上执行操作时,它应该在该窗口的事件处理程序中触发一个事件。这是您要设置的第一件事。如果这是一个 datagridview,我建议开始一个简单的测试。尝试捕获DataGridView.SelectionChanged事件。现在就扔一些东西MessageBox.Show("I copied your datas!");

这应该让您开始,您至少会了解如何向您提出此事件。

从这里开始,我们将需要更多地了解您的数据网格,以及这些行中的行和子控件。然后我们可能会在渲染事件中创建事件,这些事件将在适当的时间以适当的范围引发。

于 2008-09-15T13:24:37.660 回答