DXPRINT.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:22k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2. **-----------------------------------------------------------------------------
  3. ** Name:    dxprint.c
  4. ** Purpose: print's DX Tree View info to selected printer
  5. ** Notes:
  6. **-----------------------------------------------------------------------------
  7. */
  8. /*
  9. **-----------------------------------------------------------------------------
  10. ** Includes
  11. **-----------------------------------------------------------------------------
  12. */
  13. #include <windows.h>
  14. #include <windowsx.h>
  15. #include <mmsystem.h>
  16. #include <commctrl.h>
  17. #include <commdlg.h>        // Common Print Dialog
  18. #include <tchar.h>          // Unicode string functions and types
  19. #include <ddraw.h>
  20. #include <dsound.h>
  21. #include <dplay.h>
  22. #include <d3d.h>
  23. #include "dxview.h"
  24. /*
  25. **-----------------------------------------------------------------------------
  26. ** Local Variables
  27. **-----------------------------------------------------------------------------
  28. */
  29. BOOL g_fAbortPrint      = FALSE;       // Did User Abort Print operation ?!?
  30. HWND g_hAbortPrintDlg   = NULL;        // Print Abort Dialog handle
  31. BOOL g_PrintToFile      = FALSE;       // Don't print to printer print to dxview.log
  32. HANDLE g_FileHandle     = NULL;        // Handle to log file
  33.                                         
  34. /*
  35. **-----------------------------------------------------------------------------
  36. ** Local Prototypes
  37. **-----------------------------------------------------------------------------
  38. */
  39. BOOL CALLBACK PrintTreeStats(
  40.     HINSTANCE   hInstance,
  41.     HWND        hWindow,
  42.     HWND        hTreeWnd,
  43.     HTREEITEM   hRoot);
  44. void DoMessage (DWORD dwTitle, DWORD dwMsg);
  45. /*
  46. **-----------------------------------------------------------------------------
  47. ** Functions
  48. **-----------------------------------------------------------------------------
  49. */
  50. /*
  51. **-----------------------------------------------------------------------------
  52. ** Name:    DXView_OnPrint
  53. ** Purpose: Print user defined stuff
  54. **-----------------------------------------------------------------------------
  55. */
  56. BOOL DXView_OnPrint (
  57.     HWND hWindow, 
  58.     HWND hTreeWnd,
  59.     BOOL fPrintAll)
  60. {
  61.     HINSTANCE hInstance;
  62.     HTREEITEM hRoot;
  63.     // Check Parameters
  64.     if ((! hWindow) || (! hTreeWnd))
  65.     {
  66.         // Invalid parameters
  67.         return FALSE;
  68.     }
  69.     // Get hInstance
  70.     hInstance = (HINSTANCE)GetWindowLong (hWindow, GWL_HINSTANCE);
  71.     if (! hInstance)
  72.         return FALSE;
  73.     if (fPrintAll)
  74.     {
  75.         hRoot = NULL;
  76.     }
  77.     else
  78.     {
  79.         hRoot = TreeView_GetSelection (hTreeWnd);
  80.         if (! hRoot)
  81.         {
  82.             DoMessage (IDS_PRINT_WARNING, IDS_PRINT_NEEDSELECT);
  83.         }
  84.     }
  85.     g_PrintToFile = FALSE;
  86.     // Do actual printing
  87.     return PrintTreeStats (hInstance, hWindow, hTreeWnd, hRoot);
  88. } // End DXView_OnPrint
  89. BOOL DXView_OnFile (
  90.     HWND hWindow, 
  91.     HWND hTreeWnd,
  92.     BOOL fPrintAll)
  93. {
  94.     HINSTANCE hInstance;
  95.     HTREEITEM hRoot;
  96.     // Check Parameters
  97.     if ((! hWindow) || (! hTreeWnd))
  98.     {
  99.         // Invalid parameters
  100.         return FALSE;
  101.     }
  102.     // Get hInstance
  103.     hInstance = (HINSTANCE)GetWindowLong (hWindow, GWL_HINSTANCE);
  104.     if (! hInstance)
  105.         return FALSE;
  106.     if (fPrintAll)
  107.     {
  108.         hRoot = NULL;
  109.     }
  110.     else
  111.     {
  112.         hRoot = TreeView_GetSelection (hTreeWnd);
  113.         if (! hRoot)
  114.         {
  115.             DoMessage (IDS_PRINT_WARNING, IDS_PRINT_NEEDSELECT);
  116.         }
  117.     }
  118.     g_PrintToFile = TRUE;
  119.     // Do actual printing
  120.     return PrintTreeStats (hInstance, hWindow, hTreeWnd, hRoot);
  121. } // End DXView_OnPrint
  122. /*
  123. **-----------------------------------------------------------------------------
  124. ** Name:    PrintDialogProc
  125. ** Purpose: Dialog procedure for printing
  126. **-----------------------------------------------------------------------------
  127. */
  128. BOOL CALLBACK PrintDialogProc (
  129.     HWND    hDialog,
  130.     UINT    uiMsg,
  131.     WPARAM  wParam,
  132.     LPARAM  lParam)
  133. {
  134.     switch (uiMsg)
  135.     {
  136.     case WM_INITDIALOG:
  137.         {
  138.         // Disable system menu on dialog
  139.         HMENU hSysMenu = GetSystemMenu (hDialog, FALSE);
  140.         EnableMenuItem (hSysMenu, SC_CLOSE, MF_GRAYED);
  141.         }
  142.         return TRUE;
  143.     case WM_COMMAND:
  144.         {
  145.         // User is aborting print operation
  146.         g_fAbortPrint = TRUE;
  147.         EnableWindow (GetParent (hDialog), TRUE);
  148.         DestroyWindow (hDialog);
  149.         g_hAbortPrintDlg = NULL;
  150.         }
  151.         return TRUE;
  152.     } // End switch
  153.     return FALSE;
  154. } // End PrintDialogProc
  155. /*
  156. **-----------------------------------------------------------------------------
  157. ** Name:    AbortProc
  158. ** Purpose: Abort procedure for printing
  159. **-----------------------------------------------------------------------------
  160. */
  161. BOOL CALLBACK AbortProc (HDC hPrinterDC, int iCode)
  162. {
  163.     MSG msg;
  164.     while (! g_fAbortPrint && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
  165.     {
  166.         if ((! g_hAbortPrintDlg) || ! IsDialogMessage (g_hAbortPrintDlg, &msg))
  167.         {
  168.             TranslateMessage (&msg);
  169.             DispatchMessage (&msg);
  170.         }
  171.     }
  172.     return !g_fAbortPrint;
  173. } // End AbortProc
  174. /*
  175. **-----------------------------------------------------------------------------
  176. ** Name:    PrintStats
  177. ** Purpose: Print user defined stuff
  178. **-----------------------------------------------------------------------------
  179. */
  180. BOOL CALLBACK PrintTreeStats(
  181.     HINSTANCE   hInstance,
  182.     HWND        hWindow,
  183.     HWND        hTreeWnd,
  184.     HTREEITEM   hRoot)
  185. {
  186.     static DOCINFO  di;
  187.     static PRINTDLG pd;
  188.     BOOL        fDone           = FALSE;
  189.     BOOL        fFindNext       = FALSE;
  190.     BOOL        fResult         = FALSE;
  191.     BOOL        fStartDoc       = FALSE;
  192.     BOOL        fDisableWindow  = FALSE;
  193.     LPTSTR      pstrTitle       = NULL;
  194.     LPTSTR      pstrBuff        = NULL;
  195.     TEXTMETRIC  tm;
  196.     DWORD       dwCurrCopy;
  197.     HANDLE      hHeap;
  198.     DWORD       cbSize;
  199.     DWORD       cchLen;
  200.     TV_ITEM     tvi;
  201.     HTREEITEM   hStartTree, hTempTree;
  202.     PRINTCBINFO pci;
  203.     // Check Parameters
  204.     if ((! hInstance) || (! hWindow) || (! hTreeWnd))
  205.     {
  206.         // Error, invalid parameters
  207.         return FALSE;
  208.     }
  209.     // Get Starting point for tree
  210.     if (hRoot)
  211.         hStartTree = hRoot;
  212.     else
  213.         hStartTree = TreeView_GetRoot (hTreeWnd);
  214.     if (! hStartTree)
  215.     {
  216.         // Error, invalid tree
  217.         return FALSE;
  218.     }
  219.     
  220.     // Initialize Print Dialog structure
  221.     pd.lStructSize          = sizeof (PRINTDLG);
  222.     pd.hwndOwner            = hWindow;
  223.     pd.hDevMode             = NULL;
  224.     pd.hDevNames            = NULL;
  225.     pd.hDC                  = NULL;
  226.     pd.Flags                = PD_ALLPAGES | PD_RETURNDC;
  227.     pd.nFromPage            = 0;
  228.     pd.nToPage              = 0;
  229.     pd.nMinPage             = 0;
  230.     pd.nMaxPage             = 0;
  231.     pd.nCopies              = 1;
  232.     pd.hInstance            = NULL;
  233.     pd.lCustData            = 0L;
  234.     pd.lpfnPrintHook        = NULL;
  235.     pd.lpfnSetupHook        = NULL;
  236.     pd.lpPrintTemplateName  = NULL;
  237.     pd.lpSetupTemplateName  = NULL;
  238.     pd.hPrintTemplate       = NULL;
  239.     pd.hSetupTemplate       = NULL;
  240.     if(g_PrintToFile)
  241.     {
  242.         pci.hdcPrint = NULL;
  243.     }else
  244.     {
  245.         // Call Common Print Dialog to get printer DC
  246.         if ((! PrintDlg (&pd)) || (! pd.hDC))
  247.         {
  248.             // Error, Print Dialog failed or user canceled
  249.             return TRUE;
  250.         }
  251.         pci.hdcPrint = pd.hDC;
  252.         // Get Text metrics for printing
  253.         if (! GetTextMetrics (pci.hdcPrint, &tm))
  254.         {
  255.             // Error, TextMetrics failed
  256.             goto lblCLEANUP;
  257.         }
  258.     }
  259.     if(g_PrintToFile)
  260.     {
  261.         pci.dwLineHeight   = 1;
  262.         pci.dwCharWidth    = 1;
  263.         pci.dwCharsPerLine = 80;
  264.         pci.dwLinesPerPage = 66;
  265.     }else
  266.     {
  267.         pci.dwLineHeight   = tm.tmHeight + tm.tmExternalLeading;
  268.         pci.dwCharWidth    = tm.tmAveCharWidth;
  269.         pci.dwCharsPerLine = GetDeviceCaps (pci.hdcPrint, HORZRES) / pci.dwCharWidth;
  270.         pci.dwLinesPerPage = GetDeviceCaps (pci.hdcPrint, VERTRES) / pci.dwLineHeight;
  271.     }
  272.  
  273.     // Get Heap
  274.     hHeap = GetProcessHeap ();
  275.     if (! hHeap)
  276.     {
  277.         // Error, no heap associated with this process
  278.         goto lblCLEANUP;
  279.     }
  280.     // Create line buffer
  281.     cbSize = (pci.dwCharsPerLine + 1) * sizeof(TCHAR);
  282.     pstrBuff = (LPTSTR) HeapAlloc (hHeap, HEAP_NO_SERIALIZE, cbSize);
  283.     if (! pstrBuff)
  284.     {
  285.         // Error, not enough memory 
  286.         goto lblCLEANUP;
  287.     }
  288.     // Disable Parent window
  289.     EnableWindow (hWindow, FALSE);
  290.     fDisableWindow = TRUE;
  291.     // Start Printer Abort Dialog
  292.     g_fAbortPrint = FALSE;
  293.     g_hAbortPrintDlg = CreateDialog (hInstance, MAKEINTRESOURCE (IDD_ABORTPRINTDLG),
  294.                                      hWindow, (DLGPROC)PrintDialogProc);
  295.     if (! g_hAbortPrintDlg)
  296.     {
  297.         // Error, unable to create abort dialog
  298.         goto lblCLEANUP;
  299.     }
  300.     //
  301.     // Set Document title to Root string
  302.     //
  303.     tvi.mask            = TVIF_CHILDREN | TVIF_TEXT;
  304.     tvi.hItem           = hStartTree;
  305.     tvi.pszText         = pstrBuff;
  306.     tvi.cchTextMax      = pci.dwCharsPerLine;
  307.     if (TreeView_GetItem (hTreeWnd, &tvi))
  308.     {
  309.         SetWindowText (g_hAbortPrintDlg, pstrBuff);
  310.         SetAbortProc (pd.hDC, AbortProc);
  311.         cchLen = _tcsclen (pstrBuff);
  312.         cbSize = (cchLen + 1) * sizeof(TCHAR);
  313.         pstrTitle = (LPTSTR) HeapAlloc (hHeap, HEAP_NO_SERIALIZE, cbSize);
  314.         if (! pstrTitle)
  315.         {
  316.             // Error, not enough memory 
  317.             goto lblCLEANUP;
  318.         }
  319.         _tcsncpy (pstrTitle, pstrBuff, cchLen);
  320.         pstrTitle[cchLen] = 0;
  321.     }
  322.     else
  323.     {
  324.         SetWindowText (g_hAbortPrintDlg, TEXT("Unknown"));
  325.         SetAbortProc (pd.hDC, AbortProc);
  326.         cchLen = _tcsclen (TEXT("Unknown"));
  327.         cbSize = (cchLen + 1) * sizeof(TCHAR);
  328.         pstrTitle = (LPTSTR) HeapAlloc (hHeap, HEAP_NO_SERIALIZE, cbSize);
  329.         if (! pstrTitle)
  330.         {
  331.             // Error, not enough memory 
  332.             goto lblCLEANUP;
  333.         }
  334.         _tcsncpy (pstrTitle, TEXT("Unknown"), cchLen);
  335.         pstrTitle[cchLen] = 0;
  336.     }
  337.     // Initialize Document Structure
  338.     di.cbSize       = sizeof(DOCINFO);
  339.     di.lpszDocName  = pstrTitle; 
  340.     di.lpszOutput   = NULL; 
  341.     di.lpszDatatype = NULL;
  342.     di.fwType       = 0;
  343.     // Start document
  344.     if(g_PrintToFile)
  345.     {
  346.         g_FileHandle = CreateFile("dxview.log",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  347.     } else
  348.     if (StartDoc (pd.hDC, &di) < 0)
  349.     {
  350.         // Error, StartDoc failed
  351.         goto lblCLEANUP;
  352.     }
  353.     fStartDoc = TRUE;
  354.     // Print requested number of copies
  355.     fResult = FALSE;
  356.     for (dwCurrCopy = 0; dwCurrCopy < (DWORD)pd.nCopies; dwCurrCopy++)
  357.     {
  358.         pci.hCurrTree       = hStartTree;
  359.         pci.fStartPage      = TRUE;
  360.         pci.dwCurrIndent    = 0;
  361.         // Note:  We are basically doing an pre-order traversal
  362.         //        of the Tree.  Printing the current node
  363.         //        before moving on to it's children or siblings
  364.         fDone               = FALSE;
  365.         while (! fDone)
  366.         {
  367.             // Check if we need to start a new page
  368.             if (! PrintStartPage (&pci))
  369.             {
  370.                 goto lblCLEANUP;
  371.             }
  372.             //
  373.             // Get Current Item in Tree 
  374.             // and print it's text info and associated Node caps
  375.             //
  376.             tvi.mask            = TVIF_CHILDREN | TVIF_TEXT | TVIF_PARAM;
  377.             tvi.hItem           = pci.hCurrTree;
  378.             tvi.pszText         = pstrBuff;
  379.             tvi.lParam          = 0;
  380.             tvi.cchTextMax      = pci.dwCharsPerLine;
  381.             if (TreeView_GetItem (hTreeWnd, &tvi))
  382.             {
  383.                 cchLen = _tcslen (pstrBuff);
  384.                 if (cchLen > 0)
  385.                 {
  386.                     int xOffset = (int)(pci.dwCurrIndent * DEF_TAB_SIZE * pci.dwCharWidth);
  387.                     int yOffset = (int)(pci.dwLineHeight * pci.dwCurrLine);
  388.                     // Print this line
  389.                     if (! PrintLine (xOffset, yOffset, pstrBuff, cchLen, &pci))
  390.                     {
  391.                         goto lblCLEANUP;
  392.                     }
  393.     
  394.                     // Advance to next line in page
  395.                     if (! PrintNextLine (&pci))
  396.                     {
  397.                         goto lblCLEANUP;
  398.                     }
  399.                     // Check if there is any additional node info 
  400.                     // that needs to be printed
  401.                     if (tvi.lParam != 0)
  402.                     {
  403.                         NODEINFO * pni = (NODEINFO*)tvi.lParam;
  404.                     
  405.                         if (pni && pni->printCallback)
  406.                         {                            
  407.                             // Force indent to offset node info from tree info
  408.                             pci.dwCurrIndent += 2;
  409.                             if (! pni->printCallback(pni->lParam1, pni->lParam2, &pci))
  410.                             {
  411.                                 // Error, callback failed
  412.                                 goto lblCLEANUP;
  413.                             }
  414.                             // Recover indent
  415.                             pci.dwCurrIndent -= 2;
  416.                         }
  417.                     }
  418.                 }
  419.             } // End if TreeView_GetItem()
  420.             
  421.             
  422.             // 
  423.             // Get Next Item in tree
  424.             //
  425.             // Get first child, if any
  426.             if (tvi.cChildren)
  427.             {
  428.                 // Get First child
  429.                 hTempTree = TreeView_GetChild (hTreeWnd, pci.hCurrTree);
  430.                 if (hTempTree)
  431.                 {
  432.                     // Increase Indentation
  433.                     pci.dwCurrIndent++;
  434.                     pci.hCurrTree = hTempTree;
  435.                     continue;
  436.                 }
  437.             }
  438.             
  439.             // Exit, if we are the root
  440.             if (pci.hCurrTree == hRoot)
  441.             {
  442.                 // We have reached the root, so stop
  443.                 PrintEndPage (&pci);
  444.                 fDone = TRUE;
  445.                 continue;
  446.             }
  447.             // Get next sibling in the chain
  448.             hTempTree = TreeView_GetNextSibling (hTreeWnd, pci.hCurrTree);
  449.             if (hTempTree)
  450.             {
  451.                 pci.hCurrTree = hTempTree;
  452.                 continue;
  453.             }
  454.             // Get next Ancestor yet to be processed
  455.             // (uncle, granduncle, etc)
  456.             fFindNext = FALSE;
  457.             while (! fFindNext)
  458.             {
  459.                 hTempTree = TreeView_GetParent (hTreeWnd, pci.hCurrTree);
  460.                 if ((! hTempTree) || (hTempTree == hRoot))
  461.                 {
  462.                     // We have reached the root, so stop
  463.                     PrintEndPage (&pci);
  464.                     fDone       = TRUE;
  465.                     fFindNext   = TRUE;
  466.                 }
  467.                 else
  468.                 {
  469.                     // Move up to the parent
  470.                     pci.hCurrTree = hTempTree;
  471.                     // Decrease Indentation
  472.                     pci.dwCurrIndent--;
  473.                     // Since we have already processed the parent 
  474.                     // we want to get the uncle/aunt node
  475.                     hTempTree = TreeView_GetNextSibling (hTreeWnd, pci.hCurrTree);
  476.                     if (hTempTree)
  477.                     {
  478.                         // Found a non-processed node
  479.                         pci.hCurrTree = hTempTree;
  480.                         fFindNext = TRUE;
  481.                     }
  482.                 }
  483.             }
  484.         } // End While (! fDone)
  485.     } // End for num copies
  486.     // Success
  487.     fResult = TRUE;
  488. lblCLEANUP:    
  489.     // End Document
  490.     if (fStartDoc)
  491.     {
  492.         if(g_PrintToFile)
  493.         {
  494.             CloseHandle(g_FileHandle);
  495.         } else
  496.         EndDoc (pd.hDC);
  497.         fStartDoc = FALSE;
  498.     }
  499.     // Re-enable main window
  500.     // Note:  Do this before destroying abort dialog
  501.     //        otherwise the main window loses focus
  502.     if (fDisableWindow)
  503.     {
  504.         EnableWindow (hWindow, TRUE);
  505.         fDisableWindow = FALSE;
  506.     }
  507.     // Destroy Abort Dialog
  508.     if (g_hAbortPrintDlg)
  509.     {
  510.         DestroyWindow (g_hAbortPrintDlg);
  511.         g_hAbortPrintDlg = NULL;
  512.     }
  513.     // Free title memory
  514.     if (pstrTitle)
  515.     {
  516.         HeapFree (hHeap, 0, (LPVOID)pstrTitle);
  517.         pstrTitle       = NULL;
  518.         di.lpszDocName  = NULL; 
  519.     }
  520.     // Free buffer memory
  521.     if (pstrBuff)
  522.     {
  523.         HeapFree (hHeap, 0, (LPVOID)pstrBuff);
  524.         pstrBuff = NULL;
  525.     }
  526.     // Cleanup printer DC
  527.     if (pd.hDC)
  528.     {
  529.         DeleteDC (pd.hDC);
  530.         pd.hDC = NULL;
  531.     }
  532.     // Return success/failure
  533.     return fResult;
  534. } // End PrintTreeStats
  535. /*
  536. **-----------------------------------------------------------------------------
  537. ** Name:    PrintStartPage
  538. ** Purpose: check if we need to start a new page
  539. **-----------------------------------------------------------------------------
  540. */
  541. BOOL PrintStartPage (PRINTCBINFO * pci)
  542. {
  543.     if(g_PrintToFile)
  544.         return TRUE;
  545.     if (! pci)
  546.         return FALSE;
  547.     // Check if we need to start a new page
  548.     if (pci->fStartPage)
  549.     {
  550.         // Check for user abort
  551.         if (g_fAbortPrint)
  552.         {
  553.             // Error, user canceled printing job
  554.             return FALSE;
  555.         } 
  556.         // Start new page
  557.         if (StartPage (pci->hdcPrint) < 0)
  558.         {
  559.             // Error, StartPage failed
  560.             return FALSE;
  561.         }
  562.         // Reset line count
  563.         pci->fStartPage = FALSE;
  564.         pci->dwCurrLine = 0;
  565.     }
  566.     // Success
  567.     return TRUE;
  568. } // End PrintStartPage
  569.   
  570. /*
  571. **-----------------------------------------------------------------------------
  572. ** Name:    PrintEndPage
  573. ** Purpose: check if we need to start a new page
  574. **-----------------------------------------------------------------------------
  575. */
  576. BOOL PrintEndPage (PRINTCBINFO * pci)
  577. {
  578.     if(g_PrintToFile)
  579.         return TRUE;
  580.     if (! pci)
  581.         return FALSE;
  582.     // Check if we need to end this page
  583.     if (! pci->fStartPage)
  584.     {
  585.         // End page
  586.         if (EndPage (pci->hdcPrint) < 0)
  587.         {
  588.             // Error, end page failed
  589.             return FALSE;
  590.         }
  591.         pci->fStartPage = TRUE;
  592.         // Check for user abort
  593.         if (g_fAbortPrint)
  594.         {
  595.             // Error, user canceled printing job
  596.             return FALSE;
  597.         } 
  598.     }
  599.     // Success
  600.     return TRUE;
  601. } // End PrintEndPage
  602.   
  603. /*
  604. **-----------------------------------------------------------------------------
  605. ** Name:    PrintLine
  606. ** Purpose: Prints text to page at specified location
  607. **-----------------------------------------------------------------------------
  608. */
  609. static DWORD iLastXPos;
  610. BOOL PrintLine (
  611.     int xOffset,
  612.     int yOffset,
  613.     LPCTSTR pszBuff,
  614.     DWORD  cchBuff,
  615.     PRINTCBINFO * pci)
  616. {
  617.     if (! pci)
  618.     {
  619.         // Programming error
  620.         return FALSE;
  621.     }
  622.     // Check if we need to start a new page
  623.     if (! PrintStartPage (pci))
  624.         return FALSE;
  625.     if ((! pszBuff) || (! cchBuff))
  626.     {
  627.         // Nothing to print
  628.         // assume it's OK and just keep printing
  629.         return TRUE;
  630.     }
  631.     // Print text out to buffer current line
  632.     if(g_PrintToFile)
  633.     {
  634.         DWORD Foobar;
  635.         TCHAR Temp[80];
  636.         if(((xOffset-iLastXPos)/pci->dwCharWidth)>80)
  637.             return TRUE;
  638.         memset(Temp,' ',sizeof(TCHAR)*79);
  639.         Temp[(xOffset-iLastXPos)/pci->dwCharWidth]=0;
  640.         WriteFile(g_FileHandle,Temp,(xOffset-iLastXPos)/pci->dwCharWidth,&Foobar,NULL);
  641.         iLastXPos = (xOffset-iLastXPos)+(pci->dwCharWidth * cchBuff);
  642.             
  643.         WriteFile(g_FileHandle,pszBuff,cchBuff,&Foobar,NULL);
  644.     }else
  645.     {
  646.         TextOut (pci->hdcPrint, xOffset, yOffset, pszBuff, cchBuff);
  647.     };
  648.     return TRUE;
  649. } // End PrintLine
  650.     
  651. /*
  652. **-----------------------------------------------------------------------------
  653. ** Name:    PrintNextLine
  654. ** Purpose: advance to next line on page
  655. **-----------------------------------------------------------------------------
  656. */
  657. BOOL PrintNextLine (PRINTCBINFO * pci)
  658. {
  659.     if(g_PrintToFile)
  660.     {
  661.         DWORD Foobar;
  662.         WriteFile(g_FileHandle,"rn",2,&Foobar,NULL);
  663.         iLastXPos = 0;
  664.         return TRUE;
  665.     };
  666.     if (! pci)
  667.         return FALSE;
  668.     pci->dwCurrLine++;
  669.     // Check if we need to end the page
  670.     if (pci->dwCurrLine >= pci->dwLinesPerPage)
  671.     {
  672.         return PrintEndPage (pci);
  673.     }
  674.     // Success
  675.     return TRUE;
  676. } // End PrintNextLine
  677. /*
  678. **-----------------------------------------------------------------------------
  679. ** Name:    DoMessage
  680. ** Purpose: display warning message to user
  681. **-----------------------------------------------------------------------------
  682. */
  683. #define MAX_TITLE   64
  684. #define MAX_MESSAGE 256
  685. void DoMessage (DWORD dwTitle, DWORD dwMsg)
  686. {
  687.     TCHAR szTitle[MAX_TITLE];
  688.     TCHAR szMsg[MAX_MESSAGE];
  689.     HMODULE hModule;
  690.     hModule = GetModuleHandle (NULL);
  691.     LoadString (hModule, dwTitle, szTitle, MAX_TITLE);
  692.     LoadString (hModule, dwMsg, szMsg, MAX_MESSAGE);
  693.     MessageBox (NULL, szMsg, szTitle, MB_OK);
  694. } // End DoMessage
  695.   
  696. /*
  697. **-----------------------------------------------------------------------------
  698. ** End of File
  699. **-----------------------------------------------------------------------------
  700. */