2

[CODE CONTEXT]

Hi everyone,

I'm working on an application which launch copy or paste event by sending keyboard event to press key C and Ctrl.

I'm actually having this method to send Kb event :

[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);
    }
}

called with :

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

and getting the result with the static method :

System.Windows.Forms.Clipboard.GetText()

The user has to press other key et using mouse to launch this event, so i'm using SFML to get back the user action using the function Keyboard.IsKeyPressed(Keyboard.Key key); from SFML 2.0.

I've created a infinite loop waiting for a user event, then launch copy and process on the copy data. This code works fine Then I've created another WPF solution with some window and i'm using NotifyIcon. The main window, after be loaded, create a thread with a method whith the loop (on user event -> launchCopy).

[DEBUG]

When the user press copy event, PressKey method is called, but empty string is returned by ClipBoard.GetText () method. Using SFML I checked if the key are really pressed

  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 ();
}

And output is :

False True False

Like it should be...

[QUESTIONS]

Why the shortcut copy simulation doesn't work on this application? From the working code I :

  • put the code in another Thread
  • 1 Other thread but same application : WPF windows + NotifyIcon library

Is it possible to have a conflit with WPF ? Or a problem using PrintState method in another thread ?

I'm lost about about to debug this.

Any help or idea would be appreciated

Thanks.

nawfal
  • 70,104
  • 56
  • 326
  • 368
Marcassin
  • 1,386
  • 1
  • 11
  • 21

1 Answers1

0

never too late.

My problem was resolved by this thread, It wasn't the send event, the issue was to retrieve the clipboard data.

Here is the code i used for use the clipboard from another thread :

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;
        }
    }
Marcassin
  • 1,386
  • 1
  • 11
  • 21