关于获得打印机dc的问题

开发资料 专栏收录该内容
39 篇文章 0 订阅
知道某个打印机名称,怎么获得它的dc
因为不能用打印对话框。因为的程序是在后台运行的。


http://support.microsoft.com/kb/112641/en-us
我找到相关的文档了

extern "C"  __declspec(dllexport) BOOL GetPrinterDevice(LPTSTR pszPrinterName,enum XlPaperSize xlPage, HGLOBAL* phDevNames, HGLOBAL* phDevMode)
{
	// if NULL is passed, then assume we are setting app object's
	// devmode and devnames
	if (phDevMode == NULL || phDevNames == NULL)
		return FALSE;

	// Open printer
	HANDLE hPrinter;
	if (OpenPrinter(pszPrinterName, &hPrinter, NULL) == FALSE)
		return FALSE;

	// obtain PRINTER_INFO_2 structure and close printer
	DWORD dwBytesReturned, dwBytesNeeded;
	GetPrinter(hPrinter, 2, NULL, 0, &dwBytesNeeded);
	PRINTER_INFO_2* p2 = (PRINTER_INFO_2*)GlobalAlloc(GPTR,
		dwBytesNeeded);
	if (GetPrinter(hPrinter, 2, (LPBYTE)p2, dwBytesNeeded,
		&dwBytesReturned) == 0) {
			GlobalFree(p2);
			ClosePrinter(hPrinter);
			return FALSE;
	}
	ClosePrinter(hPrinter);

	// Allocate a global handle for DEVMODE
	HGLOBAL  hDevMode = GlobalAlloc(GHND, sizeof(*p2->pDevMode) +	p2->pDevMode->dmDriverExtra);
	//	ASSERT(hDevMode);
	DEVMODE* pDevMode = (DEVMODE*)GlobalLock(hDevMode);
	//	ASSERT(pDevMode);

	float fwidth ; 
	float fheight ;
	(*((*(p2)).pDevMode)).dmPaperSize=xlPage;
	 GetPaperSize ( xlPage, &fwidth, &fheight );
	 (*((*(p2)).pDevMode)).dmPaperWidth = fwidth*100;
	 (*((*(p2)).pDevMode)).dmPaperLength =fheight*100;

	// copy DEVMODE data from PRINTER_INFO_2::pDevMode
	memcpy(pDevMode, p2->pDevMode, sizeof(*p2->pDevMode) +	p2->pDevMode->dmDriverExtra);

	
	GlobalUnlock(hDevMode);

	// Compute size of DEVNAMES structure from PRINTER_INFO_2's data
	DWORD drvNameLen = lstrlen(p2->pDriverName)+1;  // driver name
	DWORD ptrNameLen = lstrlen(p2->pPrinterName)+1; // printer name
	DWORD porNameLen = lstrlen(p2->pPortName)+1;    // port name

	if (pDevMode->dmFields & DM_ORIENTATION)
	{
		// Pass lpDevMode as both the input and output
		// DEVMODE buffers. It is important to pass
		// in the full DEVMODE from the previous call
		// to ExtDeviceMode() as the input buffer because
		// it has been completely initialized by the
		// driver. If you do not do this, the results
		// are sporadic--sometimes it works and sometimes
		// it doesn't depending on the printer driver and
		// the setting you are trying to change.

		// Zero out all the fields and then set the bit(s)
		// for the field(s) we want to change.
		pDevMode->dmFields = 0;
		pDevMode->dmFields = DM_ORIENTATION;

		// Change to landscape.
		pDevMode->dmOrientation = DMORIENT_LANDSCAPE;

		// Call ExtDeviceMode() once more to allow the driver
		// to change the device-dependent portion of the
		// DEVMODE buffer if it needs to.



		// aka DM_COPY | DM_MODIFY

		  hdc = CreateDC(p2->pDriverName,p2->pPrinterName,p2->pPortName,pDevMode);
		  int a=33;

	}
	else
	{
		// The printer doesn't support the field you're
		// trying to change. Just use the current printer
		// settings.


		HDC hdc = CreateDC(p2->pDriverName,p2->pPrinterName,p2->pPortName,pDevMode);
	}


	// Allocate a global handle big enough to hold DEVNAMES.
	HGLOBAL hDevNames = GlobalAlloc(GHND,sizeof(DEVNAMES) +	(drvNameLen + ptrNameLen + porNameLen)*sizeof(TCHAR));
	//	ASSERT(hDevNames);
	DEVNAMES* pDevNames = (DEVNAMES*)GlobalLock(hDevNames);
	//	ASSERT(pDevNames);

	// Copy the DEVNAMES information from PRINTER_INFO_2
	// tcOffset = TCHAR Offset into structure
	int tcOffset = sizeof(DEVNAMES)/sizeof(TCHAR);
	//ASSERT(sizeof(DEVNAMES) == tcOffset*sizeof(TCHAR));

	pDevNames->wDriverOffset = tcOffset;
	memcpy((LPTSTR)pDevNames + tcOffset, p2->pDriverName,drvNameLen*sizeof(TCHAR));
	tcOffset += drvNameLen;

	pDevNames->wDeviceOffset = tcOffset;memcpy((LPTSTR)pDevNames + tcOffset, p2->pPrinterName,	ptrNameLen*sizeof(TCHAR));
	tcOffset += ptrNameLen;

	pDevNames->wOutputOffset = tcOffset;memcpy((LPTSTR)pDevNames + tcOffset, p2->pPortName,	porNameLen*sizeof(TCHAR));
	pDevNames->wDefault = 0;

	GlobalUnlock(hDevNames);
	GlobalFree(p2);   // free PRINTER_INFO_2

	// set the new hDevMode and hDevNames
	*phDevMode = hDevMode;
	*phDevNames = hDevNames;
	return TRUE;
}

