home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / MULTIPAD.PAK / PRINT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  10.6 KB  |  393 lines

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993-1995  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE: print.c
  9. //
  10. //  PURPOSE: Handle the application specific printing commands based on
  11. //    parameters gathered from the common printer dialog box.
  12. //
  13. //  FUNCTIONS:
  14. //    Print - To print a text document based on information from the common
  15. //      print dialog.
  16. //    CalcPageSize - To calculate the number of lines per page & height of a
  17. //      line.
  18. //    PrintPage - To print a single page.
  19. //    GetPageRange - To get the range of pages of a document.
  20. //    AbortProc - Processes messages for the Abort Dialog box.
  21. //    AbortDlg - Processes messages for printer abort dialog box.
  22. //
  23. //
  24. //  COMMENTS:
  25. //
  26. //  SPECIAL INSTRUCTIONS: N/A
  27. //
  28.  
  29.  
  30. #include <windows.h>            // required for all Windows applications
  31. #include "globals.h"            // prototypes specific to this application
  32. #include <string.h>
  33. #include "resource.h"
  34.  
  35.  
  36. BOOL CALLBACK AbortProc(HDC, int);
  37. LRESULT CALLBACK AbortDlg(HWND, UINT, WPARAM, LPARAM);
  38. VOID CalcPageSize(HDC);
  39. VOID PrintPage(HDC, UINT, UINT, UINT, UINT);
  40.  
  41. static HWND hdlgAbort = NULL;   // Abort dialog hanlde
  42. static BOOL fAbort = FALSE;     // Abort Flag
  43. static UINT LineSpace = 0;      // Height of line
  44. static UINT clnPage = 0;        // Number of lines per page
  45.  
  46. //
  47. //  FUNCTION:
  48. //    Print(HWND, HDC, BOOL, BOOL, BOOL, BOOL, UINT, UINT, UINT, HGLOBAL)
  49. //
  50. //  PURPOSE: To print a text document based on information from the
  51. //    common print dialog.
  52. //
  53. //  PARAMETERS:
  54. //    hwnd - The window that the print message came from.
  55. //    hdc - The display context to print to.
  56. //    fPageNums - Print the page range specified by n[From|To]Page.
  57. //    fSelection - Print the current selection.
  58. //    fCollate - Print the pages in a collated order.
  59. //    fFile - Print to a file.
  60. //    nFromPage - First page to print.  (Valid only when fPageNums == TRUE)
  61. //    nToPage - Last page to print.     (Valid only when fPageNums == TRUE)
  62. //    hDevNames -
  63. //
  64. //  RETURN VALUE:
  65. //    None.
  66. //
  67. //  COMMENTS:
  68. //
  69. //
  70.  
  71. #pragma argsused
  72. VOID Print(HWND hwnd,
  73.            HDC  hdc,
  74.            BOOL fPageNums,
  75.            BOOL fSelection,
  76.            BOOL fCollate,
  77.            BOOL fFile,
  78.            UINT nFromPage,
  79.            UINT nToPage,
  80.            UINT nCopies,
  81.            HGLOBAL hDevNames)
  82. {
  83.     HCURSOR hcurSave;
  84.     DOCINFO di;
  85.     UINT    ilnStartSel = 0;
  86.      UINT    cln;
  87.      UINT    ipg;
  88.     UINT    ipgMin;
  89.     UINT    ipgMax;
  90.  
  91.     hcurSave = SetCursor(hcursHourGlass);
  92.  
  93.     // Define the abort function
  94.     SetAbortProc(hdc, (DLGPROC)AbortProc);
  95.  
  96.     // Start the printing session
  97.     di.cbSize = sizeof(DOCINFO);
  98.     di.lpszDocName = "PrntFile text";
  99.     di.lpszOutput = NULL;
  100.     if (StartDoc(hdc, &di) < 0)
  101.     {
  102.           SetCursor(hcurSave);    // Remove the hourglass
  103.         MessageBox(hwnd, 
  104.                    "Unable to start print job", 
  105.                    SZAPPNAME, 
  106.                    MB_OK | MB_ICONHAND);
  107.         DeleteDC(hdc);
  108.         return;
  109.     }
  110.  
  111.     fAbort = FALSE; // Clears the abort flag
  112.  
  113.     // Create the Abort dialog box (modeless)
  114.     hdlgAbort = CreateDialog(hInst, "AbortDlg", hwnd, (DLGPROC)AbortDlg);
  115.  
  116.     if (!hdlgAbort)
  117.      {
  118.         SetCursor(hcurSave);    // Remove the hourglass
  119.         MessageBox(hwnd, 
  120.                    "NULL Abort window handle", 
  121.                    SZAPPNAME, 
  122.                    MB_OK | MB_ICONHAND);
  123.         DeleteDC(hdc);
  124.         return;
  125.     }
  126.  
  127.     // Now show Abort dialog
  128.     ShowWindow (hdlgAbort, SW_NORMAL);
  129.  
  130.     // Disable the main window to avoid reentrancy problems
  131.     EnableWindow(hwnd, FALSE);
  132.      SetCursor(hcurSave);      // Remove the hourglass
  133.  
  134.     CalcPageSize(hdc);
  135.  
  136.     // You can output only one line at a time, so you need a count of the
  137.     //  number of lines to print.  You can retrieve the count sending the
  138.     //  EM_GETLINECOUNT message to the edit control.
  139.  
  140.     // Calculate the first and last page to be printed
  141.  
  142.     if (fPageNums)
  143.     {
  144.         ipgMin = nFromPage - 1;
  145.         ipgMax = nToPage;
  146.         cln = ipgMax * clnPage;
  147.      }
  148.     else if (fSelection)
  149.     {
  150.         UINT ichStart;
  151.         UINT ichEnd;
  152.  
  153.         SendMessage(GetEditWindow(NULL), 
  154.                     EM_GETSEL, 
  155.                     (WPARAM)&ichStart, 
  156.                     (LPARAM)&ichEnd);
  157.  
  158.         ilnStartSel = (UINT) SendMessage(GetEditWindow(NULL), 
  159.                                          EM_LINEFROMCHAR, 
  160.                                          ichStart, 
  161.                                          0L);
  162.           ipgMin = ilnStartSel / clnPage;
  163.         cln = (UINT) SendMessage(GetEditWindow(NULL), 
  164.                                  EM_LINEFROMCHAR, 
  165.                                  ichEnd, 
  166.                                  0L) - ilnStartSel + 1;
  167.         ilnStartSel = ilnStartSel % clnPage;
  168.         ipgMax = ipgMin + cln / clnPage + 1;
  169.     }
  170.     else
  171.     {
  172.         cln = (UINT)SendMessage(GetEditWindow(NULL), EM_GETLINECOUNT, 0, 0L);
  173.         ipgMin = 0;
  174.         ipgMax = cln / clnPage + 1;
  175.     }
  176.  
  177.      do
  178.     {
  179.         for (ipg = ipgMin; ipg < ipgMax && !fAbort; ipg++)
  180.         {
  181.             // If we are printing the entire document, or just a range
  182.             // of pages, ilnStartSel will be zero.  Otherwise, it's
  183.             // the 0 based offset (from the top of the given page) to 
  184.             // the first line to print 
  185.  
  186.             UINT ilnFirst = ilnStartSel;
  187.             UINT ilnLast  = ilnFirst + clnPage - 1;
  188.  
  189.             // Special case last page
  190.             if (ipg == ipgMax-1)
  191.             {
  192.                      ilnLast = ilnFirst + ((cln-1) % clnPage);
  193.             }
  194.  
  195.             PrintPage(hdc, ipg, ilnFirst, ilnLast, fCollate ? 1 : nCopies);
  196.         }
  197.     } while (fCollate && --nCopies > 0);
  198.     EndDoc(hdc);
  199.  
  200.     EnableWindow(hwnd, TRUE);
  201.  
  202.     // Destroy the Abort dialog box
  203.  
  204.     DestroyWindow(hdlgAbort);
  205.     DeleteDC(hdc);
  206. }
  207.  
  208.  
  209. //
  210. //  FUNCTION: CalcPageSize(HDC)
  211. //
  212. //  PURPOSE: To calculate the number of lines per page & height of a line.
  213. //
  214. //  PARAMETERS:
  215. //    hdc - The printer device context used to calculate the sizes.
  216. //
  217. //  RETURN VALUE:
  218. //    NONE
  219. //
  220. //  COMMENTS:
  221. //    Sets the module static variable LineSpace and clnPage to the
  222. //    Height of a line and the number of lines per page, respectively.
  223. //
  224.  
  225. VOID CalcPageSize(HDC hdc)
  226. {
  227.     TEXTMETRIC tm;
  228.     UINT nPageSize;
  229.  
  230.     // Since you may have more than one line, you need to
  231.     //   compute the spacing between lines.  You can do that by
  232.     //   retrieving the height of the characters you are printing
  233.     //   and advancing their height plus the recommended external
  234.     //   leading height.
  235.  
  236.     GetTextMetrics(hdc, &tm);
  237.     LineSpace = tm.tmHeight + tm.tmExternalLeading;
  238.  
  239.     // Since you may have more lines than can fit on one page, you need
  240.     //  to compute the number of lines you can print per page.  You can
  241.     //  do that by retrieving the dimensions of the page and dividing
  242.     //  the height by the line spacing.
  243.  
  244.     nPageSize = GetDeviceCaps(hdc, VERTRES);
  245.     clnPage = nPageSize / LineSpace - 1;
  246. }
  247.  
  248.  
  249. //
  250. //  FUNCTION: PrintPage(HDC, UING, UINJT, UINT, UINT)
  251. //
  252. //  PURPOSE: To print a single page.
  253. //
  254. //  PARAMETERS:
  255. //    hdc - The printer device context to print on.
  256. //    ipg - The zero based index of the page to print.
  257. //    iln - The zero based index of the first line on the page to print.
  258. //    ilnEnd - The zero based index of the last line on the page to print.
  259. //    nCopies - The number of copies to print.
  260. //
  261. //  RETURN VALUE:
  262. //    NONE
  263. //
  264. //  COMMENTS:
  265. //
  266. //
  267.  
  268. VOID PrintPage(HDC hdc, UINT ipg, UINT ilnStart, UINT ilnEnd, UINT nCopies)
  269. {
  270.     UINT ilnBase = ipg * clnPage;
  271.  
  272.     while (nCopies-- > 0)
  273.     {
  274.         UINT iln = 0;
  275.  
  276.         StartPage(hdc);
  277.         while(iln + ilnStart <= ilnEnd)
  278.         {
  279.             char szLine[128];
  280.             int  cchLine;
  281.  
  282.             szLine[0] = sizeof(szLine)-1;          // Maximum buffer size
  283.             szLine[1] = 0;
  284.             cchLine = (int)SendMessage(GetEditWindow(NULL),
  285.                                        EM_GETLINE,
  286.                                        ilnBase + iln + ilnStart,
  287.                                        (DWORD)(LPSTR)szLine);
  288.             TextOut(hdc, 0, iln*LineSpace, (LPSTR)szLine, cchLine);
  289.             iln += 1;
  290.         }
  291.         EndPage(hdc);
  292.     }
  293. }
  294.  
  295.  
  296. //
  297. //  FUNCTION: GetPageRange(VOID);
  298. //
  299. //  PURPOSE: To get the range of pages of a document.
  300. //
  301. //  PARAMETERS:
  302. //
  303. //  RETURN VALUE:
  304. //
  305. //  COMMENTS:
  306. //
  307. //
  308.  
  309. DWORD GetPageRange(VOID)
  310. {
  311.     return (DWORD) MAKELONG(1,0xFFFF);
  312. }
  313.  
  314.  
  315. //
  316. //  FUNCTION: AbortProc(HDC, int)
  317. //
  318. //  PURPOSE: Processes messages for the Abort Dialog box.
  319. //
  320. //  PARAMETERS:
  321. //    hdc - The printer device context used to calculate the sizes.
  322. //    Code -  The error code
  323. //
  324. //  RETURN VALUE:
  325. //    Returns FALSE if the user has aborted, TRUE otherwise.
  326. //
  327. //  COMMENTS:
  328. //
  329. //
  330.  
  331. #pragma argsused
  332. BOOL CALLBACK AbortProc(HDC hdc, int Code)
  333. {
  334.      MSG msg;
  335.  
  336.      if (!hdlgAbort)              // If the abort dialog isn't up yet
  337.         return TRUE;
  338.  
  339.     // Process messages intended for the abort dialog box
  340.  
  341.     while (!fAbort && PeekMessage(&msg, NULL, 0, 0, TRUE))
  342.         if (!IsDialogMessage(hdlgAbort, &msg))
  343.         {
  344.             TranslateMessage(&msg);
  345.             DispatchMessage(&msg);
  346.         }
  347.  
  348.     // fAbort is TRUE (return is FALSE) if the user has aborted
  349.  
  350.     return !fAbort;
  351. }
  352.  
  353. //
  354. //  FUNCTION: AbortDlg(HWND, UINT, WPARAM, LPARAM)
  355. //
  356. //  PURPOSE: Processes messages for printer abort dialog box.
  357. //
  358. //  PARAMETERS:
  359. //    hdlg   - The dialog handle.
  360. //    msg    - The message number.
  361. //    wparam - Message specific data.
  362. //    lparam -  Message specific data.
  363. //
  364. //  RETURN VALUE:
  365. //    Depends on the message number.
  366. //
  367. //  COMMENTS:
  368. //      This dialog box is created while the program is printing, and allows
  369. //      the user to cancel the printing process.
  370. //
  371.  
  372. #pragma argsused
  373. LRESULT CALLBACK AbortDlg(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
  374. {
  375.      switch(msg)
  376.      {
  377.         // Watch for Cancel button, RETURN key, ESCAPE key, or SPACE BAR
  378.  
  379.         case WM_COMMAND:
  380.             return fAbort = TRUE;
  381.  
  382.         case WM_INITDIALOG:
  383.  
  384.             // Set the focus to the Cancel box of the dialog
  385.  
  386.             SetFocus(GetDlgItem(hdlg, IDCANCEL));
  387.             SetDlgItemText(hdlg, IDC_FILENAME, (LPCTSTR)GetFName());
  388.             return TRUE;
  389.     }
  390.  
  391.      return FALSE;
  392. }
  393.