낭만온달-위버멘쉬를 꿈꾸며... :: [Chromium] CEF4Delphi - 크롬웹브라우저에 키보드/마우스 이벤트 전달하기

[Chromium] CEF4Delphi - 크롬웹브라우저에 키보드/마우스 이벤트 전달하기

크롬웹브라우저에 키보드/마우스 이벤트 전달하기

Chromium 웹브라우저를 임베딩 시키면 일반적인 네비게이션 및 마우스 클릭 등의 동작을 이용한 추가 네비게이션 등은 동작을 하지만 키보드 입력 및 마우스 휠 동작은 웹브라우저에 전달되지 않는다. 

임베딩된 웹브라우저에 사용자 키보드 입력값 및 마우스 휠 이벤트 정보를 전달하는 방법을 살펴 보자

1. 먼저 VCL Form(TForm) 에 TApplicationEvents 컴포넌트를 올려놓는다.

2. TApplicationEvents.OnMessage 이벤트 핸들러를 작성하여 키보드 및 마우스 휠 이벤트를 웹브라우저에 전달 한다.

 

uses
	uCEFChromium, uCEFTypes, 
...

procedure TForm1.AppEventsMessage(var Msg: tagMSG; var Handled: Boolean);
var
  TempKeyEvent   : TCefKeyEvent;
  TempMouseEvent : TCefMouseEvent;
  TempTime  : integer;
  cp : TPoint;
  mouseButton : TMouseButton;
  
function GetShiftState : TShiftState;
var
  State: TKeyboardState;
begin
  result := [];

  GetKeyboardState(State);
  if ((State[VK_SHIFT] and 128) <> 0) then
    result := result + [ssShift];
  if ((State[VK_CONTROL] and 128) <> 0) then
    result := result + [ssCtrl];
  if ((State[VK_MENU] and 128) <> 0) then
    result := result + [ssAlt];
end;  

