Printing 如何在任何设备contenxt上以正确的格式打印富文本框内容?

Printing 如何在任何设备contenxt上以正确的格式打印富文本框内容?,printing,rtf,Printing,Rtf,我希望将格式为的富文本框内容打印到任何设备上下文,例如,我希望在面板或与实际打印设备关联的任何其他控件上打印 我使用面板模拟打印预览,从自定义设计的表单中绘制一些内容,富文本内容是该表单的内容之一 有没有解决这个问题的最佳方案???下面是将rtf控件的内容打印到打印机的代码。我可以适应打印到任何旧dc相当容易。该语言是powerbasic,但可以很容易地翻译成C、pascal或其他语言: SUB PrintRichTextBox ( hWnd as LONG, hInst as LONG, r

我希望将格式为的富文本框内容打印到任何设备上下文,例如,我希望在面板或与实际打印设备关联的任何其他控件上打印

我使用面板模拟打印预览,从自定义设计的表单中绘制一些内容,富文本内容是该表单的内容之一


有没有解决这个问题的最佳方案???

下面是将rtf控件的内容打印到打印机的代码。我可以适应打印到任何旧dc相当容易。该语言是powerbasic,但可以很容易地翻译成C、pascal或其他语言:

SUB PrintRichTextBox (  hWnd as LONG, hInst as LONG, rtfEdit as LONG, LM as Single, _
                        RM as Single, TM as Single, BM as Single )
   '
   '  Purpose:
   '           Prints the contents of an RTF text box given it's handle, the
   '           calling program's handle(s), and the page margins.
   '
   '  Parameters:
   '           hWnd     = Parent window (used for print common dlg)
   '           hInst    = Instance of calling program
   '           rtfEdit  = Handle of rich edit control
   '           LM       = Left Margin in inches
   '           RM       = Right Margin in inches
   '           TM       = Top Margin in inches
   '           BM       = Bottom Margin in inches
   '
   Dim fr as FORMATRANGE
   Dim rDocInfo as DOCINFO
   Dim iTextOut as LONG
   Dim iTextAmt as LONG
   Dim pd as PRINTDLGAPI
   Dim zString as ASCIIZ * 200
   Dim iWidthTwips&
   Dim iHeightTwips&

   '- Setup the print common dialog
   pd.lStructSize = len(pd)
   pd.hwndOwner = hWnd
   pd.hDevMode = %NULL
   pd.hDevNames = %NULL
   pd.nFromPage = 0
   pd.nToPage = 0
   pd.nMinPage = 0
   pd.nMaxPage = 0
   pd.nCopies = 0
   pd.hInstance = hInst
   pd.Flags = %PD_RETURNDC or %PD_NOPAGENUMS or %PD_PRINTSETUP
   pd.lpfnSetupHook = %NULL
   pd.lpPrintSetupTemplateName = %NULL
   pd.lpfnPrintHook = %NULL
   pd.lpPrintTemplateName = %NULL

   if PrintDlg(pd) then

      SetCursor LoadCursor( %NULL, BYVAL %IDC_WAIT )

      '- Fill format range structure
      '
      '  NOTE:
      '     This gave me fits. I was looking at the book from
      '     Microsoft Press called Programming the Windows 95
      '     Iterface. It said (via example) that the
      '     Rectagle was defined in Pixels. This didn't work right.
      '     The SDK, however, said the measurements needed to be
      '     in Twips! This seems to work fine.
      '
      '
      fr.hdc = pd.hDC
      fr.hdcTarget = pd.hDC
      fr.chrg.cpMin = 0
      fr.chrg.cpMax = -1

      fr.rc.nTop = TM * 1440
      fr.rcPage.nTop = fr.rc.nTop

      fr.rc.nLeft = LM * 1440
      fr.rcPage.nLeft = fr.rc.nLeft

      '- Get page dimensions in Twips
      iWidthTwips& = int((GetDeviceCaps(pd.hDC, %HORZRES) / GetDeviceCaps(pd.hDC, %LOGPIXELSX)) * 1440)
      iHeightTwips& = int((GetDeviceCaps(pd.hDC, %VERTRES) / GetDeviceCaps(pd.hDC, %LOGPIXELSY)) * 1440)

      fr.rc.nRight = iWidthTwips& - RM * 1440
      fr.rcPage.nRight = fr.rc.nRight

      fr.rc.nBottom = iHeightTwips& - BM * 1440
      fr.rcPage.nBottom = fr.rc.nBottom

      '- Fill rDocInfo structure
      rDocInfo.cbSize = len(rDocInfo)
      zString = "RTF Printer"
      rDocInfo.lpszDocName = VARPTR(zString)
      rDocInfo.lpszOutput = %NULL

      '- Here we go
      StartDoc pd.hDC, rDocInfo
      StartPage pd.hDC

      '- This does the printing. We send messages
      '  to the edit box telling it to format it's
      '  text to fit the Printer's DC.
      '
      iTextOut = 0
      iTextAmt = SendMessage(rtfEdit, %WM_GETTEXTLENGTH, 0, 0)

      do while iTextOut < iTextAmt

         iTextOut = SendMessage(rtfEdit, %EM_FORMATRANGE, _
                     1, VARPTR(fr))

         if iTextOut < iTextAmt then
            EndPage pd.hDC
            StartPage pd.hDC
            fr.chrg.cpMin = iTextOut
            fr.chrg.cpMax = -1
         end if

      loop

      SendMessage rtfEdit, %EM_FORMATRANGE, 1, %NULL

      '- Finish the printing.
      EndPage pd.hDC
      EndDoc pd.hDC

      DeleteDC pd.hDC
      SetCursor LoadCursor( %NULL, BYVAL %IDC_ARROW )

   else
      ' MsgBox "Canceled !"
   end if


END SUB
子PrintRichTextBox(hWnd为长,hInst为长,rtfEdit为长,LM为单_
RM为单个,TM为单个,BM为单个)
'
“目的:
'打印给定句柄的RTF文本框的内容
'调用程序的句柄和页边距。
'
“参数:
'hWnd=父窗口(用于打印公共dlg)
'hInst=调用程序的实例
'rtfEdit=富编辑控件的句柄
'LM=以英寸为单位的左边距
'RM=右边距(英寸)
'TM=以英寸为单位的上边距
'BM=以英寸为单位的底部边距
'
变暗fr作为格式化范围
将rDocInfo设置为文档信息
把它调暗就行了
暗淡的,如长
将pd设置为打印DLGAPI
尺寸Z字符串为ASCIIZ*200
朦胧的iWidthTwips&
调暗iHeightTwips&
“-设置“打印公用”对话框
pd.lStructSize=长度(pd)
pd.hwndOwner=hWnd
pd.hDevMode=%NULL
pd.hDevNames=%NULL
pd.nFromPage=0
pd.nToPage=0
pd.nMinPage=0
pd.nmappage=0
pd.nCopies=0
pd.hInstance=hInst
pd.Flags=%pd\u RETURNDC或%pd\u NOPAGENUMS或%pd\u PRINTSETUP
pd.lpfnSetupHook=%NULL
pd.lpPrintSetupTemplateName=%NULL
pd.lpfnPrintHook=%NULL
pd.lpPrintTemplateName=%NULL
如果打印DLG(pd),则
SetCursor LoadCursor(%NULL,BYVAL%IDC\u WAIT)
“-填充格式范围结构
'
“注:
“这让我感到很不舒服。我在看那本书
微软出版社称之为Windows 95编程
“Iterface。它(通过例子)说
'Rectagle是以像素为单位定义的。这不管用。
然而,SDK表示,需要对测量结果进行分析
“抽搐!这似乎很有效。
'
'
fr.hdc=pd.hdc
fr.hdcTarget=pd.hDC
fr.chrg.cpMin=0
fr.chrg.cpMax=-1
fr.rc.nTop=TM*1440
fr.rcPage.nTop=fr.rc.nTop
fr.rc.nLeft=LM*1440
fr.rcPage.nLeft=fr.rc.nLeft
'-获取Twips中的页面维度
iWidthTwips&=int((GetDeviceCaps(pd.hDC,%HORZRES)/GetDeviceCaps(pd.hDC,%LOGPIXELSX))*1440)
iHeightTwips&=int((GetDeviceCaps(pd.hDC,%VERTRES)/GetDeviceCaps(pd.hDC,%LOGPIXELSY))*1440)
fr.rc.nRight=iWidthTwips&-RM*1440
fr.rcPage.nRight=fr.rc.nRight
fr.rc.nBottom=iHeightTwips和-BM*1440
fr.rcPage.nBottom=fr.rc.nBottom
'-Fill-rDocInfo结构
rDocInfo.cbSize=len(rDocInfo)
zString=“RTF打印机”
rDocInfo.lpszDocName=VARPTR(zString)
rDocInfo.lpszOutput=%NULL
-我们开始
StartDoc pd.hDC,rDocInfo
起始页pd.hDC
“-这不需要打印。我们发送消息
'到编辑框,告诉它格式化
'文本以适合打印机的DC。
'
iTextOut=0
iTextAmt=SendMessage(rtfEdit,%WM\u GETTEXTLENGTH,0,0)
在iTextOut
我使用了下面的扩展控件来实现RTF打印

    using System;
    using System.Windows.Forms;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.Drawing.Printing;

    namespace RichTextBoxPrintCtrl
    {
        public class RichTextBoxPrintCtrl : RichTextBox
        {
            //Convert the unit used by the .NET framework (1/100 inch) 
            //and the unit used by Win32 API calls (twips 1/1440 inch)
            private const double anInch = 14.4;

            [StructLayout(LayoutKind.Sequential)]
            private struct RECT
            {
                public int Left;
                public int Top;
                public int Right;
                public int Bottom;
            }

            [StructLayout(LayoutKind.Sequential)]
            private struct CHARRANGE
            {
                public int cpMin;         //First character of range (0 for start of doc)
                public int cpMax;           //Last character of range (-1 for end of doc)
            }

            [StructLayout(LayoutKind.Sequential)]
            private struct FORMATRANGE
            {
                public IntPtr hdc;             //Actual DC to draw on
                public IntPtr hdcTarget;       //Target DC for determining text formatting
                public RECT rc;                //Region of the DC to draw to (in twips)
                public RECT rcPage;            //Region of the whole DC (page size) (in twips)
                public CHARRANGE chrg;         //Range of text to draw (see earlier declaration)
            }

            private const int WM_USER = 0x0400;
            private const int EM_FORMATRANGE = WM_USER + 57;

            [DllImport("USER32.dll")]
            private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);

            // Render the contents of the RichTextBox for printing
            //  Return the last character printed + 1 (printing start from this point for next page)
            public int Print(int charFrom, int charTo, PrintPageEventArgs e)
            {
                //Calculate the area to render and print
                RECT rectToPrint;
                rectToPrint.Top = (int)(e.MarginBounds.Top * anInch);
                rectToPrint.Bottom = (int)(e.MarginBounds.Bottom * anInch);
                rectToPrint.Left = (int)(e.MarginBounds.Left * anInch);
                rectToPrint.Right = (int)(e.MarginBounds.Right * anInch);

                //Calculate the size of the page
                RECT rectPage;
                rectPage.Top = (int)(e.PageBounds.Top * anInch);
                rectPage.Bottom = (int)(e.PageBounds.Bottom * anInch);
                rectPage.Left = (int)(e.PageBounds.Left * anInch);
                rectPage.Right = (int)(e.PageBounds.Right * anInch);

                IntPtr hdc = e.Graphics.GetHdc();

                FORMATRANGE fmtRange;
                fmtRange.chrg.cpMax = charTo;               //Indicate character from to character to 
                fmtRange.chrg.cpMin = charFrom;
                fmtRange.hdc = hdc;                    //Use the same DC for measuring and rendering
                fmtRange.hdcTarget = hdc;              //Point at printer hDC
                fmtRange.rc = rectToPrint;             //Indicate the area on page to print
                fmtRange.rcPage = rectPage;            //Indicate size of page

                IntPtr res = IntPtr.Zero;

                IntPtr wparam = IntPtr.Zero;
                wparam = new IntPtr(1);

                //Get the pointer to the FORMATRANGE structure in memory
                IntPtr lparam = IntPtr.Zero;
                lparam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));
                Marshal.StructureToPtr(fmtRange, lparam, false);

                //Send the rendered data for printing 
                res = SendMessage(Handle, EM_FORMATRANGE, wparam, lparam);

                //Free the block of memory allocated
                Marshal.FreeCoTaskMem(lparam);

                //Release the device context handle obtained by a previous call
                e.Graphics.ReleaseHdc(hdc);

                //Return last + 1 character printer
                return res.ToInt32();
            }

        }
    }

谢谢你提供资料,但我是个C语言的人,翻译成C语言有点困难。。有什么帮助吗?我不会用c语言编程,所以我帮不了多少忙。然而,上面的代码很容易翻译成C。重要的调用主要是win32 api调用。常量(#define)以%开头。出于某种原因,我在一些变量上加了一个类型后缀(我十多年前写过这段代码)。e、 iWidthTwips&只是意味着iWidthTwips是一个长(32位)整数。asciiz*200是char[200]。我已经使用了下面的代码来实现我的要求,如果有人寻找此类问题,它将有所帮助。