Udostępnij za pośrednictwem


Drukowanie aplikacji desktopowych

W tej sekcji opisano sposób drukowania z natywnego programu klasycznego systemu Windows.

Przegląd

Aby zapewnić najlepsze wrażenia użytkownika podczas korzystania z natywnej aplikacji Windows, program musi być zaprojektowany do drukowania z dedykowanego wątku. W natywnym programie systemu Windows program jest odpowiedzialny za zarządzanie zdarzeniami i komunikatami interfejsu użytkownika. Operacje drukowania mogą wymagać okresów intensywnych obliczeń, ponieważ zawartość aplikacji jest renderowana dla drukarki, co może uniemożliwić programowi reagowanie na interakcję użytkownika, jeśli to przetwarzanie jest wykonywane w tym samym wątku co przetwarzanie zdarzeń interakcji użytkownika.

Jeśli wiesz już, jak napisać wielowątkowy natywny program systemu Windows, przejdź bezpośrednio do Jak wydrukować z aplikacji systemu Windows i dowiedzieć się, jak dodać funkcje drukowania do programu.

Podstawowe wymagania dotyczące programu systemu Windows

Aby uzyskać najlepszą wydajność i czas odpowiedzi programu, nie wykonuj przetwarzania zadań drukowania programu w wątku, który przetwarza interakcję użytkownika.

Ta separacja drukowania z interakcji użytkownika będzie mieć wpływ na sposób, w jaki program zarządza danymi aplikacji. Przed rozpoczęciem pisania aplikacji należy dokładnie zrozumieć te implikacje. W poniższych tematach opisano podstawowe wymagania dotyczące obsługi drukowania w osobnym wątku programu.

Podstawy programu systemu Windows

Natywny program systemu Windows musi dostarczyć główną procedurę okna do przetwarzania komunikatów okna odbieranych z systemu operacyjnego. Każde okno w programie systemu Windows ma odpowiednią funkcję WndProc, która przetwarza te komunikaty okna. Wątek, w którym ta funkcja jest uruchamiana, jest nazywany wątkiem interfejsu użytkownika, czyli wątkiem UI.

Użyj zasobów dla ciągów znaków.
Użyj zasobów ciągów z pliku zasobów programu zamiast stałych ciągów dla ciągów, które mogą wymagać zmiany w przypadku obsługi innego języka. Zanim program będzie mógł użyć zasobu jako ciągu znaków, musi najpierw pobrać ten zasób z pliku zasobów i skopiować go do lokalnego bufora pamięci. Wymaga to dodatkowego programowania na początku, ale umożliwia łatwiejsze modyfikacje, tłumaczenie i lokalizację programu w przyszłości.
Przetwarzanie danych w krokach.
Przetwarzaj zadanie drukowania w krokach, które można przerwać. Ten projekt umożliwia użytkownikowi anulowanie długiej operacji przetwarzania przed jego ukończeniem i uniemożliwia programowi blokowanie innych programów, które mogą być uruchomione w tym samym czasie.
Użyj danych użytkownika okna.
Aplikacje do drukowania często mają kilka okien i wątków. Aby zachować dostęp do danych między wątkami i krokami przetwarzania bez używania zmiennych statycznych, globalnych, odwołaj się do struktur danych za pomocą wskaźnika danych, który jest częścią okna, w którym są używane.

Poniższy przykładowy kod przedstawia główny punkt wejścia dla aplikacji do drukowania. W tym przykładzie pokazano, jak używać zasobów ciągów zamiast stałych ciągów, a także przedstawia główną pętlę komunikatów, która przetwarza komunikaty okna programu.

int APIENTRY 
wWinMain(
        HINSTANCE hInstance, 
        HINSTANCE hPrevInstance, 
        LPWSTR lpCmdLine, 
        int nCmdShow
)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    MSG msg;
    HACCEL hAccelTable;
    HRESULT hr = S_OK;

    // Register the main window class name
    WCHAR szWindowClass[MAXIMUM_RESOURCE_STRING_LENGTH];            
    LoadString(
        hInstance, 
        IDC_PRINTSAMPLE, 
        szWindowClass, 
        MAXIMUM_RESOURCE_STRING_LENGTH);
    MyRegisterClass(hInstance, szWindowClass);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        // Unable to initialize this instance of the application
        //  so display error message and exit
        MessageBoxWithResourceString (
            hInstance, 
            GetDesktopWindow(), 
            IDS_ERROR_INSTINITFAIL, 
            IDS_CAPTION_ERROR, 
            (MB_OK | MB_ICONEXCLAMATION));
        return FALSE;
    }    
    
    // Init COM for printing interfaces
    if (FAILED(hr = CoInitializeEx(0, COINIT_MULTITHREADED)))
    {
        // Unable to initialize COM
        //  so display error message and exit
        MessageBoxWithResourceString (
            hInstance, 
            GetDesktopWindow(), 
            IDS_ERROR_COMINITFAIL, 
            IDS_CAPTION_ERROR, 
            (MB_OK | MB_ICONEXCLAMATION));
        return FALSE;
    }

    hAccelTable = LoadAccelerators(
                    hInstance, 
                    MAKEINTRESOURCE(IDC_PRINTSAMPLE));

    // Main message handling loop
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    // Uninitialize (close) the COM interface
    CoUninitialize();

    return (int) msg.wParam;
}

Informacje o dokumencie

Natywne programy systemu Windows przeznaczone do drukowania powinny być przeznaczone do przetwarzania wielowątkowego. Jednym z wymagań projektu wielowątkowego jest ochrona elementów danych programu tak, aby były bezpieczne dla wielu wątków do użycia w tym samym czasie. Elementy danych można chronić przy użyciu obiektów synchronizacji i organizowania danych, aby uniknąć konfliktów między wątkami. Jednocześnie program musi uniemożliwić wprowadzanie zmian w danych programu podczas drukowania. Przykładowy program używa kilku różnych technik programowania wielowątkowego.

Zdarzenia synchronizacji
Przykładowy program wykorzystuje zdarzenia, uchwyty wątków oraz funkcje oczekiwania, aby zsynchronizować przetwarzanie między wątkiem wydruku a głównym programem oraz wskazać użycie danych.
Application-Specific Komunikaty systemu Windows
Przykładowy program używa komunikatów okna specyficznych dla aplikacji, aby program był bardziej zgodny z innymi natywnymi programami systemu Windows. Podzielenie przetwarzania na mniejsze kroki i kolejkowanie tych kroków w pętli komunikatów okna ułatwia systemowi Windows zarządzanie przetwarzaniem bez blokowania innych aplikacji, które mogą być również uruchomione na komputerze.
struktury danych
Przykładowy program nie jest napisany w stylu obiektowym przy użyciu obiektów i klas, chociaż grupuje elementy danych w struktury danych. W przykładzie nie jest używane podejście obiektowe, aby uniknąć sugerowania, że jedno podejście jest lepsze lub gorsze niż inne.
Podczas projektowania programu można używać funkcji i struktur danych przykładowego programu jako punktu wyjścia. Niezależnie od tego, czy zdecydujesz się zaprojektować program obiektowy, czy nie, należy pamiętać, aby pogrupować powiązane elementy danych, aby można było bezpiecznie używać ich w różnych wątkach w razie potrzeby.

Kontekst urządzenia drukarki

Podczas drukowania można renderować zawartość do wydrukowania w kontekście urządzenia. Instrukcje: pobieranie kontekstu urządzenia drukarki opisuje różne sposoby uzyskiwania kontekstu urządzenia drukarki.

Jak drukować z aplikacji systemu Windows