begin
  case Msg.message of
    WM_SYSCHAR :
      if Panel1.Focused then
        begin
          TempKeyEvent.kind                    := KEYEVENT_CHAR;
          TempKeyEvent.modifiers               := GetCefKeyboardModifiers(Msg.wParam, Msg.lParam);
          TempKeyEvent.windows_key_code        := Msg.wParam;
          TempKeyEvent.native_key_code         := Msg.lParam;
          TempKeyEvent.is_system_key           := ord(True);
          TempKeyEvent.character               := #0;
          TempKeyEvent.unmodified_character    := #0;
          TempKeyEvent.focus_on_editable_field := ord(False);

          chrmosr.SendKeyEvent(@TempKeyEvent);
          Handled := True;
        end;

    WM_SYSKEYDOWN :
      if Panel1.Focused then
        begin
          TempKeyEvent.kind                    := KEYEVENT_RAWKEYDOWN;
          TempKeyEvent.modifiers               := GetCefKeyboardModifiers(Msg.wParam, Msg.lParam);
          TempKeyEvent.windows_key_code        := Msg.wParam;
          TempKeyEvent.native_key_code         := Msg.lParam;
          TempKeyEvent.is_system_key           := ord(True);
          TempKeyEvent.character               := #0;
          TempKeyEvent.unmodified_character    := #0;
          TempKeyEvent.focus_on_editable_field := ord(False);

          chrmosr.SendKeyEvent(@TempKeyEvent);
          Handled := True;
        end;

    WM_SYSKEYUP :
      if Panel1.Focused then
        begin
          TempKeyEvent.kind                    := KEYEVENT_KEYUP;
          TempKeyEvent.modifiers               := GetCefKeyboardModifiers(Msg.wParam, Msg.lParam);
          TempKeyEvent.windows_key_code        := Msg.wParam;
          TempKeyEvent.native_key_code         := Msg.lParam;
          TempKeyEvent.is_system_key           := ord(True);
          TempKeyEvent.character               := #0;
          TempKeyEvent.unmodified_character    := #0;
          TempKeyEvent.focus_on_editable_field := ord(False);

          chrmosr.SendKeyEvent(@TempKeyEvent);
          Handled := True;
        end;

    WM_KEYDOWN :
      if Panel1.Focused then
        begin
          TempKeyEvent.kind                    := KEYEVENT_RAWKEYDOWN;
          TempKeyEvent.modifiers               := GetCefKeyboardModifiers(Msg.wParam, Msg.lParam);
          TempKeyEvent.windows_key_code        := Msg.wParam;
          TempKeyEvent.native_key_code         := Msg.lParam;
          TempKeyEvent.is_system_key           := ord(False);
          TempKeyEvent.character               := #0;
          TempKeyEvent.unmodified_character    := #0;
          TempKeyEvent.focus_on_editable_field := ord(False);

          chrmosr.SendKeyEvent(@TempKeyEvent);
          Handled := (Msg.wParam in [VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_TAB]);
        end;

    WM_KEYUP :
      if Panel1.Focused then
        begin
          TempKeyEvent.kind                    := KEYEVENT_KEYUP;
          TempKeyEvent.modifiers               := GetCefKeyboardModifiers(Msg.wParam, Msg.lParam);
          TempKeyEvent.windows_key_code        := Msg.wParam;
          TempKeyEvent.native_key_code         := Msg.lParam;
          TempKeyEvent.is_system_key           := ord(False);
          TempKeyEvent.character               := #0;
          TempKeyEvent.unmodified_character    := #0;
          TempKeyEvent.focus_on_editable_field := ord(False);

          chrmosr.SendKeyEvent(@TempKeyEvent);
          Handled := True;
        end;

    WM_CHAR :
      if Panel1.Focused then
        begin
          TempKeyEvent.kind                    := KEYEVENT_CHAR;
          TempKeyEvent.modifiers               := GetCefKeyboardModifiers(Msg.wParam, Msg.lParam);
          TempKeyEvent.windows_key_code        := Msg.wParam;
          TempKeyEvent.native_key_code         := Msg.lParam;
          TempKeyEvent.is_system_key           := ord(False);
          TempKeyEvent.character               := #0;
          TempKeyEvent.unmodified_character    := #0;
          TempKeyEvent.focus_on_editable_field := ord(False);

          chrmosr.SendKeyEvent(@TempKeyEvent);
          Handled := True;
        end;

    WM_MOUSEWHEEL :
      if Panel1.Focused and (GlobalCEFApp <> nil) then
        begin
          TempMouseEvent.x         := Msg.lParam and $FFFF;
          TempMouseEvent.y         := Msg.lParam shr 16;
          TempMouseEvent.modifiers := GetCefMouseModifiers(Msg.wParam);
          DeviceToLogical(TempMouseEvent, GlobalCEFApp.DeviceScaleFactor);
          chrmosr.SendMouseWheelEvent(@TempMouseEvent, 0, int16(Msg.wParam shr 16));
        end;
    WM_MOUSEMOVE :
      if Panel1.Focused and (GlobalCEFApp<>nil) and (chrmosr <> nil) then
      begin
        GetCursorPos(cp);
        cp := Panel1.ScreenToClient(cp);
        if CancelPreviousClick(cp.x, cp.y, TempTime) then InitializeLastClick;

        TempMouseEvent.x         := cp.x;
        TempMouseEvent.y         := cp.y;
        TempMouseEvent.modifiers := getModifiers(GetShiftState);
        DeviceToLogical(TempMouseEvent, GlobalCEFApp.DeviceScaleFactor);
        chrmosr.SendMouseMoveEvent(@TempMouseEvent, False);
      end;
    WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_MBUTTONDOWN :
      if Panel1.Focused and (GlobalCEFApp<>nil) and (chrmosr <> nil) then
      begin
        if msg.message=WM_LBUTTONDOWN then
          mouseButton := mbLeft
        else if msg.message=WM_RBUTTONDOWN then
          mouseButton := mbRight
        else
          mouseButton := mbMiddle;

        GetCursorPos(cp);
        cp := Panel1.ScreenToClient(cp);
        Panel1.SetFocus;

        if not(CancelPreviousClick(cp.x, cp.y, TempTime)) and (mouseButton = FLastClickButton) then
          inc(FLastClickCount)
         else
          begin
            FLastClickPoint.x := cp.x;
            FLastClickPoint.y := cp.y;
            FLastClickCount   := 1;
          end;

        FLastClickTime      := TempTime;
        FLastClickButton    := mouseButton;

        TempMouseEvent.x         := cp.X;
        TempMouseEvent.y         := cp.Y;
        TempMouseEvent.modifiers := getModifiers(GetShiftState);
        DeviceToLogical(TempMouseEvent, GlobalCEFApp.DeviceScaleFactor);
        chrmosr.SendMouseClickEvent(@TempMouseEvent, GetButton(mouseButton), False, FLastClickCount);
      end;
    WM_LBUTTONUP, WM_RBUTTONUP, WM_MBUTTONUP :
      if Panel1.Focused and (GlobalCEFApp<>nil) and (chrmosr <> nil) then
      begin
        if msg.message=WM_LBUTTONUP then
          mouseButton := mbLeft
        else if msg.message=WM_RBUTTONUP then
          mouseButton := mbRight
        else
          mouseButton := mbMiddle;

        GetCursorPos(cp);
        cp := Panel1.ScreenToClient(cp);
        Panel1.SetFocus;
        TempMouseEvent.x         := cp.X;
        TempMouseEvent.y         := cp.Y;
        TempMouseEvent.modifiers := getModifiers(GetShiftState);
        DeviceToLogical(TempMouseEvent, GlobalCEFApp.DeviceScaleFactor);
        chrmosr.SendMouseClickEvent(@TempMouseEvent, GetButton(mouseButton), True, FLastClickCount);
      end;
  end;
end;

댓글()
  1. 지나가던 뉴비 2020.03.27 03:12 댓글주소  수정/삭제  댓글쓰기

    몇시간째 sendmessage로 해보려다가 안되서 혹시나 해서 검색했는데...진짜 감사합니다.