代码之家  ›  专栏  ›  技术社区  ›  Blumer

非托管C++中的默认打印机

  •  1
  • Blumer  · 技术社区  · 17 年前

    我在寻找一种使用非托管C++查找Windows默认打印机的名称(找到大量.NET示例,但没有成功的非托管)。谢谢

    5 回复  |  直到 17 年前
        1
  •  3
  •   Jonathan    13 年前

    char szPrinterName[255];
    unsigned long lPrinterNameLength;
    GetDefaultPrinter( szPrinterName, &lPrinterNameLength );
    HDC hPrinterDC;
    hPrinterDC = CreateDC("WINSPOOL\0", szPrinterName, NULL, NULL);
    

        2
  •  3
  •   KPexEA    17 年前

    下面是如何获取当前打印机列表以及默认打印机列表(如果有一台设置为默认打印机)。

    另请注意:如果用户没有打印机或未将打印机设置为默认打印机,则默认打印机名称长度为零是有效的。

    还应支持处理长打印机名称,因此首先使用NULL作为缓冲区指针调用GetDefaultPrinter将返回名称长度,然后可以分配足够大的名称缓冲区来保存名称。

    DWORD numprinters;
    DWORD defprinter=0;
    DWORD               dwSizeNeeded=0;
    DWORD               dwItem;
    LPPRINTER_INFO_2    printerinfo = NULL;
    
    // Get buffer size
    
    EnumPrinters ( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS , NULL, 2, NULL, 0, &dwSizeNeeded, &numprinters );
    
    // allocate memory
    //printerinfo = (LPPRINTER_INFO_2)HeapAlloc ( GetProcessHeap (), HEAP_ZERO_MEMORY, dwSizeNeeded );
    printerinfo = (LPPRINTER_INFO_2)new char[dwSizeNeeded];
    
    if ( EnumPrinters ( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,      // what to enumerate
                NULL,           // printer name (NULL for all)
                2,              // level
                (LPBYTE)printerinfo,        // buffer
                dwSizeNeeded,       // size of buffer
                &dwSizeNeeded,      // returns size
                &numprinters            // return num. items
              ) == 0 )
    {
        numprinters=0;
    }
    
    {
        DWORD size=0;   
    
        // Get the size of the default printer name.
        GetDefaultPrinter(NULL, &size);
        if(size)
        {
           // Allocate a buffer large enough to hold the printer name.
            TCHAR* buffer = new TCHAR[size];
    
              // Get the printer name.
            GetDefaultPrinter(buffer, &size);
    
            for ( dwItem = 0; dwItem < numprinters; dwItem++ )
            {
                              if(!strcmp(buffer,printerinfo[dwItem].pPrinterName))
                    defprinter=dwItem;
            }
            delete buffer;
        }
    }
    
        3
  •  2
  •   jeffm    7 年前

    http://support.microsoft.com/default.aspx?scid=kb;EN-US;246772

    现在不可用文章的代码:

    // You are explicitly linking to GetDefaultPrinter because linking 
    // implicitly on Windows 95/98 or NT4 results in a runtime error.
    // This block specifies which text version you explicitly link to.
    #ifdef UNICODE
      #define GETDEFAULTPRINTER "GetDefaultPrinterW"
    #else
      #define GETDEFAULTPRINTER "GetDefaultPrinterA"
    #endif
    
    // Size of internal buffer used to hold "printername,drivername,portname"
    // string. You may have to increase this for huge strings.
    #define MAXBUFFERSIZE 250
    
    /*----------------------------------------------------------------*/ 
    /* DPGetDefaultPrinter                                            */ 
    /*                                                                */ 
    /* Parameters:                                                    */ 
    /*   pPrinterName: Buffer alloc'd by caller to hold printer name. */ 
    /*   pdwBufferSize: On input, ptr to size of pPrinterName.        */ 
    /*          On output, min required size of pPrinterName.         */ 
    /*                                                                */ 
    /* NOTE: You must include enough space for the NULL terminator!   */ 
    /*                                                                */ 
    /* Returns: TRUE for success, FALSE for failure.                  */ 
    /*----------------------------------------------------------------*/ 
    BOOL DPGetDefaultPrinter(LPTSTR pPrinterName, LPDWORD pdwBufferSize)
    {
      BOOL bFlag;
      OSVERSIONINFO osv;
      TCHAR cBuffer[MAXBUFFERSIZE];
      PRINTER_INFO_2 *ppi2 = NULL;
      DWORD dwNeeded = 0;
      DWORD dwReturned = 0;
      HMODULE hWinSpool = NULL;
      PROC fnGetDefaultPrinter = NULL;
    
      // What version of Windows are you running?
      osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
      GetVersionEx(&osv);
    
      // If Windows 95 or 98, use EnumPrinters.
      if (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
      {
        // The first EnumPrinters() tells you how big our buffer must
        // be to hold ALL of PRINTER_INFO_2. Note that this will
        // typically return FALSE. This only means that the buffer (the 4th
        // parameter) was not filled in. You do not want it filled in here.
        SetLastError(0);
        bFlag = EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 2, NULL, 0, &dwNeeded, &dwReturned);
        {
          if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwNeeded == 0))
            return FALSE;
        }
    
        // Allocate enough space for PRINTER_INFO_2.
        ppi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
        if (!ppi2)
          return FALSE;
    
        // The second EnumPrinters() will fill in all the current information.
        bFlag = EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 2, (LPBYTE)ppi2, dwNeeded, &dwNeeded, &dwReturned);
        if (!bFlag)
        {
          GlobalFree(ppi2);
          return FALSE;
        }
    
        // If specified buffer is too small, set required size and fail.
        if ((DWORD)lstrlen(ppi2->pPrinterName) >= *pdwBufferSize)
        {
          *pdwBufferSize = (DWORD)lstrlen(ppi2->pPrinterName) + 1;
          GlobalFree(ppi2);
          return FALSE;
        }
    
        // Copy printer name into passed-in buffer.
        lstrcpy(pPrinterName, ppi2->pPrinterName);
    
        // Set buffer size parameter to minimum required buffer size.
        *pdwBufferSize = (DWORD)lstrlen(ppi2->pPrinterName) + 1;
      }
    
      // If Windows NT, use the GetDefaultPrinter API for Windows 2000,
      // or GetProfileString for version 4.0 and earlier.
      else if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT)
      {
        if (osv.dwMajorVersion >= 5) // Windows 2000 or later (use explicit call)
        {
          hWinSpool = LoadLibrary("winspool.drv");
          if (!hWinSpool)
            return FALSE;
          fnGetDefaultPrinter = GetProcAddress(hWinSpool, GETDEFAULTPRINTER);
          if (!fnGetDefaultPrinter)
          {
            FreeLibrary(hWinSpool);
            return FALSE;
          }
    
          bFlag = fnGetDefaultPrinter(pPrinterName, pdwBufferSize);
            FreeLibrary(hWinSpool);
          if (!bFlag)
            return FALSE;
        }
    
        else // NT4.0 or earlier
        {
          // Retrieve the default string from Win.ini (the registry).
          // String will be in form "printername,drivername,portname".
          if (GetProfileString("windows", "device", ",,,", cBuffer, MAXBUFFERSIZE) <= 0)
            return FALSE;
    
          // Printer name precedes first "," character.
          strtok(cBuffer, ",");
    
          // If specified buffer is too small, set required size and fail.
          if ((DWORD)lstrlen(cBuffer) >= *pdwBufferSize)
          {
            *pdwBufferSize = (DWORD)lstrlen(cBuffer) + 1;
            return FALSE;
          }
    
          // Copy printer name into passed-in buffer.
          lstrcpy(pPrinterName, cBuffer);
    
          // Set buffer size parameter to minimum required buffer size.
          *pdwBufferSize = (DWORD)lstrlen(cBuffer) + 1;
        }
      }
    
      // Clean up.
      if (ppi2)
        GlobalFree(ppi2);
    
      return TRUE;
    }
    #undef MAXBUFFERSIZE
    #undef GETDEFAULTPRINTER
    
    
    // You are explicitly linking to SetDefaultPrinter because implicitly
    // linking on Windows 95/98 or NT4 results in a runtime error.
    // This block specifies which text version you explicitly link to.
    #ifdef UNICODE
      #define SETDEFAULTPRINTER "SetDefaultPrinterW"
    #else
      #define SETDEFAULTPRINTER "SetDefaultPrinterA"
    #endif
    
    /*-----------------------------------------------------------------*/ 
    /* DPSetDefaultPrinter                                             */ 
    /*                                                                 */ 
    /* Parameters:                                                     */ 
    /*   pPrinterName: Valid name of existing printer to make default. */ 
    /*                                                                 */ 
    /* Returns: TRUE for success, FALSE for failure.                   */ 
    /*-----------------------------------------------------------------*/ 
    BOOL DPSetDefaultPrinter(LPTSTR pPrinterName)
    
    {
      BOOL bFlag;
      OSVERSIONINFO osv;
      DWORD dwNeeded = 0;
      HANDLE hPrinter = NULL;
      PRINTER_INFO_2 *ppi2 = NULL;
      LPTSTR pBuffer = NULL;
      LONG lResult;
      HMODULE hWinSpool = NULL;
      PROC fnSetDefaultPrinter = NULL;
    
      // What version of Windows are you running?
      osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
      GetVersionEx(&osv);
    
      if (!pPrinterName)
        return FALSE;
    
      // If Windows 95 or 98, use SetPrinter.
      if (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
      {
        // Open this printer so you can get information about it.
        bFlag = OpenPrinter(pPrinterName, &hPrinter, NULL);
        if (!bFlag || !hPrinter)
          return FALSE;
    
        // The first GetPrinter() tells you how big our buffer must
        // be to hold ALL of PRINTER_INFO_2. Note that this will
        // typically return FALSE. This only means that the buffer (the 3rd
        // parameter) was not filled in. You do not want it filled in here.
        SetLastError(0);
        bFlag = GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);
        if (!bFlag)
        {
          if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwNeeded == 0))
          {
            ClosePrinter(hPrinter);
            return FALSE;
          }
        }
    
        // Allocate enough space for PRINTER_INFO_2.
        ppi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
        if (!ppi2)
        {
          ClosePrinter(hPrinter);
          return FALSE;
        }
    
        // The second GetPrinter() will fill in all the current information
        // so that all you have to do is modify what you are interested in.
        bFlag = GetPrinter(hPrinter, 2, (LPBYTE)ppi2, dwNeeded, &dwNeeded);
        if (!bFlag)
        {
          ClosePrinter(hPrinter);
          GlobalFree(ppi2);
          return FALSE;
        }
    
        // Set default printer attribute for this printer.
        ppi2->Attributes |= PRINTER_ATTRIBUTE_DEFAULT;
        bFlag = SetPrinter(hPrinter, 2, (LPBYTE)ppi2, 0);
        if (!bFlag)
        {
          ClosePrinter(hPrinter);
          GlobalFree(ppi2);
          return FALSE;
        }
    
        // Tell all open programs that this change occurred. 
        // Allow each program 1 second to handle this message.
        lResult = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0L,
          (LPARAM)(LPCTSTR)"windows", SMTO_NORMAL, 1000, NULL);
      }
    
      // If Windows NT, use the SetDefaultPrinter API for Windows 2000,
      // or WriteProfileString for version 4.0 and earlier.
      else if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT)
      {
        if (osv.dwMajorVersion >= 5) // Windows 2000 or later (use explicit call)
        {
          hWinSpool = LoadLibrary("winspool.drv");
          if (!hWinSpool)
            return FALSE;
          fnSetDefaultPrinter = GetProcAddress(hWinSpool, SETDEFAULTPRINTER);
          if (!fnSetDefaultPrinter)
          {
            FreeLibrary(hWinSpool);
            return FALSE;
          }
    
          bFlag = fnSetDefaultPrinter(pPrinterName);
          FreeLibrary(hWinSpool);
          if (!bFlag)
            return FALSE;
        }
    
        else // NT4.0 or earlier
        {
          // Open this printer so you can get information about it.
          bFlag = OpenPrinter(pPrinterName, &hPrinter, NULL);
          if (!bFlag || !hPrinter)
            return FALSE;
    
          // The first GetPrinter() tells you how big our buffer must
          // be to hold ALL of PRINTER_INFO_2. Note that this will
          // typically return FALSE. This only means that the buffer (the 3rd
          // parameter) was not filled in. You do not want it filled in here.
          SetLastError(0);
          bFlag = GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);
          if (!bFlag)
          {
            if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwNeeded == 0))
            {
              ClosePrinter(hPrinter);
              return FALSE;
            }
          }
    
          // Allocate enough space for PRINTER_INFO_2.
          ppi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
          if (!ppi2)
          {
            ClosePrinter(hPrinter);
            return FALSE;
          }
    
          // The second GetPrinter() fills in all the current<BR/>
          // information.
          bFlag = GetPrinter(hPrinter, 2, (LPBYTE)ppi2, dwNeeded, &dwNeeded);
          if ((!bFlag) || (!ppi2->pDriverName) || (!ppi2->pPortName))
          {
            ClosePrinter(hPrinter);
            GlobalFree(ppi2);
            return FALSE;
          }
    
          // Allocate buffer big enough for concatenated string.
          // String will be in form "printername,drivername,portname".
          pBuffer = (LPTSTR)GlobalAlloc(GPTR,
            lstrlen(pPrinterName) +
            lstrlen(ppi2->pDriverName) +
            lstrlen(ppi2->pPortName) + 3);
          if (!pBuffer)
          {
            ClosePrinter(hPrinter);
            GlobalFree(ppi2);
            return FALSE;
          }
    
          // Build string in form "printername,drivername,portname".
          lstrcpy(pBuffer, pPrinterName);  lstrcat(pBuffer, ",");
          lstrcat(pBuffer, ppi2->pDriverName);  lstrcat(pBuffer, ",");
          lstrcat(pBuffer, ppi2->pPortName);
    
          // Set the default printer in Win.ini and registry.
          bFlag = WriteProfileString("windows", "device", pBuffer);
          if (!bFlag)
          {
            ClosePrinter(hPrinter);
            GlobalFree(ppi2);
            GlobalFree(pBuffer);
            return FALSE;
          }
        }
    
        // Tell all open programs that this change occurred. 
        // Allow each app 1 second to handle this message.
        lResult = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0L, 0L,
          SMTO_NORMAL, 1000, NULL);
      }
    
      // Clean up.
      if (hPrinter)
        ClosePrinter(hPrinter);
      if (ppi2)
        GlobalFree(ppi2);
      if (pBuffer)
        GlobalFree(pBuffer);
    
      return TRUE;
    }
    #undef SETDEFAULTPRINTER
    
        4
  •  1
  •   christopher_f    17 年前
        5
  •  -1
  •   Panic    17 年前

    非托管C++不存在(并且管理C++现在是C++ + CLI),如果你引用C++,使用非托管作为标签只是令人伤心的…