http://bbs.csdn.net/topics/390348527?page=1#post-393490473


Using ExtDeviceMode() to Modify Printer Settings


This article was previously published under Q112641

On This Page

SUMMARY

The sample program EXTDEV2 demonstrates the correct method for calling  ExtDeviceMode() to change the current printer's orientation to landscape. The sample code can easily be modified to change other printer settings such as paper size and print quality. This article discusses the steps necessary for using  ExtDeviceMode() properly and includes the  GetPrinterDC()function, which is used to change paper orientation in the sample. 

EXTDEV2 is based on the PRNTFILE sample from the Windows SDK versions 3.0 and 3.1. EXTDEV2 also corrects a minor bug in the PRNTFILE sample. For additional information about that bug, please see the following article in the Microsoft Knowledge Base:
101413 Diagnosing Printing Problems in Your Application

MORE INFORMATION

The following files are available for download from the Microsoft Download Center:


Extdev2.exe

For additional information about how to download Microsoft Support files, click the following article number to view the article in the Microsoft Knowledge Base:
119591 How to Obtain Microsoft Support Files from Online Services
Microsoft scanned this file for viruses. Microsoft used the most current virus-detection software that was available on the date that the file was posted. The file is stored on security-enhanced servers that help to prevent any unauthorized changes to the file. 



Beginning with Windows version 3.0, many printer drivers implement a convention for controlling print settings on a job-by-job basis, without requiring user intervention via a dialog box. This is accomplished via the  ExtDeviceMode() function as described in Chapter 17 of the Microsoft Windows SDK "Guide to Programming" for both versions 3.0 and 3.1. The  DeviceCapabilities()function, also introduced in Windows 3.0, provides information about the print settings supported by a given driver. As of Windows version 3.1, changes to printer settings are allowed on a page-by-page basis via the use of the  ResetDC() API. 

ExtDeviceMode() and  DeviceCapabilities() are supplied by the printer drivers rather than GDI. Because not all drivers support these functions, applications must ensure that the driver supports these functions before attempting to use them. 

