I took Michael's update to Dickinson's code and wrapped it in a rich edit example - but running print gives no output. In fact, the program freezes up. I select the printer, press go, and that's all that happens.
Michael, have I mis-used the code, or do you have an updated version? And BTW, I tried Dickinson's version and it worked, but the extra printed page was a bummer (although it didn't always appear - I don't know why).
Does anyone else have code for printing content of a rich edit control? Michael's code was '06 vintage and I've not found anything posted since then.
The code handles embedded $tab characters, which is a key reason I'm interested in it, plus eliminating the blank page that Michael fixed.
Here's my example, with Michael's code included.
Michael, have I mis-used the code, or do you have an updated version? And BTW, I tried Dickinson's version and it worked, but the extra printed page was a bummer (although it didn't always appear - I don't know why).
Does anyone else have code for printing content of a rich edit control? Michael's code was '06 vintage and I've not found anything posted since then.
The code handles embedded $tab characters, which is a key reason I'm interested in it, plus eliminating the blank page that Michael fixed.
Here's my example, with Michael's code included.
Code:
'Compilable Example: 'Credit: Michael Mattias/Don Dickinson 'http://www.powerbasic.com/support/pbforums/showthread.php?t=28400 #Compile Exe #Dim All #Include "Win32API.inc" #Include "RichEdit.inc" #Include "CommCtrl.inc" #Include "Comdlg32.inc" Global hDlg As Dword, hRichEdit As Dword, hInst As Dword %ID_RichEdit = 500 Function PBMain() As Long Local style&, buf$ buf$ = "This is sample" + $CrLf + "text for the" + $CrLf + "edit control." style& = %WS_Child Or %WS_Visible Or %ES_MultiLine Or %WS_VScroll Or %ES_AutoHScroll _ Or %WS_HScroll Or %ES_AutoVScroll Or %ES_WantReturn Or %ES_NoHideSel Or %WS_TabStop Dialog New Pixels, 0, "Test Code",300,300,200,150, %WS_OverlappedWindow To hDlg Control Add Button, hDlg, 100,"Push", 30,10,140,20 LoadLibrary("riched32.dll") : InitCommonControls Control Add "RichEdit", hDlg, %ID_RichEdit, buf$,20,40,160,100, style&, %WS_Ex_ClientEdge Control Handle hDlg, %ID_RichEdit To hRichEdit Dialog Show Modal hDlg Call DlgProc End Function CallBack Function DlgProc() As Long If Cb.Msg = %WM_Command And Cb.Ctl = 100 And Cb.CtlMsg = %BN_Clicked Then hInst=GetModuleHandle(ByVal %NULL) PrintRichTextBox2 hDlg, hInst, hRichEdit, 0.5, 0.5, 0.5, 0.5 End If End Function ' =============================================================== ' PrintRichTextBox2: MCM's improved version of PrintRichTextBox ' 01.24.04 Created from copy of annotated PrintRichTextBox (above) ' Above is Don Dickinson's original (Public domain) Rich Text Control printer ' Purposes: ' a) End up with printing which does not have extra blank page each time ' b) meaningful return code from FUNCTION = number of pages printed ' instead of calling as a SUB ' 05/03/06 Clean up comments to make suitable for posting ' =============================================================== ' MCM NOTE 5/3/06: These includes may vary, since I am sure later versions of the ' PowerBASIC-supplied Windows Headers files moved some of this stuff around. ' But I know you MUST have Win32API.INC and COMDLG32.INC. ' REquired #INCLUDES: ' #INCLUDE "WIN32API.INC" ' #INCLUDE "COMDLG32.INC" ' #INCLUDE "RICHEDIT.INC" Function PrintRichTextBox2 ( hWnd As Long, hInst As Long, rtfEdit As Long, LM As Single, _ RM As Single, TM As Single, BM As Single ) As Long ' ' Purpose: ' Prints the contents of an RTF text box given it 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 Local pageNO As Long Pageno = 0& ' initialize '---------------------------------------------------------------------------- ' call the PrintDlg common dialog to get printer name and a hDC for printer ' --------------------------------------------------------------------------- If PrintDlg(pd) Then SetCursor LoadCursor( %NULL, ByVal %IDC_WAIT ) '- Fill format range structure ' ' Don's 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 ' ==== MCM update here]=== ' we are not going to startpage until we know there is something to print on this page ' StartPage pd.hDC '- This does the printing. We send messages to the edit box telling it to format it ' text to fit the Printer's DC. iTextOut = 0 iTextAmt = SendMessage(rtfEdit, %WM_GETTEXTLENGTH, 0, 0) ' TOTAL LENGTH OF TEXT TO BE FORMATTED AND PRINTED ' set end index of charrange to max index; we want to always format "as much as will fit on a page" fr.chrg.cpmax = iTextAmt -1 Local iTextDone As Long ' index of last character printed... Local iLastRendered As Long Local iLastCharDone As Long iTextDone = 0 ' not yet, anyway Do While iTextDone < iTextAmt ' ========================================================================================= ' emformatrage returns ' "This message returns the index of the last character that fits in the region, plus one." ' ========================================================================================= ' MSGBOX "send em_formatrange, measure only with fr.Chrg.cpmin, fr.chrg.cpmax=" & STR$(fr.chrg.cpmin) & STR$(fr.chrg.cpmax) ' itext out will never return more than than can fit on a page! ' send EM_FORMATRANGE with wparam = 0 to measure iTextOut = SendMessage(rtfEdit, %EM_FORMATRANGE, 0&, VarPtr(fr)) ' MCM NOTE 12/28/03: MDSN says EM_FORMATRANGE returns: ' "This message returns the index of the last character that fits in the region, plus one" ' Not quite true, if it resturns less than cpmin, there is no text to print. ' (Like the trailer formatting text in a RTF document). ' is this iText is beyond the end (should never happen) ' or less than cpmin (true on last page), there is no text to format and we are done If iTextOut > fr.chrg.cpmax Then ' MSGBOX "ITextOut > cpmax, exit print loop" Exit Do ElseIf iTExtOut < fr.chrg.cpmin Then ' no renderable text left to do.. ' MSGBOX "itextout < cpmin, exit print loop" ' Exit Do End If ' ----------------------------------------------------------- ' if we get here, we can start a page, print it and end it ' ----------------------------------------------------------- StartPage pd.hDC ' start a page ' render it: iLastRendered = SendMessage(rtfEdit, %EM_FORMATRANGE, 1&, VarPtr(fr)) ' incrment the number of pages printed and end the page Incr PageNo Endpage pd.hdc ' reset the start point of FORMATRANGE structure for next page fr.chrg.cpmin = itextOut ' leave max alone, try to format ALL remaining text.. Loop ' Clean up the Richedit control: SendMessage rtfEdit, %EM_FORMATRANGE, 1, %NULL ' << MDSN says send this msg w/lparam=%NULL when ' done with the device '- Finish the printing. EndDoc pd.hDC DeleteDC pd.hDC SetCursor LoadCursor( %NULL, ByVal %IDC_ARROW ) Else ' MsgBox "Canceled !" (in PRintDlg) End If ' set return value = # pages printed Function = PageNo End Function
Comment