locked
IME can't be turned on for TextBoxes inside a Popup RRS feed

  • Question

  • I find it impossible to input Chinese charaters into Textbox inside Popup using IME.
    I Simply can't switch between English and other IMEs, there isn't any response for trying.
    Cound any one suggest on what to do?
    Thanks!

    XAML:

    <Window x:Class="WpfApplication1.Window1" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Title="Window1"
        <StackPanel > 
            <Button Name="btnShowPopup" Click="btnShowPopup_Click">Show Popup!</Button> 
            <Popup Name="popup" Placement="Bottom" PlacementTarget="{Binding ElementName=btnShowPopup}"
                <Border Background="White"
                    <StackPanel> 
                        <TextBox Width="80"/> 
                    </StackPanel> 
                </Border> 
            </Popup> 
        </StackPanel> 
    </Window> 


    CS:

        public partial class Window1 : Window 
        { 
            public Window1() 
            { 
     
                InitializeComponent(); 
     
            } 
     
            private void btnShowPopup_Click(object sender, RoutedEventArgs e) 
            { 
                popup.IsOpen = !popup.IsOpen; 
            } 
     
        } 
     

    Monday, December 29, 2008 7:59 AM

Answers

  • Windows will only send WM_IME_SETCONTEXT message to the active window, Popup by default is designed to be shown with WM_EX_NOACTIVE which means that it doesn't in active state when displaying, that's why IME could not work correctly in this regard, to workaround this issue, you could try set the Popup as the active window using win32 SetActiveWindow() API as following code shows:

    <Window x:Class="IME.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:IME"
        Title="Window1" Height="300" Width="300">
      <StackPanel >
        <StackPanel Orientation="Horizontal">
          <TextBlock>Outside popup:</TextBlock>
          <TextBox Name="txtOK" Width="100"/>
        </StackPanel>
        <Button Name="btnShowPopup" Click="btnShowPopup_Click">Show Popup!</Button>
        <local:MyPopup
            x:Name="popup"
            Placement="Bottom"
            PlacementTarget="{Binding ElementName=btnShowPopup}">
          <Border Background="White">
            <StackPanel Orientation="Horizontal">
              <TextBlock Name="txtError">Inside popup:</TextBlock>
              <TextBox Width="80" x:Name="textBox"/>
            </StackPanel>
          </Border>
        </local:MyPopup>
      </StackPanel>
    </Window>

    public class MyPopup : Popup
    {
        [DllImport("user32.dll")]
        static extern IntPtr SetActiveWindow(IntPtr hWnd);

        static MyPopup()
        {
            EventManager.RegisterClassHandler(
                typeof(MyPopup),
                Popup.PreviewGotKeyboardFocusEvent,
                new KeyboardFocusChangedEventHandler(OnPreviewGotKeyboardFocus),
                true);
        }

        private static void OnPreviewGotKeyboardFocus(Object sender, KeyboardFocusChangedEventArgs e)
        {
            var textBox = e.NewFocus as TextBoxBase;
            if (textBox != null)
            {
                var hwndSource = PresentationSource.FromVisual(textBox) as HwndSource;
                if (hwndSource != null)
                {
                    SetActiveWindow(hwndSource.Handle);
                }
            }
        }
    }

    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void btnShowPopup_Click(object sender, RoutedEventArgs e)
        {
            popup.IsOpen = !popup.IsOpen;
        }
    }

    Hope this helps


    Another Paradigm Shift
    http://shevaspace.blogspot.com
    • Marked as answer by Marco Zhou Friday, January 2, 2009 10:23 AM
    Wednesday, December 31, 2008 8:49 AM
  • add reference

    using System.Windows.Forms;



    create class level variable

    bool CtrlKeyDown = false;



            private void txt_PreviewKeyUp(object sender, System.Windows.Input.KeyEventArgs e)  
            {  
                if ((e.Key.ToString() == "LeftCtrl") || (e.Key.ToString() == "RightCtrl"))  
                {  
                    CtrlKeyDown = false;  
                }  
            }  
            private void txt_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)  
            {  
                if ((e.Key.ToString() == "LeftCtrl") || (e.Key.ToString() == "RightCtrl"))  
                {  
                    CtrlKeyDown = true;  
                }  
     
                if (CtrlKeyDown)  
                {  
                    if (e.Key.ToString() == "Space")  
                    {  
                        //sending ctrl + Shift when ctrl + space is pressed. from code.  
                        SendKeys.SendWait("^+");  
                        e.Handled = true;  
                    }  
                }  
            }  
     


            <StackPanel >    
            <StackPanel Orientation="Horizontal">    
                <TextBlock>Outside popup:</TextBlock>    
                <TextBox Name="txtOK" Width="100"/>    
            </StackPanel>    
            <Button Name="btnShowPopup" Click="btnShowPopup_Click">Show Popup!</Button>    
            <Popup Name="popup" Placement="Bottom" PlacementTarget="{Binding ElementName=btnShowPopup}">    
                <Border Background="White">    
                    <StackPanel Orientation="Horizontal">    
                        <TextBlock>Inside popup:</TextBlock>    
                        <TextBox Name="txtError" Width="80"  PreviewKeyUp="txt_PreviewKeyUp" PreviewKeyDown="txt_PreviewKeyDown"/>    
                    </StackPanel>    
                </Border>    
            </Popup> 
            </StackPanel>   


    When I press CTRL + SPACE I handle this in Preview Events which are tunneling Events.

    and I send Keys to CTRL+SHIFT to work in my system when i press CTRL+SPACE

    The same code you can modify from   if (e.Key.ToString() == "Space")  to Shift and try pressing CTRL+Shift from your system
    then sendkeys CTRL+SPACE

    CTRL="^"
    SHIFT ="+"


    I was also thinking of calling some API if this approach doesnt work, already there is one solution above by Marco Zhou. 

    Either both or any one should help you :)
     


    Prasad - www.beautifulmind.blog.co.in
    • Marked as answer by Marco Zhou Friday, January 2, 2009 10:23 AM
    Thursday, January 1, 2009 5:58 AM