Because of the Universal Printer Driver (UNIDRV), almost all Windows 3.1 printer drivers support these functions. The HP Plotter driver (HPPLOT.DRV) is a notable exception. The only way to change the settings on the HP Plotter is to display the driver's print setup dialog box, which is accomplished by calling the driver's DeviceMode function. 

Correct usage of  ExtDeviceMode() and  DeviceCapabilities() to query and/or modify printer settings is a multistep process that is not fully explained in the SDK documentation. 

Because these functions reside in the printer driver rather than GDI, applications must first get a handle to the driver, typically by calling  LoadLibrary(), and then use  GetProcAddress() to get the address of the driver's  ExtDeviceMode() and/or DeviceCapabilities() functions. If  GetProcAddress() returns NULL for either of these functions, then that function is not supported by the driver. 

Furthermore, because  ExtDeviceMode() and  DeviceCapabilities() are not Windows APIs, they are not prototyped in WINDOWS.H. Instead, function pointer types are defined for both of these functions in PRINT.H included in the Windows 3.1 SDK and in DRIVINIT.H included in the Windows 3.0 SDK. Use LPFNDEVMODE for  ExtDeviceMode(); use LPFNDEVCAPS for DeviceCapabilities(). Using these types is important for compiler type-checking and ensures that the correct arguments are passed on the stack. Not using these types (for example, using FARPROC) can lead to general protection (GP) faults in some circumstances. 

PRINT.H (or DRIVINIT.H) also defines the device-independent part of the  DEVMODE structure used for manipulating printer settings. Note that the  DEVMODE structure actually used by a printer driver contains the device-independent part followed by a driver-specific part that varies in size and content with each driver and driver version. 

Because of this driver-dependence, it is very important for applications to query the driver for the correct size of the DEVMODE structure before allocating a buffer for it. 

The following code fragment loads a printer driver, calls  ExtDeviceMode() (if supported) to get the full  DEVMODE size, and allocates a buffer for the full  DEVMODE structure:
   #include <print.h>            // Formerly DRIVINIT.H in 3.0

   HINSTANCE hDriver;            // Handle to driver
   LPFNDEVMODE ExtDeviceMode;    // Function pointer variable
   PDEVMODE pdm;                 // Pointer to DEVMODE struct
   int nSize;                    // Size of printer's DEVMODE struct

   hDriver = LoadLibrary(szDriver);
   if (hDriver < HINSTANCE_ERROR)

     return;                     // Error

   ExtDeviceMode = (LPFNDEVMODE) GetProcAddress(hDriver, "EXTDEVICEMODE");
   if (!ExtDeviceMode)

     {
     FreeLibrary(hDriver);       // ExtDeviceMode() not supported
     return;
     }

   // Get size of DEVMODE
   nSize = ExtDeviceMode(hWnd, hDriver, NULL, szDevice, szPort,
                         NULL, NULL, 0);

   // Allocate buffer for DEVMODE
   pdm = (PDEVMODE) LocalAlloc(LPTR, nSize);  // check for failure!
				
Often, it is desirable to query the driver for the current printer settings. This can be accomplished by allocating a buffer for the DEVMODE structure as above, and then calling  ExtDeviceMode() a second time, passing the address of the output buffer and using the DM_OUT_BUFFER flag (also known as DM_COPY). For example:
  ExtDeviceMode(hWnd, hDriver, pdm, szDevice, szPort, NULL, NULL, DM_COPY);
				
Once the current settings are obtained, applications should use the  dmFields member of the  DEVMODE structure to determine which of the subsequent  DEVMODE fields were initialized by the driver. Only fields with the corresponding bit set in dmFields should be used by the application; other fields are not supported by the driver. 

To change printer settings, the application should not only change the appropriate fields of  DEVMODE, but also indicate which fields were changed by setting the corresponding bits in dmFields. For example, the following code fragment sets landscape printing:
   DWORD dwFields;

   ...

   dwFields = pdm->dmFields;     // Save this
   pdm->dmFields = 0             // We haven't changed anything yet

   if (dwFields & DM_ORIENTATION)

     {
     pdm->dmFields |= DM_ORIENTATION;
     pdm->dmOrientation = DMORIENT_LANDSCAPE;
     }

   // Continue changing other settings
				
