SetPrinter 関数を使用してプリンター設定を変更する

この SetPrinter 関数を使用すると、アプリケーションでさまざまなプリンター属性を変更できます。 ただし、この記事のコードが示すように、を正しく呼び出 SetPrinterすには、一定量の準備が必要です。

元の製品バージョン: Windows
元の KB 番号: 140285

SetPrinter の hPrinter パラメーター

最初のパラメーターは、設定を変更するプリンターのハンドルです。 このパラメーターは から OpenPrinter()取得する必要があります。

SetPrinter の dwLevel パラメーター

2 番目のパラメーターは、 に渡されるデータの構造を SetPrinter()指定します。 パラメーター値は 、02345678、または 9 のいずれかです。

SetPrinter の lpbPrinter パラメーター

3 番目のパラメーターは、 PRINTER_INFO_n 2 番目のパラメーターの数値に対応する構造体 n です。 この構造体は、単に構造体のサイズのバッファーではないので、混乱を引き起こす可能性があります。 これらの構造体には、デバイスに依存しない情報が含まれていますが、デバイス ドライバーによって提供される一部の可変量のデバイス依存情報がメモリ内ですぐに続きます。 そのため、このバッファーのサイズを判断するには、少しの作業が必要です。 これは、 を呼び出 GetPrinter()すことによって実現されます。これは、必要な合計サイズに設定 pcbNeeded されます。

また、バッファーには通常、デバイスに依存しない大量の情報とデバイスに依存する情報が含まれます。 アプリケーションは、これらの構造体メンバーの大部分の値を認識したり、気にしたりしません。 そのため、関心のある変更を行うときは、これらの他のすべてのデータに対して正しい値を入力する必要があります。 これらの他のデータは、2 回目の呼び出し GetPrinter() 時に設定されます。

SetPrinter の DwCommand パラメーター

4 番目のパラメーターは、印刷の一時停止、印刷の再開、またはすべての印刷ジョブのクリアに使用されます。 通常、このパラメーターは、使用されるのと同時 lpbPrinter に使用されません。 この記事では、プリンターの状態の設定には関係ないため、サンプル コードではこのパラメーターを 0 に設定します。

DEVMODE について

多くの場合、 が指すpDevMode構造体のDEVMODE要素は、(の要素PRINTER_INFO_nではなく) 変更されます。 この場合、フラグによって、 pDevMode->dmFields 変更できるフィールドがアプリケーションに通知されます。 これは によってGetPrinter()提供されるため、変更を試みる前にフラグをdmFieldsチェックできます。

また、 のデバイスに依存しない部分DEVMODEのフィールドを変更すると、デバイス依存部分の変更にも影響する可能性があるため、 の一貫性のあるDEVMODE構造SetPrinter()を作成するには、 を呼び出す前に を呼び出DocumentProperties()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;
}