Re: Передача событий мыши в невидимый MSHTML с flash
От: dimb Россия  
Дата: 31.10.07 07:13
Оценка:
Здравствуйте, frankinshtein, Вы писали:

F>Здравствуйте.

F>Необходимо отрисовать в текстуру страничку с HTML и обрабатывать события от мыши. На страничке могут находиться flash контролы.
F>Я реализовал скрытое child окно с IWebBrowser, получаю IViewObject рисую в DC, копирую в текстуру, тут все нормально, работает.
F>Но! есть серьёзная проблема с событиями от мыши в flash контроле.
F>Они не всегда срабатывают (через раз и хуже), как будто флеш еще где-то сам опрашивает мышь.

У меня недавно была похожая проблема. У меня MFC-приложение со скрытым окном CHtmlView, тоже на страничке находится Flash. Тоже пробовал с SendMessage, ничего не получалось. В итоге пришёл к такому работающему варианту:

BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
{
    static TCHAR    szText[MAX_PATH];
    CPtrList*        pLstWindows = (CPtrList*) lParam;        
    
    GetClassName(hwnd, szText, MAX_PATH);
    if (lstrcmp(szText, _T("MacromediaFlashPlayerActiveX")) == 0)
        pLstWindows->AddTail(hwnd);

    return TRUE;
}

BOOL ClickFlash(HWND hMainWnd, int x, int y)
{
    CPtrList    lstWindows;
    HWND        hFlashWnd, hWnd;
    CRect        rect;
    MSG            msg;
    POSITION    pos;
    int            S, Smax = 0;


    EnumChildWindows(hMainWnd, EnumChildProc, (LPARAM) &lstWindows);
    if (lstWindows.IsEmpty())
        return FALSE;

    // Find the main flash window
    pos = lstWindows.GetHeadPosition();
    while (pos != NULL)
    {
        hWnd = (HWND) lstWindows.GetNext(pos);

        ::GetWindowRect(hWnd, rect);
        S = rect.Width() * rect.Height();

        if (S > Smax)
        {
            Smax = 0;
            hFlashWnd = hWnd;
        }
    }


    if (x == -1 || y == -1)
    {
        ::GetWindowRect(hFlashWnd, rect);
        x = rect.Width() / 2;
        y = rect.Height() / 2;
    }


    msg.hwnd = hFlashWnd;
    msg.message = WM_MOUSEMOVE;
    msg.wParam = 0;
    msg.lParam = (x & 0xFFFF) | ((y & 0xFFFF) << 16);
    msg.time = 0;
    msg.pt.x = 0;
    msg.pt.y = 0;

    DispatchMessage(&msg);

    msg.hwnd = hFlashWnd;
    msg.message = WM_MOUSEACTIVATE;
    msg.wParam = (WPARAM) theApp.m_pMainWnd->m_hWnd;
    msg.lParam = (HTCLIENT & 0xFFFF) | ((WM_LBUTTONDOWN & 0xFFFF) << 16);
    msg.time = 0;
    msg.pt.x = 0;
    msg.pt.y = 0;

    DispatchMessage(&msg);
    
    msg.hwnd = hFlashWnd;
    msg.message = WM_SETCURSOR;
    msg.wParam = (WPARAM) hFlashWnd;
    msg.lParam = (HTCLIENT & 0xFFFF) | ((WM_MOUSEMOVE & 0xFFFF) << 16);
    msg.time = 0;
    msg.pt.x = 0;
    msg.pt.y = 0;

    DispatchMessage(&msg);

    msg.hwnd = hFlashWnd;
    msg.message = WM_LBUTTONDOWN;
    msg.wParam = MK_LBUTTON;
    msg.lParam = (x & 0xFFFF) | ((y & 0xFFFF) << 16);
    msg.time = 0;
    msg.pt.x = 0;
    msg.pt.y = 0;

    DispatchMessage(&msg);

    msg.hwnd = hFlashWnd;
    msg.message = WM_LBUTTONUP;
    msg.wParam = 0;
    msg.lParam = (x & 0xFFFF) | ((y & 0xFFFF) << 16);
    msg.time = 0;
    msg.pt.x = 0;
    msg.pt.y = 0;
    
    DispatchMessage(&msg);

    msg.hwnd = hFlashWnd;
    msg.message = WM_SETCURSOR;
    msg.wParam = (WPARAM) hFlashWnd;
    msg.lParam = (HTCLIENT & 0xFFFF) | ((WM_MOUSEMOVE & 0xFFFF) << 16);
    msg.time = 0;
    msg.pt.x = 0;
    msg.pt.y = 0;

    DispatchMessage(&msg);

    msg.hwnd = hFlashWnd;
    msg.message = WM_MOUSEMOVE;
    msg.wParam = 0;
    msg.lParam = 0;
    msg.time = 0;
    msg.pt.x = 0;
    msg.pt.y = 0;

    DispatchMessage(&msg);


    return TRUE;
}


В ClickFlash передаётся хэндл окна CHtmlView. Далее ищутся дочерние окна, у которых класс окна "MacromediaFlashPlayerActiveX". Далее из них выбирается нужное окно и посылаются мышинные сообщения.
Нужно отметить, что такой приём не на всех сайтах срабатывает. Иногда есть только главное окно "InternetExplorer_Server", а отдельных окон для флэша нет. Здесь уже придётся перебирать все объекты, искать среди них флэш и сообщение посылать окну "InternetExplorer_Server".
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.