本節說明如何從原生 Windows 桌面程式列印。
概述
若要在從原生 Windows 程式列印時提供最佳用戶體驗,程式必須設計為從專用線程列印。 在原生 Windows 程式中,程式會負責管理使用者介面事件和訊息。 印表作業可能需要大量的計算,因為應用程式的內容需要轉譯給印表機。如果這些處理是在與使用者互動事件同一線程中進行,可能會導致程式無法回應使用者的操作。
如果您已經熟悉如何撰寫多線程原生 Windows 程式,您可以直接移至 如何從 Windows 應用程式 列印,並瞭解如何將列印功能新增至程式。
基本 Windows 程式需求
為了獲得最佳效能和程序回應性,請勿在處理使用者互動的線程中執行程式的列印作業處理。
這種列印與用戶互動的分離會影響程式管理應用程式數據的方式。 開始撰寫應用程式之前,您應該徹底瞭解這些含意。 下列主題描述在程式的不同線程中處理列印的基本需求。
Windows 程式基本概念
原生 Windows 程式必須提供主視窗程式,以處理從作系統接收的視窗訊息。 Windows 程式中的每個視窗都有一個對應的 WndProc 函式來處理這些視窗訊息。 執行此函式的線程稱為使用者介面或UI線程。
把資源用於字串。
若支援其他語言時可能需要變更文字,應使用程式資源檔中的字串資源,而非字串常數。 程序必須先從資源檔擷取字串資源,並將其複製到本機記憶體緩衝區,才能將字串資源用作字串。 這需要在一開始進行一些額外的程序設計,但未來允許更輕鬆地修改、翻譯和當地語系化程式。
逐步處理數據。
以可中斷的方式逐步處理列印工作。 此設計可讓使用者在完成之前取消長時間的處理作業,並防止程序封鎖可能同時執行的其他程式。
使用視窗用戶資料。
列印應用程式通常會有數個窗口和線程。 若要在不使用靜態全域變數的情況下,讓線程與處理步驟之間保持可用數據,請使用數據指標參考數據結構,該指標是其使用視窗的一部分。
下列程式代碼範例顯示列印應用程式的主要進入點。 此範例示範如何使用字串資源,而不是字串常數,也會顯示處理程式視窗訊息的主要訊息迴圈。
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;
}
文件資訊
列印的原生 Windows 程式應該針對多線程處理而設計。 多線程設計的其中一個需求是保護程序的數據元素,以便讓多個線程同時使用安全。 您可以使用同步處理物件和組織數據來保護資料元素,以避免線程之間的衝突。 同時,程式必須防止在列印程序數據時變更程序數據。 此範例程式使用數種不同的多線程程式設計技術。
同步處理事件
範例程式會使用事件、線程句柄和等候函式來同步處理列印線程與主要程式之間的處理,以及指出數據正在使用中。
Application-Specific Windows 訊息
此範例程式會使用應用程式特定的視窗訊息,讓程式與其他原生 Windows 程式更相容。 將處理分成較小的步驟,並在視窗訊息迴圈中排入這些步驟佇列,可讓 Windows 更輕鬆地管理處理,而不會封鎖可能也在電腦上執行的其他應用程式。
數據結構
範例程式不會使用物件和類別以面向物件樣式撰寫,不過它會將數據元素分組到數據結構中。 此範例不會使用面向物件的方法,以避免暗示某個方法比另一種方法更好或更糟。
您可以在設計程式時,使用範例程式的函式和數據結構作為起點。 不論您決定是否要設計面向物件程式,請務必記住的重要設計考慮是將相關的數據元素分組,以便在必要時安全地在不同的線程中使用這些專案。
印表機裝置環境
列印時,您可能會想將內容呈現到裝置上下文以進行列印。 如何:擷取印表機裝置內容 說明您可以取得印表機裝置內容的不同方式。
相關主題