All replies

  • Hi I dont know chaina language.
    but I copied the same code  executed and clicked on button
    i got the textbox.

    I went to http://en.wikipedia.org/wiki/China
    the following site and copy and pasted some china characters into textbox it worked.

    I you are facing some square box kind of the issue you have to do some OS settings so that it will support chaina language.

    please go through one of my article http://www.codeproject.com/KB/WPF/WITIYMIWYG.aspx which tells how to setup your pc to support indian languages. similar for chaines also and please find the language code from following microsoft link http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.aspx and also find out what setting you have to make to your pc to support your language.



    Prasad - www.beautifulmind.blog.co.in
    • Proposed as answer by prasad22 Monday, December 29, 2008 4:32 PM
    • Unproposed as answer by deer_chao Monday, December 29, 2008 4:38 PM
    Monday, December 29, 2008 4:31 PM
  • Yes I can paste Chinese Chars, but I can't TYPE in them because I can't change the keyboard layout when the TextBox got focused. I'm supposed to hit Ctrl+Space to switch to my input method (Windows default), but it doesn't work in that case, the textbox is acting like I only pressed Space - it appends a blank char in to the Text.

    Meanwhile, everything works perfectly outside the popup. I mean, if I put a TextBox in the window, I can switch my input method to type Chinese.
    Monday, December 29, 2008 4:45 PM


  • please look into this http://www.conversationexchange.com/resources/keyboard-language.php  I hope this will help you :)

    I was able to type my language by going through this. in the same popup textbox.


    Prasad - www.beautifulmind.blog.co.in
    • Proposed as answer by prasad22 Monday, December 29, 2008 4:56 PM
    • Unproposed as answer by deer_chao Monday, December 29, 2008 4:58 PM
    Monday, December 29, 2008 4:56 PM
  • Thanks for your link!

    However I think you got me wrong. I'm using Windows for quite a long time, and I know what has to be done to input my own language. Actually, I can type in Chinese Chars, and I do this everyday. And I'm doing it today on my Current dev machine,  I can even do it in my WPF application -- if I want to type them into a TextBox outside a Popup, so there has nothing to do with Windows settings.

    It's a WPF issue, It's the Popup issue.
    Monday, December 29, 2008 5:04 PM
  • Hi Buddy, you have mentiond CTRL+SPACE but  it is CTRL+SHIFT key it worked fine for me in the popup textbox also, can you try with CTRL+SHIFT Key and let me know still problem exist ?

      

    Prasad - www.beautifulmind.blog.co.in
    • Proposed as answer by prasad22 Monday, December 29, 2008 5:13 PM
    • Unproposed as answer by deer_chao Monday, December 29, 2008 5:19 PM
    Monday, December 29, 2008 5:13 PM
  • I found more weried things now.

    <Window x:Class="WpfApplication1.Window1" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Title="Window1"
        <StackPanel > 
            <StackPanel Orientation="Horizontal"
                <TextBlock>Outside popup:</TextBlock> 
                <TextBox Name="txtOK" Width="100"/> 
            </StackPanel> 
            <Button Name="btnShowPopup" Click="btnShowPopup_Click">Show Popup!</Button> 
            <Popup Name="popup" Placement="Bottom" PlacementTarget="{Binding ElementName=btnShowPopup}"
                <Border Background="White"
                    <StackPanel Orientation="Horizontal"
                        <TextBlock Name="txtError">Inside popup:</TextBlock> 
                        <TextBox Width="80"/> 
                    </StackPanel> 
                </Border> 
            </Popup> 
        </StackPanel> 
    </Window> 

    Action List A:
    1, Click "Show Popup!"
    2, Click to focus txtOK,
    3, Hit Ctrl + Space to switch to my input method
    4, Click to focus txtError
    5, Now I can switch between English and my own IME with Ctrl + Space

    Action List B:
    1, Click "Show Popup!"
    2, Click to focus txtError
    3, Now I can't switch between English and my own IME with Ctrl + Space, it acts like I'm hitting Space key only

    It's acting much more werid when I move the focus between these two TextBoxes while trying to switch IME after I launch the test app and do the action lists above, I can't even find a pattern to describ it.
    This is happening on my Windows Vista SP1, also on my users' Windows XP SP2.

    Monday, December 29, 2008 5:17 PM
  • Ctrl + Shift not working either...

    Monday, December 29, 2008 5:18 PM
  • I tryed with your second XAML Example also, it works fine for me in CTRL+SHIFT key, may be because of  different Region the equalent to this key in your country keyboard is CTRL+SPACE.  I tryed in XP-SP2 it worked fine. probabaly I have to think some alternative. I will getback once I get something.
    Prasad - www.beautifulmind.blog.co.in
    Monday, December 29, 2008 5:36 PM
  • Thanks for you help and patience.

    Ctrl + Shift should be working on my computer, just like Ctrl + Space. However neither of  them is. 
    Monday, December 29, 2008 5:41 PM
  • Windows will only send WM_IME_SETCONTEXT message to the active window, Popup by default is designed to be shown with WM_EX_NOACTIVE which means that it doesn't in active state when displaying, that's why IME could not work correctly in this regard, to workaround this issue, you could try set the Popup as the active window using win32 SetActiveWindow() API as following code shows:

    <Window x:Class="IME.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:IME"
        Title="Window1" Height="300" Width="300">
      <StackPanel >
        <StackPanel Orientation="Horizontal">
          <TextBlock>Outside popup:</TextBlock>
          <TextBox Name="txtOK" Width="100"/>
        </StackPanel>
        <Button Name="btnShowPopup" Click="btnShowPopup_Click">Show Popup!</Button>
        <local:MyPopup
            x:Name="popup"
            Placement="Bottom"
            PlacementTarget="{Binding ElementName=btnShowPopup}">
          <Border Background="White">
            <StackPanel Orientation="Horizontal">
              <TextBlock Name="txtError">Inside popup:</TextBlock>
              <TextBox Width="80" x:Name="textBox"/>
            </StackPanel>
          </Border>
        </local:MyPopup>
      </StackPanel>
    </Window>

    public class MyPopup : Popup
    {
        [DllImport("user32.dll")]
        static extern IntPtr SetActiveWindow(IntPtr hWnd);

        static MyPopup()
        {
            EventManager.RegisterClassHandler(
                typeof(MyPopup),
                Popup.PreviewGotKeyboardFocusEvent,
                new KeyboardFocusChangedEventHandler(OnPreviewGotKeyboardFocus),
                true);
        }

        private static void OnPreviewGotKeyboardFocus(Object sender, KeyboardFocusChangedEventArgs e)
        {
            var textBox = e.NewFocus as TextBoxBase;
            if (textBox != null)
            {
                var hwndSource = PresentationSource.FromVisual(textBox) as HwndSource;
                if (hwndSource != null)
                {
                    SetActiveWindow(hwndSource.Handle);
                }
            }
        }
    }

    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void btnShowPopup_Click(object sender, RoutedEventArgs e)
        {
            popup.IsOpen = !popup.IsOpen;
        }
    }

    Hope this helps


    Another Paradigm Shift
    http://shevaspace.blogspot.com
    • Marked as answer by Marco Zhou Friday, January 2, 2009 10:23 AM
    Wednesday, December 31, 2008 8:49 AM
  • add reference

    using System.Windows.Forms;



    create class level variable

    bool CtrlKeyDown = false;



            private void txt_PreviewKeyUp(object sender, System.Windows.Input.KeyEventArgs e)  
            {  
                if ((e.Key.ToString() == "LeftCtrl") || (e.Key.ToString() == "RightCtrl"))  
                {  
                    CtrlKeyDown = false;  
                }  
            }  
            private void txt_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)  
            {  
                if ((e.Key.ToString() == "LeftCtrl") || (e.Key.ToString() == "RightCtrl"))  
                {  
                    CtrlKeyDown = true;  
                }  
     
                if (CtrlKeyDown)  
                {  
                    if (e.Key.ToString() == "Space")  
                    {  
                        //sending ctrl + Shift when ctrl + space is pressed. from code.  
                        SendKeys.SendWait("^+");  
                        e.Handled = true;  
                    }  
                }  
            }  
     


            <StackPanel >    
            <StackPanel Orientation="Horizontal">    
                <TextBlock>Outside popup:</TextBlock>    
                <TextBox Name="txtOK" Width="100"/>    
            </StackPanel>    
            <Button Name="btnShowPopup" Click="btnShowPopup_Click">Show Popup!</Button>    
            <Popup Name="popup" Placement="Bottom" PlacementTarget="{Binding ElementName=btnShowPopup}">    
                <Border Background="White">    
                    <StackPanel Orientation="Horizontal">    
                        <TextBlock>Inside popup:</TextBlock>    
                        <TextBox Name="txtError" Width="80"  PreviewKeyUp="txt_PreviewKeyUp" PreviewKeyDown="txt_PreviewKeyDown"/>    
                    </StackPanel>    
                </Border>    
            </Popup> 
            </StackPanel>   


    When I press CTRL + SPACE I handle this in Preview Events which are tunneling Events.

    and I send Keys to CTRL+SHIFT to work in my system when i press CTRL+SPACE

    The same code you can modify from   if (e.Key.ToString() == "Space")  to Shift and try pressing CTRL+Shift from your system
    then sendkeys CTRL+SPACE

    CTRL="^"
    SHIFT ="+"


    I was also thinking of calling some API if this approach doesnt work, already there is one solution above by Marco Zhou. 

    Either both or any one should help you :)
     


    Prasad - www.beautifulmind.blog.co.in
    • Marked as answer by Marco Zhou Friday, January 2, 2009 10:23 AM
    Thursday, January 1, 2009 5:58 AM
  • Thanks, Marco, it's working.
    I would have marked your post as answer if I got the reply notification mail earlier.
    Friday, January 2, 2009 11:27 AM
  • prasad22, thanks for your help, again :)
    Friday, January 2, 2009 11:31 AM