スポンサーリンク

Win32APIでCEFのオフスクリーンレンダリング キーボード入力

CEFをオフスクリーンレンダリングしているときに、キー入出力を行う。各種キーイベントを取得してCEFに与えることでキーボード対応できる。日本語入力も出来るがキャレットがテキストボックスの位置に出ないことに注意。

/////////////////////////////////////////////////////////////////////////
// キー修飾フラグ変換
int GetCefKeyboardModifiers(WPARAM wparam, LPARAM lparam) {
    int modifiers = 0;

    // 押下状態
    if (GetKeyState(VK_SHIFT) & 0x8000)   modifiers |= EVENTFLAG_SHIFT_DOWN;
    if (GetKeyState(VK_CONTROL) & 0x8000) modifiers |= EVENTFLAG_CONTROL_DOWN;
    if (GetKeyState(VK_MENU) & 0x8000)    modifiers |= EVENTFLAG_ALT_DOWN;

    // Lock 状態
    if (GetKeyState(VK_CAPITAL) & 1)  modifiers |= EVENTFLAG_CAPS_LOCK_ON;
    if (GetKeyState(VK_NUMLOCK) & 1)  modifiers |= EVENTFLAG_NUM_LOCK_ON;

    // 左右キー
    switch (wparam) {
    case VK_LSHIFT:
    case VK_LCONTROL:
    case VK_LMENU:
        modifiers |= EVENTFLAG_IS_LEFT;
        break;
    case VK_RSHIFT:
    case VK_RCONTROL:
    case VK_RMENU:
        modifiers |= EVENTFLAG_IS_RIGHT;
        break;
    default:
        break;
    }

    // 拡張ビット (bit 24)
    const bool extended = (lparam & 0x01000000) != 0;

    // テンキー判定
    if ((wparam >= VK_NUMPAD0 && wparam <= VK_NUMPAD9) ||
        wparam == VK_DECIMAL || wparam == VK_ADD || wparam == VK_SUBTRACT ||
        wparam == VK_MULTIPLY || wparam == VK_DIVIDE) {
        modifiers |= EVENTFLAG_IS_KEY_PAD;
    }
    else if (wparam == VK_RETURN) {
        // Enter: Numpad Enter なら extended が true(Winで Numpad Enter は拡張付き)
        if (extended) modifiers |= EVENTFLAG_IS_KEY_PAD;
    }


    return modifiers;
}

// キー入力
void OnKeyDown(HWND hwnd, UINT msg, int wp,int lp) {
    MyHandler* handler = (MyHandler*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
    CefKeyEvent ev{};
    ev.type = KEYEVENT_RAWKEYDOWN;
    ev.windows_key_code = (int)wp;
    ev.native_key_code = (int)lp;
    ev.is_system_key = (msg == WM_SYSKEYDOWN);
    ev.modifiers = GetCefKeyboardModifiers(wp, lp);
        /* Ctrl/Shift/Alt を反映 */;
    handler->GetBrowser()->GetHost()->SendKeyEvent(ev);
}
void OnKeyUp(HWND hwnd, UINT msg, int wp, int lp) {
    MyHandler* handler = (MyHandler*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
    CefKeyEvent ev{};
    ev.type = KEYEVENT_KEYUP;
    ev.windows_key_code = (int)wp;
    ev.native_key_code = (int)lp;
    ev.is_system_key = (msg == WM_SYSKEYUP);
    ev.modifiers = GetCefKeyboardModifiers(wp, lp);
    handler->GetBrowser()->GetHost()->SendKeyEvent(ev);
}
void OnChar(HWND hwnd, UINT msg, int wp, int lp) {
    MyHandler* handler = (MyHandler*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
    CefKeyEvent ev;
    ev.type = KEYEVENT_CHAR;
    ev.character = static_cast<wchar_t>(wp);            // 入力文字
    ev.unmodified_character = static_cast<wchar_t>(wp); // 修飾なし
    ev.windows_key_code = static_cast<int>(wp);         // 互換目的
    ev.modifiers = GetCefKeyboardModifiers(wp, lp);
    handler->GetBrowser()->GetHost()->SendKeyEvent(ev);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
    MyHandler* handler = nullptr;
    LPCREATESTRUCT pcs;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (msg) {
    case WM_CLOSE:

        OnClose(hwnd);
        DestroyWindow(hwnd);

        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        OnPaint(hwnd, hdc);
        EndPaint(hwnd, &ps);
        return 0;

    case WM_CREATE:

        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    case WM_MOUSEMOVE:
        OnMouseMove(hwnd, GET_X_LPARAM(lp), GET_Y_LPARAM(lp));
        return 0;
    case WM_LBUTTONDOWN:
        OnLButtonDown(hwnd, GET_X_LPARAM(lp), GET_Y_LPARAM(lp));
        return 0;
    case WM_LBUTTONUP:
        OnLButtonUp(hwnd, GET_X_LPARAM(lp), GET_Y_LPARAM(lp));
        return 0;

    case WM_KEYDOWN:
    case WM_SYSKEYDOWN:
        OnKeyDown(hwnd,msg,wp,lp); // キーダウン
        return 0;
    case WM_KEYUP:
    case WM_SYSKEYUP:
        OnKeyUp(hwnd, msg, wp, lp); // キーアップ
        return 0;
    case WM_CHAR:
        OnChar(hwnd, msg, wp, lp); // 文字入力
        return 0;
    }

    return DefWindowProc(hwnd, msg, wp, lp);
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: