在 UserControl 上处理剪贴板副本

发布于 2024-09-03 12:16:43 字数 222 浏览 4 评论 0 原文

我有复杂的用户控件(网格、网格编辑控件等...)并且我想要处理 CTRL+C 键盘快捷键,但是我不想通过编辑控件(文本框、组合框等...)禁用本机功能。如果 CTRL+C 不由其他内部控件处理,我想自己处理它(从网格复制整行等...)。

我尝试覆盖 UserControl 中的 WndProc 方法并检查 WM_COPY 和 WM_COPYDATA,但它不起作用。它仅适用于最终目标控件(例如 TextBox)。

I have complex UserControl (grid, edit controls for grid, etc...) and I want handle CTRL+C keyboard shortcut, however I don't want disable a native functions by edit controls (textboxes, comboboxes, etc...). If the CTRL+C is not handled by other inner controls I want handle it by myself (copy whole row(s) from grid, etc...).

I tried override WndProc method in UserControl and check for WM_COPY and WM_COPYDATA, but it doesn't work. It works only on final target control (TextBox for example).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吻风 2024-09-10 12:16:43

您可以通过重写 ProcessCmdKey() 来完成此操作。检查文本框是否具有焦点。例如:

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
        if (keyData == (Keys.Control | Keys.C)) {
            var box = this.ActiveControl as TextBoxBase;
            if (box == null) {
                // Do your stuff
                MessageBox.Show("Copy!");
                return true;
            }
        }
        return base.ProcessCmdKey(ref msg, keyData);
    }

You can do this by overriding ProcessCmdKey(). Check if a text box has the focus. For example:

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
        if (keyData == (Keys.Control | Keys.C)) {
            var box = this.ActiveControl as TextBoxBase;
            if (box == null) {
                // Do your stuff
                MessageBox.Show("Copy!");
                return true;
            }
        }
        return base.ProcessCmdKey(ref msg, keyData);
    }
や三分注定 2024-09-10 12:16:43

您正在寻找一种将子控件引发的事件冒泡的方法,直到其容器,以便您可以在用户控件级别处理这些事件。

跨控件层次结构的事件自动传播内置于 WPF 中,称为路由事件。但是,此功能在 Windows 窗体中并不是开箱即用的,因此您必须实现自己的解决方案。

看看这个问题以获得一些灵感。

相关资源:

What you are looking for is a way to bubble events raised by a child control up to its container so that you can handle those events at the User Control's level.

The automatic propagation of events across the control hierarchy is built into WPF and is called Routed Events. However this functionality is not available out of the box in Windows Forms, so you will have to implement your own solution.

Have a look at this SO question to get some inspiration.

Related resources:

∞觅青森が 2024-09-10 12:16:43

我没有尝试过,我认为这很大程度上取决于用户控件内的所有子控件。但通常情况下,击键是针对具有焦点的实际控件。如果它不处理该击键(设置e.Handled = true),它将向上冒泡到其父级,如果不处理它,它将进一步前进,直到到达表单最后是角膜缘。

因此,如果您的子控件编写正确并且它们无法处理给定的击键(例如 Control + C),则应该很容易将处理程序添加到您的 UserControl 中KeyDown 活动并做任何你喜欢的事情。

更新

阅读您的评论后,我仍然认为恩里科和我所展示的方式应该是正确的。所以我认为问题是,如果您的第 3 方控件之一具有焦点,它无法处理复制快捷方式,但它设置了 e.Handled = true 导致没有进一步的信息有关快捷方式的父控件。

因此,首先您应该联系您的控件供应商并向他发送有关此错误行为的错误报告。

另外还有另一种hacky方式:
在表单中,您可以设置 KeyPreview 设置为 true 并拦截传入的按键。现在您可以检查是否在 ActiveControl 是正确处理快捷方式的东西(可能是针对 DictionaryHashSetmissingControls 进行检查)只需保留该功能或执行任何您想要的操作并自行设置 e.Handled = true 即可。

更新 2

一个小片段来说明我的意思:

this.KeyPreview = true;

HashSet<Type> scrappyControls = new HashSet<Type>();
//ToDo: Add all controls that say it handles Ctrl-C
//      but doesn't it the right way.
scrappyControls.Add(typeof(TextBox));

this.KeyDown += (sender, e) =>
{
    if (e.KeyData == (Keys.Control | Keys.C))
    {
        if (scrappyControls.Contains(this.ActiveControl.GetType()))
        {
            //ToDo: Do copy to clipboard on yourself
            e.Handled = true;
        }
    }
};

此功能的缺点是,它必须放入您的表单中,而不是放入您自己编写的 UserControl 中。但是这样,当 TextBox 获得焦点并且 Control + C 被按下时,您会收到通知。

I didn't try it out and i think it heavy depends on all the child controls, which are within your UserControl. But normally a keystroke is given to the actual control that has the focus. If it doesn't handle that keystroke (setting e.Handled = true), it would be bubble up to its parent and if that doesn't handle it, it would go further till it reaches the form and finally the limbus.

So if your child controls are properly written and they can't handle the given keystroke (e.g. Control + C) it should be easy to add a handler into your UserControl to the KeyDown event and do whatever you like.

Update

After reading your comments, i still think that the way shown by Enrico and me should be the correct one. So i think the problem is that if one of your 3rd party controls has the focus it is not able to handle the copy shortcut, but it sets the e.Handled = true leading to no further informations of the parent controls about the shortcut.

So at first you should contact your control vendor and send him a bug report about this wrong behaviour.

Alternative there exists another hacky way:
In your form you can set the KeyPreview to true and intercept the incoming key. Now you could check if within the ActiveControl is something that handles the shortcut correctly (maybe a check against a Dictionary<Type, bool> or a HashSet<Type> lackingControls) and just leave the function or do whatever you want and setting the e.Handled = true by yourself.

Update 2

A little snippet to illustrate what i meant:

this.KeyPreview = true;

HashSet<Type> scrappyControls = new HashSet<Type>();
//ToDo: Add all controls that say it handles Ctrl-C
//      but doesn't it the right way.
scrappyControls.Add(typeof(TextBox));

this.KeyDown += (sender, e) =>
{
    if (e.KeyData == (Keys.Control | Keys.C))
    {
        if (scrappyControls.Contains(this.ActiveControl.GetType()))
        {
            //ToDo: Do copy to clipboard on yourself
            e.Handled = true;
        }
    }
};

The drawback of this functionality is, that it must be placed into your form, not into your self-written UserControl. But that way you will be informed, when a TextBox has the focus and Control + C is pressed within.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文