zoukankan      html  css  js  c++  java
  • 不在同一程序内,如何在光标处(当前有焦点的窗体输入框)输入字符

    因测试一个程序,该程序的安卓端执行扫描条码二维码操作,然后服务器端需要在PC当前处于激活状态的窗体的当前光标处显示安卓程序扫描到的条形码。这是博主“小李飞菜刀”的扫描宝服务程序。场景就是苦于手边没有扫描枪,又想测试条码扫描。“小李飞菜刀”同学使用的是 "SendKeys"的“Send”方法。这是同一应用才能有效的办法。如果需要在其他应用的光标处输入字符,就只有使用"SendMessage"的windows api了。经过一番搜索,抄到段代码,测试了一下没有效果,TNND。请围观:

            [DllImport("user32.dll")]
            public static extern IntPtr GetForegroundWindow();
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
            [DllImport("user32.dll")]
            static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
    
            [DllImport("user32.dll")]
            static extern bool GetGUIThreadInfo(uint idThread, ref GUITHREADINFO lpgui);
    
    
            [StructLayout(LayoutKind.Sequential)]
            public struct GUITHREADINFO
            {
                public int cbSize;
                public int flags;
                public IntPtr hwndActive;
                public IntPtr hwndFocus;
                public IntPtr hwndCapture;
                public IntPtr hwndMenuOwner;
                public IntPtr hwndMoveSize;
                public IntPtr hwndCaret;
                public RECT rectCaret;
            }
    
            public static GUITHREADINFO? GetGuiThreadInfo(IntPtr hwnd)
            {
                if (hwnd != IntPtr.Zero)
                {
                    //Mbox.Info(GetTitle(hwnd), "O");
                    uint threadId = GetWindowThreadProcessId(hwnd, IntPtr.Zero);
    
                    GUITHREADINFO guiThreadInfo = new GUITHREADINFO();
                    guiThreadInfo.cbSize = Marshal.SizeOf(guiThreadInfo);
    
                    if (GetGUIThreadInfo(threadId, ref guiThreadInfo) == false)
                        return null;
                    return guiThreadInfo;
                }
                return null;
            }
    
            public static void SendText(string text)
            {
                IntPtr hwnd = GetForegroundWindow();
                if (String.IsNullOrEmpty(text))
                    return;
                Hwindow.GUITHREADINFO? guiInfo = Hwindow.GetGuiThreadInfo(hwnd);
                if (guiInfo != null)
                {
                    IntPtr ptr = (IntPtr)guiInfo.Value.hwndCaret;
                    if (ptr != IntPtr.Zero)
                    {
                        for (int i = 0; i < text.Length; i++)
                        {
                            SendMessage(ptr, Message.WM_CHAR, (IntPtr)(int)text[i], IntPtr.Zero);
                        }
                    }
                }
            }
    

     这是csdn抄的,原文:C#怎么获得当前屏幕光标的位置,然后在光标的位置上输入想输入数据

    发现RECT没办法被感知,又一番搜索发现是个结构体:

    [StructLayout(LayoutKind.Sequential)]
            public struct RECT
            {
                int left;
                int top;
                int right;
                int bottom;
            }
    

    加上之后可以编译成功。但是没效果,仔细调试下来对方法“SendText”进行了修改。代码的主要思路:用GetForegroundWindow找到焦点窗体,

    然后GetWindowThreadProcessId和GetGUIThreadInfo找到含有光标的控件句柄,即GUITHREADINFO中的hwndCaret,然后用该句柄发送消息。

    下面贴上修改后有效果的代码:

     [DllImport("user32.dll")]
            public static extern IntPtr GetForegroundWindow();
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
            [DllImport("user32.dll")]
            static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
            [DllImport("user32.dll")]
            static extern bool GetGUIThreadInfo(uint idThread, ref GUITHREADINFO lpgui);
            [StructLayout(LayoutKind.Sequential)]
            public struct GUITHREADINFO
            {
                public int cbSize;
                public int flags;
                public IntPtr hwndActive;
                public IntPtr hwndFocus;
                public IntPtr hwndCapture;
                public IntPtr hwndMenuOwner;
                public IntPtr hwndMoveSize;
                public IntPtr hwndCaret;
                public RECT rectCaret;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct RECT
            {
                int left;
                int top;
                int right;
                int bottom;
            }
            public GUITHREADINFO? GetGuiThreadInfo(IntPtr hwnd)
            {
                if (hwnd != IntPtr.Zero)
                {
                    uint threadId = GetWindowThreadProcessId(hwnd, IntPtr.Zero);
                    GUITHREADINFO guiThreadInfo = new GUITHREADINFO();
                    guiThreadInfo.cbSize = Marshal.SizeOf(guiThreadInfo);
                    if (GetGUIThreadInfo(threadId, ref guiThreadInfo) == false)
                        return null;
                    return guiThreadInfo;
                }
                return null;
            }
    
            protected void SendText(string text)
            {
                IntPtr hwnd = GetForegroundWindow();
                if (String.IsNullOrEmpty(text))
                    return;
                GUITHREADINFO? guiInfo = GetGuiThreadInfo(hwnd);
                if (guiInfo != null)
                {
                    for (int i = 0; i < text.Length; i++)
                    {
                        SendMessage(guiInfo.Value.hwndFocus, 0x0102, (IntPtr)(int)text[i], IntPtr.Zero);
                    }
                }
            }
    

      

    主要发现 “IntPtr ptr = (IntPtr)guiInfo.Value.hwndCaret;”,这里始终是0.改成: SendMessage(guiInfo.Value.hwndFocus, 0x0102, (IntPtr)(int)text[i], IntPtr.Zero);

    hwndFocus字面意思就是当前光标处的句柄。搞定,收工!

  • 相关阅读:
    codeforces 616E. Sum of Remainders 数学
    codeforces 620F. Xors on Segments
    codeforces 417D. Cunning Gena 状压dp
    bzoj 1934 : [Shoi2007]Vote 善意的投票 最小割
    codeforces 628F. Bear and Fair Set 网络流
    codeforces 626E. Simple Skewness 三分
    div嵌套,内层的margin-top会跑到外层
    测试用导航(为了方便在各个测试页面间进行跳转,只需将此js代码引入每个页面即可) V2.0
    ECS_8080端口连接拒绝问题排查
    京东技术架构(二)构建需求响应式亿级商品详情页
  • 原文地址:https://www.cnblogs.com/datacool/p/win_api_sendmessage_hwndFocus.html
Copyright © 2011-2022 走看看