如何定制一款12306抢票浏览器——用户界面
用户界面
我不打算写个Windows界面。因为这个软件的全部就是个浏览器。我准备将”浏览器“进行到底,所以我选择使用html作为我们的用户界面。我也并不打算从头开始写一个浏览器,我使用了《内嵌IE网页窗口中消除IE默认脚本设置影响的方法》中基于WTL的浏览器代码。(转载请指明出于breaksoftware的csdn博客)界面如下
我观察了下12306的页面,它预留了5个乘客信息,所以我也就预留了5个乘客信息。因为我不会写HTML和javascript,我就从12306中copy出相应的页面元素,并加以修改。在此感谢下12306网页设计同学,帮我完成了不少我不会的东西。
一般来说,我们可能一次性不会购买5个人的票。所以在上面的界面中,你想填多少人信息就填多少人信息,我会在代码中读取这些人的信息。当我们填完乘客信息后,我们要输入车次信息。然后我们要点击一下确定,我会在代码中捕获点击确定的操作,并将已经填写的信息读入内存。在之后的抢票过程中,我们将使用到这些信息。最后,我们就要点击最下面那个超链接,跳转到12306这个页面,开始我们真正的抢票工作。
我们来看一下源代码。首先是界面的,我列一个人的信息代码出来:
HRESULT CDeal12306WebPage::GetPassengerInfo( CComPtr<IHTMLElement> & spElem, StSinglePassengerInfo & stSinglePassenger ){ HRESULT hr = E_FAIL; do { CString cstrSeat; hr = GetOptionValueHelper(spElem, L"seat", cstrSeat); CHECKHR(hr); stSinglePassenger.ListSeat.push_back(cstrSeat); hr = GetOptionValueHelper(spElem, L"ticket", stSinglePassenger.cstrTicket ); CHECKHR(hr); hr = GetOptionValueHelper(spElem, L"cardtype", stSinglePassenger.cstrCardtype); CHECKHR(hr); hr = GetInputValueHelper(spElem, L"name", stSinglePassenger.cstrName); CHECKHR(hr); hr = GetInputValueHelper(spElem, L"cardno", stSinglePassenger.cstrCardNo); CHECKHR(hr); hr = GetInputValueHelper(spElem, L"mobileno", stSinglePassenger.cstrMobileNo); } while (0); return hr;}HRESULT CDeal12306WebPage::GetOptionValueHelper( CComPtr<IHTMLElement> & spElem, const CString& cstrID, CString& cstrValue ){ HRESULT hr = E_FAIL; do { CComPtr<IHTMLElement> spTd; hr = GetElementByID(spElem, cstrID, spTd); CHECKHRPOINTER(hr, spTd); CComPtr<IHTMLElement> spSel; hr = GetElementByIndex(spTd, 0, spSel); CHECKHRPOINTER(hr, spSel); CComPtr<IHTMLSelectElement> spSelect; hr = spSel->QueryInterface(IID_IHTMLSelectElement, (LPVOID*)&spSelect); CHECKHRPOINTER(hr, spSelect); CComBSTR bstrValue; hr = spSelect->get_value(&bstrValue); CHECKHR(hr); cstrValue = bstrValue; } while (0); return hr;}HRESULT CDeal12306WebPage::GetInputValueHelper( CComPtr<IHTMLElement> & spElem, const CString& cstrID, CString & cstrValue ){ HRESULT hr = E_FAIL; do { CComPtr<IHTMLElement> spTd; hr = GetElementByID(spElem, cstrID, spTd); CHECKHRPOINTER(hr, spTd); CComPtr<IHTMLElement> spInput; hr = GetElementByIndex(spTd, 0, spInput); CHECKHRPOINTER(hr, spInput); CComPtr<IHTMLInputElement> spInputElem; hr = spInput->QueryInterface(IID_IHTMLInputElement, (LPVOID*)&spInputElem); CHECKHRPOINTER(hr, spInputElem); CComBSTR bstrValue; hr = spInputElem->get_value(&bstrValue); CHECKHR(hr); cstrValue = bstrValue; } while (0); return hr;}HRESULT CDeal12306WebPage::GetTrainNoInSettingPage( CComPtr<IHTMLDocument2> & spDoc, CString & cstrValue ){ HRESULT hr = E_FAIL; do { CComPtr<IHTMLElement> spBody; hr = spDoc->get_body(&spBody); CHECKHRPOINTER(hr, spBody); CComPtr<IHTMLElement> spTable; hr = GetElementByID(spBody, L"trainnotable", spTable); CHECKHRPOINTER(hr, spTable); CComPtr<IHTMLElement> spTBody; hr = GetElementByIndex( spTable, 0, spTBody); CHECKHRPOINTER(hr, spTBody); CComPtr<IHTMLElement> spTr; hr = GetElementByIndex(spTBody, 0, spTr); CHECKHRPOINTER(hr, spTr); CComPtr<IHTMLElement> spTd; hr = GetElementByID(spTr, L"trainno", spTd); CHECKHRPOINTER(hr, spTd); CComPtr<IHTMLElement> spInput; hr = GetElementByIndex(spTd, 0, spInput); CHECKHRPOINTER(hr, spInput); CComPtr<IHTMLInputElement> spInputElem; hr = spInput->QueryInterface(IID_IHTMLInputElement, (LPVOID*)&spInputElem); CHECKHRPOINTER(hr, spInputElem); CComBSTR bstrValue; hr = spInputElem->get_value(&bstrValue); CHECKHR(hr); cstrValue = bstrValue; } while (0); return hr;}