2

[代码上下文]

大家好,

我正在开发一个应用程序,它通过发送键盘事件来启动复制或粘贴事件以按下键 C 和 Ctrl。

我实际上有这种方法来发送 Kb 事件:

[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);

public static void PressKey(Keys key, bool up)
{
    const int KEYEVENTF_EXTENDEDKEY = 0x1;
    const int KEYEVENTF_KEYUP = 0x2;
    if (up)
    {
        keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, (UIntPtr)0);
    }
    else
    {
        keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY, (UIntPtr)0);
    }
}

调用:

private void launchCopy()
{
    PressKey(Keys.ControlKey, false);
    PressKey(Keys.C, false);
    PressKey(Keys.C, true);
    PressKey(Keys.ControlKey, true);
}

并使用静态方法获得结果:

System.Windows.Forms.Clipboard.GetText()

用户必须使用鼠标按下其他键 et 才能启动此事件,所以我使用 SFML 来使用Keyboard.IsKeyPressed(Keyboard.Key key);SFML 2.0 中的功能取回用户操作。

我创建了一个无限循环等待用户事件,然后启动复制并处理复制数据。这段代码工作正常 然后我用一些窗口创建了另一个 WPF 解决方案,我正在使用NotifyIcon。加载主窗口后,使用循环方法创建一个线程(在用户事件-> launchCopy 上)。

[调试]

当用户按下复制事件时,会调用 PressKey 方法,但ClipBoard.GetText ()方法返回的是空字符串。使用 SFML 我检查了键是否真的被按下

  private void PrintState ()
  {
    Console.WriteLine(Keyboard.IsKeyPressed(Keyboard.Key.C)  &&
                      (Keyboard.IsKeyPressed(Keyboard.Key.LControl) ||
                       Keyboard.IsKeyPressed(Keyboard.Key.RControl)));
  }

private void launchCopy()
{
    PrintState ();
    PressKey(Keys.ControlKey, false);
    PressKey(Keys.C, false);
    PrintState ();
    PressKey(Keys.C, true);
    PressKey(Keys.ControlKey, true);
    PrintState ();
}

输出是:

假 真 假

就像它应该...

[问题]

为什么快捷方式复制模拟不适用于此应用程序?从工作代码我:

  • 将代码放在另一个线程中
  • 1 其他线程但相同的应用程序:WPF windows + NotifyIcon 库

是否有可能与 WPF 发生冲突?PrintState 或者在另一个线程中使用方法的问题?

我迷失了要调试这个。

任何帮助或想法将不胜感激

谢谢。

4

1 回答 1

0

永远都不迟。

这个线程解决了我的问题,不是发送事件,问题是检索剪贴板数据。

这是我用于从另一个线程使用剪贴板的代码:

public static class fastClipboard
{
        [DllImport("user32.dll")]
        static extern IntPtr GetClipboardData(uint uFormat);
        [DllImport("user32.dll")]
        static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);
        [DllImport("user32.dll")]
        static extern bool IsClipboardFormatAvailable(uint format);
        [DllImport("user32.dll", SetLastError = true)]
        static extern bool OpenClipboard(IntPtr hWndNewOwner);
        [DllImport("user32.dll", SetLastError = true)]
        static extern bool CloseClipboard();
        [DllImport("kernel32.dll")]
        static extern IntPtr GlobalLock(IntPtr hMem);
        [DllImport("kernel32.dll")]
        static extern bool GlobalUnlock(IntPtr hMem);

        const uint CF_UNICODETEXT = 13;

        public static bool SetText(string data)
        {
            if (!IsClipboardFormatAvailable(CF_UNICODETEXT))
                return false;
            if (!OpenClipboard(IntPtr.Zero))
                return false;

            var ptr = Marshal.StringToHGlobalUni(data);
            var res = SetClipboardData(CF_UNICODETEXT, ptr);
            CloseClipboard();
            if (res != IntPtr.Zero)
                return true;
            else
                return false;
        }

        public static string GetText()
        {
            if (!IsClipboardFormatAvailable(CF_UNICODETEXT))
                return null;
            if (!OpenClipboard(IntPtr.Zero))
                return null;

            string data = null;
            var hGlobal = GetClipboardData(CF_UNICODETEXT);
            if (hGlobal != IntPtr.Zero)
            {
                var lpwcstr = GlobalLock(hGlobal);
                if (lpwcstr != IntPtr.Zero)
                {
                    data = Marshal.PtrToStringUni(lpwcstr);
                    GlobalUnlock(lpwcstr);
                }
            }
            CloseClipboard();
            return data;
        }
    }
于 2013-10-12T15:36:34.353 回答