A driver may support modifying a certain  DEVMODE field without supporting all of the available settings for that field. For example, an application cannot use  ExtDeviceMode() to switch to Executive paper if the printer only supports Letter, Legal, and A4 paper sizes. Applications should use  DeviceCapabilities() to query the driver for this type of information. For an example of using  DeviceCapabilities(), please see the following article in the Microsoft Knowledge Base:
81245 DeviceCapabilities() Function Sample Code


When the application is done modifying  DEVMODE, it is necessary to call  ExtDeviceMode() again to allow the driver to merge the new settings and to update the driver-dependent part of the  DEVMODE structure if necessary. This is done by providing both an input and an output  DEVMODE (a single buffer can be used) and by using both the DM_OUT_BUFFER and DM_IN_BUFFER (also known as DM_COPY and DM_MODIFY) flags.
   ExtDeviceMode(hWnd, hDriver, pdm, szDevice, szPort,

                 pdm, NULL, DM_IN_BUFFER|DM_OUT_BUFFER);
				
DEVMODE is now ready for use in  CreateDC() or  ResetDC() for printing. 

Changes made to printer settings in this manner are specific to the particular print job. It is also possible to change the system-wide default settings for a printer by using DM_OUT_DEFAULT (also known as DM_UPDATE) in addition to DM_IN_BUFFER and DM_OUT_BUFFER in the final call to  ExtDeviceMode() above. However, this is discouraged. It is more appropriate for the user to make changes to default settings through the Control Panel. 

The following function from the EXTDEV2 sample demonstrates the above method for changing the printer orientation to landscape:

Code Sample

   #include <windows.h>
   #include <print.h>    // Formerly DRIVINIT.H in 3.0

