2017-01-28 8 views
3

IWebBrowser2 인터페이스를 사용하여 부모 응용 프로그램 내에 임베디드 브라우저를로드하고 있습니다. 내 코드는 dll로 컴파일됩니다. 즉, 브라우저 구성 요소는 플러그인 인터페이스를 통해 런타임에 동적으로로드됩니다.IWebBrowser2 인스턴스에 WM_KEYDOWN 메시지를 전달하는 방법은 무엇입니까?

내가 가지고있는 문제는 내 DLL을로드하는 응용 프로그램이 특정 keydown 메시지를 트래핑하고있어 따라서 내 IWebBrowser2 인스턴스에 도달하지 못하고 있다는 것입니다.

따라서 나는 내 DLL에 SetWindowsHookEx() API를 사용하여 이러한 메시지를 캡처하고 있습니다.

WM_KEYDOWN 또는 WM_CHAR 메시지를 내 IWebBrowser2 인스턴스에 전달하면 어떻게 될 수 있습니까? 브라우저에서 텍스트 상자에 텍스트를 입력하는 데 사용 하시겠습니까?

것 같다
+0

호스팅에 의해 차단되지 않은 메시지의 이중 효과를 방지 브라우저 컨트롤이 때 전자 키보드 포커스를 가지고 있는가 통풍구가 분실 되었습니까? – Anders

+0

@ 앤더스 나는 그렇게 생각한다. 일부 이벤트가 통과하고 다른 이벤트가 차단된다는 사실은 포커스가 획득되었다고 제안 할 것입니다. –

+1

후크를 설정하는 것은 꽤 큰 망치입니다. 나는 호스트 응용 프로그램이 왜 그 메시지를 당신의 윈도우에 전달하지 않는지를 이해하는 것이 더 낫다고 생각한다. 당신은 또한 어떤 사람들은오고 있지만 다른 사람들은 그렇지 않다고 말했습니다. 어떤 패턴을 발견 했습니까? –

답변

1

호스트 응용 프로그램의 메시지 대기열 구현에 문제가 있다고 생각합니다. 예를 들어 단축키를 구현하는 대신 전달하는 대신 일부 메시지가 처리됩니다. 코드를 변경할 수 없으므로 메시지 대기열을 연결하는 것이 합리적인 방법으로 들립니다.

은 다음 코드 조각은 문제 및 솔루션을 모두 보여줍니다

#define WINDOW_CLASS _T("StackOverflow_41911104") 

HINSTANCE g_Instance = 0; 
HHOOK  g_Hook = 0; 
HWND  g_TargetWindow = 0; 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch (message) 
    { 
    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 
    default: 
     return DefWindowProc(hWnd, message, wParam, lParam); 
    } 
    return 0; 
} 

HWND CreateMainWindow() 
{ 
    WNDCLASSEXW wcex; 
    wcex.cbSize = sizeof(WNDCLASSEX); 
    wcex.style   = CS_HREDRAW | CS_VREDRAW; 
    wcex.lpfnWndProc = WndProc; 
    wcex.cbClsExtra  = 0; 
    wcex.cbWndExtra  = 0; 
    wcex.hInstance  = g_Instance; 
    wcex.hIcon   = nullptr; 
    wcex.hCursor  = LoadCursor(nullptr, IDC_ARROW); 
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 
    wcex.lpszMenuName = nullptr; 
    wcex.lpszClassName = WINDOW_CLASS; 
    wcex.hIconSm  = nullptr; 

    ATOM windowClass = RegisterClassExW(&wcex); 
    HWND mainWindow  = CreateWindowW(WINDOW_CLASS, WINDOW_CLASS, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 400, 400, nullptr, nullptr, g_Instance, nullptr); 

    g_TargetWindow  = CreateWindow(_T("Edit"), nullptr, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE, 0, 0, 300, 300, mainWindow, (HMENU)1000, g_Instance, nullptr); 

    return mainWindow; 
} 

HACCEL CreateAccelerators() 
{ 
    ACCEL acceleratorsList[] = 
    { 
     {FVIRTKEY, 'R', 1000}, 
     {FVIRTKEY, 'T', 1001}, 
    }; 

    return CreateAcceleratorTable(acceleratorsList, _countof(acceleratorsList)); 
} 

void ProcessHookMessage(MSG* a_Message) 
{ 
    // Only affect our window and its children 
    if ((g_TargetWindow != a_Message->hwnd) && !IsChild(g_TargetWindow, a_Message->hwnd)) 
     return; 

    // Deliver the message directly 
    TranslateMessage(a_Message); 
    DispatchMessage(a_Message); 

    // Do not allow to process this message the second time 
    a_Message->message = WM_NULL; 
} 

LRESULT CALLBACK Hook_GetMsgProc(int a_Code, WPARAM a_WParam, LPARAM a_LParam) 
{ 
    if ((HC_ACTION == a_Code) && (PM_REMOVE == a_WParam)) 
     ProcessHookMessage((MSG*)a_LParam); 

    return CallNextHookEx(g_Hook, a_Code, a_WParam, a_LParam); 
} 

