建立狀態回呼函式
本教學課程說明如何建立用來監視因特網要求狀態的狀態回呼函式。
狀態回呼函式會在任何源自任何傳遞非零內容值的 WinINet 函式的因特網要求上接收狀態回呼。
建立狀態回呼函式需要下列步驟:
定義情境值
內容值可以是任何不帶正負號的整數值。 理想情況下,上下文值應該識別已完成的請求,以及任何相關聯資源的位置(如果需要)。
使用內容值的最有用方式之一是傳遞結構的位址,並將它轉換成 DWORD_PTR。 結構可用來儲存要求的相關信息,以便傳遞至狀態回呼函式。
下列結構是可能的內容值範例。 結構的成員會以 InternetOpenUrl 函式來選擇。
typedef struct{
HWND hWindow; // Window handle
int nStatusList; // List box control to hold callbacks
HINTERNET hResource; // HINTERNET handle created by InternetOpenUrl
char szMemo[512]; // String to store status memo
} REQUEST_CONTEXT;
在此範例中,狀態回呼函式可以存取視窗句柄,以允許它顯示使用者介面。 InternetOpenUrl 所建立的 HINTERNET 句柄可以傳遞至另一個函式,該函式可以下載資源,還有一個字元陣列可以用來傳遞關於請求的信息。
結構的成員可以變更以符合特定應用程式的需求,因此請勿受到此範例的限制。
建立狀態回呼函式
狀態回呼函式必須遵循 InternetStatusCallback的格式。 若要這樣做:
撰寫狀態回呼函式的函式宣告。
下列範例顯示範例宣告。
void CALLBACK CallMaster( HINTERNET, DWORD_PTR, DWORD, LPVOID, DWORD );
判斷您的狀態回呼函式將執行什麼動作。 對於進行異步呼叫的應用程式,狀態回呼函式必須處理INTERNET_STATUS_REQUEST_COMPLETE值,表示異步要求已完成。 狀態回呼函式也可用來追蹤因特網要求的進度。
一般而言,最好使用 switch 陳述式搭配 dwInternetStatus 作為 switch 值,以及 case 陳述式的狀態值。 視應用程式所呼叫的函式類型而定,您可以忽略某些狀態值。 如需不同狀態值的定義,請參閱 InternetStatusCallback的 dwInternetStatus 參數底下的清單。
下列 switch 語句是如何處理狀態回呼的範例。
switch (dwInternetStatus) { case INTERNET_STATUS_REQUEST_COMPLETE: // Add code break; default: // Add code break; }
建立程式代碼來處理狀態值。
處理每個狀態值的程式代碼,取決於您預期使用的狀態回呼函式。 對於只是追蹤要求進度的應用程式,將字串寫入清單框可能是您所需要的一切。 針對異步操作,程式碼必須處理回呼中傳回的部分數據。
下列狀態回呼函式會使用 switch 函式來判斷狀態值是什麼,並建立字串,其中包含狀態值的名稱和先前呼叫的函式,其儲存在REQUEST_CONTEXT 結構的 szMemo 成員中。
void __stdcall CallMaster( HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength ) { UNREFERENCED_PARAMETER(hInternet); UNREFERENCED_PARAMETER(lpvStatusInformation); UNREFERENCED_PARAMETER(dwStatusInformationLength); REQUEST_CONTEXT *cpContext; cpContext = (REQUEST_CONTEXT*)dwContext; char szStatusText[80]; switch (dwInternetStatus) { case INTERNET_STATUS_CLOSING_CONNECTION: StringCchPrintfA( szStatusText, 80, "%s CLOSING_CONNECTION", cpContext->szMemo); break; case INTERNET_STATUS_CONNECTED_TO_SERVER: StringCchPrintfA( szStatusText, 80, "%s CONNECTED_TO_SERVER", cpContext->szMemo ); break; case INTERNET_STATUS_CONNECTING_TO_SERVER: StringCchPrintfA( szStatusText, 80, "%s CONNECTING_TO_SERVER", cpContext->szMemo ); break; case INTERNET_STATUS_CONNECTION_CLOSED: StringCchPrintfA( szStatusText, 80, "%s CONNECTION_CLOSED", cpContext->szMemo ); break; case INTERNET_STATUS_HANDLE_CLOSING: StringCchPrintfA( szStatusText, 80, "%s HANDLE_CLOSING", cpContext->szMemo ); break; case INTERNET_STATUS_HANDLE_CREATED: StringCchPrintfA( szStatusText, 80, "%s HANDLE_CREATED", cpContext->szMemo); break; case INTERNET_STATUS_INTERMEDIATE_RESPONSE: StringCchPrintfA( szStatusText, 80, "%s INTERMEDIATE_RESPONSE", cpContext->szMemo ); break; case INTERNET_STATUS_NAME_RESOLVED: StringCchPrintfA( szStatusText, 80, "%s NAME_RESOLVED", cpContext->szMemo); break; case INTERNET_STATUS_RECEIVING_RESPONSE: StringCchPrintfA( szStatusText, 80, "%s RECEIVING_RESPONSE", cpContext->szMemo); break; case INTERNET_STATUS_RESPONSE_RECEIVED: StringCchPrintfA( szStatusText, 80, "%s RESPONSE_RECEIVED", cpContext->szMemo); break; case INTERNET_STATUS_REDIRECT: StringCchPrintfA( szStatusText, 80, "%s REDIRECT", cpContext->szMemo ); break; case INTERNET_STATUS_REQUEST_COMPLETE: StringCchPrintfA( szStatusText, 80, "%s REQUEST_COMPLETE", cpContext->szMemo); break; case INTERNET_STATUS_REQUEST_SENT: StringCchPrintfA( szStatusText, 80, "%s REQUEST_SENT", cpContext->szMemo); break; case INTERNET_STATUS_RESOLVING_NAME: StringCchPrintfA( szStatusText, 80, "%s RESOLVING_NAME", cpContext->szMemo ); break; case INTERNET_STATUS_SENDING_REQUEST: StringCchPrintfA( szStatusText, 80, "%s SENDING_REQUEST", cpContext->szMemo ); break; case INTERNET_STATUS_STATE_CHANGE: StringCchPrintfA( szStatusText, 80, "%s STATE_CHANGE", cpContext->szMemo ); break; default: StringCchPrintfA( szStatusText, 80, "%s Unknown Status %d Given", cpContext->szMemo, dwInternetStatus); break; } SendDlgItemMessage( cpContext->hWindow, cpContext->nStatusList, LB_ADDSTRING, 0, (LPARAM)szStatusText ); }
使用 InternetSetStatusCallback 函式,在您想要接收狀態回呼的 HINTERNET 句柄上設定狀態回呼函式。
下列範例示範如何設定狀態回呼函式。
HINTERNET hOpen; // Root HINTERNET handle INTERNET_STATUS_CALLBACK iscCallback; // Holds the callback function // Create the root HINTERNET handle. hOpen = InternetOpen( TEXT("Test Application"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); // Set the status callback function. iscCallback = InternetSetStatusCallback( hOpen, (INTERNET_STATUS_CALLBACK)CallMaster );
注意
WinINet 不支援伺服器實作。 此外,不應該透過服務來使用。 針對伺服器實作或服務,請使用 Microsoft Windows HTTP 服務 (WinHTTP)。
相關主題