SetPrinter 함수를 사용하여 프린터 설정 수정

SetPrinter 함수를 사용하면 애플리케이션에서 다양한 프린터 특성을 변경할 수 있습니다. 그러나 이 문서의 코드에서 알 수 있듯이 를 올바르게 호출 SetPrinter하려면 일정량의 준비가 필요합니다.

원래 제품 버전: Windows
원본 KB 번호: 140285

SetPrinter에 대한 hPrinter 매개 변수

첫 번째 매개 변수는 설정을 변경해야 하는 프린터에 대한 핸들입니다. 이 매개 변수는 에서 OpenPrinter()검색해야 합니다.

SetPrinter에 대한 dwLevel 매개 변수

두 번째 매개 변수는 에 전달 SetPrinter()되는 데이터의 구조를 지정합니다. 매개 변수 값은 0, 2, 3, 4,5, 6, 7, 8 또는 9일 수 있습니다.

SetPrinter에 대한 lpbPrinter 매개 변수

세 번째 매개 변수는 두 번째 매개 변수의 수에 해당하는 구조 n 체입니다PRINTER_INFO_n. 이 구조체는 단순히 구조체 크기의 버퍼가 아니기 때문에 혼동을 일으킬 수 있습니다. 이러한 구조체는 디바이스 독립적 정보를 포함하지만 디바이스 드라이버에서 제공하는 일부 가변적인 양의 디바이스 종속 정보로 즉시 메모리에서 수행됩니다. 따라서 이 버퍼의 중요도를 결정하는 데 약간의 작업이 포함됩니다. 이 작업은 필요한 총 크기로 설정 pcbNeeded 되는 를 호출GetPrinter()하여 수행됩니다.

또한 버퍼에는 일반적으로 많은 양의 디바이스 독립적 및 디바이스 종속 정보가 있습니다. 애플리케이션은 대부분의 구조체 멤버의 값을 알거나 신경 쓰지 않습니다. 따라서 관심 있는 변경 내용을 적용할 때는 이러한 다른 모든 데이터에 대해 올바른 값을 연결해야 합니다. 이러한 다른 데이터 조각은 두 번째로 호출 GetPrinter() 할 때 설정됩니다.

SetPrinter에 대한 DwCommand 매개 변수

네 번째 매개 변수는 인쇄를 일시 중지하거나 인쇄를 다시 시작하거나 모든 인쇄 작업을 지우는 데 사용됩니다. 이 매개 변수는 일반적으로 가 사용되는 것과 lpbPrinter 동시에 사용되지 않습니다. 이 문서에서는 프린터 상태를 설정하지 않으므로 샘플 코드는 이 매개 변수를 0으로 설정합니다.

DEVMODE 정보

가 가리키는 pDevMode 구조체의 DEVMODE 요소가 의 요소 PRINTER_INFO_n대신 수정되는 경우가 많습니다. 이 경우 플래그는 애플리케이션에 pDevMode->dmFields 변경할 수 있는 필드를 알려줍니다. 에 의해 GetPrinter()제공되므로 변경을 시도하기 전에 플래그를 dmFields 검사 수 있습니다.

또한 의 디바이스 독립적 부분에서 필드를 수정하면 디바이스 종속 부분의 DEVMODE 변경에도 영향을 미칠 수 있으므로 에 대한 SetPrinter()일관된 DEVMODE 구조를 만들기 위해 를 호출하기 전에 를 호출 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;
}