SetPrinter機能を使用すると、アプリケーションでさまざまなプリンター属性を変更できます。 ただし、この記事のコードで示すように、 SetPrinterを正しく呼び出すには一定の準備が必要です。
元の製品バージョン: Windows
元の KB 番号: 140285
SetPrinter の hPrinter パラメーター
最初のパラメーターは、設定を変更するプリンターのハンドルです。 このパラメーターは、 OpenPrinter()から取得する必要があります。
SetPrinter の dwLevel パラメーター
2 番目のパラメーターは、 SetPrinter()に渡されるデータの構造を指定します。 パラメーター値は、 0、 2、、 3、 4、5、 6、 7、 8、または 9にすることができます。
SetPrinter の lpbPrinter パラメーター
3 番目のパラメーターは、PRINTER_INFO_nが 2 番目のパラメーターの数値に対応するn構造体です。 この構造体は、構造体のサイズの単なるバッファーではないので、混乱を引き起こす可能性があります。 これらの構造体には、デバイスに依存しない情報が含まれていますが、デバイス ドライバーによって提供される、いくつかの可変量のデバイスに依存する情報がメモリ内ですぐに続きます。 そのため、このバッファーの意味を判断するには、少しの作業が必要です。 これは、必要な合計サイズにGetPrinter()を設定するpcbNeededを呼び出すことによって実現されます。
また、バッファーには通常、デバイスに依存しない大量の情報とデバイスに依存する情報が含まれています。 アプリケーションは、これらの構造体メンバーのほとんどの値を認識したり、考慮したりしません。 そのため、関心のある変更を行うときは、これらの他のすべてのデータに対して正しい値をプラグインする必要があります。 これらの他のデータは、2 回目 GetPrinter() 呼び出すときに設定されます。
SetPrinter の DwCommand パラメーター
4 番目のパラメーターは、印刷の一時停止、印刷の再開、またはすべての印刷ジョブのクリアに使用されます。 通常、このパラメーターは、 lpbPrinter が使用されるのと同時には使用されません。 この記事はプリンターの状態の設定には関係ないため、サンプル コードではこのパラメーターを 0 に設定します。
DEVMODE について
多くの場合、DEVMODEが指すpDevMode構造体の要素が (PRINTER_INFO_n の要素ではなく) 変更されます。 この場合、 pDevMode->dmFields フラグによって、変更できるフィールドがアプリケーションに通知されます。 これは GetPrinter()によって与えられるので、変更を試みる前に dmFields フラグを確認できます。
また、DEVMODEのデバイスに依存しない部分のフィールドを変更すると、デバイス依存部分の変更にも影響する可能性があるため、DocumentProperties()の一貫したSetPrinter()構造を作成するには、DEVMODEを呼び出す前にSetPrinter()を呼び出す必要があります。
サンプル コード
// MySetPrinter
// Demonstrates how to use the SetPrinter API. This particular function changes the orientation
// for the printer specified in pPrinterName to the orientation specified in dmOrientation.
// Valid values for dmOrientation are:
// DMORIENT_PORTRAIT (1) or DMORIENT_LANDSCAPE (2)
BOOL MySetPrinter(LPTSTR pPrinterName, short dmOrientation)
{
HANDLE hPrinter = NULL;
DWORD dwNeeded = 0;
PRINTER_INFO_2 *pi2 = NULL;
DEVMODE *pDevMode = NULL;
PRINTER_DEFAULTS pd;
BOOL bFlag;
LONG lFlag;
// Open printer handle (on Windows NT, you need full-access because you
// will eventually use SetPrinter)...
ZeroMemory(&pd, sizeof(pd));
pd.DesiredAccess = PRINTER_ALL_ACCESS;
bFlag = OpenPrinter(pPrinterName, &hPrinter, &pd);
if (!bFlag || (hPrinter == NULL))
return FALSE;
// The first GetPrinter tells you how big the buffer should be in
// order to hold all of PRINTER_INFO_2. Note that this should fail with
// ERROR_INSUFFICIENT_BUFFER. If GetPrinter fails for any other reason
// or dwNeeded isn't set for some reason, then there is a problem...
SetLastError(0);
bFlag = GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);
if ((!bFlag) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwNeeded == 0))
{
ClosePrinter(hPrinter);
return FALSE;
}
// Allocate enough space for PRINTER_INFO_2...
pi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
if (pi2 == NULL)
{
ClosePrinter(hPrinter);
return FALSE;
}
// The second GetPrinter fills in all the current settings, so all you
// need to do is modify what you're interested in...
bFlag = GetPrinter(hPrinter, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);
if (!bFlag)
{
GlobalFree(pi2);
ClosePrinter(hPrinter);
return FALSE;
}
// If GetPrinter didn't fill in the DEVMODE, try to get it by calling
// DocumentProperties...
if (pi2->pDevMode == NULL)
{
dwNeeded = DocumentProperties(NULL, hPrinter,
pPrinterName,
NULL, NULL, 0);
if (dwNeeded <= 0)
{
GlobalFree(pi2);
ClosePrinter(hPrinter);
return FALSE;
}
pDevMode = (DEVMODE *)GlobalAlloc(GPTR, dwNeeded);
if (pDevMode == NULL)
{
GlobalFree(pi2);
ClosePrinter(hPrinter);
return FALSE;
}
lFlag = DocumentProperties(NULL, hPrinter,
pPrinterName,
pDevMode, NULL,
DM_OUT_BUFFER);
if (lFlag != IDOK || pDevMode == NULL)
{
GlobalFree(pDevMode);
GlobalFree(pi2);
ClosePrinter(hPrinter);
return FALSE;
}
pi2->pDevMode = pDevMode;
}
// Driver is reporting that it doesn't support this change...
if (!(pi2->pDevMode->dmFields & DM_ORIENTATION))
{
GlobalFree(pi2);
ClosePrinter(hPrinter);
if (pDevMode)
GlobalFree(pDevMode);
return FALSE;
}
// Specify exactly what we are attempting to change...
pi2->pDevMode->dmFields = DM_ORIENTATION;
pi2->pDevMode->dmOrientation = dmOrientation;
// Do not attempt to set security descriptor...
pi2->pSecurityDescriptor = NULL;
// Make sure the driver-dependent part of devmode is updated...
lFlag = DocumentProperties(NULL, hPrinter,
pPrinterName,
pi2->pDevMode, pi2->pDevMode,
DM_IN_BUFFER | DM_OUT_BUFFER);
if (lFlag != IDOK)
{
GlobalFree(pi2);
ClosePrinter(hPrinter);
if (pDevMode)
GlobalFree(pDevMode);
return FALSE;
}
// Update printer information...
bFlag = SetPrinter(hPrinter, 2, (LPBYTE)pi2, 0);
if (!bFlag)
// The driver doesn't support, or it is unable to make the change...
{
GlobalFree(pi2);
ClosePrinter(hPrinter);
if (pDevMode)
GlobalFree(pDevMode);
return FALSE;
}
// Tell other apps that there was a change...
SendMessageTimeout(HWND_BROADCAST, WM_DEVMODECHANGE, 0L,
(LPARAM)(LPCSTR)pPrinterName,
SMTO_NORMAL, 1000, NULL);
// Clean up...
if (pi2)
GlobalFree(pi2);
if (hPrinter)
ClosePrinter(hPrinter);
if (pDevMode)
GlobalFree(pDevMode);
return TRUE;
}