/**************************************************************************
**
   FUNCTION: GetPrinterDC()

    PURPOSE:  Get hDC for default device according to information in the
              "device" entry in the "windows" section of WIN.INI. Set
              the device context to landscape orientation if supported.

    COMMENTS: Calls ExtDeviceMode() in printer driver to set the device
              context to landscape if supported.

              See the documentation for ExtDeviceMode() and the DEVMODE
              structure for more information.

    RETURNS:  hDC > 0 if success
              hDC = 0 if failure

***************************************************************************

*/ 

   HANDLE GetPrinterDC()
   {

    char          pPrintInfo[80];
    LPSTR         lpTemp;
    LPSTR         lpPrintType;
    LPSTR         lpPrintDriver;
    LPSTR         lpPrintPort;
    char          pmodule[32];
    HANDLE        hDriver = 0;
    HANDLE        hDevMode = 0;
    LPDEVMODE     lpDevMode = NULL;
    LPFNDEVMODE   lpfnExtDeviceMode;
    HDC           hDC;
    int           count;

    // Get the default printer information from WIN.ini.
    // The string contains the printer name, driver filename, and port.
    if (!GetProfileString("windows", "Device", (LPSTR)"", pPrintInfo, 80))
        return (NULL);

    // Parse the string we just got from WIN.INI.
    // lpPrintDriver will be the driver filename (for example, HPPCL5MS).
    // lpPrintType will be the printer name (for example, HP Laserjet III).
    // lpPrintPort will be the port (for example, LPT1:).

    lpTemp = lpPrintType = pPrintInfo;
    lpPrintDriver = lpPrintPort = 0;

    while (*lpTemp)
    {
        if (*lpTemp == ',')
        {
            *lpTemp++ = 0;
            while (*lpTemp == ' ')
                lpTemp = AnsiNext(lpTemp);
            if (!lpPrintDriver)
                lpPrintDriver = lpTemp;
            else
            {
                lpPrintPort = lpTemp;
                break;
            }
        }
        else
            lpTemp = AnsiNext(lpTemp);
    }

    // Build driver name
    wsprintf (pmodule, "%s.drv",(LPSTR)lpPrintDriver);

    // Load driver
    if ((hDriver = LoadLibrary(pmodule)) > 31)
    {
        // Get a function pointer to the ExtDeviceMode() function.
        // ExtDeviceMode() resides in the driver so we can't call it
        // directly.
        if (lpfnExtDeviceMode = (LPFNDEVMODE)GetProcAddress(hDriver,
                                               (LPSTR)"EXTDEVICEMODE"))
        {
           // Get the number of bytes in the full DEVMODE buffer.
           // This includes the device-dependent part at the end
           // of the DEVMODE struct.
           count = lpfnExtDeviceMode(0,
                                     hDriver,
                                     NULL,
                                     lpPrintType,
                                     lpPrintPort,
                                     NULL,
                                     NULL,
                                     0);    // 0 = get buffer size

           if (count != -1)
           {
               // Allocate storage for the DEVMODE buffer.
               hDevMode = GlobalAlloc(GHND, count);

               if (hDevMode)
               {
                  lpDevMode = (LPDEVMODE)GlobalLock(hDevMode);

                  // Get the current printer settings.
                  count = lpfnExtDeviceMode(0,
                                            hDriver,
                                            lpDevMode,   // Output buffer
                                            lpPrintType,
                                            lpPrintPort,
                                            NULL,
                                            NULL,
                                            DM_OUT_BUFFER); // aka DM_COPY

                  // Check to see if this printer supports changing
                  // the orientation. You should check dmFields
                  // before changing any printer setting.

                  if (lpDevMode->dmFields & DM_ORIENTATION)
                  {
                     // Pass lpDevMode as both the input and output
                     // DEVMODE buffers. It is important to pass
                     // in the full DEVMODE from the previous call
                     // to ExtDeviceMode() as the input buffer because
                     // it has been completely initialized by the
                     // driver. If you do not do this, the results
                     // are sporadic--sometimes it works and sometimes
                     // it doesn't depending on the printer driver and
                     // the setting you are trying to change.

                     // Zero out all the fields and then set the bit(s)
                     // for the field(s) we want to change.
                     lpDevMode->dmFields = 0;
                     lpDevMode->dmFields = DM_ORIENTATION;

                     // Change to landscape.
                     lpDevMode->dmOrientation = DMORIENT_LANDSCAPE;

                     // Call ExtDeviceMode() once more to allow the driver
                     // to change the device-dependent portion of the
                     // DEVMODE buffer if it needs to.

                     count = lpfnExtDeviceMode(0,
                                             hDriver,
                                             lpDevMode,  //Output buffer
                                             lpPrintType,
                                             lpPrintPort,
                                             lpDevMode,  // Input buffer
                                             NULL,
                                             DM_OUT_BUFFER | DM_IN_BUFFER);

                                             // aka DM_COPY | DM_MODIFY

                     hDC = CreateDC(lpPrintDriver,
                                    lpPrintType,
                                    lpPrintPort,
                                    (void FAR*)lpDevMode);
                  }
                  else
                  {
                     // The printer doesn't support the field you're
                     // trying to change. Just use the current printer
                     // settings.
                     hDC = CreateDC(lpPrintDriver,
                                    lpPrintType,
                                    lpPrintPort,
                                    (void FAR*)lpDevMode);
                  }
                  GlobalUnlock(hDevMode);
                  GlobalFree(hDevMode);
                  FreeLibrary(hDriver);
                  return hDC;

               } // end hDevMode
           }  // end count != -1
        } // end lpfnExtDeviceMode != 0
    } // end hDriver > 31

// If we got here, an error has occurred so finish cleanup and return NULL.

    if (hDriver)
       FreeLibrary(hDriver);

    return NULL;

   } // end GetPrinterDC
				
There are some common variations to the above method when calling  ExtDeviceMode(). For example, if you just want to create a printer HDC using the current printer settings, you only need to call  ExtDeviceMode() twice, as described above. The first call is to get the size of the full DEVMODE and the second call is to get the current printer settings. You then just pass the initialized LPDEVMODE to CreateDC. 

