Dialogfeld mit SetPrinter ändern


Zusammenfassung


SetPrinter ist eine neue API für Windows 95, Windows NT, Windows 2000 und Windows XP, die Clientanwendungen Druckerattribute ändern können. Da das Codebeispiel in diesem Artikel ist ein gewisses Maß an Vorbereitung erforderlich SetPrinter ordnungsgemäß aufzurufen.

Weitere Informationen


Die Parameter für SetPrinter() sind wie folgt:

hPrinter

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

dwLevel

Der zweite Parameter gibt die Struktur der Daten
SetPrinter(). Windows 95 kann dies 0, 2, 3, 4 oder 5. Für Windows NT kann dies 0, 2 oder 3 sein. Diese Zahlen entsprechen den Datentyp (PRINTER_INFO_n) über den dritten Parameter übergeben.

lpbPrinter

Der dritte Parameter ist eine PRINTER_INFO_n -Struktur entspricht, n im zweiten Parameter. Dadurch kann Verwirrung stiften, da es nicht einfach einen Puffer von der Größe der Struktur. Diese Strukturen geräteunabhängige enthalten jedoch gewisse geräteabhängige Informationen vom Gerätetreiber angegebenen Variable im Speicher unmittelbar folgt. Daher ist ein wenig Aufwand ermitteln, wie groß dieser Puffer. Dies geschieht durch Aufrufen
GetPrinter(), die PcbNeeded der erforderlichen Größe festgelegt wird.


Außerdem enthält der Puffer in der Regel eine große Datenmenge geräteunabhängige und geräteabhängige. Die Anwendung wird nicht kennen oder die Werte in den meisten dieser Strukturmember kümmern. Wenn die Änderungen an denen Sie interessiert sind müssen Sie also die Werte aller dieser andere Datenelemente anschließen. Dieser andere Datenelemente werden festgelegt, wenn GetPrinter() ein zweites Mal aufrufen.

dwCommand

Der vierte Parameter dient, Druckvorgang anhalten oder Fortsetzen des Druckvorgangs alle Druckaufträge löschen. Dies ist normalerweise nicht gleichzeitig verwendet LpbPrinter verwendet wird. Dieser Artikel befasst sich nicht mit den Druckerstatus im Beispielcode wird dieser Parameter auf NULL festgelegt.

Über DEVMODE

Häufig werden Bestandteil der DEVMODE -Struktur auf den pDevMode (statt ein Element PRINTER_INFO_n) geändert. Wenn dies der Fall ist, die pDevMode -> DmFields Flags sagen, dass die Anwendung die Felder geändert werden kann. Da dies für Sie durch GetPrinter()angegeben ist, können Sie vor der Änderung DmFields Flag überprüfen.


Auch da Änderungen in der geräteabhängige Felder im DEVMODE geräteunabhängigen Teil ändern auch bewirken kann, müssen Sie aufrufen
DocumentProperties() vor dem Aufruf von SetPrinter() zu einer konsistenten DEVMODE -Struktur für SetPrinter().

Beispielcode

// MySetPrinter
//
// Demonstrates how to use the SetPrinter API. This particular function changes the orienation
// 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;
}