home *** CD-ROM | disk | FTP | other *** search
Wrap
/* Project richctrl DHB Software Copyright ⌐ 1996. All Rights Reserved. SUBSYSTEM: richctrl.apx Application FILE: rchedtcn.cpp AUTHOR: David H. Borg OVERVIEW ======== Source file for implementation of RichEditControl (TEdit). */ #include <owl\owlpch.h> #pragma hdrstop #include <dir.h> #include "rchctrla.h" #include "flopndlg.h" #include "filsvdlg.h" #include "rchedtcn.h" // // Build a response table for all messages/commands handled // by the application. // DEFINE_RESPONSE_TABLE1(RichEditControl, TEdit) //{{RichEditControlRSP_TBL_BEGIN}} EV_MESSAGE( WM_CHANGEFONTFACE, CmChangeFontFace), EV_COMMAND_ENABLE( IDC_FONTFACE, CmEnFontFace), EV_MESSAGE( WM_CHANGEFONTSIZE, CmChangeFontSize), EV_COMMAND_ENABLE( IDC_FONTSIZE, CmEnFontSize), EV_COMMAND(CM_FILENEW, CmFileNew), EV_COMMAND(CM_FILESAVE1, CmFileSave), EV_COMMAND_ENABLE(CM_FILESAVE1, CmEnFileSave), EV_COMMAND(CM_FILEOPENRTF, CmFileOpenRtf), EV_COMMAND(CM_FILEOPENTEXT, CmFileOpenText), EV_COMMAND(CM_SAVEASRTF, CmSaveAsRtf), EV_COMMAND(CM_SAVEASTEXT, CmSaveAsText), EV_COMMAND_ENABLE(CM_SAVEASRTF, CmEnSaveAs), EV_COMMAND_ENABLE(CM_SAVEASTEXT, CmEnSaveAs), EV_COMMAND(CM_EDITFIND, CmEditFind), EV_COMMAND_ENABLE(CM_EDITFIND, CmEnEditFindReplace), EV_COMMAND(CM_EDITFINDNEXT, CmEditFindNext), EV_COMMAND_ENABLE(CM_EDITFINDNEXT, CmEnEditFindNext), EV_REGISTERED(FINDMSGSTRING, EvFindMsg), EV_COMMAND(CM_FORMATBOLD, CmFormatBold), EV_COMMAND_ENABLE(CM_FORMATBOLD, CmEnFormatBold), EV_COMMAND(CM_FORMATITALIC, CmFormatItalic), EV_COMMAND_ENABLE(CM_FORMATITALIC, CmEnFormatItalic), EV_COMMAND(CM_FORMATUNDERLINE, CmFormatUnderline), EV_COMMAND_ENABLE(CM_FORMATUNDERLINE, CmEnFormatUnderline), EV_COMMAND(CM_FORMATLEFT, CmFormatLeft), EV_COMMAND_ENABLE(CM_FORMATLEFT, CmEnFormatLeft), EV_COMMAND(CM_FORMATCENTER, CmFormatCenter), EV_COMMAND_ENABLE(CM_FORMATCENTER, CmEnFormatCenter), EV_COMMAND(CM_FORMATRIGHT, CmFormatRight), EV_COMMAND_ENABLE(CM_FORMATRIGHT, CmEnFormatRight), EV_COMMAND(CM_FORMATFONT, CmFormatFont), EV_COMMAND_ENABLE(CM_FORMATFONT, CmEnFormatFont), EV_WM_KEYDOWN, EV_WM_LBUTTONDOWN, //{{RichEditControlRSP_TBL_END}} END_RESPONSE_TABLE; //{{RichEditControl Implementation}} RichEditControl::RichEditControl (TWindow* parent, int id, const char far* text, int x, int y, int w, int h, uint textLen, bool multiline, TModule* module): TEdit(parent, id, text, x, y, w, h, textLen, multiline, module), FileName(0), FindReplaceDialog(0), FindReplaceCmd(0), streamFormat(SF_RTF), updtFontFace(true), updtFontSize(true) { // INSERT>> Your constructor code here. // add custom styles for this control Attr.ExStyle = WS_EX_CLIENTEDGE; Attr.Param = 0; Attr.Style = WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_SAVESEL | ES_NOHIDESEL | ECO_AUTOVSCROLL | WS_VSCROLL; // Common file file flags and filters for Open/Save As dialogs. Filename and directory are // computed in the member functions CmFileOpen, and CmSaveAs. FileData.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; FileData.SetFilter( "Rich Text Files (*.rtf)|*.RTF|" "Text Files (*.txt)|*.TXT|" "All Files (*.*)|*.*|"); FileData.FilterIndex = 0; // initialize flags to create a plain and simple find dialog FindReplaceData.Flags = FR_HIDEUPDOWN | FR_HIDEMATCHCASE | FR_HIDEWHOLEWORD; } RichEditControl::~RichEditControl () { Destroy(); // INSERT>> Your destructor code here. } // this identifies that the window is a rich edit control char far* RichEditControl::GetClassName () { return "RICHEDIT"; } void RichEditControl::CmFileNew () { // INSERT>> Your code here. if (CanClear()) { streamFormat = SF_RTF; Clear(); ClearModify(); SetFileName(0); Invalidate(); } } void RichEditControl::CmFileSave () { // INSERT>> Your code here. if( IsModified()){ if( FileName == 0){ DoSaveAsCmd(); } else if( Save( FileName)) { ClearModify(); } else { string message( GetModule()->LoadString( IDS_UNABLEWRITE)); char* buf = new char[MAXPATH + message.length()]; wsprintf( buf, message.c_str(), FileName); MessageBox( buf, GetApplication()->GetName(), MB_ICONEXCLAMATION | MB_OK); delete buf; } } return; } void RichEditControl::CmEnFileSave (TCommandEnabler &tce) { // INSERT>> Your code here. tce.Enable( IsModified()); } void RichEditControl::CmFileOpenRtf () { // INSERT>> Your code here. // open a file as an rtf document streamFormat = SF_RTF; DoFileOpenCmd(); } void RichEditControl::CmFileOpenText () { // INSERT>> Your code here. // open a file as a text only document streamFormat = SF_TEXT; DoFileOpenCmd(); } void RichEditControl::CmSaveAsRtf () { // INSERT>> Your code here. streamFormat = SF_RTF; DoSaveAsCmd(); } void RichEditControl::CmSaveAsText () { // INSERT>> Your code here. streamFormat = SF_TEXT; DoSaveAsCmd(); } void RichEditControl::DoFileOpenCmd () { // INSERT>> Your code here. if( CanClear()) { Clear(); SetFileName(0); *FileData.FileName = 0; if( streamFormat == SF_RTF) FileData.FilterIndex = 1; else FileData.FilterIndex = 2; if( FileOpenDialog( this, FileData).Execute() == IDOK) if( Open( FileData.FileName)){ SetFileName( FileData.FileName); Invalidate(); } else { string message( GetModule()->LoadString(IDS_UNABLEREAD)); char* buf = new char[MAXPATH + message.length()]; wsprintf( buf, message.c_str(), FileData.FileName); MessageBox( buf, GetApplication()->GetName(), MB_ICONEXCLAMATION | MB_OK); delete buf; } } } void RichEditControl::DoSaveAsCmd () { // INSERT>> Your code here. if( FileName == 0) *FileData.FileName = 0; else strcpy( FileData.FileName, FileName); if( streamFormat == SF_RTF) FileData.FilterIndex = 1; else FileData.FilterIndex = 2; if( FileSaveDialog( this, FileData).Execute() == IDOK) { if( Save( FileData.FileName)){ ClearModify(); SetFileName( FileData.FileName); } else { string message( GetModule()->LoadString( IDS_UNABLEWRITE)); char* buf = new char[MAXPATH + message.length()]; wsprintf( buf, message.c_str(), FileData.FileName); MessageBox( buf, GetApplication()->GetName(), MB_ICONEXCLAMATION | MB_OK); delete buf; } } return; } void RichEditControl::CmEditFind () { // INSERT>> Your code here. if (!FindReplaceCmd) { delete FindReplaceDialog; FindReplaceCmd = CM_EDITFIND; FindReplaceDialog = new TFindDialog( this, FindReplaceData); FindReplaceDialog->Create(); } } void RichEditControl::CmEnEditFindReplace (TCommandEnabler &tce) { // INSERT>> Your code here. tce.Enable( !FindReplaceCmd); } void RichEditControl::CmEditFindNext () { // INSERT>> Your code here. if (FindReplaceDialog) FindReplaceDialog->UpdateData(); FindReplaceData.Flags |= FR_FINDNEXT; DoFind(); } void RichEditControl::CmEnEditFindNext (TCommandEnabler &tce) { // INSERT>> Your code here. tce.Enable((FindReplaceData.FindWhat && *(FindReplaceData.FindWhat)) ? true : false); } // Perform a search or replace operation based on information in FindReplaceData void RichEditControl::DoFind() { FINDTEXT findText; uint startSel, endSel; GetSelection( startSel, endSel); findText.chrg.cpMin = endSel; findText.chrg.cpMax = -1; findText.lpstrText = FindReplaceData.FindWhat; long position = (long)SendMessage( EM_FINDTEXT, (WPARAM)true, (LPARAM)&findText); if( position >= 0) { SetSelection( position, position + strlen( FindReplaceData.FindWhat)); } else { if( FindReplaceData.Flags & (FR_FINDNEXT)) { string errTemplate(GetModule()->LoadString(IDS_CANNOTFIND)); char errMsg[81]; wsprintf(errMsg, errTemplate.c_str(), (const char far*)FindReplaceData.FindWhat); TWindow* w = FindReplaceDialog ? (TWindow*)FindReplaceDialog : (TWindow*)this; w->MessageBox(errMsg, GetApplication()->GetName(), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL); SetSelection( 0, 0); } } } // Respond to the message sent by the modeless find/replace dialog by // performing a search. Or, if the dialog has terminated, zero search command LRESULT RichEditControl::EvFindMsg(WPARAM, LPARAM lParam) { PRECONDITION(FindReplaceDialog); FindReplaceDialog->UpdateData(lParam); if (FindReplaceData.Flags & FR_DIALOGTERM) FindReplaceCmd = 0; else DoFind(); return 0; } // returns true if the text is unchanged, or if it is ok to delete it bool RichEditControl::CanClear() { bool retVal = true; int choice; if( IsModified()) { string message( GetModule()->LoadString( IDS_FILECHANGED)); string empty( GetModule()->LoadString( IDS_UNTITLEDFILE)); char* buf = new char[MAXPATH+message.length()]; wsprintf( buf, message.c_str(), FileName ? (const char far*)FileName : empty.c_str()); choice = MessageBox( buf, GetApplication()->GetName(), MB_YESNOCANCEL|MB_ICONQUESTION); if( choice == IDYES){ CmFileSave(); } else if( choice == IDCANCEL){ retVal = false; } delete buf; } return retVal; } // set the new file name and update the window's caption void RichEditControl::SetFileName (const char far* newName) { if( newName != FileName) { delete FileName; FileName = newName != 0 ? strnewdup(newName) : 0; } if( FileName != 0){ SetDocTitle( FileName, 0); } else { string noName( GetModule()->LoadString(IDS_UNTITLEDFILE)); SetDocTitle( noName.c_str(), 0); } } bool RichEditControl::Open ( const char far* fileName) { HFILE hFile; OFSTRUCT ofStruct; EDITSTREAM editStream; ofStruct.cBytes = sizeof(ofStruct); if( (hFile = OpenFile( fileName, &ofStruct, OF_READ)) != HFILE_ERROR) { // dwCookie is an app-defined value that holds // the handle to the file. editStream.dwCookie = hFile; editStream.pfnCallback = OpenCallback; editStream.dwError = 0; long bytesRead = 0; while( bytesRead == editStream.dwError){ bytesRead = (long)SendMessage( EM_STREAMIN, (WPARAM)streamFormat, (LPARAM)&editStream); } if( bytesRead >= 0) editStream.dwError = 0; // Reset the dirty bit. ClearModify(); CloseHandle((HANDLE)hFile); return !editStream.dwError; } return false; } DWORD CALLBACK RichEditControl::OpenCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR *pcb) { return( !ReadFile( (HANDLE)dwCookie, pbBuff, cb, (unsigned long *)pcb, 0)); } bool RichEditControl::Save( const char far* fileName) { HFILE hFile; OFSTRUCT ofStruct; EDITSTREAM editStream; if( (hFile = OpenFile( fileName, &ofStruct, OF_CREATE)) != HFILE_ERROR) { editStream.dwCookie = hFile; editStream.dwError = 0; editStream.pfnCallback = SaveCallback; SendMessage( EM_STREAMOUT, (WPARAM)streamFormat, (LPARAM)&editStream); CloseHandle( (HANDLE)hFile); return true; } return false; } DWORD CALLBACK RichEditControl::SaveCallback (DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR *pcb) { return( !WriteFile( (HANDLE)dwCookie, pbBuff, cb, (unsigned long *)pcb, 0)); } void RichEditControl::CmFormatBold () { // INSERT>> Your code here. // fill out character format structure to get bold format information charFormat.cbSize = sizeof(charFormat); charFormat.dwMask = CFM_BOLD; // get current character format SendMessage( EM_GETCHARFORMAT, true, (LPARAM)&charFormat); // toggle the bold effect charFormat.dwEffects ^= CFE_BOLD; // set the new character format SendMessage( EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&charFormat); UpdateFormats(); } void RichEditControl::CmEnFormatBold (TCommandEnabler &tce) { // INSERT>> Your code here. // toggle the bold effect button tce.SetCheck( (charFormat.dwEffects & CFE_BOLD) == CFE_BOLD); } void RichEditControl::CmFormatItalic () { // INSERT>> Your code here. // fill out character format structure to get italic format information charFormat.cbSize = sizeof(charFormat); charFormat.dwMask = CFM_ITALIC; // get current character format SendMessage( EM_GETCHARFORMAT, true, (LPARAM)&charFormat); // toggle the italic effect charFormat.dwEffects ^= CFE_ITALIC; // set the new character format SendMessage( EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&charFormat); UpdateFormats(); } void RichEditControl::CmEnFormatItalic (TCommandEnabler &tce) { // INSERT>> Your code here. // toggle the italic effect button tce.SetCheck( (charFormat.dwEffects & CFE_ITALIC) == CFE_ITALIC); } void RichEditControl::CmFormatUnderline () { // INSERT>> Your code here. // fill out character format structure to get underline format information charFormat.cbSize = sizeof(charFormat); charFormat.dwMask = CFM_UNDERLINE; // get current character format SendMessage( EM_GETCHARFORMAT, true, (LPARAM)&charFormat); // toggle the underline effect charFormat.dwEffects ^= CFE_UNDERLINE; // set the new character format SendMessage( EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&charFormat); UpdateFormats(); } void RichEditControl::CmEnFormatUnderline (TCommandEnabler &tce) { // INSERT>> Your code here. // toggle the underline effect button tce.SetCheck( (charFormat.dwEffects & CFE_UNDERLINE) == CFE_UNDERLINE); } void RichEditControl::CmFormatLeft () { // INSERT>> Your code here. // fill out paragraph format structure with left alignment information paraFormat.cbSize = sizeof(paraFormat); paraFormat.dwMask = PFM_ALIGNMENT; paraFormat.wAlignment = PFA_LEFT; // set the new paragraph alignment SendMessage( EM_SETPARAFORMAT, 0, (LPARAM)¶Format); } void RichEditControl::CmEnFormatLeft (TCommandEnabler &tce) { // INSERT>> Your code here. // toggle the left justify effect button tce.SetCheck( paraFormat.wAlignment == PFA_LEFT); } void RichEditControl::CmFormatCenter () { // INSERT>> Your code here. // fill out paragraph format structure with left alignment information paraFormat.cbSize = sizeof(paraFormat); paraFormat.dwMask = PFM_ALIGNMENT; paraFormat.wAlignment = PFA_CENTER; // set the new paragraph alignment SendMessage( EM_SETPARAFORMAT, 0, (LPARAM)¶Format); } void RichEditControl::CmEnFormatCenter (TCommandEnabler &tce) { // INSERT>> Your code here. // toggle the center effect button tce.SetCheck( paraFormat.wAlignment == PFA_CENTER); } void RichEditControl::CmFormatRight () { // INSERT>> Your code here. // fill out paragraph format structure with left alignment information paraFormat.cbSize = sizeof(paraFormat); paraFormat.dwMask = PFM_ALIGNMENT; paraFormat.wAlignment = PFA_RIGHT; // set the new paragraph alignment SendMessage( EM_SETPARAFORMAT, 0, (LPARAM)¶Format); } void RichEditControl::CmEnFormatRight (TCommandEnabler &tce) { // INSERT>> Your code here. // toggle the right justify effect button tce.SetCheck( paraFormat.wAlignment == PFA_RIGHT); } void RichEditControl::CmFormatFont () { // INSERT>> Your code here. // set all FontData structure parameters based on charFormat information FontData.DC = 0; FontData.Flags = CF_EFFECTS | CF_FORCEFONTEXIST | CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT; FontData.Color = TColor(charFormat.crTextColor); FontData.FontType = SCREEN_FONTTYPE; TDC dc( ::GetDC( HWindow)); FontData.LogFont.lfHeight = MulDiv( -charFormat.yHeight / 20, dc.GetDeviceCaps(LOGPIXELSY), 72); ::ReleaseDC( HWindow, dc); FontData.LogFont.lfWeight = (charFormat.dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL; FontData.LogFont.lfItalic = (charFormat.dwEffects & CFE_ITALIC) ? (BYTE)1 : (BYTE)0; FontData.LogFont.lfUnderline = (charFormat.dwEffects & CFE_UNDERLINE) ? (BYTE)1 : (BYTE)0; FontData.LogFont.lfStrikeOut = (charFormat.dwEffects & CFE_STRIKEOUT) ? (BYTE)1 : (BYTE)0; strncpy( FontData.LogFont.lfFaceName, charFormat.szFaceName, LF_FACESIZE); FontData.SizeMin = 0; FontData.SizeMax = 0; // execute Windows 95 standard choosefont dialog if (TChooseFontDialog(this, FontData).Execute() == IDOK) { // fill out character format structure to get font type information charFormat.cbSize = sizeof(charFormat); charFormat.dwMask = CFM_ITALIC | CFM_BOLD | CFM_UNDERLINE | CFM_COLOR | CFM_SIZE | CFM_FACE | CFM_STRIKEOUT; charFormat.dwEffects = 0; // clear old effects charFormat.dwEffects |= FontData.LogFont.lfWeight == FW_BOLD ? CFE_BOLD : 0; charFormat.dwEffects |= FontData.LogFont.lfItalic ? CFE_ITALIC : 0; charFormat.dwEffects |= FontData.LogFont.lfUnderline ? CFE_UNDERLINE : 0; charFormat.dwEffects |= FontData.LogFont.lfStrikeOut ? CFE_STRIKEOUT : 0; strncpy( charFormat.szFaceName, FontData.LogFont.lfFaceName, LF_FACESIZE); charFormat.yHeight = FontData.PointSize / 10 * 20; charFormat.crTextColor = (COLORREF)FontData.Color; // set the new character format SendMessage( EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&charFormat); } updtFontSize = true; updtFontFace = true; UpdateFormats(); } void RichEditControl::CmEnFormatFont (TCommandEnabler &tce) { // INSERT>> Your code here. tce.Enable(); } LRESULT RichEditControl::CmChangeFontFace(WPARAM /*wParam*/, LPARAM lParam) { char far* faceName = (char far*)lParam; // fill out character format structure to get font type information charFormat.cbSize = sizeof(charFormat); charFormat.dwMask = CFM_ITALIC | CFM_BOLD | CFM_UNDERLINE; SendMessage( EM_GETCHARFORMAT, true, (LPARAM)&charFormat); // set mask for rich edit control to change font typeface charFormat.dwMask |= CFM_FACE; // set the new font typeface while preserving old effects strcpy( charFormat.szFaceName, faceName); SendMessage( EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&charFormat); return 0; } LRESULT RichEditControl::CmChangeFontSize(WPARAM wParam, LPARAM /*lParam*/) { int pointSize = (int)wParam; // fill out character format structure to get font size information charFormat.cbSize = sizeof(charFormat); charFormat.dwMask = CFM_SIZE; // convert units to twips charFormat.yHeight = pointSize * 20; // set the new font point size SendMessage( EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&charFormat); return 0; } void RichEditControl::Clear () { TEdit::Clear(); // INSERT>> Your code here. CHARRANGE charRange; // select entire contents charRange.cpMin = 0; charRange.cpMax = -1; // clear contents SetRedraw( false); SendMessage( EM_EXSETSEL, 0, (LPARAM)&charRange); // fill out character format structure with default information charFormat.cbSize = sizeof(charFormat); // set mask for rich edit control to change all effects charFormat.dwMask = CFM_FACE | CFM_SIZE | CFM_ITALIC | CFM_BOLD | CFM_UNDERLINE; // clear all effects charFormat.dwEffects = 0; // set text height convert units to twips charFormat.yHeight = 12 * 20; // set the new font typeface while preserving old effects strcpy( charFormat.szFaceName, "Times New Roman"); SendMessage( EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&charFormat); // clear everything from the rtf control SetRedraw( true); SendMessage( EM_REPLACESEL, 0, (LPARAM)""); ClearModify(); UpdateFormats(); } void RichEditControl::SetupWindow () { TEdit::SetupWindow(); // INSERT>> Your code here. Clear(); } void RichEditControl::CmEnSaveAs (TCommandEnabler &tce) { // INSERT>> Your code here. tce.Enable(); } bool RichEditControl::CanClose () { return CanClear(); } void RichEditControl::CmEnFontFace (TCommandEnabler &tce) { // INSERT>> Your code here. if( updtFontFace){ tce.SetText( charFormat.szFaceName); updtFontFace = false; } } void RichEditControl::CmEnFontSize (TCommandEnabler &tce) { // INSERT>> Your code here. static char buf[17]; // get text height convert units from twips int height = charFormat.yHeight / 20; if( updtFontSize){ tce.SetText( itoa( height, buf, 10)); updtFontSize = false; } } void RichEditControl::UpdateFormats () { // INSERT>> Your code here. // fill out character format structure to get font type information charFormat.cbSize = sizeof(charFormat); // set mask for rich edit control to read all character formats charFormat.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE |CFM_STRIKEOUT | CFM_PROTECTED | CFM_SIZE | CFM_COLOR | CFM_FACE | CFM_OFFSET | CFM_CHARSET; // get the new font typeface SendMessage( EM_GETCHARFORMAT, true, (LPARAM)&charFormat); // fill out paragraph format structure with alignment information paraFormat.cbSize = sizeof(paraFormat); paraFormat.dwMask = PFM_ALIGNMENT; // set the new paragraph alignment SendMessage( EM_GETPARAFORMAT, 0, (LPARAM)¶Format); // flags to indicate time to update combo boxes updtFontFace = updtFontSize = true; } void RichEditControl::EvKeyDown (uint key, uint repeatCount, uint flags) { TEdit::EvKeyDown(key, repeatCount, flags); // INSERT>> Your code here. UpdateFormats(); } void RichEditControl::EvLButtonDown (uint modKeys, TPoint& point) { TEdit::EvLButtonDown(modKeys, point); // INSERT>> Your code here. UpdateFormats(); } void RichEditControl::CmFilePrint () { // INSERT>> Your code here. PRINTDLG pDlg; FORMATRANGE fmtRng; DOCINFO docInfo; LONG textSent, totalAmount; // Initialize the PRINTDLG structure. pDlg.lStructSize = sizeof(PRINTDLG); pDlg.hwndOwner = HWindow; pDlg.hDevMode = (HANDLE)0; pDlg.hDevNames = (HANDLE)0; pDlg.nFromPage = 0; pDlg.nToPage = 0; pDlg.nMinPage = 0; pDlg.nMaxPage = 0; pDlg.nCopies = 0; pDlg.hInstance = GetApplication()->GetInstance(); pDlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION | PD_PRINTSETUP; pDlg.lpfnSetupHook = (LPSETUPHOOKPROC)(FARPROC)0; pDlg.lpSetupTemplateName = (LPTSTR)0; pDlg.lpfnPrintHook = (LPPRINTHOOKPROC)(FARPROC)0; pDlg.lpPrintTemplateName = (LPTSTR)0; // Get the printer DC. if (PrintDlg(&pDlg) == TRUE) { // Fill out the FORMATRANGE structure for the RTF output. fmtRng.hdc = fmtRng.hdcTarget = pDlg.hDC; // HDC fmtRng.chrg.cpMin = 0; // Print fmtRng.chrg.cpMax = -1; // entire contents fmtRng.rc.top = fmtRng.rcPage.top = fmtRng.rc.left = fmtRng.rcPage.left = 0; fmtRng.rc.right = fmtRng.rcPage.right = ::GetDeviceCaps(pDlg.hDC, HORZRES); fmtRng.rc.bottom = fmtRng.rcPage.bottom = ::GetDeviceCaps(pDlg.hDC, VERTRES ); // Fill out the DOCINFO structure. docInfo.cbSize = sizeof(DOCINFO); docInfo.lpszDocName = "(RTF Test)"; docInfo.lpszOutput = NULL; // Be sure that the printer DC is in text mode. SetMapMode(pDlg.hDC, MM_TEXT); StartDoc( pDlg.hDC, &docInfo); StartPage( pDlg.hDC ); textSent = 0; totalAmount = SendMessage( WM_GETTEXTLENGTH, 0, 0); while (textSent < totalAmount) { textSent = SendMessage( EM_FORMATRANGE, TRUE, (LPARAM) &fmtRng); if (textSent < totalAmount) { EndPage( pDlg.hDC ); StartPage( pDlg.hDC ); fmtRng.chrg.cpMin = textSent; fmtRng.chrg.cpMax = -1; } } // Reset the formatting of the rich edit control. SendMessage( EM_FORMATRANGE, TRUE, (LPARAM)NULL); // Finish the document. EndPage( pDlg.hDC ); EndDoc( pDlg.hDC ); // Delete the printer DC. DeleteDC( pDlg.hDC ); } } // // Paint routine for Window, Printer, and PrintPreview for an TEdit client. // void RichEditControl::Paint (TDC& dc, bool /*erase*/, TRect& rect) { RichCtrlApp *theApp = TYPESAFE_DOWNCAST(GetApplication(), RichCtrlApp); if (theApp) { // Only paint if we're printing and we have something to paint, otherwise do nothing. if (theApp->Printing && theApp->Printer && !rect.IsEmpty()) { // Use pageSize to get the size of the window to render into. For a Window it's the client area, // for a printer it's the printer DC dimensions and for print preview it's the layout window. TSize pageSize(rect.right - rect.left, rect.bottom - rect.top); TPrintDialog::TData &printerData = theApp->Printer->GetSetup(); // Do the text stuff: int fromPage = printerData.FromPage == -1 ? 1 : printerData.FromPage; int nPages; // rich text edit control stuff FORMATRANGE fmtRng; LONG textSent, totalAmount, textBegin; // Fill out the FORMATRANGE structure for the RTF output. fmtRng.hdc = fmtRng.hdcTarget = dc; // print device HDC fmtRng.chrg.cpMin = 0; fmtRng.chrg.cpMax = -1; // print entire contents fmtRng.rc.top = fmtRng.rcPage.top = fmtRng.rc.left = fmtRng.rcPage.left = 0; // get printer device capacity TSize printRes( dc.GetDeviceCaps(LOGPIXELSX), dc.GetDeviceCaps(LOGPIXELSY)); // Convert to TWIPS fmtRng.rc.right = fmtRng.rcPage.right = pageSize.cx * 1440 / printRes.cx; fmtRng.rc.bottom = fmtRng.rcPage.bottom = pageSize.cy * 1440 / printRes.cy; // minimum number of pages to print printerData.MinPage = 1; printerData.MaxPage = 1; // move to current page textBegin = textSent = 0; nPages = 1; totalAmount = SendMessage( WM_GETTEXTLENGTH, 0, 0); // determine how many pages are needed to print document while( textSent < totalAmount){ if( nPages == fromPage) textBegin = textSent; // format range but don't actually print it fmtRng.chrg.cpMin = textSent = SendMessage( EM_FORMATRANGE, false, (LPARAM) &fmtRng); printerData.MaxPage = nPages++; } // reset formatrange SendMessage( EM_FORMATRANGE, false, (LPARAM)0); fmtRng.chrg.cpMin = textBegin; // reset rc to rcPage size (rc was adjusted to area printed) fmtRng.rc.right = fmtRng.rcPage.right; fmtRng.rc.bottom = fmtRng.rcPage.bottom; // output text to printer or preview DC SendMessage( EM_FORMATRANGE, true, (LPARAM) &fmtRng); // reset formatrange SendMessage( EM_FORMATRANGE, true, (LPARAM)0); } } }