#include #include "ole2.h" #include "Exdisp.h" #include #include #include #include #include #include "Scene.h" #include "browser.h" //#pragma optimize("",off) static HWND LastEnumeratedHwnd = NULL; // not thread-safe #define MAX_WEB_BROWSER 16 HHOOK hHook = NULL; int nbHookInst = 0; CWebBrowser *webBrowser[MAX_WEB_BROWSER]; int nbWebBrowser= 0; // Adapted from http://www.cppfrance.com/codes/NAVIGATEUR-WEB-API_29247.aspx extern HINSTANCE hBigInstance; extern WORLD *TheScene; extern HWND hWnd; LRESULT CALLBACK GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam) { LPMSG lpMsg = (LPMSG) lParam; // keyboard fix if( (nCode >= 0) && PM_REMOVE == wParam && ((lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST) || lpMsg->message == WM_LBUTTONDOWN)) { int msgProcessDone = 0; int forceRefresh = lpMsg->message == WM_KEYDOWN && lpMsg->wParam == VK_F5; for (int wBroserIndex=0; !msgProcessDone && wBroserIndexGetOwnWindow(), lpMsg)) { IOleInPlaceActiveObject* pIOIPAO; if SUCCEEDED(webBrowser[wBroserIndex]->GetIWeb()->QueryInterface(IID_IOleInPlaceActiveObject,(void**)&pIOIPAO)) { // fixed a bug with activeX with double key // few keys are called twice, maybe by the parent ? if(lpMsg->wParam != VK_BACK && lpMsg->wParam != VK_RIGHT && lpMsg->wParam != VK_UP && lpMsg->wParam != VK_DOWN && lpMsg->wParam != VK_LEFT ) { pIOIPAO->TranslateAccelerator(lpMsg); pIOIPAO->Release(); } } msgProcessDone = 1; } } if (!msgProcessDone) { //TranslateMessage(lpMsg); // let proceed to CallNextHook() otherwise doubleclick is broken //DispatchMessage(lpMsg); } else { lpMsg->message = WM_NULL; lpMsg->lParam = 0L; lpMsg->wParam = 0; } } // Right click disable if( (nCode >= 0) && PM_REMOVE == wParam && lpMsg->hwnd != TheScene->OwnerHwnd && (lpMsg->message == WM_RBUTTONDOWN || lpMsg->message == WM_RBUTTONUP)) { lpMsg->message = WM_NULL; lpMsg->lParam = 0L; lpMsg->wParam = 0; } // Desactive mouse for inactive browser if(nCode >= 0 && PM_REMOVE == wParam && lpMsg->hwnd != TheScene->OwnerHwnd) //&& (lpMsg->message == WM_LBUTTONDOWN || lpMsg->message == WM_LBUTTONUP || lpMsg->message == WM_LBUTTONDBLCLK //|| lpMsg->message == WM_MBUTTONDBLCLK || lpMsg->message == WM_MBUTTONUP || lpMsg->message == WM_MBUTTONDOWN //|| lpMsg->message == WM_RBUTTONDBLCLK)) for (int wBroserIndex=0; wBroserIndexisActive() && IsDialogMessage(webBrowser[wBroserIndex]->GetOwnWindow(), lpMsg)) { lpMsg->message = WM_NULL; lpMsg->lParam = 0L; lpMsg->wParam = 0; } } return CallNextHookEx(hHook, nCode, wParam, lParam); } LRESULT CALLBACK NavProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: if (!hHook) { hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMessageProc, hBigInstance, GetCurrentThreadId()); } ++nbHookInst; break; case WM_DESTROY: // Remove webBrowser for (int wBroserIndex=0; wBroserIndexGetOwnWindow() == hWnd) { CWebBrowser *curWebBrowser = webBrowser[wBroserIndex]; curWebBrowser->killed(); // delete curWebBrowser ? for (int i=wBroserIndex+1; irgvarg[6].pdispVal; _Browser->processWindowsMessage(_HWnd,BEFORENAVIGATE2,(WPARAM)pIUnk,0); break; case DISPID_DOWNLOADBEGIN: _Browser->processWindowsMessage(_HWnd,DOWNLOADBEGIN,0,0); break; case DISPID_DOWNLOADCOMPLETE: _Browser->processWindowsMessage(_HWnd,DOWNLOADCOMPLETE,0,0); break; case DISPID_NAVIGATECOMPLETE2: pIUnk = pDispParams->rgvarg[1].pdispVal; vurl= pDispParams->rgvarg[0].pvarVal; _URL = vurl->bstrVal; _Browser->processWindowsMessage(_HWnd,NAVIGATECOMPLETE2,(WPARAM)pIUnk,(LPARAM)_URL); break; case DISPID_DOCUMENTCOMPLETE: pIUnk = pDispParams->rgvarg[1].pdispVal; _Browser->processWindowsMessage(_HWnd,DOCUMENTCOMPLETE,(WPARAM)pIUnk,0); break; case DISPID_COMMANDSTATECHANGE: long command; command = pDispParams->rgvarg[1].lVal; VARIANT_BOOL newState; newState = pDispParams->rgvarg[0].boolVal; _Browser->processWindowsMessage(_HWnd,COMMANDSTATECHANGE,(WPARAM)command,(LPARAM)newState); break; case DISPID_NEWWINDOW2: // Block any pop-up window //pDispParams->rgvarg[0].pvarVal->vt = VT_BOOL; //pDispParams->rgvarg[0].pvarVal->boolVal = VARIANT_TRUE; break; case DISPID_NEWWINDOW3: // ::MessageBox(NULL, "NEWWINDOW3", "", MB_OK); pIUnk = pDispParams->rgvarg[4].pdispVal; NewWindowParam paramStruct; paramStruct.URL = pDispParams->rgvarg[0].bstrVal; paramStruct.CancelFlagPtr = pDispParams->rgvarg[3].pboolVal; _Browser->processWindowsMessage(_HWnd,NEWWINDOW3,(WPARAM)pIUnk,0, (void*)¶mStruct); break; case DISPID_NAVIGATEERROR: { pIUnk = pDispParams->rgvarg[4].pdispVal; VARIANT * plong = pDispParams->rgvarg[1].pvarVal; vurl = pDispParams->rgvarg[3].pvarVal; DocumentError paramStruc; paramStruc.URL = vurl->bstrVal; paramStruc.StatusCode = (int)plong->lVal; _Browser->processWindowsMessage(_HWnd,DOCUMENTERROR,(WPARAM)pIUnk, 0, (void*)¶mStruc); } break; default: break; } return S_OK; } // *************************************************************************** bool CWebBrowser::init(HWND hParentWnd, DWORD windowStyle) { if (_Initialized) return true; // Load ATL library _HDLL = LoadLibrary("atl.dll"); typedef HRESULT (WINAPI *PAttachControl)(IUnknown*, HWND,IUnknown**); PAttachControl AtlAxAttachControl = (PAttachControl) GetProcAddress(_HDLL, "AtlAxAttachControl"); //* //To launch in a new window: WNDCLASS wc; //HINSTANCE hInst = 0; if (!GetClassInfo(hBigInstance, "Navigateur", &wc)) { wc.lpszClassName = "Navigateur"; wc.hInstance = hBigInstance; wc.lpfnWndProc = NavProc; wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wc.lpszMenuName = NULL; wc.hbrBackground = NULL; //GetSysColorBrush(COLOR_BTNFACE); wc.style = 0; wc.cbClsExtra = 0; wc.cbWndExtra = 0; if (!RegisterClass(&wc)) return false; } if (windowStyle & WS_CHILD) _WidgetWnd = CreateWindowEx(WS_EX_TOOLWINDOW /* not in taskbar */, "Navigateur","YouUp",windowStyle ,_X, _Y, _W, _H, hWnd, 0, hBigInstance,0); else _WidgetWnd = CreateWindowEx(WS_EX_TOPMOST, "Navigateur","YouUp",windowStyle ,_X, _Y, _W, _H, 0, 0, hBigInstance,0); ShowWindow(_WidgetWnd, SW_SHOW ); UpdateWindow( _WidgetWnd ); /*/// _WidgetWnd = CreateWindowEx(0, "EDIT", "", windowStyle, _X, _Y, _W, _H, hParentWnd,0,0,0); //*/ _ParentWnd = hParentWnd; CoInitialize(0); CoCreateInstance(CLSID_WebBrowser,0,CLSCTX_ALL,IID_IWebBrowser2,(void**)&_IWeb); AtlAxAttachControl(_IWeb,_WidgetWnd,NULL); // Install event handler IConnectionPointContainer* pCPContainer; _IWeb->QueryInterface(IID_IConnectionPointContainer,(void**)&pCPContainer); pCPContainer->FindConnectionPoint(DIID_DWebBrowserEvents2, &_ConnectionPoint); _WebEventHandler = new WebEventHandler(_WidgetWnd, this); _ConnectionPoint->Advise(_WebEventHandler, &_Cookie); if (pCPContainer) pCPContainer->Release(); _Initialized = true; _LastUrlVisited = ""; _CurrentUrl = ""; webBrowser[nbWebBrowser++] = this; return true; } // *************************************************************************** void CWebBrowser::release() { if (!_Initialized) return; // Uninstall event handler //---- YTEST OK ? //_ConnectionPoint->Unadvise(_Cookie); //_ConnectionPoint->Release(); //delete _WebEventHandler; //---- YTEST OK ? // Close window SendMessage(_WidgetWnd, WM_CLOSE, 0, 0); // Delete web browser ActiveX control and ATL library _IWeb->Release(); CoUninitialize(); FreeLibrary(_HDLL); } std::string CWebBrowser::GetUrl () { std::string url = ""; _WebEventHandler->GetUrl (&url); return url; } //static float FFff = 0; // *************************************************************************** void CWebBrowser::processWindowsMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, void* userParam) { if (!_Initialized) return; switch (message) { case BEFORENAVIGATE2: case DOWNLOADBEGIN: case DOCUMENTCOMPLETE: case COMMANDSTATECHANGE: case DOWNLOADCOMPLETE: case DOCUMENTERROR: case NEWWINDOW3: notifyObserver(message, wParam, userParam); break; case NAVIGATECOMPLETE2: if((IUnknown*)wParam!=_IWeb) break; // Update list of cookies grabAllCookies(); // WE put this code here because we cant get new URL if the link is on the browser BSTR url; GetIWeb()->get_LocationURL(&url); char currentURL[2048]; wcstombs(currentURL, url, 2047); if(!_CurrentUrl.empty() && !_DoNotSaveUrl) _LastUrlVisited = _CurrentUrl; _CurrentUrl = currentURL; // Call observer update notifyObserver(message, wParam, userParam); _DoNotSaveUrl = false; break; default:; } } // *************************************************************************** bool CWebBrowser::navigate(char *url) { // From http://www.codeguru.com/forum/showthread.php?t=315418 USES_CONVERSION; if (!_Initialized) return false; BSTR bURL = SysAllocString(CT2W(url)); _IWeb->Navigate(bURL, 0, 0, 0, 0); //Account.startAsyncLogInSSO("0S%252F9kU2y8lYyVgDKm8u3b6DkmSf4QF%252B9MbpVJz6Snj5H7jvqvrlv8xt8VErBghE874Iq3uJRYpj6l29%252BD%252BLs9qsw8MLr3MrF7f%252FFEEPKSljz5UzPJWmSiogPSR1zpZjHymtVWPOvcEZywOXJ6gDTW1Nc%252FL4%252F5QQ5jVEIQtFgOaQthokGXF7Z9IvOFcHEeiuf"); SysFreeString(bURL); setVisible(true); // Experimentation, can't get it to work //VARIANT zoomSize; //VariantInit(&zoomSize); //zoomSize.vt = VT_I4; // VT_INT //zoomSize.lVal = 40; // 3 //_IWeb->ExecWB(/*OLECMDID_ZOOM*/OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, &zoomSize, NULL); return true; } // *************************************************************************** bool CWebBrowser::navigateBack() { if(!_LastUrlVisited.empty()) { _DoNotSaveUrl = true; return navigate((char*)_LastUrlVisited.c_str()); } else return false; } bool CWebBrowser::getHtmlContent(std::string * html) { IDispatch *htmlDispatch; HRESULT hr = GetIWeb()->get_Document(&htmlDispatch); if (SUCCEEDED(hr) && htmlDispatch) { IHTMLDocument2 *iHtml; hr = htmlDispatch->QueryInterface(IID_IHTMLDocument2, (void**)&iHtml); if (SUCCEEDED(hr) && iHtml) { IHTMLElementCollection *pAll = NULL; hr = iHtml->get_all( &pAll); if(!SUCCEEDED(hr)) return false; VARIANT name; name.vt = VT_BSTR; name.bstrVal = L"HTML"; IDispatch *pTags = NULL; hr = pAll->tags( name, &pTags ); if(!SUCCEEDED(hr)) return false; IHTMLElementCollection *pEles = NULL; hr = pTags->QueryInterface(IID_IHTMLElementCollection, (void**)&pEles ); if(!SUCCEEDED(hr)) return false; VARIANT elename; elename.vt = VT_EMPTY; VARIANT ind; ind.lVal = 0; ind.vt = VT_I4; IDispatch* pEleDisp = NULL; hr = pEles->item(elename, ind, &pEleDisp ); if(!SUCCEEDED(hr)) return false; IHTMLElement *pEle = NULL; hr = pEleDisp->QueryInterface( IID_IHTMLElement, (void**) &pEle ); if(!SUCCEEDED(hr)) return false; BSTR bstr_html; hr = pEle->get_innerHTML(&bstr_html); if(!SUCCEEDED(hr)) return false; char currentURL[4096]; wcstombs(currentURL, bstr_html, 511); *html = std::string(currentURL); pEle->Release(); pEleDisp->Release(); return true; } } return false; } // *************************************************************************** // IWebBrowser2 to IHTMLWindow2 IWebBrowser2 * CWebBrowser::GetIWeb() const { return _IWeb;//HHHH; } HWND CWebBrowser::GetOwnWindow() const { return _WidgetWnd;//HHHH; } /*void CWebBrowser::SendMouseMessage(int X , int Y , int ButtonDown) const { HRESULT hr = S_OK; CComQIPtr pContainer; CComQIPtr pDoc; CComQIPtr pWindow; hr = _IWeb->get_Document(&pDisp); if (FAILED(hr)) return ; pContainer = pDisp; if (!pContainer) return ; pDoc = pDisp; if (!pDoc) return ; hr = pDoc->get_parentWindow(&pWindow); if (FAILED(hr) && !pWindow) return ; LPDISPATCH dispFO = CFunctionObject::CreateEventFunctionObject(this, MouseMoveCallback, DISPID_MOUSEMOVE); VARIANT vIn; V_VT(&vIn) = VT_DISPATCH; V_DISPATCH(&vIn) = dispFO; pDoc->put_onmousemove(vIn); }*/ HWND CWebBrowser::GetActiveXWindow() const { HWND hwndBrowser = NULL; IServiceProvider* pServiceProvider = NULL; if (SUCCEEDED(_IWeb->QueryInterface( IID_IServiceProvider, (void**)&pServiceProvider))) { IOleWindow* pWindow = NULL; if (SUCCEEDED(pServiceProvider->QueryService( SID_SShellBrowser, IID_IOleWindow, (void**)&pWindow))) { pWindow->GetWindow(&hwndBrowser); pWindow->Release(); } pServiceProvider->Release(); } return hwndBrowser; } BOOL CALLBACK EnumChildGetDeepest(HWND hwnd, LPARAM lParam) { LastEnumeratedHwnd = hwnd; return TRUE; } BOOL CALLBACK EnumChildTestHWnd(HWND hwnd, LPARAM lParam) { if ((HWND)lParam == hwnd) { LastEnumeratedHwnd = hwnd; return FALSE; } return TRUE; } HWND CWebBrowser::GetIEWindow() const { EnumChildWindows(_WidgetWnd, EnumChildGetDeepest, 0); return LastEnumeratedHwnd; } //void CWebBrowser::setHTMLContent(const char *html, bool append) // TODO: append mode //{ // if (!_Initialized) // return; // // IDispatch *htmlDispatch; // HRESULT hr = _IWeb->get_Document(&htmlDispatch); // if (SUCCEEDED(hr) && htmlDispatch) // { // IHTMLDocument2 *iHtml; // hr = htmlDispatch->QueryInterface(IID_IHTMLDocument2, (void**)&iHtml); // if (SUCCEEDED(hr) && iHtml) // { // VARIANT *param; // SAFEARRAY *sfArray; // size_t len = strlen(html); // BSTR bstr = SysAllocStringByteLen(html, len*2); // mbstowcs(bstr, html, len); // sfArray = SafeArrayCreateVector(VT_VARIANT, 0, 1); // if (sfArray) // { // hr = SafeArrayAccessData(sfArray,(LPVOID*) & param); // param->vt = VT_BSTR; // param->bstrVal = bstr; // hr = SafeArrayUnaccessData(sfArray); // hr = iHtml->write(sfArray); // } // SysFreeString(bstr); // if (sfArray != NULL) // SafeArrayDestroy(sfArray); // } // } //} void CWebBrowser::setVisible(bool visible) { if (!_Initialized || _ForceHidden) return; ShowWindow(_WidgetWnd, visible ? SW_SHOW : SW_HIDE); } bool CWebBrowser::isVisible() const { if (!_Initialized) return false; return IsWindowVisible(_WidgetWnd); } void CWebBrowser::killed() { notifyObserver(WM_DESTROY, 0, NULL); } bool CWebBrowser::hasFocus() const { if (_WidgetWnd == NULL) return false; HWND focusedWin = GetFocus(); if (focusedWin == _WidgetWnd) return true; else { LastEnumeratedHwnd = NULL; EnumChildWindows(_WidgetWnd, EnumChildTestHWnd, (LPARAM)focusedWin); return (LastEnumeratedHwnd != NULL); } } void CWebBrowser::grabAllCookies() { IDispatch* _iDispatch; HRESULT result; IHTMLDocument2 *iHtml; BSTR bstr_cookie; // Get the document of the page result = _IWeb->get_Document(&_iDispatch); // Get HtmlDoc result = _iDispatch->QueryInterface(IID_IHTMLDocument2, (void**)&iHtml); // Get All infos now result = iHtml->get_cookie(&bstr_cookie); // Fill map if(bstr_cookie) { // Convert BSTRtoChar* char temp[16384]; wcstombs(temp, bstr_cookie, 16383); std::string stvalue, stname, stcookies; stcookies = temp; // std::string::size_type stTemp = stcookies.find("; "); // Clear the previous map _CookiesList.clear(); while(true) { // if the char is not found, we have only one element if(stTemp != std::string::npos) stvalue = stcookies.substr(0, stTemp); else stvalue = stcookies; // set name and value stname = stvalue.substr(0, stvalue.find("=")); stvalue = stvalue.substr(stvalue.find("=") + 1); // insert new pair in the map _CookiesList.insert( std::make_pair (stname, stvalue)); // get the rest of cookies stcookies = stcookies.substr(stTemp + 2); // if the char is empty, break wthe while if(stTemp != std::string::npos) stTemp = stcookies.find("; "); else break; } } } std::string CWebBrowser::getCookieValue(const std::string& name) { // Search in the map CookiesList::iterator it = _CookiesList.find(name); if(it != _CookiesList.end()) // find return it->second; else return std::string(); } bool CWebBrowser::getAllCookies(std::string * cookies) { for(CookiesList::iterator it = _CookiesList.begin(); it != _CookiesList.end(); ++ it) { *cookies = *cookies + std::string(";") + it->first + std::string("=") + it->second; } return true; } void CWebBrowser::attachObserver(BrowserObserver* obs) { // To avoid doublon for (ObserverList::iterator it = _ObserverList.begin(); it != _ObserverList.end(); ++ it) { // If existing, just active it if needed if(it->second == obs) { if(!it->first) it->first = true; return; } } // Add the new observer _ObserverList.push_back(std::make_pair(true, obs)); } void CWebBrowser::detachObserver(BrowserObserver* obs) { // Set bool to false in order to delete it during the next call to "notify" for (ObserverList::iterator it = _ObserverList.begin(); it != _ObserverList.end(); ++ it) { if(it->second == obs) { it->first = false; return ; } } } void CWebBrowser::notifyObserver(UINT message, WPARAM wParam, void* userParam) { for (ObserverList::iterator it = _ObserverList.begin(); it != _ObserverList.end();) { if(it->first) { it->second->updateEvent(this, message, wParam, userParam); ++ it; } else it = _ObserverList.erase(it); } } bool CWebBrowser::checkLastURLVisited(char * url) { return (_LastUrlVisited.compare(url) == 0); } bool CWebBrowser::isFirstLoading() const { return _LastUrlVisited.empty(); } void CWebBrowser::clearHistory() { _LastUrlVisited.clear(); _CurrentUrl.clear(); } #ifndef USER_MODE unsigned int CWebBrowser::getMemoryUsage() const { unsigned int size = 0; size += sizeof(*this); size += sizeof(std::string::value_type) * (_LastUrlVisited.capacity() + _CurrentUrl.capacity()); for (CookiesList::const_iterator it = _CookiesList.begin(); it != _CookiesList.end(); ++ it) { size += sizeof(std::string::value_type) * (it->first.capacity() + it->second.capacity()); } size += _ObserverList.size() * (sizeof(bool) + sizeof(void*)); /* IWebBrowser2 *_IWeb; // MS Web Browser interface IConnectionPoint *_ConnectionPoint; // event handler connection point WebEventHandler *_WebEventHandler; */ return size; } #endif void CWebBrowser::setPosAndSize(int x, int y, int w, int h) { _X = x; _Y = y; _W = w; _H = h; // remplaced _ParentWnd by HWND_TOP , it didnt work else .. if (_WidgetWnd) SetWindowPos(_WidgetWnd, HWND_TOP, _X, _Y, _W, _H, SWP_SHOWWINDOW); } //bool CWebBrowser::setOnTop() //{ // if (_WidgetWnd) // return (SetWindowPos(_WidgetWnd, HWND_TOP/*_ParentWnd*/, _X, _Y, _W, _H, 0) != 0); // else // return false; //}