📄 webreplaydlg.cpp
字号:
{
MSXML2::IXMLDOMNodePtr objXMLURL = objXMLAction->selectSingleNode(_T("@url"));
_bstr_t bstrNavigateURL = objXMLURL->text;
if (bstrNavigateURL != _bstr_t(_T("")))
{
sprintf(strReplayMessage, "Replaying scenario step %d action %d navigate \"%s\" ...", intStep, intAction, (LPCTSTR)bstrNavigateURL);
m_objReplayStatus.SetWindowText(strReplayMessage);
m_objExplorer.Navigate(bstrNavigateURL, NULL, NULL, NULL, NULL);
// Go to Next Step
blnNextStep = true;
}
}
else if (bstrActionType == _bstr_t(_T("control")))
{
MSXML2::IXMLDOMNodePtr objXMLName = objXMLAction->selectSingleNode(_T("@name"));
_bstr_t bstrHTMLControlName = objXMLName->text;
MSXML2::IXMLDOMNodePtr objXMLValue = objXMLAction->selectSingleNode(_T("@value"));
_bstr_t bstrHTMLControlValue;
if (objXMLValue)
{
bstrHTMLControlValue = objXMLValue->text;
}
MSXML2::IXMLDOMNodePtr objXMLEvent = objXMLAction->selectSingleNode(_T("@event"));
_bstr_t bstrHTMLControlEvent = objXMLEvent->text;
if (bstrHTMLControlEvent == _bstr_t(_T("click")))
{
sprintf(strReplayMessage, "Replaying scenario step %d action %d control name=\"%s\" value=\"%s\" click...", intStep, intAction, (LPCTSTR)bstrHTMLControlName, (LPCTSTR)bstrHTMLControlValue);
m_objReplayStatus.SetWindowText(strReplayMessage);
// Simulate a click on the requested button
if (SUCCEEDED(SimulateHTMLElementClick(bstrHTMLControlName, bstrHTMLControlValue)))
{
// Action succeeded: increase counter
this->m_objExplorer.m_nScenarioAction++;
// Go to Next Step
blnNextStep = true;
}
else
{
// Stop execution of following actions
blnNextStep = false;
break;
}
}
else if (bstrHTMLControlEvent == _bstr_t(_T("set_value")))
{
sprintf(strReplayMessage, "Replaying scenario step %d action %d control name=\"%s\" value=\"%s\" set_value...", intStep, intAction, (LPCTSTR)bstrHTMLControlName, (LPCTSTR)bstrHTMLControlValue);
m_objReplayStatus.SetWindowText(strReplayMessage);
MSXML2::IXMLDOMNodePtr objXMLValue = objXMLAction->selectSingleNode(_T("@value"));
_bstr_t bstrHTMLControlValue = objXMLValue->text;
if (SUCCEEDED(SimulateTextInput(bstrHTMLControlName, bstrHTMLControlValue, bstrHTMLControlValue)))
{
// Action succeeded: increase counter
this->m_objExplorer.m_nScenarioAction++;
// Go to Next Step
blnNextStep = true;
}
else
{
// Stop execution of following actions
blnNextStep = false;
break;
}
}
else if (bstrHTMLControlEvent == _bstr_t(_T("wait")))
{
sprintf(strReplayMessage, "Replaying scenario step %d action %d control name=\"%s\" value=\"%s\" wait...", intStep, intAction, (LPCTSTR)bstrHTMLControlName, (LPCTSTR)bstrHTMLControlValue);
m_objReplayStatus.SetWindowText(strReplayMessage);
if (bstrHTMLControlName == _bstr_t(_T("status")))
{
if (bstrHTMLControlValue == m_bstrStatusBarText)
{
// Action succeeded: increase counter
this->m_objExplorer.m_nScenarioAction++;
// Go to Next Step
blnNextStep = true;
}
else
{
// Set timer to wait for status bar text to appear
this->SetTimer(CWEB_HTML_ELEMENT_TIMER, m_intTimeoutMilliseconds, NULL);
// Do not proceed with next step - we must wait until the control has the requested value
blnNextStep = false;
// Stop execution of following actions
break;
}
}
else
{
MessageBox(_T("ERROR: Unknown wait control name: must be 'status'"));
break;
}
}
else
{
MessageBox(_T("ERROR: Unknown control event: must be 'click', 'wait' or 'set_value'"));
break;
}
}
else
{
MessageBox(_T("ERROR: Unknown action type: must be 'navigate' or 'control'"));
break;
}
} // if (this->m_objExplorer.m_nScenarioAction >= intAction)
} // for (long intAction = 0; intAction < objXMLActions->length; intAction++)
if (blnNextStep)
{
this->m_objExplorer.m_nScenarioStep++;
this->m_objExplorer.m_nScenarioAction = 0;
break;
}
} // if (objXMLActions->length > 0)
} // if (this->m_objExplorer.m_nScenarioStep >= intStep)
} // for (long intStep = 0; intStep < objXMLSteps->length; intStep++)
if (this->m_objExplorer.m_nScenarioStep == objXMLSteps->length)
{
// End of loop - reset state
this->m_objExplorer.m_nScenarioLoops++;
if (blnInfiniteLoops)
{
if (TRUE) // TODO test if last action is not navigate or click
{
EndScenario();
}
// Start replaying all over again
this->m_objExplorer.m_nScenarioStep = 0;
this->m_objExplorer.m_nScenarioAction = 0;
// Post message to simulate a click on Replay button
CWnd * pReplayButton = GetDlgItem(IDC_BUTTON_REPLAY);
if (pReplayButton)
{
::PostMessage(pReplayButton->m_hWnd, BM_CLICK, (WPARAM)0, (LPARAM)0);
}
}
else
{
// Stop replaying
this->m_objExplorer.m_nScenarioStep = -1;
this->m_objExplorer.m_nScenarioAction = 0;
if (TRUE) // TODO test if last action is not navigate or click
{
EndScenario();
}
}
} // if (this->m_objExplorer.m_nScenarioStep == objXMLSteps->length)
} // if ((bool)varOut == FALSE)
}
void CWebReplayDlg::EndScenario()
{
m_objReplayStatus.SetWindowText("Scenario completed.");
// Put back focus on scenario file name (so that you can REPLAY again by pressing the ENTER key)
CWnd * pFocus = m_objScenarioFileName.SetFocus();
m_objScenarioFileName.SetSel(0, -1);
// Enable "Replay" button
m_objReplayButton.EnableWindow(TRUE);
m_objScenarioFileName.EnableWindow(TRUE);
}
//
// ***************************************************************************
//
// UTML Element and Event Handling Functions
//
// ***************************************************************************
//
CComQIPtr<IHTMLElement, &IID_IHTMLElement> CWebReplayDlg::GetHTMLElement(const OLECHAR *BSTRElementName, const OLECHAR *BSTRElementValue)
{
CComQIPtr<IHTMLElement, &IID_IHTMLElement> pHTMLElement;
VARIANT name, index;
_bstr_t strRequestedValue = _bstr_t(BSTRElementValue);
VariantInit(&name);
V_VT(&name) = VT_BSTR;
V_BSTR(&name) = SysAllocString(BSTRElementName);
VariantInit(&index);
V_VT(&index) = VT_I2;
V_I2(&index) = 0;
CComPtr<IHTMLElementCollection> pEltColl = NULL;
CComPtr<IDispatch> pEltDisp = NULL;
CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> pDoc2;
CComPtr<IDispatch> pDisp = NULL;
CHECKPTR(pDisp = m_objExplorer.get_Document());
CHECKPTR(pDoc2 = pDisp);
//Get the element you want to fire the event on.
HRESULT hResult = pDoc2->get_all(&pEltColl);
if (SUCCEEDED(hResult) && pEltColl)
{
// We are assuming there's only one element with that name on the page,
// else you must expect a collection instead of a single element.
if (name == L"" && BSTRElementValue != L"")
{
// Search by value (manual search with a loop on all HTML Elements in document - could be long!)
long intElements = 0;
pEltColl->get_length(&intElements);
for (int intElement = 0; intElement < intElements; intElement++)
{
CComPtr<IDispatch> pCurrentDispatch = NULL;
VARIANT vElementIndex;
VariantInit(&vElementIndex);
V_VT(&vElementIndex) = VT_I4;
V_I4(&vElementIndex) = intElement;
hResult = pEltColl->item(vElementIndex, index, &pCurrentDispatch);
if (SUCCEEDED(hResult))
{
// Read value from current element
CComQIPtr<IHTMLInputElement, &IID_IHTMLInputElement> pCurrentInputElement = pCurrentDispatch;
if (pCurrentInputElement)
{
BSTR bstrValue = NULL;
pCurrentInputElement->get_value(&bstrValue);
_bstr_t strValue = bstrValue;
if (strValue == strRequestedValue)
{
// Found input element with requested value - return this
pHTMLElement = pCurrentDispatch;
// Cleanup
if (bstrValue)
{
SysFreeString(bstrValue);
}
break;
}
// Cleanup
if (bstrValue)
{
SysFreeString(bstrValue);
}
}
else
{
// Try with an hyperlink (search in its HREF and innerText attributes)
CComQIPtr<IHTMLAnchorElement, &IID_IHTMLAnchorElement> pCurrentAnchorElement = pCurrentDispatch;
if (pCurrentAnchorElement)
{
CComQIPtr<IHTMLElement, &IID_IHTMLElement> pCurrentHTMLElement = pCurrentDispatch;
BSTR bstrHref = NULL;
pCurrentAnchorElement->get_href(&bstrHref);
_bstr_t strHref = bstrHref;
BSTR bstrInnerText = NULL;
pCurrentHTMLElement->get_innerText(&bstrInnerText);
_bstr_t strInnerText = bstrInnerText;
if (strInnerText == strRequestedValue || strHref == strRequestedValue)
{
// Found input element with requested value - return this
pHTMLElement = pCurrentDispatch;
// Cleanup
if (bstrInnerText)
{
SysFreeString(bstrInnerText);
}
break;
}
// Cleanup
if (bstrInnerText)
{
SysFreeString(bstrInnerText);
}
}
} // if (pCurrentHTMLElement)
}
}
}
else
{
hResult = pEltColl->item(name, index, &pEltDisp);
if (FAILED(hResult) || !pEltDisp)
{
/*
_TCHAR strErrorMessage[4096];
sprintf(strErrorMessage, _T("ERROR: Can't find HTML Element named \"%S\"!"), BSTRElementName);
MessageBox(strErrorMessage);
*/
}
else
{
pHTMLElement = pEltDisp;
}
}
}
if (!pHTMLElement)
{
// Add delay before issuing error and giving up - some HTML Element are generated dynamically
// long after the document has been loaded!
this->SetTimer(CWEB_HTML_ELEMENT_TIMER, m_intTimeoutMilliseconds, NULL);
}
cleanup:
if (V_BSTR(&name))
SysFreeString(V_BSTR(&name));
return(pHTMLElement);
}
HRESULT CWebReplayDlg::SimulateHTMLElementClick(const OLECHAR *BSTRElementName, const OLECHAR *BSTRElementValue)
{
HRESULT hResult = E_FAIL;
CComQIPtr<IHTMLElement, &IID_IHTMLElement> pHTMLElement = GetHTMLElement(BSTRElementName, BSTRElementValue);
if (pHTMLElement)
{
// Directly click on element
hResult = pHTMLElement->click();
}
return(hResult);
}
HRESULT CWebReplayDlg::SimulateTextInput(const OLECHAR *BSTRHtmlControlName, const OLECHAR *BSTRHtmlControlValue, const OLECHAR *BSTRText)
{
HRESULT hResult = E_FAIL;
CComQIPtr<IHTMLElement, &IID_IHTMLElement> pHTMLElement = GetHTMLElement(BSTRHtmlControlName, BSTRHtmlControlValue);
// Try with an HMTL Input element
CComQIPtr<IHTMLInputElement, &IID_IHTMLInputElement> pInputElement = pHTMLElement;
if (pInputElement)
{
// Directly change the "value" attribute of HTML Element
hResult = pInputElement->put_value(OLE2BSTR(BSTRText));
// Fire the "onblur" event - some javascript handler may require this after a value changes...
SimulateFireEvent(pHTMLElement, L"onblur");
}
else
{
// Try with an HTML SELECT element
CComQIPtr<IHTMLSelectElement, &IID_IHTMLSelectElement> pSelectElement = pHTMLElement;
if (pSelectElement)
{
// Directly change the "value" attribute of HTML Element
hResult = pSelectElement->put_value(OLE2BSTR(BSTRText));
// Fire the "onblur" event - some javascript handler may require this after a value changes...
SimulateFireEvent(pHTMLElement, L"onblur");
}
}
return(hResult);
}
HRESULT CWebReplayDlg::SimulateFireEvent(CComQIPtr<IHTMLElement, &IID_IHTMLElement> pHTMLElement, const OLECHAR *BSTREventName)
{
HRESULT hResult = E_FAIL;
BSTR eventName = NULL;
VARIANT eventobj;
VARIANT_BOOL vBool;
CComPtr<IDispatch> pDisp = NULL;
CComQIPtr<IHTMLDocument4, &IID_IHTMLDocument4> pDoc4;
CComPtr<IHTMLEventObj> pEvent = NULL;
CComQIPtr<IDispatch, &IID_IDispatch> pEventDisp;
CComQIPtr<IHTMLElement3, &IID_IHTMLElement3> pElt3;
CHECKPTR(pDisp = m_objExplorer.get_Document());
CHECKPTR(pDoc4 = pDisp);
hResult = pDoc4->createEventObject(NULL, &pEvent);
if (FAILED(hResult) || !pEvent)
{
goto cleanup;
}
CHECKPTR(pEventDisp = pEvent);
// Set event name
eventName = SysAllocString(BSTREventName);
VariantInit(&eventobj);
V_VT(&eventobj) = VT_DISPATCH;
V_DISPATCH(&eventobj) = pEventDisp;
// Fire the event.
CHECKPTR(pElt3 = pHTMLElement);
hResult = pElt3->fireEvent(eventName, &eventobj, &vBool);
cleanup:
if (eventName)
SysFreeString(eventName);
return(hResult);
}
void CWebReplayDlg::OnBnClickedButtonReplay()
{
m_objReplayButton.EnableWindow(FALSE);
m_objScenarioFileName.EnableWindow(FALSE);
// Save scenaro file name
CString strXMLFileName;
m_objScenarioFileName.GetWindowText(strXMLFileName);
WritePrivateProfileString("WebReplay", "ScenarioFileName", strXMLFileName, m_strConfigFile);
ResetScenario();
ReplayScenario();
}
void CWebReplayDlg::OnBnClickedCancel()
{
OnCancel();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -