Modifier les paramètres de l’imprimante à l’aide de la fonction SetPrinter

La SetPrinter fonction permet aux applications de modifier différents attributs d’imprimante. Toutefois, comme le montre le code de cet article, une certaine préparation est nécessaire pour appeler SetPrintercorrectement .

              Version d’origine du produit : Windows
Numéro de la base de connaissances d’origine : 140285

Paramètre hPrinter pour SetPrinter

Le premier paramètre est un handle de l’imprimante dont les paramètres doivent être modifiés. Ce paramètre doit être récupéré à partir de OpenPrinter().

Paramètre dwLevel pour SetPrinter

Le deuxième paramètre spécifie la structure des données passées à SetPrinter(). La valeur du paramètre peut être 0, 2, 3, 4, 5, 6, 7, 8 ou 9.

Paramètre lpbPrinter pour SetPrinter

Le troisième paramètre est une PRINTER_INFO_n structure où n correspond au nombre dans le deuxième paramètre. Cette structure peut être source de confusion, car il ne s’agit pas simplement d’une mémoire tampon de la taille de la structure. Ces structures contiennent des informations indépendantes de l’appareil, mais sont immédiatement suivies en mémoire d’une quantité variable d’informations dépendantes de l’appareil, qui sont fournies par le pilote de périphérique. Par conséquent, un peu de travail est impliqué pour déterminer l’importance de cette mémoire tampon. Pour ce faire, appelez GetPrinter(), qui définira pcbNeeded la taille totale nécessaire.

En outre, la mémoire tampon contient généralement une grande quantité d’informations indépendantes de l’appareil et dépendantes de l’appareil. Votre application ne connaît pas ou ne s’intéresse pas aux valeurs de la plupart de ces membres de structure. Par conséquent, lorsque vous apportez les modifications qui vous intéressent, vous devez brancher les valeurs correctes pour tous ces autres éléments de données. Ces autres éléments de données sont définis lorsque vous appelez GetPrinter() une deuxième fois.

Paramètre DwCommand pour SetPrinter

Le quatrième paramètre est utilisé pour suspendre l’impression, reprendre l’impression ou effacer tous les travaux d’impression. Ce paramètre n’est généralement pas utilisé en même temps que lpbPrinter celui utilisé. Cet article ne concerne pas la définition de l’état de l’imprimante. Par conséquent, l’exemple de code définit ce paramètre sur zéro.

À propos de DEVMODE

Souvent, un élément de la DEVMODE structure pointée par pDevMode est modifié (au lieu d’un élément de PRINTER_INFO_n). Dans ce cas, les pDevMode->dmFields indicateurs indiquent à l’application quels champs peuvent être modifiés. Comme cela vous est donné par GetPrinter(), vous pouvez case activée l’indicateur dmFields avant de tenter la modification.

En outre, étant donné que la modification de champs dans la partie indépendante de l’appareil de DEVMODE peut également affecter des modifications dans la partie dépendante de l’appareil, vous devez appeler DocumentProperties() avant d’appeler SetPrinter() afin d’établir une structure cohérente DEVMODE pour SetPrinter().

Exemple de code

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