建立狀態回呼函式
本教學課程說明如何建立用來監視網際網路要求狀態的狀態回呼函式。
狀態回呼函式會在任何源自于傳遞非零內容值之 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) 。
相關主題