home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 31 / CDASC_31_1996_juillet_aout.iso / vrac / vbprnt20.zip / SRC / VBPRNT32.C < prev    next >
C/C++ Source or Header  |  1996-05-31  |  15KB  |  488 lines

  1. /* VBPRNT32.DLL v2.0 Last Updated 05-29-1996 by Robert Simpson
  2.     This version designed for 32-bit Windows apps
  3.  
  4.     NOTES
  5.     This version is designed specifically for 32-bit operation, using the
  6.     expanded DEVMODE structure in Windows 95.
  7.  
  8.     The sample programs, DLL files and all source code have been released
  9.     to the public domain.
  10.  
  11.     This DLL was written and compiled in Borland C++ 4.5
  12. */
  13.  
  14. #include <windows.h>
  15. #include <string.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <math.h>
  19. #include <ctype.h>
  20. #include <dos.h>
  21. #include <ole2.h>
  22.  
  23. #ifdef WIN16
  24. #include <print.h>
  25. #include <olenls.h>
  26. #include <variant.h>
  27. #include <compobj.h>
  28. #include <dispatch.h>
  29. #endif
  30.  
  31. /*  Exported Functions are listed below, here are the proper VB declares:
  32.  
  33. Declare Function VBGetPrinters          Lib "vbprnt32.dll" () As String
  34. Declare Function VBGetDriverFromName  Lib "vbprnt32.dll" (printername As String) As String
  35. Declare Function VBSetDefPrinter          Lib "vbprnt32.dll" (printername As String) As Integer
  36. Declare Function VBGetDefPrinter          Lib "vbprnt32.dll" () As String
  37. Declare Function VBExtDeviceMode          Lib "vbprnt32.dll" (ByVal hWnd As Integer, printername As String, inDev As DEVMODE_TYPE, outDev As DEVMODE_TYPE, ByVal fMode As Integer) As Integer
  38. Declare Function VBDevModeToStr          Lib "vbprnt32.dll" (inDev As DEVMODE_TYPE) As String
  39. Declare Function VBStrToDevMode          Lib "vbprnt32.dll" (dmString As String, outDev As DEVMODE_TYPE) As Integer
  40. Declare Function VBDeviceCapabilities Lib "vbprnt32.dll" (printername As String, ByVal iCap As Integer, lpStr As Any, inDev As DEVMODE_TYPE) As Long
  41. Declare Function VBResetDC            Lib "vbprnt32.dll" (ByVal hDC As Integer, outDev As DEVMODE_TYPE) As Integer
  42.  
  43. ' Here is the VB DEVMODE that should be used in all calls to this DLL requiring a DEVMODE structure:
  44.  
  45. Type DEVMODE_TYPE
  46.   dmDeviceName As String * 32
  47.   dmSpecVersion As Integer
  48.   dmDriverVersion As Integer
  49.   dmSize As Integer
  50.   dmDriverExtra As Integer
  51.   dmFields As Long
  52.   dmOrientation As Integer
  53.   dmPaperSize As Integer
  54.   dmPaperLength As Integer
  55.   dmPaperWidth As Integer
  56.   dmScale As Integer
  57.   dmCopies As Integer
  58.   dmDefaultSource As Integer
  59.   dmPrintQuality As Integer
  60.   dmColor As Integer
  61.   dmDuplex As Integer
  62.   dmYResolution As Integer
  63.   dmTTOption As Integer
  64.   dmCollate As Integer
  65.   dmFormName As String * 32
  66.   dmLogPixels As Integer
  67.   dmBitsPerPel As Long
  68.   dmPelsWidth As Long
  69.   dmPelsHeight As Long
  70.   dmDisplayFlags As Long
  71.   dmDisplayFrequency As Long
  72.   dmPrivate As String
  73. End Type
  74.  
  75. '  The DEVMODE_TYPE structure in VB is essentially a base DEVMODE structure with a dynamic
  76. '  string attached to the end (the C version is directly below, named VBDEVMODE) which
  77. '  holds the printer's private data (if there is any).
  78. */
  79.  
  80. #define PRINTERLIST 2048 // Size of the buffer that holds the available printers
  81.  
  82. #ifdef WIN32
  83. #define CCONV  _stdcall
  84. #else
  85. #define CCONV  FAR PASCAL _export
  86. #endif
  87.  
  88. struct VBDEVMODE      // The C equivilent to the VB DEVMODE_TYPE structure above
  89. {
  90.   DEVMODE dm;        // The size of the DEVMODE structure is larger in Win95 than in Win31
  91.   BSTR *dmPrivate;   // To compensate for size differences, this dmPrivate area holds the extra data
  92. };                   // required by Win95 and by the specific printer driver (if it DOES require anything).
  93.  
  94. // Exported functions
  95. BSTR        CCONV VBGetPrinters(void);
  96. BSTR        CCONV VBGetDriverFromName(BSTR *printername);
  97. short int   CCONV VBSetDefPrinter(BSTR *);
  98. BSTR        CCONV VBGetDefPrinter(void);
  99. short int   CCONV VBExtDeviceMode(HWND,BSTR *,struct VBDEVMODE *,struct VBDEVMODE *,WORD);
  100. BSTR        CCONV VBDevModeToStr(struct VBDEVMODE *);
  101. short int   CCONV VBStrToDevMode(BSTR *,struct VBDEVMODE *);
  102. long        CCONV VBDeviceCapabilities(BSTR *,WORD,LPSTR,struct VBDEVMODE *);
  103. HDC         CCONV VBResetDC(HDC, struct VBDEVMODE *);
  104.  
  105. // Internal functions
  106. short int      GetDriverFromName(BSTR *,LPSTR,LPSTR,LPSTR);
  107. DEVMODE       *GetVBDevMode(struct VBDEVMODE *);
  108. void           SetVBDevMode(DEVMODE *,struct VBDEVMODE *);
  109.  
  110. // 16-Bit Windows only
  111. #ifdef WIN16
  112. typedef int (FAR PASCAL *ExtDeviceMode)(HWND,HANDLE,LPDEVMODE,LPSTR,LPSTR,LPDEVMODE,LPSTR,WORD);
  113. typedef DWORD (FAR PASCAL *DeviceCapabilities)(LPSTR,LPSTR,WORD,LPSTR,LPDEVMODE);
  114. #endif
  115.  
  116. /* This function works similar to the VB Dir$() function.  The first time it is
  117.     called, it retrieves the list of installed printers and returns them one at a
  118.     time to VB.  Each call returns the next installed printer.  A NULL return value
  119.     indicates the end of the list. */
  120. BSTR CCONV VBGetPrinters(void)
  121. {
  122.   static short int prevcall;
  123.   static char printers[PRINTERLIST];
  124.   static char buff[256];
  125.   char printer[64];
  126.   LPSTR driver;
  127.   LPSTR port;
  128.   char output[128];
  129.   LPSTR port2;
  130.  
  131.   if (*printers == 0)
  132.      {
  133.         if (prevcall == 1)
  134.           {
  135.              prevcall = 0;
  136.              return 0;
  137.           }
  138.         prevcall = 1;
  139.         memset(printers,0,PRINTERLIST);
  140.         GetProfileString("devices",NULL,"",printers,PRINTERLIST);
  141.      }
  142.   if (buff[0] != 0)
  143.      {
  144.         port = strchr(buff,',');
  145.         if (port == 0) return 0;
  146.         *port = 0;
  147.         port ++;
  148.         strncpy(printer,buff,(int)(port-buff));
  149.         printer[(int)(port-buff)] = 0;
  150.         driver = strchr(port,',');
  151.         if (driver == 0) return 0;
  152.         driver[0] = 0;
  153.         sprintf(output,"%s on %s",printer,port);
  154.         memmove(buff,driver+1,sizeof buff-(int)(driver-buff));
  155.      }
  156.   else
  157.      {
  158.         strcpy(printer,printers);
  159.         GetProfileString("devices",printer,"",output,sizeof output);
  160.         strtok(output,",");
  161.         port = strtok(NULL,",");
  162.         port2 = strtok(NULL,",");
  163.         while (port2 != 0)
  164.           {
  165.              strcat(buff,printer);
  166.              strcat(buff,",");
  167.              strcat(buff,port2);
  168.              strcat(buff,",");
  169.              port2 = strtok(NULL,",");
  170.           }
  171.         sprintf(output,"%s on %s",printer,port);
  172.         memmove(printers,printers+strlen(printer)+1,PRINTERLIST-(strlen(printer)));
  173.      }
  174. #ifdef WIN32
  175.   return SysAllocStringByteLen(output,strlen(output));
  176. #else
  177.   return SysAllocStringLen((BSTR)output,strlen(output));
  178. #endif
  179.   }
  180.  
  181. /* This function returns the printer driver assigned to the specified printer.
  182.     It's of little use other than reference purposes.  The <printername> VB string
  183.     must follow the format "<printername> on <port>" such as "Epson Stylus COLOR on LPT1:"
  184.     This is the same format that VBGetPrinters() returns the available printers. */
  185. BSTR CCONV VBGetDriverFromName(BSTR *name)
  186. {
  187.   char pname[80];
  188.   char driver[80];
  189.   char port[80];
  190.  
  191.   if (GetDriverFromName(name,pname,driver,port) != 0)
  192. #ifdef WIN32
  193.      return SysAllocStringByteLen(driver,strlen(driver));
  194. #else
  195.      return SysAllocStringLen((BSTR)driver,strlen(driver));
  196. #endif
  197.   return 0;
  198. }
  199.  
  200. /* Internal function to parse the name of a printer and determine its driver and port.
  201.     The caller provides pointers for the name, driver and port that this function
  202.     will fill in */
  203. short int GetDriverFromName(BSTR *name,LPSTR pname,LPSTR pdriver,LPSTR pport)
  204. {
  205.   char printer[128];
  206.   LPSTR port;
  207.   LPSTR driver;
  208.   char iniprinter[128];
  209.   LPSTR found;
  210.  
  211.   strcpy(printer,(LPSTR)*name);
  212.   if (strlen(printer) == 0) return 0;
  213.   found = strstr(printer," on ");
  214.   if (found == 0) return 0;
  215.   *found = 0;
  216.   GetProfileString("devices",printer,"",iniprinter,sizeof iniprinter);
  217.   if (iniprinter[0] == 0) return 0;
  218.   driver = strtok(iniprinter,",");
  219.   port = found+4;
  220.   strcpy(pname,printer);
  221.   strcpy(pdriver,driver);
  222.   strcpy(pport,port);
  223.   return -1;
  224. }
  225.  
  226. /* Sets the default Windows printer. */
  227. short int CCONV VBSetDefPrinter(BSTR *printer)
  228. {
  229.   char newprinter[128];
  230.   char port[32];
  231.   char driver[32];
  232.   char name[32];
  233.  
  234.   if (GetDriverFromName(printer,name,driver,port) == NULL) return 0;
  235.  
  236.   sprintf(newprinter,"%s,%s,%s",name,driver,port);
  237.   WriteProfileString("windows","device",newprinter);
  238.   return -1;
  239. }
  240.  
  241. /* Gets the default Windows printer from the INI file and parses it */
  242. BSTR CCONV VBGetDefPrinter(void)
  243. {
  244.   LPSTR name;
  245.   LPSTR port;
  246.   char inistring[128];
  247.   char final[128];
  248.  
  249.   GetProfileString("windows","device","",inistring,sizeof inistring);
  250.   if (inistring[0] == 0) return 0;
  251.   name = strtok(inistring,",");
  252.   strtok(NULL,",");
  253.   port = strtok(NULL,",");
  254.   sprintf(final,"%s on %s",name,port);
  255. #ifdef WIN32
  256.   return SysAllocStringByteLen(final,strlen(final));
  257. #else
  258.   return SysAllocStringLen((BSTR)final,strlen(final));
  259. #endif
  260.   }
  261.  
  262. /* Converts a VB DevMode structure to one long string so it can be saved to
  263.     disk easier. */
  264. BSTR CCONV VBDevModeToStr(struct VBDEVMODE *inmode)
  265. {
  266.   DEVMODE *outmode;
  267.   int size;
  268.   BSTR str;
  269.  
  270.   size = inmode->dm.dmSize + inmode->dm.dmDriverExtra;
  271.   if (size < 0) return 0;
  272.   if (size == 0) size = sizeof(DEVMODE);
  273.   outmode = GetVBDevMode(inmode);
  274.   if (outmode == 0) return 0;
  275. #ifdef WIN32
  276.   str = SysAllocStringByteLen((LPSTR)outmode,size);
  277. #else
  278.   str = SysAllocStringLen((BSTR)outmode,size);
  279. #endif
  280.   free (outmode);
  281.   return str;
  282. }
  283.  
  284. /* Converts a string (hopefully created with the VBDevModeToStr() function)
  285.     back to a VB DevMode structure */
  286. short int CCONV VBStrToDevMode(BSTR *str,struct VBDEVMODE *outmode)
  287. {
  288.   DEVMODE *inmode;
  289.   int size;
  290.  
  291. #ifdef WIN32
  292.   size = SysStringByteLen(*str);
  293. #else
  294.   size = SysStringLen(*str);
  295. #endif
  296.   if (size < sizeof (DEVMODE)) return 0;
  297.   inmode = malloc((size_t)size);
  298.   if (inmode == 0) return 0;
  299.   memcpy((LPSTR)inmode,(LPSTR)*str,size);
  300.   SetVBDevMode(inmode,outmode);
  301.   return -1;
  302. }
  303.  
  304. /* Here's the real meat.  Calls the printer's ExtDeviceMode function.  This one function allows you
  305.     to bring up the printer's configuration screen, get a copy of the default config, write out a new
  306.     config and all sorts of other nEeT stuff! */
  307. short int CCONV VBExtDeviceMode(HWND hwnd,BSTR *printername,struct VBDEVMODE *indata,struct VBDEVMODE *outdata,WORD mode)
  308. {
  309.   DEVMODE *realoutput;
  310.   DEVMODE *indev = 0;
  311.   char pname[64];
  312.   char pdriver[32];
  313.   char pport[32];
  314.   HANDLE hlib;
  315.   short int retval;
  316.   int size;
  317. #ifdef WIN16
  318.   ExtDeviceMode EDM;
  319. #endif
  320.  
  321.   if (GetDriverFromName(printername,pname,pdriver,pport) == NULL) return 0;
  322.  
  323. #ifdef WIN32
  324.   OpenPrinter(pname,&hlib,NULL);
  325.   if (hlib == 0)  return 0;
  326.   size = DocumentProperties(hwnd,hlib,pname,NULL,NULL,0);
  327. #else
  328.   strcat(pdriver,".drv");
  329.   if ((hlib = LoadLibrary(pdriver)) < 32) return 0;
  330.   if ((EDM = (ExtDeviceMode)GetProcAddress(hlib,"EXTDEVICEMODE")) == 0)
  331.   {
  332.      FreeLibrary(hlib);
  333.      return 0;
  334.   }
  335.   size = EDM(hwnd,hlib,NULL,pname,pport,NULL,NULL,0);
  336. #endif
  337.   if (size != 0)
  338.      {
  339.         realoutput = malloc(size);
  340.         if (indata->dm.dmSize != 0)
  341.           indev = GetVBDevMode(indata);
  342.         if (realoutput != 0)
  343.           {
  344. #ifdef WIN32
  345.              retval = (short int)DocumentProperties(hwnd,hlib,pname,realoutput,indev,mode);
  346.              ClosePrinter(hlib);
  347. #else
  348.              retval = EDM(hwnd,hlib,realoutput,pname,pport,indev,NULL,mode);
  349.              FreeLibrary(hlib);
  350. #endif
  351.              if (retval == 1) SetVBDevMode(realoutput,outdata);
  352.              return retval;
  353.           }
  354.         else
  355.           {
  356.              if (size != 0) free(realoutput);
  357.              if (indev != 0) free(indev);
  358.           }
  359.      }
  360.   return 0;
  361. }
  362.  
  363. /* Query the printer device.  This function allows you to get information on paper
  364.     bins, paper sizes, available resolutions and etc from the printer driver. */
  365. long CCONV VBDeviceCapabilities(BSTR *printername,WORD caps,LPSTR output,struct VBDEVMODE *indata)
  366. {
  367.   DEVMODE *indev = 0;
  368.   HANDLE hlib;
  369.   char pname[64];
  370.   char pdriver[32];
  371.   char pport[32];
  372.   DWORD retval;
  373.   LPSTR buffer;
  374.   LPSTR pos;
  375.   LPSAFEARRAY array;
  376.   long lbound,ubound,count,size;
  377. #ifdef WIN32
  378.   char temp[128];
  379. #else
  380.   DeviceCapabilities DevCap;
  381. #endif
  382.  
  383.   if (GetDriverFromName(printername,pname,pdriver,pport) == NULL) return 0;
  384. #ifdef WIN32
  385.   if (!OpenPrinter(pname,&hlib,NULL)) return 0;
  386.   ClosePrinter(hlib);
  387. #else
  388.   strcat(pdriver,".drv");
  389.   if ((hlib = LoadLibrary(pdriver)) < 32) return 0;
  390.   if ((DevCap = (DeviceCapabilities)GetProcAddress(hlib,"DEVICECAPABILITIES")) == 0)
  391.   {
  392.      FreeLibrary(hlib);
  393.      return 0;
  394.   }
  395. #endif
  396.   if (indata->dm.dmSize != 0) indev = GetVBDevMode(indata);
  397.   if (output != 0 && (caps==DC_BINS||caps==DC_BINNAMES||
  398.                              caps==DC_ENUMRESOLUTIONS||caps==DC_FILEDEPENDENCIES||
  399.                              caps==DC_PAPERNAMES||caps==DC_PAPERS||caps==DC_PAPERSIZE))
  400.   {
  401.      memcpy(&array,output,4);
  402.      size = SafeArrayGetElemsize(array);
  403.      SafeArrayGetLBound(array,1,&lbound);
  404.      SafeArrayGetUBound(array,1,&ubound);
  405.      buffer = malloc((size_t)(size*(ubound-lbound+1)));
  406.      memset(buffer,0,(size_t)(size*(ubound-lbound+1)));
  407.   }
  408.   else buffer = output;
  409. #ifdef WIN32
  410.   retval = DeviceCapabilities(pname,pport,caps,buffer,indev);
  411. #else
  412.   retval = DevCap(pname,pport,caps,buffer,indev);
  413.   FreeLibrary(hlib);
  414. #endif
  415.   if (indev != 0) free(indev);
  416.   if (output != buffer)
  417.   {
  418.      pos = buffer;
  419.      for (count = lbound;count <= ubound;count++)
  420.      {
  421. #ifdef WIN32
  422.         if (caps==DC_BINNAMES||caps==DC_FILEDEPENDENCIES||caps==DC_PAPERNAMES)
  423.         {
  424.           memset(temp,0,sizeof temp);
  425.           MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,(LPCSTR)pos,strlen(pos),(LPWSTR)temp,sizeof temp);
  426.           SafeArrayPutElement(array,&count,temp);
  427.           pos = pos + size/2;
  428.         }
  429.         else
  430. #endif
  431.         {
  432.           SafeArrayPutElement(array,&count,pos);
  433.           pos = pos + (int)size;
  434.         }
  435.      }
  436.      free(buffer);
  437.   }
  438.   return retval;
  439. }
  440.  
  441. HDC CCONV VBResetDC(HDC dc, struct VBDEVMODE *indata)
  442. {
  443.   DEVMODE *indev;
  444.   HDC retval = 0;
  445.  
  446.   if (indata->dm.dmSize == 0) return 0;
  447.   indev = GetVBDevMode(indata);
  448.   if (indev != 0) retval = ResetDC(dc,indev);
  449.   if (indev != 0) free(indev);
  450.   return retval;
  451. }
  452.  
  453. DEVMODE *GetVBDevMode(struct VBDEVMODE *inmode)
  454. {
  455.   DEVMODE *outdevmode;
  456.   int extra;
  457.   int size;
  458.  
  459.   size = inmode->dm.dmSize + inmode->dm.dmDriverExtra;
  460.   extra = inmode->dm.dmSize-sizeof(DEVMODE)+inmode->dm.dmDriverExtra;
  461.   if (size < sizeof(DEVMODE))
  462.   {
  463.      size = sizeof(DEVMODE);
  464.      extra = 0;
  465.   }
  466.   outdevmode = malloc(size);
  467.   if (outdevmode == 0) return 0;
  468.   if (extra != 0)
  469.      memcpy(outdevmode+1,inmode->dmPrivate,extra);
  470.   memcpy(outdevmode,inmode,sizeof(DEVMODE));
  471.   return outdevmode;
  472. }
  473.  
  474. void SetVBDevMode(DEVMODE *inmode,struct VBDEVMODE *outmode)
  475. {
  476.   int extra;
  477.  
  478.   extra = inmode->dmSize-sizeof(DEVMODE)+inmode->dmDriverExtra;
  479.   if (extra < 0) extra = 0;
  480.   memcpy(outmode,inmode,sizeof(DEVMODE));
  481. #ifdef WIN32
  482.   SysReAllocStringLen((BSTR *)&outmode->dmPrivate,(BSTR)(inmode+1),extra/2);
  483. #else
  484.   SysReAllocStringLen((BSTR *)&outmode->dmPrivate,(BSTR)(inmode+1),extra);
  485. #endif
  486.   free(inmode);
  487. }
  488.