none
Winfrom 中使用 ImmGetContext,返回值总是0,请问如何破? RRS feed

  • 问题

  • 我的使用的是 .Net Framework 4.0,winform 程序

    在项目中我为了控制输入法显示,使用了 ImmGetContext(IntPtr hwnd),但是该方法返回值总是0,这是怎么回事儿,求解

    我的代码如下:

                _fixime = delegate
                {
                    IntPtr HIme = ImmGetContext(this.Handle);
                    
                    ImmSetOpenStatus(HIme, false);
                };
                this.BeginInvoke(_fixime);
    希望各位帮帮忙啊
    2014年1月7日 3:05

全部回复

  • 请参考以下代码,在我的机器上运行没有问题,可以判断输入法的状态:

    public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            //声明一些API函数
            [DllImport("imm32.dll")]
            public static extern IntPtr ImmGetContext(IntPtr hwnd);
            [DllImport("imm32.dll")]
            public static extern bool ImmGetOpenStatus(IntPtr himc);
            [DllImport("imm32.dll")]
            public static extern bool ImmSetOpenStatus(IntPtr himc, bool b);
            [DllImport("imm32.dll")]
            public static extern bool ImmGetConversionStatus(IntPtr himc, ref int lpdw, ref int lpdw2);
            [DllImport("imm32.dll")]
            public static extern int ImmSimulateHotKey(IntPtr hwnd, int lngHotkey);
            private const int IME_CMODE_FULLSHAPE = 0x8;
            private const int IME_CHOTKEY_SHAPE_TOGGLE = 0x11;
            //重载Form的OnActivated
            protected override void OnActivated(EventArgs e)
            {
                base.OnActivated(e);
    
                this.textBox1.Focus();
    
                IntPtr HIme = ImmGetContext(this.Handle);
                if (ImmGetOpenStatus(HIme))  //如果输入法处于打开状态
                {
                    int iMode = 0;
                    int iSentence = 0;
                    bool bSuccess = ImmGetConversionStatus(HIme, ref iMode, ref iSentence);  //检索输入法信息
                    if (bSuccess)
                    {
                        if ((iMode & IME_CMODE_FULLSHAPE) > 0)   //如果是全角
                            ImmSimulateHotKey(this.Handle, IME_CHOTKEY_SHAPE_TOGGLE);  //转换成半角
                    }
    
                }
            }
        }
    ImmGetContext只能获取到当前进程的输入上下文,所以要保证检查的句柄在当前线程中。

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    2014年1月8日 6:47
    版主
  • 请参考以下代码,在我的机器上运行没有问题,可以判断输入法的状态:

    public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            //声明一些API函数
            [DllImport("imm32.dll")]
            public static extern IntPtr ImmGetContext(IntPtr hwnd);
            [DllImport("imm32.dll")]
            public static extern bool ImmGetOpenStatus(IntPtr himc);
            [DllImport("imm32.dll")]
            public static extern bool ImmSetOpenStatus(IntPtr himc, bool b);
            [DllImport("imm32.dll")]
            public static extern bool ImmGetConversionStatus(IntPtr himc, ref int lpdw, ref int lpdw2);
            [DllImport("imm32.dll")]
            public static extern int ImmSimulateHotKey(IntPtr hwnd, int lngHotkey);
            private const int IME_CMODE_FULLSHAPE = 0x8;
            private const int IME_CHOTKEY_SHAPE_TOGGLE = 0x11;
            //重载Form的OnActivated
            protected override void OnActivated(EventArgs e)
            {
                base.OnActivated(e);
    
                this.textBox1.Focus();
    
                IntPtr HIme = ImmGetContext(this.Handle);
                if (ImmGetOpenStatus(HIme))  //如果输入法处于打开状态
                {
                    int iMode = 0;
                    int iSentence = 0;
                    bool bSuccess = ImmGetConversionStatus(HIme, ref iMode, ref iSentence);  //检索输入法信息
                    if (bSuccess)
                    {
                        if ((iMode & IME_CMODE_FULLSHAPE) > 0)   //如果是全角
                            ImmSimulateHotKey(this.Handle, IME_CHOTKEY_SHAPE_TOGGLE);  //转换成半角
                    }
    
                }
            }
        }
    ImmGetContext只能获取到当前进程的输入上下文,所以要保证检查的句柄在当前线程中。



    你说的“要保证检查的句柄在当前线程中”,是不是因为我用了MDI容器的原因?在我的项目中会有个主窗体MainForm,此窗体的IsMdiContainer属性为true,然后其他所有显示的窗体都会指定MdiParent 属性为MainForm,经过多次测试,发现:只要控制输入法显示的窗体不指定MdiParent属性,则ImmGetContext(IntPtr hwnd)能正常返回句柄。

    这是为什么?

    2014年1月10日 2:21
  • 不好意思,我输入错误:ImmGetContext只能获取到当前进程的输入上下文,所以要保证检查的句柄在当前进程中。

    可以参考一下MSDN文档:http://msdn.microsoft.com/zh-cn/library/windows/desktop/dd318558(v=vs.85).aspx

    其中有一段说明:

    An application should routinely use this function to retrieve the current input context before attempting to access information in the context.

    The application must call ImmReleaseContext when it is finished with the input context.

     我经过测试发现只要窗体没有获取到输入焦点,那么这个函数就会返回0,但是给它一个输入焦点的话就可以返回正常值。就像我上面代码里面的这句:

    this.textBox1.Focus();


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2014年1月10日 5:28
    版主
  •  我经过测试发现只要窗体没有获取到输入焦点,那么这个函数就会返回0,但是给它一个输入焦点的话就可以返回正常值。就像我上面代码里面的这句:

    this.textBox1.Focus();

    谢谢你的答复,我也不想麻烦你了,唉,我不知道我哪里出问题了,我按你说的设置焦点了,只要是我在Show的时候指定MdiParent属性后,ImmGetContext(IntPtr hwnd)还是不能获取到句柄,它的返回值为0,不指定MdiParent属性就没问题。

    我的子窗体是MrPrintForm,里面的控制输入法代码如下:(请不要纠结中文命名,这是测试方便查看)

            private void txt姓名_Enter(object sender, EventArgs e)
            {
                txt姓名.Focus();
    
                IntPtr HIme = ImmGetContext(this.Handle);
                ImmSetOpenStatus(HIme, true);
            }

    MainForm窗体中显示MrPrintForm窗体的代码:(请不要纠结中文命名,这是测试方便查看)

            private void 病案打印ToolStripMenuItem_Click(object sender, EventArgs e)
            {
                var aForm = MrPrintForm.GetInstance();
                aForm.MdiParent = this;
                aForm.Show();
                aForm.WindowState = FormWindowState.Maximized;
            }


    2014年1月15日 3:02
  • DebugException:

    我测试下来是完全正常可以的,附上我的测试图片:


    顺便附上代码:

    【MinForm,父窗体】

                   
    namespaceCSharp
    {
        publicpartialclassMainForm : Form
        {
            publicMainForm()
            {
                InitializeComponent();
            }
     
            privatevoidcreateToolStripMenuItem_Click(objectsenderEventArgse)
            {
                SubFormsf=newSubForm();
                sf.MdiParent=this;
                sf.Show();
    sf.WindowState = FormWindowState.Maximized;         }     } }

    【SubForm,子窗体】

    namespace CSharp
    {
        public partial class SubForm : Form
        {
            //声明一些API函数
            [DllImport("imm32.dll")]
            public static extern IntPtr ImmGetContext(IntPtr hwnd);
            [DllImport("imm32.dll")]
            public static extern bool ImmGetOpenStatus(IntPtr himc);
            [DllImport("imm32.dll")]
            public static extern bool ImmSetOpenStatus(IntPtr himcbool b);
            [DllImport("imm32.dll")]
            public static extern bool ImmGetConversionStatus(IntPtr himcref int lpdwref int lpdw2);
            [DllImport("imm32.dll")]
            public static extern int ImmSimulateHotKey(IntPtr hwndint lngHotkey);
            private const int IME_CMODE_FULLSHAPE = 0x8;
            private const int IME_CHOTKEY_SHAPE_TOGGLE = 0x11;
     
            public SubForm()
            {
                InitializeComponent();
            }
     
            private void SubForm_Load(object senderEventArgs e)
            {
                IntPtr HIme = ImmGetContext(this.Handle);
                if (ImmGetOpenStatus(HIme))  //如果输入法处于打开状态
                {
                    int iMode = 0;
                    int iSentence = 0;
                    bool bSuccess = ImmGetConversionStatus(HImeref iModeref iSentence);  //检索输入法信息
                    if (bSuccess)
                    {
                        if ((iMode & IME_CMODE_FULLSHAPE> 0)   //如果是全角
                            ImmSimulateHotKey(this.HandleIME_CHOTKEY_SHAPE_TOGGLE);  //转换成半角
                    }
     
                }
            }
        }
    

    PS:你的单利模式怎么实现的?

    var aForm = MrPrintForm.GetInstance();

    ASP.NET Questions
    Other Discussions
    FreeRice Donate
    Issues to report
    Free Tech Books Search

    2014年1月17日 3:11
    版主