Ändern der Druckereinstellungen mithilfe der SetPrinter-Funktion

Die SetPrinter -Funktion ermöglicht es Anwendungen, verschiedene Druckerattribute zu ändern. Wie der Code in diesem Artikel zeigt, ist jedoch eine bestimmte Vorbereitung erforderlich, um ordnungsgemäß aufzurufen SetPrinter.

              Originalversion des Produkts: Windows
Ursprüngliche KB-Nummer: 140285

hPrinter-Parameter für SetPrinter

Der erste Parameter ist ein Handle für den Drucker, dessen Einstellungen geändert werden sollen. Dieser Parameter sollte aus OpenPrinter()abgerufen werden.

dwLevel-Parameter für SetPrinter

Der zweite Parameter gibt die Struktur der Daten an, die an SetPrinter()übergeben werden. Der Parameterwert kann 0, 2, 3, 4,5, 6, 7, 8 oder 9 sein.

lpbPrinter-Parameter für SetPrinter

Der dritte Parameter ist eine PRINTER_INFO_n Struktur, bei n der der Zahl im zweiten Parameter entspricht. Diese Struktur kann zu Verwirrung führen, da es sich nicht einfach um einen Puffer der Größe der Struktur handelt. Diese Strukturen enthalten geräteunabhängige Informationen, werden aber sofort im Arbeitsspeicher von einer variablen Menge an geräteabhängigen Informationen gefolgt, die vom Gerätetreiber angegeben werden. Daher ist ein wenig Arbeit erforderlich, um zu bestimmen, wie wichtig dieser Puffer sein sollte. Dies wird erreicht, indem aufgerufen GetPrinter()wird, wodurch auf die erforderliche Gesamtgröße festgelegt pcbNeeded wird.

Außerdem enthält der Puffer in der Regel eine große Menge an geräteunabhängigen und geräteabhängigen Informationen. Ihre Anwendung wird die Werte in den meisten dieser Strukturmember nicht kennen oder interessieren. Wenn Sie also die Änderungen vornehmen, an denen Sie interessiert sind, müssen Sie die richtigen Werte für alle anderen Daten angeben. Diese anderen Daten werden festgelegt, wenn Sie ein zweites Mal aufrufen GetPrinter() .

DwCommand-Parameter für SetPrinter

Der vierte Parameter wird verwendet, um den Druck anzuhalten, den Druck fortzusetzen oder alle Druckaufträge zu löschen. Dieser Parameter wird in der Regel nicht gleichzeitig verwendet, als lpbPrinter er verwendet wird. In diesem Artikel geht es nicht um das Festlegen des Druckerzustands, sodass der Beispielcode diesen Parameter auf 0 (null) festlegt.

Informationen zu DEVMODE

Häufig wird ein Element der -Struktur geändert, auf das DEVMODE von pDevMode gezeigt wird (anstelle eines Elements von PRINTER_INFO_n). Wenn dies der Fall ist, teilen die pDevMode->dmFields Flags der Anwendung mit, welche Felder geändert werden können. Da dies von GetPrinter()angegeben wird, können Sie das dmFields Flag überprüfen, bevor Sie die Änderung versuchen.

Da sich das Ändern von Feldern im geräteunabhängigen Teil von DEVMODE auch auf Änderungen im geräteabhängigen Teil auswirken kann, müssen Sie vor dem Aufrufen SetPrinter() aufrufenDocumentProperties(), um eine konsistente DEVMODE Struktur für SetPrinter()zu erstellen.

Beispielcode

// 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;
}