Udostępnij przez


Tworzenie funkcji wywołania zwrotnego statusu

W tym samouczku opisano sposób tworzenia funkcji wywołania zwrotnego stanu używanej do monitorowania stanu żądania internetowego.

Funkcje wywołań zwrotnych statusu odbierają wywołania zwrotne statusu dotyczące wszystkich żądań internetowych pochodzących z dowolnej funkcji WinINet, której przekazano wartość kontekstu niezerowego.

Następujące kroki są niezbędne do utworzenia funkcji wywołania zwrotnego stanu:

  1. Zdefiniuj wartość kontekstu.
  2. Utwórz funkcję wywołania zwrotnego stanu.

Definiowanie wartości kontekstu

Wartość kontekstu może być dowolną niepodpisaną długą liczbą całkowitą. W idealnym przypadku wartość kontekstu powinna określić, które żądanie zostało właśnie ukończone, oraz lokalizację wszelkich skojarzonych zasobów, jeśli jest to konieczne.

Jednym z najbardziej przydatnych sposobów użycia wartości kontekstu jest przekazanie adresu struktury i rzutowanie go na DWORD_PTR. Struktura może służyć do przechowywania informacji o żądaniu, dzięki czemu jest przekazywana do funkcji wywołania zwrotnego stanu.

Poniższa struktura jest przykładem możliwej wartości kontekstu. Członkowie struktury są dobierani z myślą o funkcji 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;

W tym przykładzie funkcja wywołania zwrotnego stanu ma dostęp do uchwytu okna, co pozwoli jej wyświetlić interfejs użytkownika. Uchwyt utworzony przez InternetOpenUrl można przekazać do innej funkcji, która może pobrać zasób i wykorzystać tablicę znaków do przekazania informacji o żądaniu.

Elementy struktury można zmieniać, aby dostosować je do potrzeb określonej aplikacji, więc nie czujcie się ograniczeni przez ten przykład.

Tworzenie funkcji wywołania zwrotnego stanu

Funkcja wywołania zwrotnego stanu musi być zgodna z formatem InternetStatusCallback. W tym celu:

  1. Napisz deklarację funkcji dla funkcji wywołania zwrotnego stanu.

    Poniższy przykład przedstawia przykładową deklarację.

    void CALLBACK CallMaster( HINTERNET,
                              DWORD_PTR,
                              DWORD,
                              LPVOID,
                              DWORD );
    
  2. Określ, co zrobi funkcja wywołania zwrotnego stanu. W przypadku aplikacji wykonujących wywołania asynchroniczne funkcja wywołania zwrotnego stanu musi obsługiwać wartość INTERNET_STATUS_REQUEST_COMPLETE, która wskazuje, że żądanie asynchroniczne zostało ukończone. Funkcję wywołania zwrotnego stanu można również użyć do śledzenia postępu żądania internetowego.

    Ogólnie rzecz biorąc, najlepiej użyć instrukcji 'switch' z dwInternetStatus jako wartości przełącznika i wartości stanu dla instrukcji 'case'. W zależności od typów funkcji wywoływanych przez aplikację można zignorować niektóre wartości stanu. Aby uzyskać definicję różnych wartości statusu, zobacz listę pod parametrem dwInternetStatus w funkcji InternetStatusCallback.

    Poniższa instrukcja switch to przykład obsługi wywołań zwrotnych stanu.

    switch (dwInternetStatus)
    {
        case INTERNET_STATUS_REQUEST_COMPLETE:
            // Add code
            break;
        default:
            // Add code
            break;
    }
    
  3. Utwórz kod, aby obsłużyć wartości stanu.

    Kod do obsługi każdej z wartości stanu zależy w dużym stopniu od zamierzonego użycia funkcji wywołania zwrotnego stanu. W przypadku aplikacji, które śledzą postęp żądania, zapisanie ciągu do pola listy może wystarczyć. W przypadku operacji asynchronicznych kod musi obsługiwać niektóre dane zwrócone w wywołaniu zwrotnym.

    Następująca funkcja wywołania zwrotnego używa instrukcji switch do określenia wartości stanu i tworzy ciąg znaków zawierający nazwę tej wartości stanu oraz nazwę poprzednio wywołanej funkcji, która jest przechowywana w składowej szMemo struktury REQUEST_CONTEXT.

    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. Użyj funkcji InternetSetStatusCallback, aby ustawić funkcję wywołania zwrotnego stanu dla uchwytu HINTERNET, dla którego chcesz odbierać wywołania zwrotne stanu.

    W poniższym przykładzie pokazano, jak ustawić funkcję wywołania zwrotnego stanu.

    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 );
    

Notatka

Usługa WinINet nie obsługuje implementacji serwera. Ponadto nie należy jej używać z usługi. W przypadku implementacji serwera lub usług należy użyć usług HTTP systemu Microsoft Windows (WinHTTP).

 

Tworzenie funkcji zwrotnych dla statusu

InternetSetStatusCallback

InternetStatusCallback