Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu bölüm aşağıdaki amaçlar için örnek kodu içerir:
- Ham Veri Girişine Kayıt Olma
- Ham Girişin Standart Okumasını Gerçekleştirme
- Ham Girişin Arabelleğe Alınan Okumasını Gerçekleştirme
Ham Girişe Kaydolma
Örnek 1
Bu örnekte bir uygulama, oyun kumandalarından (oyun tuş takımı ve oyun çubuğu) ve yanıtlama makineleri dışında telefon kullanımı sayfasından tüm cihazlardan gelen ham girişi belirtir.
RAWINPUTDEVICE Rid[4];
Rid[0].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC
Rid[0].usUsage = 0x05; // HID_USAGE_GENERIC_GAMEPAD
Rid[0].dwFlags = 0; // adds game pad
Rid[0].hwndTarget = 0;
Rid[1].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC
Rid[1].usUsage = 0x04; // HID_USAGE_GENERIC_JOYSTICK
Rid[1].dwFlags = 0; // adds joystick
Rid[1].hwndTarget = 0;
Rid[2].usUsagePage = 0x0B; // HID_USAGE_PAGE_TELEPHONY
Rid[2].usUsage = 0x00;
Rid[2].dwFlags = RIDEV_PAGEONLY; // adds all devices from telephony page
Rid[2].hwndTarget = 0;
Rid[3].usUsagePage = 0x0B; // HID_USAGE_PAGE_TELEPHONY
Rid[3].usUsage = 0x02; // HID_USAGE_TELEPHONY_ANSWERING_MACHINE
Rid[3].dwFlags = RIDEV_EXCLUDE; // excludes answering machines
Rid[3].hwndTarget = 0;
if (RegisterRawInputDevices(Rid, 4, sizeof(Rid[0])) == FALSE)
{
//registration failed. Call GetLastError for the cause of the error.
}
Örnek 2
Bu örnekte, bir uygulama klavye ve fareden ham giriş istiyor, ancak eski klavye ve fare pencere iletilerini yoksaymak istiyor (aynı klavye ve fareden gelebilir).
RAWINPUTDEVICE Rid[2];
Rid[0].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC
Rid[0].usUsage = 0x02; // HID_USAGE_GENERIC_MOUSE
Rid[0].dwFlags = RIDEV_NOLEGACY; // adds mouse and also ignores legacy mouse messages
Rid[0].hwndTarget = 0;
Rid[1].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC
Rid[1].usUsage = 0x06; // HID_USAGE_GENERIC_KEYBOARD
Rid[1].dwFlags = RIDEV_NOLEGACY; // adds keyboard and also ignores legacy keyboard messages
Rid[1].hwndTarget = 0;
if (RegisterRawInputDevices(Rid, 2, sizeof(Rid[0])) == FALSE)
{
//registration failed. Call GetLastError for the cause of the error
}
Ham Girişin Standart Okumasını Gerçekleştirme
Bu örnek, WM_INPUT ileti işleyicisinden standart okuma ham girişinin en düşük desenini gösterir. Her WM_INPUT iletisi, geçerli giriş olayına başvuran lParam'da bir HRAWINPUT tanıtıcısı taşır; DefWindowProc çağrılmadan önce GetRawInputData aracılığıyla okunmalıdır.
1000 Hz'deki fareler gibi yüksek frekanslı cihazlar için ileti döngüsü yinelemeleri arasında birden çok olay birikebilir. Bu durumda, kalan kuyruğu boşaltmak için GetRawInputBuffer ile ilerleyin. Aşağıdaki isteğe bağlı 2. Aşamaya bakın.
/* Initialized once at startup */
UINT g_bufferSize = 64 * sizeof(RAWINPUT);
void* g_pBuffer = NULL;
/* Call once before entering the message loop: */
/* g_pBuffer = malloc(g_bufferSize); */
void ProcessInput(const RAWINPUT* input)
{
if (input->header.dwType == RIM_TYPEKEYBOARD)
{
const RAWKEYBOARD* kb = &input->data.keyboard;
const char* transition = (kb->Flags & RI_KEY_BREAK) ? "up" : "down";
const char* extended = (kb->Flags & RI_KEY_E0) ? " e0" :
(kb->Flags & RI_KEY_E1) ? " e1" : "";
printf("keyboard: vk=0x%02x scan=0x%02x %s%s msg=0x%04x extra=0x%08x\n",
kb->VKey, kb->MakeCode, transition, extended,
kb->Message, kb->ExtraInformation);
}
else if (input->header.dwType == RIM_TYPEMOUSE)
{
const RAWMOUSE* mouse = &input->data.mouse;
const char* moveMode = (mouse->usFlags & MOUSE_MOVE_ABSOLUTE) ? "abs" : "rel";
printf("mouse: move %s dx=%d dy=%d\n", moveMode, mouse->lLastX, mouse->lLastY);
if (mouse->usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) printf(" left down\n");
if (mouse->usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) printf(" left up\n");
if (mouse->usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) printf(" right down\n");
if (mouse->usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) printf(" right up\n");
if (mouse->usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) printf(" middle down\n");
if (mouse->usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) printf(" middle up\n");
if (mouse->usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) printf(" x1 down\n");
if (mouse->usButtonFlags & RI_MOUSE_BUTTON_4_UP) printf(" x1 up\n");
if (mouse->usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) printf(" x2 down\n");
if (mouse->usButtonFlags & RI_MOUSE_BUTTON_5_UP) printf(" x2 up\n");
if (mouse->usButtonFlags & RI_MOUSE_WHEEL)
printf(" wheel delta=%d\n", (int)(short)mouse->usButtonData);
if (mouse->usButtonFlags & RI_MOUSE_HWHEEL)
printf(" hwheel delta=%d\n", (int)(short)mouse->usButtonData);
}
else if (input->header.dwType == RIM_TYPEHID)
{
const RAWHID* hid = &input->data.hid;
printf("hid: count=%u size=%u\n", hid->dwCount, hid->dwSizeHid);
}
}
void DrainRawInputQueue(void)
{
for (;;)
{
UINT bufferSize = g_bufferSize;
UINT count = GetRawInputBuffer((RAWINPUT*)g_pBuffer, &bufferSize, sizeof(RAWINPUTHEADER));
if (count == 0)
break;
if (count == (UINT)-1)
{
/* Buffer too small — grow and retry. */
g_bufferSize = max(bufferSize, g_bufferSize * 2);
g_pBuffer = realloc(g_pBuffer, g_bufferSize);
if (g_pBuffer == NULL)
break;
continue;
}
{
RAWINPUT* ri = (RAWINPUT*)g_pBuffer;
UINT i;
for (i = 0; i < count; ++i, ri = NEXTRAWINPUTBLOCK(ri))
ProcessInput(ri);
}
/* Do not break — there may be more events in the queue. */
}
}
/* ... */
case WM_INPUT:
{
/* Phase 1: read the event carried by this WM_INPUT message. */
UINT bufferSize = g_bufferSize;
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, g_pBuffer, &bufferSize, sizeof(RAWINPUTHEADER)) != (UINT)-1)
{
ProcessInput((RAWINPUT*)g_pBuffer);
}
/* Phase 2 (optional): drain any additional events that accumulated in the queue since this message was posted.
* Recommended for high-frequency devices such as mice at 1000Hz. */
DrainRawInputQueue();
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
Ham Girişin Arabelleğe Alınan Okumasını Gerçekleştirme
Bu örnek, periyodik bir zamanlayıcı kullanarak sabit hızda toplu gruplar halinde ham girdinin nasıl okunacağını gösterir. WM_INPUT iletiler dispatchMessage aracılığıyla kasıtlı olarak hiçbir zaman gönderilmez; getMessage döndürmeden önce iletileri ham giriş kuyruğundan kaldırdığından, yalnızca açık ileti aralığı filtrelerine sahip PeekMessage kullanılır ve WM_INPUT tamamen atlanır. Diğer tüm iletiler DispatchMessage aracılığıyla normal şekilde gönderilir. Bu, tüm ham giriş olaylarını GetRawInputBuffer'ın her zamanlayıcı tikinde hepsini bir kerede tüketebileceği kuyrukta tutar. Bu yaklaşım, her olaya ayrı ayrı tepki vermek yerine sabit bir hızda girişi işleyen oyun döngüleri ve diğer uygulamalar için uygundur.
MSG msg;
BOOL running = TRUE;
HWND hWnd = CreateWindowExW(0, L"Message", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
RAWINPUTDEVICE rid[2] = {
{ 0x01, 0x02, RIDEV_INPUTSINK, hWnd }, /* mouse */
{ 0x01, 0x06, RIDEV_INPUTSINK, hWnd }, /* keyboard */
};
RegisterRawInputDevices(rid, 2, sizeof(RAWINPUTDEVICE));
/* Drain raw input queue every 16ms (~60Hz) */
SetTimer(hWnd, 1, 16, NULL);
/* Message loop — WM_INPUT is skipped via range filters so it
* accumulates in the raw input queue for DrainRawInputQueue to drain. */
while (running)
{
while (PeekMessageW(&msg, NULL, 0, WM_INPUT - 1, PM_REMOVE) ||
PeekMessageW(&msg, NULL, WM_INPUT + 1, 0xFFFF, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
running = FALSE;
break;
}
if (msg.message == WM_TIMER)
{
DrainRawInputQueue();
}
DispatchMessageW(&msg);
}
if (running)
WaitMessage();
}