void InstallHook() 
{ 
    g_Hook = SetWindowsHookEx(WH_GETMESSAGE, Hook_GetMsgProc, g_Instance, GetCurrentThreadId()); 
} 

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int) 
{ 
    g_Instance = hInstance; 

    HWND mainWindow = CreateMainWindow(); 
    HACCEL hAccelTable = CreateAccelerators(); 
    InstallHook(); 

    MSG msg; 
    while (GetMessage(&msg, nullptr, 0, 0)) 
    { 
     // The problem lurks here: some messages are handled directly and never reach the target window 
     if (TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
      continue; 

     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    return 0; 
} 

이 코드에서 당신이 InstallHook() 호출을 주석하는 경우, 당신은 RT을 인쇄 할 수 있기 때문에하지 않습니다 이러한 키는 가속기 테이블에 사용됩니다. 그러나 InstallHook()을 사용하면 일반 메시지 큐 동작을 강제로 수행하고 모든 것이 정상적으로 작동합니다.

제안 후크 코드가 관심의 다음과 같은 사항이 : 그것은 단지 그것은 일반적인 메시지 큐와 같은 방식으로 작동 창문 및 다른

  • 아무것도에 영향을

    1. 을 것 대신 SendMessage 덤비는의/PostMessage
    2. 그것은 응용 프로그램
  • +0

    감사합니다.이 답변을 수락했습니다. 왜냐하면 나는'PostMessage()'를 사용하고 있다는 것을 제외하고는 내가 지금하고있는 일에 매우 가깝기 때문이다. 나는 당신의'ProcessHookMessage()'에 기초하여 이것을 제거하는 방법을 살펴볼 것이다. –

    0

    , 이것은 메시지를 보내는 평소보다 조금 복잡합니다 : 첫째

    을, 당신은 TranslateAccelerator (https://msdn.microsoft.com/en-us/library/windows/desktop/ms693360(v=vs.85).aspx)를 호출 한 후 웹 브라우저의에서 장소 활성 객체 (https://msdn.microsoft.com/en-us/library/windows/desktop/ms691299(v=vs.85).aspx)을 획득하고해야합니다 그 위에.

    HRESULT hr; 
    IOleInPlaceActiveObject* pIOIPAO; 
    
    hr = webBrowser2->QueryInterface(webBrowser2, 
          &IID_IOleInPlaceActiveObject, (LPVOID*)&pIOIPAO); 
    
    if (SUCCEEDED(hr)) 
    { 
        result = pIOIPAO->lpVtbl->TranslateAccelerator(pIOIPAO, msg); 
    } 
    
    msg 당신이 따라 채워야 메시지 ( MSG를)입니다

    webBrowser2IWebBrowser2입니다 : 같은

    매우 높은 수준의 의사가 보일 것이다.

    PS : 당신의 자신의 위험 :)에서 사용이 코드를 시도하지 않았나요

    +0

    감사합니다. IWebBrowser2는 'lpVtbl' 멤버가없는 것 같습니다. 웹에서 주위를 둘러 보니 C 인터페이스의 일부인 것처럼 보입니다. C++이 무엇인지 알고 있습니까? –

    +0

    'TranslateAccelerator()'에서 좀 더 살펴보면 질문을 잘못 이해했을 수도 있습니다. 나는'IWebBrowser2' 컴포넌트에 액셀러레이터 키를 보내지 않고 그냥 일반적인 키 누르기를 보려고합니다. keydown을 캡쳐하고 디버그 콘솔에 문자를 인쇄 할 수 있습니다. 웹 컴포넌트에 전달하는 방법을 알 수 없습니다. –

    +0

    제대로 이해하면'QueryInterface'는'IUnknown'의 일부입니다. 고정 응답. https://msdn.microsoft.com/en-us/library/ms682521(v=vs.85).aspx – fritzone

    1

    루트에 문제가 창에 초점을 혼동 할 수있는 호스트 응용 프로그램의 윈도우가 아닌 다른 스레드에 있다는 것이다처럼 소리 상태. 호스트 윈도우와 호스트 윈도우가 모두 포커스가 있다고 생각하는 상황에 쉽게 빠질 수 있습니다.

    그 해결책은 부모 창과 동일한 스레드에서 창을 만드는 것이고, 가능하지 않은 경우 (예 : 플러그인 모델 또는 플러그인이 별도의 프로세스에서 실행되기 때문에) AttachThreadInput을 사용하십시오 .

    몇 년 동안 웹 브라우저 컨트롤을 사용하지 않았지만 다른 프로세스에서 웹 브라우저 컨트롤을 창 자식으로 추가했을 때 비슷한 문제가 있었던 한 프로젝트를 생각해보십시오. AttachThreadInput을 사용하면 많은 버그가 해결되었습니다. 단점은 두 스레드의 버그 (중단과 같은)가 두 스레드를 효과적으로 중단한다는 것입니다. 우리는 또한 teardown 동안 스레드를 분리하는 데주의해야했습니다.

    +0

    Spy ++에 따르면 UI가 호스트 응용 프로그램의 윈도우와 동일한 스레드에 있습니다. 실제로 키보드를 사용할 수 있습니다. 'SetWindowsHookEx()'와'PostMessage()'의 조합을 사용하여 입력 작업을 할 수 있습니다. 마우스 휠 이벤트가 발생하지 않습니다. Argh! –

    관련 문제