/******************************************************************************
* *
* RichEdit example program. Demonstrates some basics of a RichEdit control. *
* Allows you to change the text color on the fly, save and load RTF data *
* using stream callbacks. *
* *
******************************************************************************/
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#include "commdlg.h"
#include "richedit.h"
// === Function Prototypes ====================================================
BOOL WINAPI MainDlgProc( HWND, UINT, WPARAM, LPARAM );
BOOL SaveEditAsStream( HWND );
DWORD CALLBACK RTFSaveStreamCallback( DWORD, LPBYTE, LONG, LONG * );
BOOL LoadEditAsStream( HWND );
DWORD CALLBACK RTFLoadStreamCallback( DWORD, LPBYTE, LONG, LONG * );
BOOL GetNewTextColor( HWND );
// === Global Variables =======================================================
HINSTANCE hInst; // Program instance handle
HANDLE hRichEdit; // RICHED32.DLL handle
DWORD dwTextColor; // Current text color
// === Program Entry Points ===================================================
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmd,
int nShow )
{
hInst = hInstance; // Save program instance in global
hRichEdit = LoadLibrary( "RICHED32.DLL" ); // Load Rich Edit control
if( ! hRichEdit )
{ // If Rich Edit DLL load fails, exit
MessageBox( NULL, "Unable to load the Rich Edit control!",
"RETest", MB_OK | MB_ICONEXCLAMATION );
return( FALSE );
}
// Call main dialog box
DialogBox( hInst, MAKEINTRESOURCE( 10000 ), NULL, MainDlgProc );
FreeLibrary( hRichEdit ); // Release Rich Edit DLL before leaving
return( FALSE );
}
// === Main Dialog Proc =======================================================
BOOL WINAPI MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_INITDIALOG:
{
CHARFORMAT cf;
if( GetDlgItem( hDlg, 100 ) ) // Sanity Check
{
dwTextColor = 0x0000FF00;
memset( &cf, 0, sizeof(CHARFORMAT) ); // Initialize structure
cf.cbSize = sizeof(CHARFORMAT); // Initialize RichEdit
cf.dwMask = CFM_COLOR | CFM_FACE | CFM_SIZE; // control structure
cf.crTextColor = dwTextColor;
cf.yHeight = 32;
strcpy( cf.szFaceName, "Courier" );
// Set character formatting and background color
SendDlgItemMessage( hDlg, 100, EM_SETCHARFORMAT, 4, (LPARAM)&cf );
SendDlgItemMessage( hDlg, 100, EM_SETBKGNDCOLOR, FALSE, 0 );
}
return( TRUE ); // End of dialog initialization code
}
case WM_COMMAND:
if( wParam == 101 ) // "Color" button pressed
{
GetNewTextColor( hDlg ); // Get new color for text
SetFocus( GetDlgItem( hDlg, 100 ) ); // Back to edit control
break;
}
if( wParam == 102 ) // "Save" button pressed
{
SaveEditAsStream( hDlg ); // Save rich edit contents to file
SetFocus( GetDlgItem( hDlg, 100 ) ); // Back to edit control
break;
}
if( wParam == 103 ) // "Load" button pressed
{
LoadEditAsStream( hDlg ); // Load RTF file into richedit
SetFocus( GetDlgItem( hDlg, 100 ) ); // Back to edit control
break;
}
if( wParam == IDCANCEL ) // Close dialog if Esc pressed
{
EndDialog( hDlg, TRUE );
return( TRUE );
}
break;
}
return( FALSE );
} // End of MainDlgProc
// === Read RTF Data as a Rich Edit stream ====================================
BOOL SaveEditAsStream( HWND hDlg )
{
EDITSTREAM es;
LONG lOut;
OPENFILENAME ofn;
HANDLE hFile;
char szFilename[ 256 ];
memset( &ofn, 0, sizeof(OPENFILENAME) ); // Initialize structure
strcpy( szFilename, "*.rtf" ); // Initialize filename field
ofn.lStructSize = sizeof(OPENFILENAME); // Fill in OPENFILENAME struct
ofn.hwndOwner = hDlg;
ofn.lpstrFilter = "RTF File\0*.rtf\0All Files\0*.*\0\0";
ofn.lpstrFile = szFilename;
ofn.nMaxFile = 256;
ofn.lpstrTitle = "Save RTF File";
ofn.Flags = OFN_OVERWRITEPROMPT;
if( ! GetSaveFileName( &ofn ) ) // Get a filename or quit
return( FALSE );
// Create the specified file
hFile = CreateFile( szFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE )
return( FALSE ); // Quit if file creation fails
es.dwCookie = (DWORD)hFile; // Pass file handle to callback
es.dwError = 0; // so the callback can do the file write
es.pfnCallback = (EDITSTREAMCALLBACK)RTFSaveStreamCallback;
// Start the callback proc
lOut = SendDlgItemMessage( hDlg, 100, EM_STREAMOUT, SF_RTF, (LPARAM)&es );
CloseHandle( hFile ); // Close file handle and exit
return( TRUE );
} // End of SaveEditAsStream
// === RichEdit RTF Output Stream Handler =====================================
DWORD CALLBACK RTFSaveStreamCallback( DWORD dwCookie, LPBYTE lpBuffer,
LONG lSize, LONG *plRead )
{
if( ! lSize ) // Sanity check...exit if nothing passed
return( 1 );
*plRead = 0; // Initialize "amount read" variable for WriteFile()
// dwCookie is the file handle
WriteFile( (HANDLE)dwCookie, lpBuffer, lSize, plRead, NULL );
return( 0 ); // Continue, if needed
}
// === Load RTF File into Rich Edit Control ===================================
BOOL LoadEditAsStream( HWND hDlg )
{
EDITSTREAM es;
LONG lOut;
OPENFILENAME ofn;
HANDLE hFile;
char szFilename[ 256 ];
memset( &ofn, 0, sizeof(OPENFILENAME) ); // Initialize OPENFILENAME struct
strcpy( szFilename, "*.rtf" ); // Initialize filename field
ofn.lStructSize = sizeof(OPENFILENAME); // Fill in structure
ofn.hwndOwner = hDlg;
ofn.lpstrFilter = "RTF File\0*.rtf\0All Files\0*.*\0\0";
ofn.lpstrFile = szFilename;
ofn.nMaxFile = 256;
ofn.lpstrTitle = "Open RTF File";
ofn.Flags = OFN_FILEMUSTEXIST;
if( ! GetOpenFileName( &ofn ) ) // Get file name or exit
return( FALSE );
// Attempt to open specified file
hFile = CreateFile( szFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE )
return( FALSE ); // Exit if open fails
es.dwCookie = (DWORD)hFile; // Pass file handle to callback
es.dwError = 0;
es.pfnCallback = (EDITSTREAMCALLBACK)RTFLoadStreamCallback;
// Start the callback proc
lOut = SendDlgItemMessage( hDlg, 100, EM_STREAMIN, SF_RTF, (LPARAM)&es );
CloseHandle( hFile ); // Close file handle before leaving
return( TRUE );
}
// === RichEdit RTF Input Stream Handler ======================================
DWORD CALLBACK RTFLoadStreamCallback( DWORD dwCookie, LPBYTE lpBuffer,
LONG lSize, LONG *plRead )
{
if( ! lSize ) // Sanity check...exit if nothing passed
return( 1 );
*plRead = 0; // Initialize amount read variable
// dwCookie is the file handle
ReadFile( (HANDLE)dwCookie, lpBuffer, lSize, plRead, NULL );
return( 0 );
}
// === Specify New Text Color =================================================
BOOL GetNewTextColor( HWND hDlg )
{
CHOOSECOLOR cc;
CHARFORMAT cf;
DWORD dwColors[ 16 ];
memset( &cc, 0, sizeof(CHOOSECOLOR) );
cc.lStructSize = sizeof(CHOOSECOLOR);
cc.hwndOwner = hDlg;
cc.lpCustColors = dwColors;
cc.Flags = CC_RGBINIT;
cc.rgbResult = dwTextColor;
if( ! ChooseColor( &cc ) )
return( FALSE );
dwTextColor = cc.rgbResult;
memset( &cf, 0, sizeof(CHARFORMAT) );
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_COLOR;
cf.crTextColor = dwTextColor;
SendDlgItemMessage( hDlg, 100, EM_SETCHARFORMAT,
SCF_SELECTION, (LPARAM)&cf );
return( TRUE );
}
// ============================================================================