在 DEVMODE 結構如記錄由 Win 32 SDK 包含公共或"設備獨立數據"和專用或"設備相關數據。 在 DEVMODE 的專用部分存在緊跟公共由 DEVMODE 結構的內存的連續緩衝區中定義的部分。
程序不能預測此緩衝區的大小,因爲它是打印機驅動程序的不同打印機並從版本的打印機。 此外,一個程序只是聲明的 DEVMODE 結構沒有足夠空間的專用設備數據。 如果缺少專用數據的 DEVMODE 緩衝區傳遞給函數 (如 CreateDC() 、 ResetDC() 和 DocumentProperties() ,可能會失敗,函數。
若要可靠地的設備驅動程序中使用一個 DEVMODE,創建,並按以下步驟修改:
- 確定所需從該的設備緩衝區的大小,並且然後會爲其分配足夠的內存。
DocumentProperties() 返回最後一個參數設置爲 0 時所需的 DEVMODE 緩衝區字節的數。 本文中的示例代碼使用此技術確定正確緩衝區的大小。 然後,示例代碼使用 C 運行時內存分配函數的 malloc() 分配足夠大的緩衝區。 因爲 DocumentProperties() 和功能 (如 ResetDC() 和 CreateDC() 採取作爲參數的 DEVMODE 的指針,大多數應用程序可以分配的指針的內存。
但是,函數如常見 PrintDlg() 接受所需爲全局內存的句柄參數。 如果程序使用最終的 DEVMODE 緩衝區爲這些函數的參數,它應分配使用 GlobalAlloc() 的內存,並獲取指向使用 GlobalLock() 的緩衝區指針。 - 要求設備驅動程序初始化 DEVMODE 緩衝區使用默認設置。
該示例代碼將調用 DocumentProperties() 第二次初始化分配的緩衝區使用當前的默認設置。 DocumentProperties() 填充稱爲 pDevModeOutput 參數了打印機的當前設置 fMode 參數中傳遞 DM_OUT_BUFFER 命令時的緩衝區。 - 對在 DEVMODE 的公共部分進行更改請求設備驅動程序通過調用 DocumentProperties() 所做的更改合併在 DEVMODE 的專用部分。
在初始化了在步驟 2 中的當前設置緩衝區後的代碼示例對在 DEVMODE 的公共部分進行更改。 請參閱 Win32 SDK 文檔的 DEVMODE 成員的說明。 此示例代碼來確定是否可以使用方向和雙面打印 (雙面) 設置打印機,並相應地更改它們。
注意 : 在 DEVMODE 的 dmFields 成員 A 標誌並只表示打印機使用相關的結構成員。 打印機具有各種不同的物理特徵,因此,可能只支持 DEVMODE 的記錄功能的子集。 若要確定 DEVMODE 的字段的受支持的設置,應用程序應使用 DeviceCapabilities() 。
該示例代碼然後使第三個調用 DocumentProperties() ,pDevModeInput 和 pDevModeOutput 參數中傳遞 DEVMODE 緩衝區。 它還使用 OR("|") 運算符傳遞 DM_IN_BUFFER 和 DM_OUT_BUFFER fMode 參數中合併的命令。 這些命令告訴函數需要輸入緩衝區中包含任何設置,併合並它們使用當前設置爲該設備。 然後它會結果寫入到輸出參數中指定的緩衝區。
注意 : DocumentProperties() 指向特定打印機的打印機句柄: hPrinter。 從 OpenPrinter() ,它還闡釋了示例代碼獲取此句柄。 OpenPrinter() 需要一個打印機通常是友好名稱打印機的操作系統的外殼程序中顯示的名稱。 從 EnumPrinters() 、 返回 PrintDlg() , DEVNAMES 結構或默認打印機,可以獲取此名稱。
有關默認打印機單擊下面的文章編號,以查看 Microsoft 知識庫中的相應:
注意 : 在這篇文章,分配緩衝區的正確的大小和初始化該緩衝區的前兩個步驟執行與 DocumentProperties() 。 您也可以使用 GetPrinter() 按照這些步驟。 有關其他信息和這種示例,請單擊下面該文章編號,以查看 Microsoft 知識庫中相應:
示例代碼
<script type="text/javascript"></script> 示例代碼遵循以下三個的步驟,有關獲得和更改 DEVMODE 緩衝區。 該函數採用指定的打印機,並配置它支持這些功能的情況下打印雙面和以橫向方向的 DEVMODE。 返回到調用方的該結果 DEVMODE 是適用於使用 DEVMODE 緩衝區如 CreateDC() 、 SetPrinter() 、 PrintDlg() 或 ResetDC() 的其他 API 調用。 當調用方完成使用 DEVMODE 緩衝區時, 調用方負責釋放內存。
LPDEVMODE GetLandscapeDevMode(HWND hWnd, char *pDevice)
{
HANDLE hPrinter;
LPDEVMODE pDevMode;
DWORD dwNeeded, dwRet;
/* Start by opening the printer */
if (!OpenPrinter(pDevice, &hPrinter, NULL))
return NULL;
/*
* Step 1:
* Allocate a buffer of the correct size.
*/
dwNeeded = DocumentProperties(hWnd,
hPrinter, /* Handle to our printer. */
pDevice, /* Name of the printer. */
NULL, /* Asking for size, so */
NULL, /* these are not used. */
0); /* Zero returns buffer size. */
pDevMode = (LPDEVMODE)malloc(dwNeeded);
/*
* Step 2:
* Get the default DevMode for the printer and
* modify it for your needs.
*/
dwRet = DocumentProperties(hWnd,
hPrinter,
pDevice,
pDevMode, /* The address of the buffer to fill. */
NULL, /* Not using the input buffer. */
DM_OUT_BUFFER); /* Have the output buffer filled. */
if (dwRet != IDOK)
{
/* If failure, cleanup and return failure. */
free(pDevMode);
ClosePrinter(hPrinter);
return NULL;
}
/*
* Make changes to the DevMode which are supported.
*/
if (pDevMode->dmFields & DM_ORIENTATION)
{
/* If the printer supports paper orientation, set it.*/
pDevMode->dmOrientation = DMORIENT_LANDSCAPE;
}
if (pDevMode->dmFields & DM_DUPLEX)
{
/* If it supports duplex printing, use it. */
pDevMode->dmDuplex = DMDUP_HORIZONTAL;
}
/*
* Step 3:
* Merge the new settings with the old.
* This gives the driver an opportunity to update any private
* portions of the DevMode structure.
*/
dwRet = DocumentProperties(hWnd,
hPrinter,
pDevice,
pDevMode, /* Reuse our buffer for output. */
pDevMode, /* Pass the driver our changes. */
DM_IN_BUFFER | /* Commands to Merge our changes and */
DM_OUT_BUFFER); /* write the result. */
/* Finished with the printer */
ClosePrinter(hPrinter);
if (dwRet != IDOK)
{
/* If failure, cleanup and return failure. */
free(pDevMode);
return NULL;
}
/* Return the modified DevMode structure. */
return pDevMode;
}