Pergunta

Estamos a desenvolver um controle de interface do usuário no WPF para ser consumido dentro de um Windows Forms existentes / motor aplicativo MFC (Rhino 3D).

O motor de aplicação expõe a capacidade criar um "Dockbar", que essencialmente permite que você coloque controles Windows Forms dentro de uma janela filho que pode encaixar com os motores de Interface.

Eu estou tentando colocar um simples WPF TextBox dentro de um controle ElementHost, que é adicionado ao Dockbar. Isso parece funcionar bem, à primeira vista; mas depois de tentar digitar na caixa de texto única certas sequências realmente aparecer na caixa de texto. O Excluir , RETROCESSO , COPY , Colar e Selecionando texto trabalho. Se você digitar A-Z, 1-9, etc. essas chaves não aparecem.

Eu percorri a rede, e ter ouvido falar sobre o ElementHost.EnableModelessKeyboardInterop() , mas isso só se aplica a WPF Windows que está sendo criado a partir do formulário. Eu só estou criando UserControls WPF e hospedagem-los no controle ElementHost.

Eu vi um post que falava sobre o Dispatcher.Run (), e que tipo de obras, mas quebra o resto do formulário:

System.Windows.Threading.Dispatcher.Run();

O PreviewKeyUp , PreviewKeyDown , KeyUp e KeyDown todos os eventos de incêndio na caixa de texto, mas infelizmente não texto aparece na caixa de texto.

Eu não sei muito sobre mensagens do Windows, mas usando WinSpector notei que nenhuma mensagem WM_GETTEXT vinham da caixa de texto (se eles ainda devem ser eu não sei).

Eu também criar um novo projeto Windows Forms e fez a mesma coisa lá dentro, e ele funciona muito bem, por isso deve ser um problema com a forma como as janelas são criados e encaixado dentro do motor Rhino 3D.

Aqui está o código de exemplo que não funciona:

ElementHost el = new ElementHost();
System.Windows.Controls.TextBox t = new System.Windows.Controls.TextBox();
t.Width = 100;
t.Text = "TEST";
el.Child = t;
panel1.Controls.Add(el);
Foi útil?

Solução

Eu finalmente descobri-lo após 2 dias de scatching cabeça ...

A janela de diálogo MFC estava tomando os WM_CHAR mensagens e impedindo o controle de manipulação de entrada. Então, para evitar isso, eu ligar o HwndSource e sempre que eu receber o WM_GETDLGCODE mensagem que responder de volta com os tipos de entrada para aceitar, e depois marcar o evento como tratado.

Eu criei minha própria caixa de texto, a fim de evitar ter que corrigir cada caixa de texto (veja abaixo):

    /// <summary>
    /// Interop Enabled TextBox : This TextBox will properly handle WM_GETDLGCODE Messages allowing Key Input
    /// </summary>
    class IOTextBox : 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 IOTextBox() : base()
        {
            Loaded += delegate
                          {
                              HwndSource s = HwndSource.FromVisual(this) as HwndSource;
                              if (s != null)
                                  s.AddHook(new HwndSourceHook(ChildHwndSourceHook));
                          };
        }

        IntPtr ChildHwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == WM_GETDLGCODE)
            {
                handled = true;
                return new IntPtr(DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL);
            }
            return IntPtr.Zero;
        }
    }

Outras dicas

Confira minha própria pergunta sobre esta mesma coisa. No final, porém, tudo que você precisa é algo como isto:

Window window1 = new Window();
ElementHost.EnableModelessKeyboardInterop(window1);
window1.Show();

Por que meu WPF caixa de texto "meio que" somente leitura?

Eu tenho um problema semelhante com uma janela wxWidgets pai e controles WPF TextBox embutidos. Eu achei que, embora anexando ChildHwndSourceHook não resolve o problema de não receber a entrada do teclado, eu acabei com caracteres de espaço duplicado ocasionais. Parece que a mensagem WM_KEYDOWN lida com os caracteres de espaço de forma confiável, mas uma mensagem WM_CHAR duplicado também é recebido por alguns dos espaços. Para resolver este eu adicionei a seguinte cláusula para o corpo da função ChildHwndSourceHook, que simplesmente ignora o caractere de espaço WM_CHAR:

        const UInt32 WM_CHAR = 0x0102;

        if (msg == WM_CHAR)
        {
            // avoid duplicated spaces when parent window is a native window
            if (wParam.ToInt32() == 32)
                handled = true;
        }

Não é necessário para criar TextBox derivada. O código para IOTextBox pode ser usado em um UserControl caixas de texto de hospedagem. Eu testei-lo com sucesso com o controle WPF usado para a página de opções personalizadas usadas no pacote VS2010.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top