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字面意思就是当前光标处的句柄。搞定,收工!

  • 相关阅读:
    Software Architecture软件架构(方法、模式与框架)纵横谈
    SOLID: OOP的五大原则(译)
    《第一行代码》14章cool weather酷欧天气 网络请求相关问题
    前后端数据交互利器--Protobuf
    树状数组基础
    endless 如何实现不停机重启 Go 程序?
    fasthttp:比net/http快十倍的Go框架(server 篇)
    Mysql MVCC机制
    Docker构建mysql主从
    浅析b站2021/7/13日晚服务崩溃问题
  • 原文地址:https://www.cnblogs.com/datacool/p/win_api_sendmessage_hwndFocus.html
Copyright © 2011-2022 走看看