home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / PRTSCN.ZIP / PRTSCN.TXT
Text File  |  1991-09-02  |  15KB  |  437 lines

  1. /*****************************************************************************/
  2.  
  3. The following code segments are drawn from a much larger system
  4. that I manage at work.  The intent is to show how to provide
  5. a graphical print screen capability in a PM program.  We install
  6. a hook to watch for the print screen key and then take a bit map
  7. snapshot of the screen.  This bit map is then sent to the printer.
  8. Forgive me if I don't go into all the details about the non-related
  9. data structures -- it's late and my mind is a bit foggy.
  10.  
  11. Feel free to use anything here.  Please add some kind of acknowledgement,
  12. if you use them as is, like:
  13.  
  14.     "Print routines (c) 1990, 1991 Applied Signal Technology, Inc."
  15.  
  16. Comment, questions, ridicule should be directed to:
  17.  
  18.     Jeff Hitchcock
  19.     CompuServe 71601,260
  20.  
  21.     or U.S. Mail to
  22.  
  23.     Applied Signal Technology, Inc.
  24.     470 Spring Park Place, Suite 700
  25.     Herndon, VA 22070
  26.  
  27.     or phone to
  28.  
  29.     703/478-5619
  30.  
  31. /*****************************************************************************/
  32.  
  33. 1.  During the WM_CREATE message processing, add the following:
  34.  
  35.    // Set the print screen hook
  36.  
  37.    WinSetHook (hab, HMQ_CURRENT, HK_INPUT, (PFN) PrintScreenHook,
  38.                (HMODULE) NULL);
  39.  
  40. /*****************************************************************************/
  41.  
  42. 2.  Somewhere, have this function:
  43.  
  44. BOOL CALLBACK PrintScreenHook (HAB hab, PQMSG pQmsg, USHORT fs)
  45.  
  46. {
  47.  
  48.     if ( pQmsg->msg == WM_CHAR )
  49.         if ( ( SHORT1FROMMP(pQmsg->mp1) & KC_KEYUP) &&
  50.              ( SHORT1FROMMP(pQmsg->mp1) & KC_VIRTUALKEY ) &&
  51.              ( SHORT2FROMMP(pQmsg->mp2) == VK_PRINTSCRN) )
  52.                 PrintScreen (hab);
  53.  
  54.     return FALSE;
  55. }
  56.  
  57. /*****************************************************************************/
  58.  
  59. 3.  Here's the "driver:"
  60.  
  61. VOID EXPENTRY PrintScreen (HAB hab)
  62.  
  63. {
  64.     HBITMAP      hbm;
  65.  
  66.     hbm = ScreenToBitmap (hab);
  67.  
  68.     PrintBitMap(hbm);
  69. }
  70.  
  71. /*****************************************************************************/
  72.  
  73. 4.  Here's a general print-related structure we use.  We often
  74. have many print threads running concurrently, but we only allow
  75. one to "run" at a time.  We use a semaphore to show availability
  76. of the printer (so to speak), and only one thread at a time gets
  77. it.  If we didn't do this, and more than a few print threads are
  78. running (especially graphical prints), even a 486/33 with 16 MB of
  79. RAM begins to C-R-A-W-L.  So, for what it's worth, these are the
  80. structures that we use:
  81.  
  82. /**************************************************************
  83. *                                                             *
  84. *   PRINTTHREADPARAMS structure                               *
  85. *                                                             *
  86. *   Parameters that are used to manage separate print threads *
  87. *                                                             *
  88. *   Item             Contents/Use                             *
  89. *   --------------   ---------------------------------------- *
  90. *                                                             *
  91. *   sJobNumber       Print job number, used for cancelling    *
  92. *   aiThreadStack    Thread's stack                           *
  93. *   hwndNotify       Window to which notif. msgs are sent     *
  94. *   tidPrint         System task id                           *
  95. *   hssmPrinter...   Semaphore for printer available          *
  96. *   fSemSet          TRUE if semaphore was made and cleared   *
  97. *   szSummary        Print summary (e.g., fax printout)       *
  98. *   fStart           Can't start until TRUE (default FALSE)   *
  99. *   fContinue        Quit if FALSE (default is TRUE)          *
  100. *   fHold            Hold if TRUE (default is FALSE)          *
  101. *   sStartingPage    For multipage, start here                *
  102. *   sEndingPage      For multipage, end here                  *
  103. *   usParam          Module-dependent USHORT                  *
  104. *   ulParam          Module-dependent ULONG                   *
  105. *   pPrintData       PVOID to the print data                  *
  106. *                                                             *
  107. *   PAGESETUP structure                                       *
  108. *                                                             *
  109. *   Parameters used to describe the appearance                *
  110. *                                                             *
  111. *   Item             Contents/Use                             *
  112. *   --------------   ---------------------------------------- *
  113. *                                                             *
  114. *   szFont           The name of the font to use              *
  115. *   sLinesPerPage    Used to scale font                       *
  116. *   sCharsPerLine    Used to scale font                       *
  117. *   sLeft            Used to position on page, in chars       *
  118. *   sRight           Used to position on page, in char        *
  119. *   sTop             Used to position on page, in lines       *
  120. *   sBottom          Used to position on page, in lines       *
  121. *   szHeader         Text to place on top of each page        *
  122. *   fIncludeSummary  If TRUE, include SRI summary on page 1   *
  123. *   fHeaderEveryPage TRUE for every page, false for pg 1      *
  124. *   fHeaderUnderline TRUE for underline                       *
  125. *   szFooter         Text to place at bottom of each page     *
  126. *   fFooterEveryPage TRUE for every page, false for pg 1      *
  127. *   fOverlineFooter  TRUE for overline                        *
  128. *                                                             *
  129. *   HEADER AND FOOTER OPTIONS:                                *
  130. *                                                             *
  131. *   Special Flags that should be supported in each module:    *
  132. *                                                             *
  133. *           &l  Left justify                                  *
  134. *           &c  Center                                        *
  135. *           &r  Right justify                                 *
  136. *           &d  Date                                          *
  137. *           &t  Time                                          *
  138. *           &p  Page number                                   *
  139. *                                                             *
  140. **************************************************************/
  141.  
  142. typedef struct
  143.     {
  144.     CHAR       szFont[FACESIZE] ;
  145.     SHORT      sLinesPerPage ;
  146.     SHORT      sCharsPerLine ;
  147.     SHORT      sLeft ;
  148.     SHORT      sRight ;
  149.     SHORT      sTop ;
  150.     SHORT      sBottom ;
  151.     BOOL       fIncludeSummary ;
  152.     CHAR       szHeader[HEADERFOOTERLENGTH] ;
  153.     BOOL       fHeaderEveryPage ;
  154.     BOOL       fUnderlineHeader ;
  155.     CHAR       szFooter[HEADERFOOTERLENGTH] ;
  156.     BOOL       fFooterEveryPage ;
  157.     BOOL       fOverlineFooter ;
  158.     }
  159.     PAGESETUP ;
  160.  
  161. typedef PAGESETUP FAR *PPAGESETUP ;
  162.  
  163. typedef struct
  164.     {
  165.     SHORT        sJobNumber ;
  166.     int          aiThreadStack[STACKSIZE / sizeof (int)] ;
  167.     HWND         hwndNotify ;
  168.     HSYSSEM      hssmPrinterAvailable ;
  169.     BOOL         fSemSet ;
  170.     CHAR         szSummary[HEADERFOOTERLENGTH] ;
  171.     BOOL         fStart ;
  172.     BOOL         fRunning ;
  173.     BOOL         fContinue ;
  174.     BOOL         fHold ;
  175.     SHORT        sStartingPage ;
  176.     SHORT        sEndingPage ;
  177.     PAGESETUP    page ;
  178.     USHORT       usParam ;
  179.     ULONG        ulParam ;
  180.     VOID huge    *pPrintData ;
  181.     }
  182.     PRINTTHREADPARAMS ;
  183.  
  184. typedef PRINTTHREADPARAMS FAR *PPRINTTHREADPARAMS ;
  185.  
  186. /*****************************************************************************/
  187.  
  188. 5.  This function saves the screen display to a bitmap.
  189.  
  190. HBITMAP ScreenToBitmap (HAB hab)
  191.  
  192.      {
  193.      BITMAPINFOHEADER bmp ;
  194.      HBITMAP          hbm ;
  195.      HDC              hdcMemory ;
  196.      HPS              hpsScreen, hpsMemory ;
  197.      LONG             alBitmapFormats [2] ;
  198.      POINTL           aptl[3] ;
  199.      SIZEL            sizl ;
  200.      SHORT            cxScreen;
  201.      SHORT            cyScreen;
  202.      BOOL             fMonochrome = FALSE;
  203.                                    // Create memory DC and PS
  204.  
  205.      cxScreen = (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN);
  206.      cyScreen = (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN);
  207.  
  208.      hdcMemory = DevOpenDC (hab, OD_MEMORY, "*", 0L, NULL, NULL) ;
  209.  
  210.      sizl.cx = sizl.cy = 0 ;
  211.      hpsMemory = GpiCreatePS (hab, hdcMemory, &sizl,
  212.                               PU_PELS    | GPIF_DEFAULT |
  213.                               GPIT_MICRO | GPIA_ASSOC) ;
  214.  
  215.                                    // Create bitmap for destination
  216.  
  217.  
  218.      bmp.cbFix     = sizeof bmp ;
  219.  
  220.      if (fMonochrome)
  221.           {
  222.           bmp.cPlanes   = 1 ;
  223.           bmp.cBitCount = 1 ;
  224.           }
  225.      else
  226.           {
  227.           GpiQueryDeviceBitmapFormats (hpsMemory, 2L, alBitmapFormats) ;
  228.  
  229.           bmp.cPlanes   = (USHORT) alBitmapFormats[0] ;
  230.           bmp.cBitCount = (USHORT) alBitmapFormats[1] ;
  231.           }
  232.  
  233.      bmp.cx        = cxScreen ;
  234.      bmp.cy        = cyScreen ;
  235.  
  236.      hbm = GpiCreateBitmap (hpsMemory, &bmp, 0L, NULL, NULL) ;
  237.  
  238.                                    // Copy from screen to bitmap
  239.  
  240.      if (hbm != NULL)
  241.           {
  242.           GpiSetBitmap (hpsMemory, hbm) ;
  243.           hpsScreen = WinGetScreenPS (HWND_DESKTOP) ;
  244.  
  245.           aptl[0].x = 0 ;
  246.           aptl[0].y = 0 ;
  247.           aptl[1].x = cxScreen ;
  248.           aptl[1].y = cyScreen ;
  249.           aptl[2].x = 0 ;
  250.           aptl[2].y = 0 ;
  251.  
  252.           WinLockVisRegions (HWND_DESKTOP, TRUE) ;
  253.  
  254.           GpiBitBlt (hpsMemory, hpsScreen, 3L, aptl,
  255.                      fMonochrome ? ROP_NOTSRCCOPY : ROP_SRCCOPY, BBO_IGNORE) ;
  256.  
  257.           WinLockVisRegions (HWND_DESKTOP, FALSE) ;
  258.  
  259.           WinReleasePS (hpsScreen) ;
  260.           GpiDestroyPS (hpsMemory) ;
  261.           DevCloseDC (hdcMemory) ;
  262.           }
  263.  
  264.      return hbm ;
  265.      }
  266.  
  267. /*****************************************************************************
  268.  
  269. 6.  The "core" function:
  270.  
  271. This function prints a bitmap to the printer.  The bitmap is scaled according
  272. to the size of the printer.  No distortion is allowed of the bitmap image.
  273.  
  274. Returns False : if an error occurrs
  275.         Trues : no Error occurred
  276.  
  277. Known bug:
  278.  
  279.  
  280.     Areas on the screen that have a black forground and a gray background
  281.     are completely black when printed.  For example, when a window does
  282.     not have the focus it's title bar becomes black lettering on a gray
  283.     background.  When this window is printed the entire title bar is black and
  284.     no title can be read.  This is using the Hewlett Packard LaserJet Series II
  285.     printer.
  286.  
  287.     According to microsoft online help this is a know bug with the
  288.     printer device driver.  To fix the bug you must go to the control
  289.     panel and change the colors of the inactive window.
  290.  
  291. ************************************************************************/
  292.  
  293. SHORT  sBitmapToPrinter(PPRINTTHREADPARAMS pptp,
  294.                     HPS                hpsPrinter,
  295.                     HDC                hdcPrinter,
  296.                     HAB                habPrinter,
  297.                     SIZEL              *psizlPage,
  298.                     SIZEL              *psizlChar)
  299. {
  300.  
  301.     HDC             hdcPrinterMemory;
  302.     HPS             hpsPrinterMemory;
  303.     POINTL          ptl;
  304.     SHORT           sPage = 1;
  305.     RECTL           rcl;            // Coordinates of region
  306.  
  307.     long            lCapsHRes;
  308.     long            lCapsVRes;
  309.     float           fYAspectRatio;
  310.     float           fXAspectRatio;
  311.     SIZEL           sizl;
  312.  
  313.     HBITMAP         hbm;
  314.     POINTL          aptl [4] ;
  315.     SHORT           cxScreen;
  316.     SHORT           cyScreen;
  317.     float           fltScale;
  318.  
  319.     // Skip down top margin, ...
  320.  
  321.     ptl.x = pptp->page.sLeft * psizlChar->cx ;
  322.     ptl.y = psizlPage->cy - (pptp->page.sTop * psizlChar->cy) ;
  323.  
  324.     // Print header, if requested
  325.  
  326.     if (pptp->page.szHeader[0] != '\0')
  327.         {
  328.         PrintHeaderFooter (hpsPrinter, &ptl, pptp,
  329.                            psizlPage, psizlChar,
  330.                            pptp->page.szHeader,
  331.                            sPage, PRINT_HEADER) ;
  332.         }
  333.  
  334.     hbm = pptp->pPrintData;
  335.  
  336.     // Find the aspect ratio of the printer
  337.  
  338.     DevQueryCaps(hdcPrinter,CAPS_HORIZONTAL_RESOLUTION,1L,&lCapsHRes);
  339.     DevQueryCaps(hdcPrinter,CAPS_VERTICAL_RESOLUTION,1L,&lCapsVRes);
  340.  
  341.     if ( (lCapsVRes == 0) || (lCapsHRes == 0) ) {
  342.         fXAspectRatio = (float) 1;
  343.         fYAspectRatio = (float) 1;
  344.     }
  345.     else {
  346.         fXAspectRatio = (float) ((float) lCapsVRes / (float) lCapsHRes);
  347.         fYAspectRatio = (float) ((float) lCapsHRes / (float) lCapsVRes);
  348.     }
  349.  
  350.     // determine coordinates to print on printer
  351.  
  352.     rcl.xLeft =  pptp->page.sLeft * psizlChar->cx; // Printer left
  353.  
  354.     rcl.xRight = psizlPage->cx -
  355.                   (pptp->page.sRight * psizlChar->cx); // Printer right
  356.  
  357.     rcl.yBottom = (pptp->page.sBottom + 1) * psizlChar->cy; // Printer bottom
  358.  
  359.     rcl.yTop =   psizlPage->cy -
  360.                  ( (pptp->page.sTop + 1) * psizlChar->cy);     // Printer top
  361.  
  362.  
  363.     cxScreen = (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN);
  364.     cyScreen = (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN);
  365.  
  366.     ScaleToWindowSize ((SHORT) (rcl.xRight - rcl.xLeft),   // sXtarget
  367.                        (SHORT) (rcl.yTop - rcl.yBottom),   // sYTarget
  368.                        cxScreen,                           // sXSource
  369.                        cyScreen,                           // sYSource
  370.                        &fltScale) ;
  371.  
  372.  
  373.     // Create a memory device context
  374.     // Memory device contexts are used to contain bitmaps
  375.  
  376.     hdcPrinterMemory = DevOpenDC (habPrinter, OD_MEMORY, "*", 0L, NULL, hdcPrinter);
  377.  
  378.     if ( hdcPrinterMemory == DEV_ERROR )
  379.         return FALSE;
  380.  
  381.     sizl.cx = 0;
  382.     sizl.cy = 0;
  383.  
  384.     // Create a presentation space and associate it the memory device context
  385.  
  386.     hpsPrinterMemory = GpiCreatePS (habPrinter, hdcPrinterMemory, &sizl,
  387.                                 PU_PELS    | GPIF_DEFAULT |
  388.                                 GPIT_NORMAL | GPIA_ASSOC);
  389.  
  390.     if( ! hpsPrinterMemory) {
  391.         DevCloseDC (hdcPrinterMemory);
  392.          return FALSE;
  393.     }
  394.  
  395.  
  396.     GpiSetBitmap(hpsPrinterMemory,hbm);
  397.  
  398.  
  399.     aptl [0].x = rcl.xRight - (long) ((float) cxScreen * fltScale);
  400.     aptl [0].y = rcl.yTop - (long) ((float) cyScreen * fltScale * fYAspectRatio);
  401.     aptl [1].x = rcl.xRight;
  402.     aptl [1].y = rcl.yTop;
  403.     aptl [2].x = 0;
  404.     aptl [2].y = 0;
  405.     aptl [3].x = cxScreen;
  406.     aptl [3].y = cyScreen;
  407.  
  408.  
  409.     GpiBitBlt(hpsPrinter,hpsPrinterMemory,4L,aptl,ROP_SRCCOPY,BBO_IGNORE);
  410.  
  411.  
  412.     GpiAssociate   (hpsPrinterMemory, NULL) ;
  413.     GpiDestroyPS   (hpsPrinterMemory);
  414.     DevCloseDC     (hdcPrinterMemory);
  415.  
  416.  
  417.     // If a footer is defined, ...
  418.  
  419.     if (pptp->page.szFooter[0] != '\0')
  420.         {
  421.         // ... compute its position ...
  422.  
  423.         ptl.x = pptp->page.sLeft * psizlChar->cx ;
  424.         ptl.y = pptp->page.sBottom * psizlChar->cy ;
  425.  
  426.         // ... and print it.
  427.  
  428.         PrintHeaderFooter (hpsPrinter, &ptl, pptp,
  429.                            psizlPage, psizlChar,
  430.                            pptp->page.szFooter,
  431.                            sPage, PRINT_FOOTER) ;
  432.         }
  433.  
  434.    return( TRUE);
  435.  
  436. }
  437.