2012-04-23 18 views
5

Próbuję użyć SendMessage, aby wysłać naciśnięcie klawisza i naprawdę nie rozumiem lParam. Rozumiem, że różne bity reprezentują każdy parametr i że muszą być uporządkowane w kolejności.Jak utworzyć lParam z SendMessage WM_KEYDOWN

Czytałem this question & this, więc wiem jakiej kolejności bity muszą być, po prostu nie wiem jak to zrobić ...

Jak utworzyć następujące lParam?

repeat cound = 0, 
scan code = {Don't know what this is?}, 
extended key = 1, 
reserved = 0, 
context code = 0, 
previous key state = 1, 
transition state = 0 
+0

Jak połączonych państw post, nie używać SendMessage wysłać naciśnięcia klawiszy, zamiast używać SendInput. http://blogs.msdn.com/b/oldnewthing/archive/2005/05/30/423202.aspx –

+1

@RussC: Dzięki, ale trzeba to zrobić z SendMessage, ponieważ chcę wysłać klucz do okna innego niż aktywny. Naprawdę po prostu muszę wiedzieć, jak zbudować ten LParam. – Drahcir

+0

Zaktualizowałem swoją odpowiedź poniżej. Czy możesz wyjaśnić, że będziesz wysyłać wiadomość WM_KEYDOWN do SendMessage? –

Odpowiedz

8

uświadomiłem sobie, że AutoIT posiada funkcjonalność, że muszę, więc mieć spojrzał na source plików sendKeys.cpp i znaleźć następujący fragment kodu C++ dla tej funkcji, to będzie dość łatwy do przełożenia na C#:

scan = MapVirtualKey(vk, 0); 

// Build the generic lparam to be used for WM_KEYDOWN/WM_KEYUP/WM_CHAR 
lparam = 0x00000001 | (LPARAM)(scan << 16);   // Scan code, repeat=1 
if (bForceExtended == true || IsVKExtended(vk) == true) 
    lparam = lparam | 0x01000000;  // Extended code if required 

if ((m_nKeyMod & ALTMOD) && !(m_nKeyMod & CTRLMOD)) // Alt without Ctrl 
    PostMessage(m_hWnd, WM_SYSKEYDOWN, vk, lparam | 0x20000000); // Key down, AltDown=1 
else 
    PostMessage(m_hWnd, WM_KEYDOWN, vk, lparam); // Key down 

Kod skanowania może być gener ated z MapVirtualKey

C# Tłumaczenie:

public static void sendKey(IntPtr hwnd, VKeys keyCode, bool extended) 
{ 
    uint scanCode = MapVirtualKey((uint)keyCode, 0); 
    uint lParam; 

    //KEY DOWN 
    lParam = (0x00000001 | (scanCode << 16)); 
    if (extended) 
    { 
     lParam |= 0x01000000; 
    } 
    PostMessage(hwnd, (UInt32)WMessages.WM_KEYDOWN, (IntPtr)keyCode, (IntPtr)lParam); 

    //KEY UP 
    lParam |= 0xC0000000; // set previous key and transition states (bits 30 and 31) 
    PostMessage(hwnd, WMessages.WM_KEYUP, (uint)keyCode, lParam); 
} 

[DllImport("user32.dll", CharSet = CharSet.Auto)] 
private static extern uint MapVirtualKey(uint uCode, uint uMapType); 
1

Jeśli koniecznie trzeba używać SendMessage, to trzeba włączyć bity swojej int w odpowiednich pozycjach.

Ta strona dokumenty, jak to zrobić w C#:

http://codeidol.com/csharp/csharpckbk2/Classes-and-Structures/Turning-Bits-On-or-Off/

Odnosząc się do pytania, scancode jest wartość klucza, który próbujesz wysłać i reprezentuje pewne stany zbyt. Na przykład kod skanowania naciskając A różni się od kodu do zwalniania A.

Wikipedia ma artykuł o nich:

http://en.wikipedia.org/wiki/Scancode