创建状态回调函数

本教程介绍如何创建用于监视 Internet 请求状态的状态回调函数。

状态回调函数接收来自传递非零上下文值的任何 WinINet 函数发出的任何 Internet 请求的状态回调。

创建状态回调函数需要执行以下步骤:

  1. 定义上下文值。
  2. 创建状态回调函数。

定义上下文值

上下文值可以是任何无符号长整数值。 理想情况下,上下文值应标识刚刚完成的请求以及任何关联资源的位置(如果需要)。

使用上下文值的最有用方法之一是传递结构的地址并将其强制转换为 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 的格式。 为此,请按以下步骤操作:

  1. 为状态回调函数编写函数声明。

    以下示例演示一个示例声明。

    void CALLBACK CallMaster( HINTERNET,
                              DWORD_PTR,
                              DWORD,
                              LPVOID,
                              DWORD );
    
  2. 确定状态回调函数将执行的操作。 对于进行异步调用的应用程序,状态回调函数必须处理INTERNET_STATUS_REQUEST_COMPLETE值,该值指示异步请求已完成。 状态回调函数还可用于跟踪 Internet 请求的进度。

    通常,最好使用具有 dwInternetStatus 的 switch 语句作为开关值和 case 语句的状态值。 根据应用程序调用的函数类型,可以忽略某些状态值。 有关不同状态值的定义,请参阅 InternetStatusCallbackdwInternetStatus 参数下的列表。

    以下 switch 语句是如何处理状态回调的示例。

    switch (dwInternetStatus)
    {
        case INTERNET_STATUS_REQUEST_COMPLETE:
            // Add code
            break;
        default:
            // Add code
            break;
    }
    
  3. 创建代码来处理状态值。

    处理每个状态值的代码在很大程度上取决于状态回调函数的预期用途。 对于仅跟踪请求进度的应用程序,可能需要将字符串写入列表框。 对于异步操作,代码必须处理回调中返回的某些数据。

    以下状态回调函数使用 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 );
    
    }
    
  4. 使用 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 Services (WinHTTP)

 

创建状态回调函数

InternetSetStatusCallback

InternetStatusCallback