状態コールバック関数の作成

このチュートリアルでは、インターネット要求の状態を監視するために使用される状態コールバック関数を作成する方法について説明します。

状態コールバック関数は、0 以外のコンテキスト値を渡された WinINet 関数から送信されたすべてのインターネット要求で状態コールバックを受け取ります。

状態コールバック関数を作成するには、次の手順が必要です。

  1. コンテキスト値を定義します。
  2. 状態コールバック関数を作成します。

コンテキスト値の定義

コンテキスト値には、任意の符号なし long 整数値を指定できます。 コンテキスト値は、完了したばかりの要求と、必要に応じて関連付けられているリソースの場所を識別する必要があるのが理想的です。

コンテキスト値を使用する最も便利な方法の 1 つは、構造体のアドレスを渡して 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値を処理する必要があります。 状態コールバック関数を使用して、インターネット要求の進行状況を追跡することもできます。

    一般に、switch ステートメントと dwInternetStatus をスイッチ値として使用し、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 );
    

Note

WinINet では、サーバーの実装はサポートされていません。 また、サービスから使用しないでください。 サーバーの実装またはサービスの場合は、 Microsoft Windows HTTP サービス (WinHTTP) を使用します。

 

状態コールバック関数の作成

InternetSetStatusCallback

InternetStatusCallback