ExtDeviceMode() can also be used to display the printer driver's setup dialog box. Note that this dialog box is driver-specific, and may be slightly different than the common dialog box's (COMMDLG.dll) setup dialog box, which is displayed by calling the PrintDlg function. 

To display the driver's setup dialog box with the current printer settings, you only need to call  ExtDeviceMode() twice as describe above but with one minor change. On the second call to  ExtDeviceMode(), use the flags DM_IN_PROMPT | DM_OUT_BUFFER (also known as DM_PROMPT | DM_COPY). The DM_IN_PROMPT flag displays the dialog box and the DM_OUT_BUFFER flag copies the settings from the dialog box into the LPDEVMODE. 

You can also display the driver's setup dialog box and change which dialog box controls are selected when the dialog box is displayed. For example, if you want to display the printer driver's setup dialog box but have the dialog box displayed with the landscape control selected, use the above approach with one minor change. On the third call to  ExtDeviceMode(), specify the flags DM_OUT_BUFFER | DM_IN_BUFFER | DM_IN_PROMPT. DM_IN_BUFFER initializes the dialog box controls, DM_IN_PROMPT displays the setup dialog box, and DM_OUT_BUFFER copies the settings from the dialog box into the LPDEVMODE.

Properties

Article ID: 112641 - Last Review: March 7, 2005 - Revision: 2.3
APPLIES TO
  • Microsoft Windows Software Development Kit 3.1
Keywords: 
kbdownload kb16bitonly kbfile kbinfo kbsample KB112641
Retired KB Content Disclaimer
This article was written about products for which Microsoft no longer offers support. Therefore, this article is offered "as is" and will no longer be updated.
http://support.microsoft.com/kb/112641/en-us


http://my.csdn.net/baiyizhujian

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

客户端安装个软件。负责监控该电脑的打印动作。并把内容转成图片储存。并将图片传送到服务器机器上,并将打印内容传到服务器上面. 解决方案: 1. 先用api打印函数连接到指定的打印机.再试着用枚举函数()获得打印作业信息.根据信息得知打印的内容,及当前的状态. 2. 获知内容,得知打印内容所在的位置,再某种方式将数据导在图片;再传到服务器上. 技术问题: 1. 打印枚举函数中找不到JOB_INFO_1 或 JOB_INFO_2结构的定义.(已解决) 2. 怎么样获得打印内容.是通过原本的驱动还是其它办法, 其它: 文件传给pdf打印机之前已经存成raw格式了,应该是从缓冲池中直接读取数据 接下去要完成的应该是怎么把raw格式读出来, 具我推测在获得打印信息的时候肯定有某个参数跟这个RAW格式是对应的.读出某个参数后才能再继续读取对RAW文件读取 具微软件网站显示,打印机的格式应该分成5种.raw的三种格式,text,emf(增强型图元文件) RAW格式指是最原始的数据 CreateDC("WINSPOOL", printer, null, ref dv);//用DISPLAY,是获取整个屏幕的设备场景;2、用WINSPOOL,则是访问打印驱动 返回新设备场景句柄,若出错则为零 EMFStreamPrintDocument 实力问题:就算获得句柄也没有办法接下去要做什么.(想错了) 目前状态:EMF图片取出来,监控也可以实现了.但监控的打印作业跟EMF图片不知道怎么产生关联.而且EMF图片读起出来比较慢. 取EMF图片本身spl就已经读入内存,但是有一种办法为了要读取图片只能将spl文件考出来再做成emf文件. 新的思路能不能将文件 shd文件中包含了一个作业ID RPC 命名管道 Server(服务器) Server 系统服务提供 RPC 支持以及文件、打印和命名管道在网络上的共享。Server 服务允许本地资源(如磁盘和打印机)共享,因此网络上的其他用户可以访问它们。它还允许在其他计算机上的应用程序与您计算机上的应用程序之间进行命名管道通信,这是用于 RPC 的。命名管道通信是为一个进程的输出(此输出用作另外一个进程的输入)而保留的内存。接受输入的进程不必是本地进程。
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值