home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / WRITEPAD.PAK / PRINT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  9.2 KB  |  319 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. //    AbortProc - Processes messages for the Abort Dialog box.
  17. //    AbortDlg - Processes messages for printer abort dialog box.
  18. //
  19. //
  20. //  COMMENTS:
  21. //
  22. //  SPECIAL INSTRUCTIONS: N/A
  23. //
  24.  
  25.  
  26. #include <windows.h>            // required for all Windows applications
  27. #include "globals.h"            // prototypes specific to this application
  28. #include "resource.h"
  29. #include <richedit.h>
  30. #include <string.h>
  31.  
  32. #define RECTWIDTH(r)  (r.right - r.left)
  33. #define RECTHEIGHT(r) (r.bottom - r.top)
  34.  
  35. BOOL CALLBACK AbortProc(HDC, int);
  36. LRESULT CALLBACK AbortDlg(HWND, UINT, WPARAM, LPARAM);
  37.  
  38. static HWND hdlgAbort = NULL;   // Abort dialog hanlde
  39. static BOOL fAbort = FALSE;     // Abort Flag
  40.  
  41. //
  42. //  FUNCTION:
  43. //    Print(HWND, HDC, BOOL, BOOL, BOOL, BOOL, UINT, UINT, UINT, HGLOBAL)
  44. //
  45. //  PURPOSE: To print a text document based on information from the
  46. //    common print dialog.
  47. //
  48. //  PARAMETERS:
  49. //    hwnd - The window that the print message came from.
  50. //    hdc - The display context to print to.
  51. //    fPageNums - Print the page range specified by n[From|To]Page.
  52. //    fSelection - Print the current selection.
  53. //    fCollate - Print the pages in a collated order.
  54. //    fFile - Print to a file.
  55. //    nFromPage - First page to print.  (Valid only when fPageNums == TRUE)
  56. //    nToPage - Last page to print.     (Valid only when fPageNums == TRUE)
  57. //    hDevNames -
  58. //
  59. //  RETURN VALUE:
  60. //    None.
  61. //
  62. //  COMMENTS:
  63. //
  64. //
  65.  
  66. #pragma argsused
  67. VOID Print(HWND hwnd,
  68.            HDC  hdc,
  69.            BOOL fPageNums,
  70.            BOOL fSelection,
  71.            BOOL fCollate,
  72.            BOOL fFile,
  73.            UINT nFromPage,
  74.            UINT nToPage,
  75.            UINT nCopies,
  76.            HGLOBAL hDevNames)
  77. {
  78.     HCURSOR hcurSave;
  79.     DOCINFO di;
  80.     UINT ipg, i, j, nCollateCopies;
  81.     LONG lTextLength;
  82.     FORMATRANGE fr;
  83.     TCHAR szTitle[MAX_PATH];
  84.     LPTSTR szName;
  85.     RECT rcTmp;
  86.  
  87.     hcurSave = SetCursor(hcursHourGlass);
  88.  
  89.     // Clear the abort flag before setting abort proc or calling StartDoc
  90.     fAbort = FALSE;
  91.  
  92.     // Define the abort function
  93.     SetAbortProc(hdc, AbortProc);
  94.  
  95.     // Start the printing session
  96.     ZeroMemory(&di, sizeof(DOCINFO));
  97.     di.cbSize = sizeof(DOCINFO);
  98.     szName = GetFName();
  99.     if (0 == GetFileTitle(szName, szTitle, sizeof(szTitle)/sizeof(TCHAR)))
  100.         di.lpszDocName = szTitle;
  101.     else
  102.         di.lpszDocName = szName;
  103.     di.lpszOutput = (fFile ? TEXT("FILE:") : NULL);
  104.  
  105.     if (StartDoc(hdc, &di) < 0)
  106.     {
  107.         DWORD dwErr = GetLastError();
  108.         char szErr[128];
  109.         wsprintf(szErr, "Unable to start print job- Error %ld, hdc = %ld", dwErr, (DWORD)hdc);
  110.         SetCursor(hcurSave);    // Remove the hourglass
  111.         MessageBox(hwnd, 
  112.                    szErr, 
  113.                    szAppName, 
  114.                    MB_OK | MB_ICONHAND);
  115.         DeleteDC(hdc);
  116.         return;
  117.     }
  118.  
  119.     // Create the Abort dialog box (modeless)
  120.     hdlgAbort = CreateDialog(hInst, "AbortDlg", hwnd, (DLGPROC)AbortDlg);
  121.  
  122.     if (!hdlgAbort)
  123.     {
  124.         SetCursor(hcurSave);    // Remove the hourglass
  125.         MessageBox(hwnd, 
  126.                    "NULL Abort window handle", 
  127.                    szAppName, 
  128.                    MB_OK | MB_ICONHAND);
  129.         DeleteDC(hdc);
  130.         return;
  131.     }
  132.  
  133.     // Now show Abort dialog
  134.     ShowWindow(hdlgAbort, SW_NORMAL);
  135.     UpdateWindow(hdlgAbort);
  136.  
  137.     // Disable the main window to avoid reentrancy problems
  138.     EnableWindow(hwnd, FALSE);
  139.     SetCursor(hcurSave);      // Remove the hourglass
  140.  
  141.     // Find out real size of document in characters
  142.     lTextLength = SendMessage(GetEditWindow(NULL), WM_GETTEXTLENGTH, 0, 0);
  143.  
  144.     // Rendering to the same DC we are measuring
  145.     fr.hdc = hdc;
  146.     fr.hdcTarget = hdc;
  147.  
  148.     // Set page rect to phys page size in twips
  149.     fr.rcPage.left   = 0;
  150.     fr.rcPage.top    = 0;
  151.     fr.rcPage.right  = MulDiv(GetDeviceCaps(hdc, PHYSICALWIDTH),
  152.                               1440,
  153.                               GetDeviceCaps(hdc, LOGPIXELSX));
  154.     fr.rcPage.bottom = MulDiv(GetDeviceCaps(hdc, PHYSICALHEIGHT),
  155.                               1440,
  156.                               GetDeviceCaps(hdc, LOGPIXELSY));
  157.  
  158.     // Set up 3/4" horizontal and 1" vertical margins, but leave a minimum of 1"
  159.     // printable space in each direction.  Otherwise, use full page.
  160.     fr.rc = fr.rcPage; // start with full page
  161.     if (fr.rcPage.right > 2*3*1440/4 + 1440)
  162.         fr.rc.right -= (fr.rc.left = 3*1440/4);
  163.     if (fr.rcPage.bottom > 3*1440)
  164.         fr.rc.bottom -= (fr.rc.top = 1440);
  165.  
  166.     rcTmp = fr.rc;  // save for later
  167.  
  168.     if (fCollate)
  169.     {
  170.         nCollateCopies = nCopies;
  171.         nCopies = 1;
  172.     }
  173.     else
  174.         nCollateCopies = 1;
  175.  
  176.     for (i = 0; i < nCollateCopies && !fAbort; i++)
  177.     {
  178.         ipg = 1; // First page
  179.  
  180.         // Set range for the entire document (default)
  181.         fr.chrg.cpMin = 0;
  182.         fr.chrg.cpMax = lTextLength;
  183.        
  184.         // Are we only printing the current selection?
  185.         if (fSelection)
  186.         {
  187.             SendMessage(GetEditWindow(NULL), EM_EXGETSEL, 0, (LPARAM)&fr.chrg);
  188.             if (fr.chrg.cpMax >= fr.chrg.cpMin)
  189.                 lTextLength = fr.chrg.cpMax;    // don't go past this character
  190.         }
  191.        
  192.         do
  193.         {
  194.             // Format as much as will fit on a page. The return value
  195.             // is the index of the first character on the next page.
  196.             fr.chrg.cpMin = SendMessage(GetEditWindow(NULL), 
  197.                                         EM_FORMATRANGE, 
  198.                                         FALSE,      // FALSE ==> format only (don't print)
  199.                                         (LPARAM)&fr);
  200.        
  201.             // Print the page if supposed to
  202.             if (!(fPageNums && ipg < nFromPage))
  203.             {
  204.                 for (j = 0; j < nCopies && !fAbort; j++)
  205.                 {
  206.                     StartPage(hdc);
  207.                     SendMessage(GetEditWindow(NULL), 
  208.                                 EM_DISPLAYBAND, 
  209.                                 0,
  210.                                 (LPARAM)&fr.rc);
  211.                     EndPage(hdc);
  212.                 }
  213.             }
  214.        
  215.             fr.rc = rcTmp;  // EM_FORMATRANGE tends to modify fr.rc.bottom, reset here
  216.        
  217.             ipg++;          // next page
  218.        
  219.             // Are we done?
  220.             if (fPageNums && ipg > nToPage)
  221.                 break;
  222.         }
  223.         while (fr.chrg.cpMin < lTextLength && !fAbort);
  224.  
  225.     }   // collate loop
  226.  
  227.     // Restore the RTF Edit control to its original, upright position
  228.     SendMessage(GetEditWindow(NULL), EM_FORMATRANGE, TRUE, (LPARAM)NULL);
  229.  
  230.     if (!fAbort)
  231.         EndDoc(hdc);
  232.  
  233.     // Clean up
  234.  
  235.     EnableWindow(hwnd, TRUE);
  236.     DestroyWindow(hdlgAbort);
  237.     DeleteDC(hdc);
  238. }
  239.  
  240. //
  241. //  FUNCTION: AbortProc(HDC, int)
  242. //
  243. //  PURPOSE: Processes messages for the Abort Dialog box.
  244. //
  245. //  PARAMETERS:
  246. //    hdc - The printer device context used to calculate the sizes.
  247. //    Code -  The error code
  248. //
  249. //  RETURN VALUE:
  250. //    Returns FALSE if the user has aborted, TRUE otherwise.
  251. //
  252. //  COMMENTS:
  253. //
  254. //
  255.  
  256. #pragma argsused
  257. BOOL CALLBACK AbortProc(HDC hdc, int Code)
  258. {
  259.      MSG msg;
  260.  
  261.     if (!hdlgAbort)              // If the abort dialog isn't up yet
  262.         return TRUE;
  263.  
  264.     // Process messages intended for the abort dialog box
  265.  
  266.     while (!fAbort && PeekMessage(&msg, NULL, 0, 0, TRUE))
  267.         if (!IsDialogMessage(hdlgAbort, &msg))
  268.         {
  269.             TranslateMessage(&msg);
  270.             DispatchMessage(&msg);
  271.         }
  272.  
  273.     // fAbort is TRUE (return is FALSE) if the user has aborted
  274.  
  275.      return !fAbort;
  276. }
  277.  
  278. //
  279. //  FUNCTION: AbortDlg(HWND, UINT, WPARAM, LPARAM)
  280. //
  281. //  PURPOSE: Processes messages for printer abort dialog box.
  282. //
  283. //  PARAMETERS:
  284. //    hdlg   - The dialog handle.
  285. //    msg    - The message number.
  286. //    wparam - Message specific data.
  287. //    lparam -  Message specific data.
  288. //
  289. //  RETURN VALUE:
  290. //    Depends on the message number.
  291. //
  292. //  COMMENTS:
  293. //      This dialog box is created while the program is printing, and allows
  294. //      the user to cancel the printing process.
  295. //
  296.  
  297. #pragma argsused
  298. LRESULT CALLBACK AbortDlg(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
  299. {
  300.      switch(msg)
  301.     {
  302.         // Watch for Cancel button, RETURN key, ESCAPE key, or SPACE BAR
  303.  
  304.         case WM_COMMAND:
  305.             return fAbort = TRUE;
  306.  
  307.         case WM_INITDIALOG:
  308.  
  309.             // Set the focus to the Cancel box of the dialog
  310.  
  311.             SetFocus(GetDlgItem(hdlg, IDCANCEL));
  312.             SetDlgItemText(hdlg, IDC_FILENAME, (LPCTSTR)GetFName());
  313.             return TRUE;
  314.     }
  315.  
  316.     return FALSE;
  317. }
  318.  
  319.