Method 1: implemented through the COM interface provided by the IE control
1. My program is based on the dialog box instead of htmlview. Therefore, you must first put an IE control (insert ActiveX control, which contains a Microsoft Web browser) on the dialog box ), give the IE control a name, such as m_ctrlweb. In addition, remember to add the <mshtml. h> header file, and put everything on the ie com interface in it. <Comdef. h> and <atlbase. h> must be added if they do not exist.
2. Use classwizard to add a response to the downloadcomplete event, so that after the webpage is downloaded, you can complete the work such as filling out a table. Of course, you can also perform these operations in events such as progresschange, but you have to determine whether the webpage is almost downloaded to the appropriate location. It is easy to figure and use downloadcomplete directly.
3. The next step is to use this control to open the target webpage. When can I open it in initdialog and the code is as follows:
Colevariant vaurl = "http://www.onlytest.net ";
M_ctrlweb.navigate2 (& vaurl, & vtmissing, & vtmissing );
The vtmissing parameter is used as the default parameter.
4. Then the main operations are completed. These operations are stored in ondownloadcompleteexplorer. For convenience, I have written several functions to complete specific functions. Before specific operations in ondownloadcompleteexplorer, I will explain these functions first.
// Function: determines whether the webpage contains elements specified by strname.
// Parameter: pobjallelement: Set of all elements in a webpage
// Strname: The ID or name of the element in the webpage
Bool hasitem (ihtmlelementcollection * pobjallelement, cstring strname)
{
Ccomptr <idispatch> Pdisp;
Pobjallelement-> item (colevariant (strname), colevariant (long) 0), & Pdisp );
If (Pdisp = NULL)
Return false;
Else
Return true;
}
// Function: enter a string in the text box of the webpage.
// Parameter: pobjallelement: Set of all elements in a webpage
// Strname: ID or name of the text box to be edited
// Strtext: the content to be written in the text box
Void putietext (ihtmlelementcollection * pobjallelement, cstring strname, cstring strtext)
{
Ccomptr Pdisp;
Pobjallelement-> item (colevariant (strname), colevariant (long) 0), & Pdisp );
Ccomqiptr pelement;
If (Pdisp = NULL)
{
Afxmessagebox (strname + "not found! ");
}
Else
{
Pelement = Pdisp;
Pelement-> put_value (strtext. allocsysstring ());
}
}
// Function: Submit a webpage form
// Parameter: pobjallelement: Set of all elements in a webpage
// Strname: ID or name of the button that can be submitted for form (you can also directly submit the form submit)
Void submitpage (ihtmlelementcollection * pobjallelement, cstring strname)
{
Ccomptrpdisp;
Pobjallelement-> item (colevariant (strname), colevariant (long) 0), & Pdisp );
Ccomqiptrpelement;
If (Pdisp = NULL)
{
Afxmessagebox (strname + "not found! ");
}
Else
{
Pelement = Pdisp;
Pelement-> click ();
}
}
// Function: select a checkbox in the webpage (actually click it)
// Parameter: pobjallelement: Set of all elements in a webpage
// Strname: ID or name of the checkbox to be selected
Void checkitem (ihtmlelementcollection * pobjallelement, cstring strname)
{
Ccomptr Pdisp;
Pobjallelement-> item (colevariant (strname), colevariant (long) 0), & Pdisp );
Ccomqiptr <ihtmlelement, & iid_ihtmlelement> pelement;
If (Pdisp = NULL)
{
Afxmessagebox (strname + "not found! ");
}
Else
{
Pelement = Pdisp;
Pelement-> click ();
}
}
Using these functions can easily complete the voting operation. The code in ondownloadcompleteexplorer is listed below.
Assume that the voting page is http://www.onlytest.com/vote.htm, and the data is forwarded to http://www.onlytest.com/vote2.asp.
Void cvotedlg: ondownloadcompleteexplorer ()
{
// Todo: add your control notification handler code here
Ihtmlelementcollection * objallelement = NULL;
Ihtmldocument2 * objdocument = NULL;
Cstring strurl, strtemp;
Strurl = m_ctrlweb.getlocationurl (); // obtain the URL of the current webpage
If (strurl. isempty ())
Return;
Objdocument = (ihtmldocument2 *) m_ctrlweb.getdocument (); // obtain the ihtmldocument2 interface pointer from the control
Objdocument-> get_all (& objallelement); // obtain the set of all elements on the webpage.
// This function is executed after all pages are downloaded. Therefore, the message source page must be determined based on the URL.
If (strurl = "http://www.onlytest.com/vote.htm ")
{
Ccomptr <idispatch> Pdisp;
If (hasitem (objallelement, "voteform") = true) // voteform is the form of the voting option.
{
Objallelement-> item (colevariant ("voteform"), colevariant (long) 0), & Pdisp );
Ccomqiptr <ihtmlformelement, & iid_ihtmlformelement> pelement;
If (Pdisp = NULL)
{
// The interface pointer fails to be obtained and ends the program. The reason is as follows:
Enddialog (idok );
Return;
}
Else
{
// If the voting result is displayed in a new window, modify the webpage code to display the result in this control.
Pelement = Pdisp;
Pelement-> put_target (ccombstr ("_ Self"); // equivalent to target = "_ Self"
Pelement-> put_action (ccombstr ("vote2.asp"); // equivalent to action = "vote2.asp"
}
Checkitem (objallelement, "CHK2"); // select the checkbox with the ID of CHK2 in the form.
Submitpage (objallelement, "Vote"); // submit the webpage. The vote is the ID or name of the submit button.
}
}
Else if (strurl = "http://www.onlytest.com/vote2.asp ")
{
Enddialog (idok); // If the voting page has been downloaded, end the program. The reason is as follows.
}
}
Now the vote has been cast out, but you may wonder why do you need to end the program with enddialog after the vote is cast or an error occurs in the middle, instead of continuing to vote? This is the case. Some websites can only vote for one session, while an IE control is created and connected to the server (with a session ), the session key is settled (one statement), So if you continue to vote with this IE control, the server will tell you that you have voted (of course, if the voting program is stupid, this is much simpler ). I wanted to solve this problem by analyzing the running process of wininet API, But it seems very troublesome. So I used a very stupid but simple method: the voting program as a program, then another program calls the voting program. After the vote, the voting program ends and the main program runs the voting program again. As for the restrictions on the number of voting programs, using shared memory segments is the simplest (in the saying goes). I will not discuss it here.
Method 2: Use the wininet API to submit a form.
This method has a small amount of code, and because it does not need to download too much useless data (such as fragments), the page where the form is located does not need to be downloaded, so the efficiency is much higher, in addition, the implementation code is a function that is suitable for use in the thread.
The key to using this method is to know what data should be submitted to the server. If you go to the webpage file and analyze what data should be submitted to the server, the webpage is very simple and similar. If the webpage is complex, it is a thankless task. Now it's not an exam, so we don't want to do that. Now there is a simpler way to use the network monitor under win2000 to manually vote to see what data has been submitted to the server. In this way, we can copy the part of the data that belongs to the HTTP protocol. The data copied directly from the monitor cannot be used, because the text displayed on the monitor replaces the characters such as carriage return and line breaks with the decimal point, the original carriage return and line feed are required for these parts (the HTTP header can be left empty, as long as you can distinguish the boundary ). Note that Content-Length may exist in the submitted information. If you modify the content of the submitted data and the Data Length changes, the value of Content-Length must be changed. For example, if the original value of Content-Length is 100 and there is a data record "1", and you change it to "12", the Content-Length must be changed to 101, otherwise, the server returns an error.
The voting function is listed below:
Uint vote (lpvoid)
{
Cinternetsession session;
Theapp. m_nthreads ++; // used to record the number of voting threads
Try
{
Chttpconnection * pconnection = session. gethttpconnection ("www.onlytest.net"); // The website Server
Chttpfile * pfile = pconnection-> openrequest (chttpconnection: http_verb_post, "vote2.asp"); // submit data directly to the voting page.
// Add an HTTP header to the submitted data, which can be obtained by the Network Monitor.
Pfile-> addrequestheaders ("accept: image/GIF, image/X-xbitmap, image/JPEG, image/pjpeg, application/vnd. MS-PowerPoint, application/vnd. MS-Excel, application/MSWord ,*/*");
Pfile-> addrequestheaders ("Referer: http://www.onlytest.net/vote.htm ");
Pfile-> addrequestheaders ("Accept-language: ZH-CN ");
Pfile-> addrequestheaders ("Content-Type: multipart/form-data; boundary = --------------------------- 7d11dc24268052c ");
Pfile-> addrequestheaders ("Accept-encoding: gzip, deflate ");
Pfile-> addrequestheaders ("User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0 )");
Pfile-> addrequestheaders ("Content-Length: 1351 ");
Pfile-> addrequestheaders ("connection: keep-alive ");
Pfile-> addrequestheaders ("cache-control: No-Cache ");
// The real data should be followed by the HTTP header. In theapp. m_strformdata, the data to be submitted is displayed. The server processes the returned information in pfile.
Pfile-> sendrequest (null, 0, theapp. m_strformdata.getbuffer (0), theapp. m_strformdata.getlength (); // submit all data
// In fact, the voting here can be completed. However, if you want to see the results, you can analyze the returned page and get some data.
Char szbuffer [11001]; // used to store the returned processing page, depending on the actual situation. Of course, it can also be dynamically allocated.
Int nlen = pfile-> Read (szbuffer, 11000); // read the returned content, which is actually the HTML code on the voting result page.
Szbuffer [nlen] = 0;
Cstring strtemp = szbuffer; // although the cstring is too popular, it is convenient to use it ~
Pfile-> close (); // after the data is read, close all the items that are closed.
Pconnection-> close ();
Delete pfile;
Delete pconnection;
Session. Close ();
// The following code is used to analyze the HTML code to get the data you are interested in. It has nothing to do with voting and will not be explained in detail.
Int NPOs = strtemp. Find ("option ");
Int ntemppos = NPOs;
If (NPOs =-1)
{
Theapp. m_nthreads --;
Return 0;
}
NPOs = strtemp. Find ("table width = 100> <tr> <TD align = right>", NPOs) + 36;
Int nendpos = strtemp. Find ("ticket", NPOs );
M_nournum = atoi (strtemp. mid (NPOs, nendpos-NPOs ));
NPOs = strtemp. Find ("<tr bgcolor = # dee6eb> <TD align = center width = 50> 1 </TD> ");
NPOs = strtemp. Find ("table width = 100> <tr> <TD align = right>", NPOs) + 36;
Nendpos = strtemp. Find ("ticket", NPOs );
M_ndiff = atoi (strtemp. mid (NPOs, nendpos-NPOs)-m_nournum;
M_nvote ++;
}
Catch (...)
{
}
Theapp. m_nthreads --;
Return 0;
}
As you can see, the key code is just a few lines. If the voting result is not analyzed, it is much less than method 1, and it is not as messy as method 1. However, this method also has the session repetition problem described in method 1. In addition, I tried to repeat the new thread session. So I guess the session key is determined by the process ID (let's talk about it ). However, if you start n threads at the same time, all n threads can successfully vote in, rather than saying "you have already voted ". It is estimated that the information is submitted at the same time. When the server processes a piece of information, it does not know that this session has actually been voted. I don't know whether this is the reason. You can discuss it.