SUMMARY
To properly simulate a Form submission using WinInet, you need to send a header that indicates the proper Content-Type. For Forms, the proper Content-Type header is: Content-Type: application/x-www-form-urlencoded
MORE INFORMATION
In many cases, the server does not respond appropriately if a Content-Type is not specified. For example, the Active Server Pages component of IIS 3.0 actually checks this header specifically for 'application/x-www-form- urlencoded' before adding form variables to the "Request.Form" object. This MIME/Content-Type indicates that the data of the request is a list of URL- encoded form variables. URL-encoding means that space character (ASCII 32) is encoded as ' ', special character such '!' encoded in hexadecemal form as '!'.
Here is a snippet of code that uses the MFC WinInet classes to simulate a Form POST request:
CString strHeaders = _T("Content-Type: application/x-www-form-urlencoded");
// URL-encoded form variables -
// name = "John Doe", userid = "hithere", other = "P&Q"
CString strFormData = _T("name=John Doe&userid=hithere&other=P&Q");
CInternetSession session;
CHttpConnection* pConnection = session.GetHttpConnection(_T("ServerNameHere"));
CHttpFile* pFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,_T("FormActionHere"));
BOOL result = pFile->SendRequest(strHeaders,(LPVOID)(LPCTSTR)strFormData, strFormData.GetLength());
Without MFC, the same code translates to straight SDK calls as follows:
static
TCHAR hdrs[] = _T("Content-Type: application/x-www-form-urlencoded");
static
TCHAR frmdata[] = _T("name=John Doe&userid=hithere&other=P&Q");
statuc TCHAR accept[] = _T("Accept: */*");
// for clarity, error-checking has been removed
HINTERNET hSession = InternetOpen("MyAgent",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET hConnect = InternetConnect(hSession, _T("ServerNameHere"),
INTERNET_DEFAULT_HTTP_PORT,
NULL,
NULL,
INTERNET_SERVICE_HTTP,
0,
1);
HINTERNET hRequest = HttpOpenRequest(hConnect,
"POST",
_T("FormActionHere"),
NULL,
NULL,
accept,
0,
1);
HttpSendRequest(hRequest,
hdrs,
strlen(hdrs),
frmdata,
strlen(frmdata));
// close any valid internet-handles
我这里有一段程序,用来在一个对话框里显示出一次http request的原始信息,不过使用Inet API做的,希望能有帮助。
void CHTTPRequestDlg::OnButtonRequest()


{
UpdateData(TRUE);
HINTERNET hInternet = InternetOpen("Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0)",
INTERNET_OPEN_TYPE_DIRECT,
NULL,
NULL,
NULL);
HINTERNET hSession = InternetConnect(hInternet,
m_strHost,
m_nPort,
"username",
"password",
INTERNET_SERVICE_HTTP,
0,
0);

char* szAccept[] =
{"*/*",NULL};
CString strVerb;
m_comboVerb.GetWindowText(strVerb);
HINTERNET hRequest = HttpOpenRequest(hSession,
strVerb,
m_strObject,
NULL,
NULL,
(LPCSTR*)szAccept,
0,
0);
struct

{
char* Language;
char* Encoding;
char* ContentType;

}Headers =
{"Accept-Language:zh-cn\r\n",
"Accept-Encoding:gzip,deflate\r\n",
"Content-Type:application/x-www-form-urlencoded\r\n"};
if(m_bLanguage)

{
HttpAddRequestHeaders(hRequest,
Headers.Language,
-1,
HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);
}
if(m_bEncoding)

{
HttpAddRequestHeaders(hRequest,
Headers.Encoding,
-1,
HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);
}
if(m_bContentType)

{
HttpAddRequestHeaders(hRequest,
Headers.ContentType,
-1,
HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);
}
LPCSTR lpAddHeader = NULL;
LPCSTR lpContent = NULL;

if(m_strHeaders.GetLength())

{
if(m_strHeaders.Right(2) != "\r\n")

{
m_strHeaders+="\r\n";
}
lpAddHeader = (LPCSTR)m_strHeaders;
}
if(m_strContent.GetLength() && (strVerb == "POST" || strVerb == "PUT"))

{
lpContent = (LPCSTR)m_strContent;
}
HttpSendRequest(hRequest,
lpAddHeader,
-1,
(LPVOID)lpContent,
m_strContent.GetLength());
m_editContentGot.SetSel(0,-1);
m_editContentGot.ReplaceSel("");
LPSTR lpszData; //buffer for the data
DWORD dwSize; //size of the data available
DWORD dwDownloaded; //size of the downloaded data
//Set the cursor to an hourglass.
SetCursor(LoadCursor(NULL,IDC_WAIT));
// This loop handles reading the data.
while(1)

{
// The call to InternetQueryDataAvailable determines the amount of
// data available to download.
if (!InternetQueryDataAvailable(hRequest,&dwSize,0,0))

{
SetCursor(LoadCursor(NULL,IDC_ARROW));
break;
}
else

{
// Allocates a buffer of the size returned by InternetQueryDataAvailable
lpszData = new char[dwSize+1];
// Reads the data from the HINTERNET handle.
if(!InternetReadFile(hRequest,(LPVOID)lpszData,dwSize,&dwDownloaded))

{
delete[] lpszData;
break;
}
else

{
// Adds a null terminator to the end of the data buffer
lpszData[dwDownloaded]='\0';
int nLen = m_editContentGot.GetWindowTextLength();
m_editContentGot.SetSel(nLen-1, nLen-1);
m_editContentGot.ReplaceSel(lpszData);
// Delete the two buffers
delete[] lpszData;
// Check the size of the remaining data. If it is zero, break.
if (dwDownloaded == 0)

{
break;
}
}
}
}
// Close the HINTERNET handle
InternetCloseHandle(hRequest);
InternetCloseHandle(hSession);
InternetCloseHandle(hInternet);
// Set the cursor back to an arrow
SetCursor(LoadCursor(NULL,IDC_ARROW));
}
==========================================
使用MFC示例如下:
首先设置m_strRequest请求字符串 eg."name=aaa&pass=bbb";
m_strServerName 服务器名称或者IP eg."www.yahoo.com"
m_strObjectName 请求文件位置 eg. "pub/aaa.asp"
请求的结果存放在m_strHtml中
void func()


{
CInternetSession m_InetSession("session");
CHttpConnection *pServer = NULL;
CHttpFile* pFile = NULL;
try

{
INTERNET_PORT nPort;
nPort=80;
pServer = m_InetSession.GetHttpConnection(m_strServerName, nPort);
pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST,m_strObjectName);
char szHeaders[100];
strcpy(szHeaders,"Accept: text*/*\r\nContent-Type: application/x-www-form-urlencoded");
pFile->AddRequestHeaders(szHeaders);
pFile->SendRequestEx(m_strRequest.GetLength());
pFile->WriteString(m_strRequest);//重要-->m_Request 中有"name=aaa&name2=BBB&
"
pFile->EndRequest();
DWORD dwRet;
pFile->QueryInfoStatusCode(dwRet);
CString str;
m_Mutex.Lock();
m_strHtml="";
char szBuff[1024];

if (dwRet == HTTP_STATUS_OK)

{
UINT nRead;
while ((nRead = pFile->Read(szBuff,1023))>0)

{
m_strHtml += CString(szBuff,nRead);
}
}
m_Mutex.Unlock();
delete pFile;
delete pServer;
}
catch (CInternetException* e)

{
CString s;
s.Format("Internet Exception\r\nm_dwError%u,m_dwContextError%u",e->m_dwError,e->m_dwContext);
AfxMessageBox(s);
//catch errors from WinInet
}
}
============================
1、获得WebBrowser Control的DWebBrowserEvents2::DocumentComplete事件
2、在DWebBrowserEvents2::DocumentComplete事件中根据IWebBrowser2::Document获得IHTMLDocument2
3、IHTMLDocument2::forms得到IHTMLElementCollection
4、在IHTMLElementCollection中根据name、tagName、ID得到指定的IHTMLElement
5、从IHTMLElement得到IHTMLFormElement
6、执行IHTMLFormElement::submit
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了