前段時間在開發過程中需要訪問網頁,用CInternetSession很方便的實現同步訪問,但用異步訪問是總是彈出assert錯誤,極不爽快,而我的程序想實現異步訪問,在網上搜尋了許久,但所述都不夠詳細,經鄙人一段時間的摸索,終于成功實現異步訪問網頁。。。特寫此文,以供有需要者共享,如果需要演示代碼,可以發信至 ,本人無償供應源代碼。
下面簡要敘述一下實現步驟:
1,用InternetOpen建立internet handle
HINTERNET hInternet=InternetOpen("MyProgram/1.0",PRE_CONFIG_INTERNET_ACCESS, 0,0,INTERNET_FLAG_ASYNC)
2, 調用InternetSetStatusCallback建立回調函數
INTERNET_STATUS_CALLBACK pRet =
InternetSetStatusCallback(m_hInternet, OnStatusCallback);
3,調用InternetOpenUrl函數打開一個URL
InternetOpenUrl(hInternet,pstrURL,NULL,0,
INTERNET_FLAG_TRANSFER_ASCII,
(DWORD)hWnd);這里的hWnd句柄為接受回調函數發送的消息的窗口句柄
4,處理回調函數
void AFXAPI OnStatusCallback( HINTERNET hInternet,DWORD dwContext, DWORD dwInternetStatus,
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength )
{
// AFX_MANAGE_STATE( AfxGetAppModuleState( ) );
HWND hwnd=(HWND)dwContext
switch(dwInternetStatus)
{
case INTERNET_STATUS_CONNECTION_CLOSED:
// closed the connection to the server. The lpvStatusInformation parameter is NULL.
if(IsWindow(hwnd))
PostMessage(m_hWndParent,WM_CONNECT_CLOSED,0,0);
break;
case INTERNET_STATUS_REQUEST_COMPLETE :
{
// by the Win32 API function InternetConnect to indicate that it has created the new handle. This lets the application call the Win32 function InternetCloseHandle from another thread if the connect is taking too long. See the ActiveX SDK for more information about these functions.
INTERNET_ASYNC_RESULT* res = (INTERNET_ASYNC_RESULT*)lpvStatusInformation;
HINTERNET hInet = (HINTERNET)(res->dwResult);
if(IsWindow(hwnd))
PostMessage(hwnd,WM_REQUEST_COMPLETE,(WPARAM)res->dwError ,(LPARAM)hInet);
}
break;
default:
// Message("Unknown status:%d",dwInternetStatus);
break;
}
}
5,在擁有hwnd句柄的窗口類里處理WindowProc函數,在頭文件里定義類變量
HINTERNET m_hInternet
TCHAR m_buf[1024];
INTERNET_BUFFERS ip;
在CPP文件里處理WindowProc函數
LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
switch(message)
{
case WM_CONNECT_CLOSED:
{
if(ip.dwBufferLength>0)
{
m_buf[ip.dwBufferLength]=0;
ib.dwBufferTotal+=ip.dwBufferLength;
// Message(m_buf);//here storage or show m_buf;
}
TRACE("--Bufferlen:%d,Total:%d----\n",ib.dwBufferLength,ib.dwBufferTotal);
//////////////here close two internet handle
}
break;
case WM_REQUEST_COMPLETE:
{
if(wParam!=0)
{//error
char buf[255];
sprintf(buf,"\r\n------Error:%d--------\r\n",wParam);
Message(buf);
}
else
{
HINTERNET hinet=(HINTERNET)lParam;
if(hinet>(HINTERNET)2)
m_hInternet=hinet;
else
{//=1, meaning last pending complete
hinet=m_hInternet;
TRACE("-Buffer:%d--\n",ib.dwBufferLength);
if(ib.dwBufferLength>0)
{
m_buf[ib.dwBufferLength]=0;
TRACE("---Receive Length:%d\n",ib.dwBufferLength);
ib.dwBufferTotal+=ib.dwBufferLength;
// show or storage m_buf
}
// clear m_buf;
m_buf[0]=0;
}
ib.dwBufferLength=1;
BOOL bOk;
while(ib.dwBufferLength!=0 )
{
memset(m_buf,0,sizeof(m_buf));
ib.lpvBuffer = m_buf;
ib.dwBufferLength = sizeof(m_buf)-1;
bOk = InternetReadFileEx(hinet, &ib, IRF_ASYNC, (LPARAM)this->m_hWnd );
if(!bOk && GetLastError()==ERROR_IO_PENDING)
{
TRACE("---------Pending----------");
break;
}
if(bOk && ib.dwBufferLength!=0)
{
m_buf[ib.dwBufferLength]=0;
TRACE("---Receive Length:%d\n",ib.dwBufferLength);
ib.dwBufferTotal+=ib.dwBufferLength;
Message(m_buf);
m_buf[0]=0;
}
}
}
}
break;
}
return CFrameWnd::WindowProc(message, wParam, lParam);
}
5, 如果對以上步驟有不理解者,或者最后不能實現異步訪問者,請與我聯系,歡迎大家。