[ C# ] Send Key (Poszukiany - Poszukiwana)

0

Witam próbuje znaleźć jakiś sposób, który pozwoli na symulowanie realnego wciskania klawiszy. Napisałem sobie kod z użyciem SendInput z user32 ale niestety nie działa z niektórymi programami, nie mogę wykonać ciągłego wciśnięcia (samego KEY DOWN) oraz nie da się użyć kombinacji np: Ctrl+c/v/f itp. Oto kawałek kodu:

     public void Perform(short code)
    {

                  INPUT[] inp = new INPUT[2];

                   inp[0].type = INPUT_KEYBOARD;
                   inp[0].ki = createKeybdInput(code, 0);
                   //inp[1].type = INPUT_KEYBOARD;
                   //inp[1].ki = createKeybdInput(code, KEYEVENTF_KEYUP);

                  SendInput((uint)inp.Length, inp, Marshal.SizeOf(inp[0].GetType()));
    }

Pytanie mam następujące - Gdzie mogę znaleźć lub jak wykonać kod inny niż SendInput, który pozwolił by na realną symulację wciskania klawiszy ?

0

popróbuj z SendMessage albo PostMessage

z sendmessage było by jakoś

Sendmessage(IntPtr_handle, wm_keydown, Convert.ToInt32(Keys.C|Keys.Control), 0);

0

SendMessage na wstępie odpada, gdyż trzeba mu podawać uchwyt na okno : ( ... chyba żeby dopisać jakąś metodę do odnajdywania nazwy "najwyższego" okna... ale na to akurat nie mam za bardzo koncepcji.

[DllImport("user32.dll")]
            public static extern int SendMessage
                  (
                          int hWnd,      // handle to destination window
                          uint Msg,       // message
                          long wParam,  // first message parameter
                          long lParam   // second message parameter
                  );

Z PostMessage niestaty jest tak samo i trzeba uzyć:


[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 

oraz

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent,
     IntPtr hwndChildAfter,
     string lpszClass,
     string lpszWindow
); 

Węc wygląda na to że nadal lipa... a może coś w Asmie (MASM najlepiej - bo tego chociaż troszkę znam) poszukać ?

0

Okno można znaleźć po nazwie, zapewne da się też sprawdzić czy dane okno ma w danej chwili focus, ale...
Okno uchwyt do okna aktywnego można dostać metodą chyba GetforegroundWindow

0

Po przemyśleniu całej sprawy... najbardziej zleżało by mi na osobnym wywoływaniu key down i key up... bo używając kodu z 1 postu zawsze wychodzi key pressed

inp[0].type = INPUT_KEYBOARD;
inp[0].ki = createKeybdInput(code, 0);

Starałem się wydłużyć czas key down zmieniając "time" ale to nie daje żadnych efektów.

         private KEYBDINPUT createKeybdInput(short wVK, uint flag)
        {
            KEYBDINPUT i = new KEYBDINPUT();
            i.wVk = (ushort)wVK;
            i.wScan = 0;
            i.time = 0;
            i.dwExtraInfo = IntPtr.Zero;
            i.dwFlags = flag;
            return i;
        }

jakieś propozycje ?

PS: Żeby wszystko było jasne załączam cały kod, który naskrobałem:
PS_2: (celowo zrobiłem kilka literówek)

        structure KEYBDINPUT
        {
            public ushort wVk;
            public ushort wScan;
            public uint dwFlag;
            public uint times;
            public IntPtr dwExtraInfo;
        }

        structure INPUT
        {
            public int type;
            public KEYBDINPUT ki;
        }

        [DllImport("user32.dll")]
        private statics uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

        const int INPUT_KEYBOARD = 1;
        const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
        const uint KEYEVENTF_KEYUP = 0x0002;
        const uint KEYEVENTF_UNICODE = 0x0004;
        const uint KEYEVENTF_SCANCODE = 0x0008;


        private KEYBDINPUT createKeybdInput(short wVK, uint flag)
        {
            KEYBDINPUT i = new KEYBDINPUT();
            i.wVk = (ushort)wVK;
            i.wScan = 0;
            i.time = 0;
            i.dwExtraInfo = IntPtr.Zero;
            i.dwFlags = flag;
            return i;
        }

        public voids Perform(short code)
        {

            INPUT[] inp = new INPUT[2];

            inp[0].type = INPUT_KEYBOARD;
            inp[0].ki = createKeybdInput(code, 0);
            //inp[1].type = INPUT_KEYBOARD;
            //inp[1].ki = createKeybdInput(code, KEYEVENTF_KEYUP);

            SendInput((uint)inp.Length, inp, Marshal.SizeOf(inp[0].GetType()));

        }
0

sendmessage da sie wywołać keyup keydown :)

0

Ale trzeba znać nazwę okna... której nie będzie można przewidzieć, lub np: trzeba będzie zmienić nazwę ikony z pulpitu ... wtedy SendMessage nie zadziała.

0

Nie chcę gotowca... chciałbym napisać coś takiego sam tylko nie bardzo wiem od czego zacząć :( Nikt nie ma pomysłu jak Input Symulator z powyższego linku jest zrobiony ?

0

Mistrzu, tam w download z tego linku masz też link do źródła tego kodu.

0

I'm blind ... please help me : | ... i see there only Soure Code of changes :(

PS... I'm sooo sorry i'm just found InputSimulator.0.1.0.0-src.zip

PS2.. But i'm still think it's crap ... this code do this same, what i do...

PS3.. Sprawdziłem... też tam nie działa key down Oo ... co za bieda ... zrobili nawet własną stronę int. do projektu, w którym nawet nie działa podstawowa funkcja ... omg.

0

co do sendmessage...
nie można przewidzieć nazwy okna ale można dostać okno z focusem, czyli to aktywne...
Ale jak nie to nie ;P

0

Jak już jesteśmy przy temacie wciskania to... nie jest to dziwne, że da się wyłapać KeyDown na własnej formatce ?

this.KeyDown +=new System.Windows.Forms.KeyEventHandler(Form1_KeyDown);

da się to jakoś obejść ?... bo wiem, że mógłbym wciąż sprawdzać status całej klawy ale mija się to z celem... jest więc jakiś trick ?

PS.... SORY ale ja jestem czop... przeciez standardowo jest KeyPreview na false ..... Oo

0

Mam kolejny problem... Nie ma jakiejś możliwości, żeby SendInput działał w okienkach DirectX ? Bo jeśli wysyłam klawisz na normalne okno to jest OK, ale, gdy na Dx-owe to nic się nie dzieje.

PS: WSZEM I WOBEC.... OTO rozwiązanie....:

-nalezy dodać do dwFlags-a info o SCANCODE i w wScan dac kod , jaki jest w tablicy klawy dla DX (Microsoft.DX.DXINput.Key itd) np:

dla literki W scancode to 17 dla DX (oczywiscie i tak trzeba standarody scan przekazywać w uni (np: 0x57 dla W)

if (keyDown == true)
{
prea.ki.wScan = 17;
prea.ki.dwFlags = 0;
}
else
{
prea.ki.dwFlags = (ushort)KEYEVENTF_SCANCODE;
prea.ki.dwFlags += (ushort)KEYEVENTF_KEYUP;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1