【问题标题】:How to host a WPF UserControl in ElementHost without Window with KeyPresses如何使用 KeyPresses 在没有窗口的 ElementHost 中托管 WPF UserControl
【发布时间】:2015-09-11 16:24:38
【问题描述】:

通过将 Child 属性设置为自定义用户控件,我使用 ElementHost 在 Windows 应用程序中嵌入了 WPF 用户控件。

不幸的是,我的文本框没有收到任何按键输入,所以我根本无法使用我的加载项。

当我找到以下代码行时,我以为我找到了解决方法。

ElementHost.EnableModelessKeyboardInterop([System.Windows.Window]);

这不起作用,因为我没有使用窗口。实际上,没有办法在元素宿主中承载 System.Windows.Window 或将窗口作为宿主。

这个插件在开发过程中没有任何文本输入功能,所以它已经完全停止了。

如何让我的文本框接受输入?

【问题讨论】:

    标签: c# wpf com wpf-controls elementhost


    【解决方案1】:

    我在网上找到了一个链接,它子类 TextBox 并允许击键original post

    我稍微改变了一些东西,但它几乎是一样的。它没有经过全面测试,但按键会进入文本框。

    class TextInput : TextBox
    {
        private const UInt32 DLGC_WANTARROWS = 0x0001;
        private const UInt32 DLGC_WANTTAB = 0x0002;
        private const UInt32 DLGC_WANTALLKEYS = 0x0004;
        private const UInt32 DLGC_HASSETSEL = 0x0008;
        private const UInt32 DLGC_WANTCHARS = 0x0080;
        private const UInt32 WM_GETDLGCODE = 0x0087;
        public TextInput()
        {
            Loaded += delegate
            {
                var s = PresentationSource.FromVisual(this) as HwndSource;
                s?.AddHook(ChildHwndSourceHook);
            };
        }
        static IntPtr ChildHwndSourceHook(IntPtr hwnd, int msg, 
             IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg != WM_GETDLGCODE) return IntPtr.Zero;
            handled = true;
            return new IntPtr(DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL);
        }
    }
    

    另一个角度是创建元素宿主的子类并在那里添加代码。这样,如果有任何进一步的挂钩自定义,您可以在一个地方进行调整,它将级联到您的所有 wpf 控件。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Forms.Integration;
    using System.Windows.Interop;
    using Automated.ToolWindow;
    
    namespace Automated
    {
    
        public class MyElementHost : ElementHost
        {
            protected override void Dispose(bool disposing)
            {
                if (_contentControl != null)
                {
                    _contentControl.Loaded -= OnContentControlOnLoaded;
                    _contentControl = null;
                }
    
                base.Dispose(disposing);
            }
    
            private ContentControl _contentControl;
            // Hide the child element.
            public new UIElement Child 
            {
                get { return base.Child; }
                set
                {
                    _contentControl = new ContentControl();
                    _contentControl.Loaded += OnContentControlOnLoaded;
                    _contentControl.Content = value;
                    base.Child = _contentControl;
                }
            }
    
            private void OnContentControlOnLoaded(object sender, RoutedEventArgs e)
            {
                var s = PresentationSource.FromVisual(_contentControl) as HwndSource;
                s?.AddHook(ChildHwndSourceHook);
            }
    
            private const UInt32 DLGC_WANTARROWS = 0x0001;
            private const UInt32 DLGC_WANTTAB = 0x0002;
            private const UInt32 DLGC_WANTALLKEYS = 0x0004;
            private const UInt32 DLGC_HASSETSEL = 0x0008;
            private const UInt32 DLGC_WANTCHARS = 0x0080;
            private const UInt32 WM_GETDLGCODE = 0x0087;
    
            static IntPtr ChildHwndSourceHook(IntPtr hwnd, 
              int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            {
                if (msg != WM_GETDLGCODE) return IntPtr.Zero;
                handled = true;
                return new IntPtr(DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL);
            }
        }
    }
    

    我添加主机的代码在执行后如下所示。

    ElementHost = new MyElementHost()
    { 
        Child =  new RootXamlControl()
    };
    
    TaskPanes.Add(_host.TaskPanes.Add((int) ElementHost.Handle, "", 
          TaskPaneCaption, "Auto"));
    

    旁注,如果您正在编写一个 COM 插件并且不注意内存管理,那么对于那些不得不关心垃圾收集的人来说,您将获得全新的赞赏。来自 C#.Net 开发人员!

    【讨论】:

    • 您能帮忙解决以下问题吗:TaskPanes.Add(_host.TaskPanes.Add((int) ElementHost.Handle, "", TaskPaneCaption, "Auto"));因为看不懂,所以无法根据自己的项目进行修改。
    猜你喜欢
    • 2015-02-17
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多