Putting it all together: The Myword Application
The sample program shown in Figure 12-8 demonstrates many of the principles discussed in the preceding sections MyWord is a miniature word processor built around a CRichEditView MFC's CRichEditView class is like a CEditView on steroids;.. Based on the rich text edit control supplied in . the common controls library, it features superior text formatting capabilities and the ability to read and write rich text format (RTF) files with a simple function call myWord does not use all the features of a CRichEditView; in fact, it barely scratches the surface. (for a more in-depth look at CRichEditView, see the Wordpad sample program provided with MFC. The Wordpad files are the actual source code for the Wordpad applet that ships with Windows.) But myWord packs a lot of punch for a program That's Only A Few Hundred Lines Long, And It's A Good Starting Point for Writing CricheditView-based Applications of Your Own.
Figure 12-8. The myword window.
MyWord uses two toolbars and one status bar. The main toolbar includes buttons that serve as shortcuts for the New, Open, and Save items in the File menu and the Cut, Copy, Paste, and Undo items in the Edit menu. The other toolbar , which I'll refer to as the style bar, includes check push buttons for setting the character format (bold, italic, and underline), radio push buttons for setting the paragraph alignment (left aligned, centered, and right aligned), and . combo boxes for selecting typefaces and font sizes Both toolbars can be detached from the frame window, floated, and docked at other locations; and both can be resized while they're floating Try it: Drag the main toolbar to the right side of. the window, and dock it in a vertical position. Grab the style bar and release it in the center of the window so that it becomes a floating palette. Use the View menu to hide and display the toolbars and the status bar. You can also Hide a Toolbar by Clicking The Close Button in the mini f .....................
The status bar at the bottom of MyWord's frame window displays help text for menu items and toolbar controls. It also includes Caps Lock and Num Lock indicators and a line number display that's continually updated as the caret moves through the document. The Caps Lock and Num Lock indicators were added using MFC's predefined ID_INDICATOR_CAPS and ID_INDICATOR_NUM IDs. The line number indicator is updated by an ON_UPDATE_COMMAND_UI handler that, when called, retrieves the current line number from the CRichEditView, formulates a text string containing the line number, and updates the status bar display with CCmdUI :: SetText. The line number pane is sized to fit the dummy string "Line 00000," whose resource ID, ID_INDICATOR_LINE, is identical to the status bar pane's ID. The dummy string is never seen because the pane is updated with A REAL LINE NUMBER Before The Status Bar Appears on The screen.
I used AppWizard to begin MyWord. I checked the Docking Toolbar and Initial Status Bar options in AppWizard's Step 4 dialog box, and in Step 6, I selected CRichEditView as the base class for the view. I next derived a class named CStyleBar to represent the style bar, added a CStyleBar data member to the frame window class, and modified the frame window's OnCreate function to create the style bar. (I used ClassWizard to perform the class derivation, but because ClassWizard does not support CToolBar as a base class, I derived CStyleBar from CCmdTarget and then manually patched up the code to change the base class to CToolBar.) I used Visual C 's Insert-Resource command to create the toolbar resource from which the style bar is created, and I added buttons in the toolbar editor .......................................... and style bar classes is listed in Figure 12-9. Take a moment to look it over to see how the toolbars and status bar are handled. Then go to "The Main Toolbar" to read about pertinent parts of the source code in greater detail .
Figure 12-9. The myword application.
Mainfrm.h // mainfrm.h: interface of the cmainframe class
//
///
#if! defined (
AFX_MAINFRM_H__C85C9089_A154_11D2_8E53_006008A82731__included_)
#define AFX_MAINFRM_H__C85C9089_A154_11D2_8E53_006008A82731__included_
#include "stylebar.h" // address by classview
#iF _MSC_VER> 1000
#pragma overce
#ENDIF / / 100 m _ _ _
Class CMAINFRAME: PUBLIC CFRAMEWND
{
protected: // Create from Serialization Only
CMAINFRAME ();
Declare_Dyncreate (CMAINFRAME) // attributes
PUBLIC:
// Operations
PUBLIC:
// Overrides
// ClassWizard Generated Virtual Function Overrides
// {{AFX_VIRTUAL (CMAINFRAME)
Virtual Bool PrecreateWindow (CreateStruct & Cs);
//}} AFX_VIRTUAL
// Implementation
PUBLIC:
Virtual ~ cmainframe ();
#ifdef _Debug
Virtual void assertvalid () const;
Virtual Void Dump (CDumpContext & DC) Const;
#ENDIF
protected: // control bar Embedded Member
CStylebar M_WndStylebar;
CSTATUSBAR M_WNDSTATUSBAR;
CToolbar M_Wndtoolbar;
// generated message map functions
protected:
Bool CreateToolbar ();
Bool createstylebar ();
Bool createstatusbar ();
// {{AFX_MSG (CMAINFRAME)
AFX_MSG Int Oncreate (LPCReatestruct LPCreateStruct);
AFX_MSG void onclose ();
//}} AFX_MSG
Declare_message_map ()
}
///
// {{AFX_INSERT_LOCATION}}
// Microsoft Visual C Will Insert Additional Declarations
// Immediately Before The Previous Line.
#ENDIF
//! Defined (AFX_MAINFRM_H__C85C9089_A154_11D2_8E53_006008A82731__INCLUDED_)
Mainfrm.cpp // mainfrm.cpp: importation of the cmainframe class
//
#include "stdafx.h"
#include "myword.h"
#include "mainfrm.h"
#ifdef _Debug
#define new debug_new
#undef this_file
Static char this_file [] = __file__;
#ENDIF
///
// CMAINFRAME
Implement_dyncreate (CMAINFRAME, CFRAMEWND)
Begin_MESSAGE_MAP (CMAINFRAME, CFRAMEWND)
// {{AFX_MSG_MAP (CMAINFRAME)
ON_WM_CREATE ()
ON_WM_CLOSE ()
//}} AFX_MSG_MAP
ON_COMMAND_EX (idw_style_bar, onbarcheck)
ON_UPDATE_COMMAND_UI (IDW_Style_bar, OnupdateControlbarmenu)
END_MESSAGE_MAP ()
///
// CMAINFRAME CONSTRUCTION / DESTRUCTION
CMAINFRAME :: CMAINFRAME ()
{
}
CMAINFRAME :: ~ cmainframe ()
{
}
INT CMAINFRAME :: OnCreate (lpcreatestruct lpcreatestruct) {
IF (cframewnd :: oncreate (lpcreatestruct) == -1)
Return -1;
//
// Tell the frame window to permit docking.
//
Enabledocking (CBRS_ALIGN_ANY);
//
// Create The Toolbar, Style Bar, And Status Bar.
//
IF (! CreateToolbar () ||
CREATESTYLBAR () ||
CreateStatusbar ())
Return -1;
//
// load the Saved Bar State (if any).
//
Loadbarstate (_T ("mainbarstate")));
Return 0;
}
Bool CMAINFRAME :: PrecreateWindow (CreateStruct & Cs)
{
IF (! cframeWnd :: PrecreateWindow (CS))
Return False;
Return True;
}
///
// CMAINFRAME DIAGNOSTICS
#ifdef _Debug
Void CMAINFRAME :: assertvalid () const
{
CframeWnd :: assertvalid ();
}
Void CMAINFRAME :: Dump (CDumpContext & DC) Const
{
CframeWnd :: DUMP (DC);
}
#ENDIF / / _ Debug
///
// CMAINFRAME MESSAGE HANDLERS
Void cmainframe :: onClose ()
{
Savebarstate (_t ("mainbarstate"));
CframeWnd :: onClose ();
}
Bool CMAINFRAME :: CreateToolbar ()
{
IF (! m_wndtoolbar.create (this) ||
! m_wndtoolbar.loadtoolbar (idR_mainframe))
Return False;
m_wndtoolbar.setbarstyle (m_wndtoolbar.get barStyle () |
CBRS_Tooltips | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
m_wndtoolbar.SetWindowText (_t ("main"));
m_wndtoolbar.enabledocking (CBRS_ALIGN_ANY);
DockControlbar (& M_WndToolbar);
Return True;
}
Bool CMAINFRAME :: CreateStylebar ()
{
IF (! m_wndstylebar.create (this, ws_child | ws_visible | CBRS_TOP |
CBRS_ToolTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC, IDW_STYLE_BAR))
Return False;
M_WndStyleBar.SetWindowText (_t ("styles"));
M_WndStylebar.enableDocking (CBRS_ALIGN_TOP | CBRS_ALIGN_BOTTOM);
DockControlbar; & m_WndStylebar;
Return True;
}
Bool CMAINFRAME :: Createstatusbar ()
{
Static uint nindicators [] = {ID_SEPARATOR,
ID_Indicator_Line,
ID_indicator_caps,
ID_indicator_num
}
IF (! m_wndstatusbar.create (this))
Return False;
M_WndStatusBar.Setindicators (Nindicators, 4);
Return True;
}
Myworddoc.h // myworddoc.h: interface of the cmywordddoc class
//
///
#if! defined (
AFX_MYWORDDOC_H__C85C908B_A154_11D2_8E53_006008A82731__included_)
#define AFX_MYWORDDOC_H__C85C908B_A154_11D2_8E53_006008A82731__included_
#iF _MSC_VER> 1000
#pragma overce
#ENDIF / / 100 m _ _ _
Class CMYWORDDOC: PUBLIC CRICHEDITDOC
{
protected: // Create from Serialization Only
CMYWORDDOC ();
Declare_DyncReate (CMYWORDDOC)
// attributes
PUBLIC:
// Operations
PUBLIC:
// Overrides
// ClassWizard Generated Virtual Function Overrides
// {{AFX_VIRTUAL (CMYWORDDOC)
PUBLIC:
Virtual bool onnewdocument ();
Virtual Void Serialize (CARCHIVE & A);
//}} AFX_VIRTUAL
Virtual crichditcntritem * createclientItem (Reobject * preo) const;
// Implementation
PUBLIC:
Virtual ~ cmywordddoc ();
#ifdef _Debug
Virtual void assertvalid () const;
Virtual Void Dump (CDumpContext & DC) Const;
#ENDIF
protected:
// generated message map functions
protected:
// {{AFX_MSG (CMYWORDDOC)
// Note - The ClassWizard Will Add and Remove Member functions here.
// Do Not Edit What You See in these Blocks of generated code!
//}} AFX_MSG
Declare_message_map ()
}
///
// {{AFX_INSERT_LOCATION}}
// Microsoft Visual C Will Insert Additional Declarations
// Immediately Before The Previous Line.
#ENDIF
//! Defined (
// AFX_MYWORDDOC_H__C85C908B_A154_11D2_8E53_006008A82731__included_)
MywordDoc.cpp // myworddoc.cpp: Implementation of the cmywordddoc Class
//
#include "stdafx.h"
#include "myword.h" #include "myworddoc.h"
#include "cntritem.h"
#ifdef _Debug
#define new debug_new
#undef this_file
Static char this_file [] = __file__;
#ENDIF
///
// CMYWORDDOC
Implement_dyncreate (CMYWORDDOC, CRICHEDITDOC)
Begin_MESSAGE_MAP (CMYWORDDOC, CRICHEDITDOC)
// {{AFX_MSG_MAP (CMYWORDDOC)
// Note - The Classwizard Will Add and Remove Mapping Macros Here.
// Do Not Edit What You See in these Blocks of generated code!
//}} AFX_MSG_MAP
// enable default ole Container Implementation
ON_UPDATE_COMMAND_UI (id_ole_edit_links,
Cricheditdoc :: onupdateEditlinksmenu)
ON_COMMAND (ID_OLE_EDIT_LINKS, CRICHEDITDOC :: OneDitLinks)
ON_UPDATE_COMMAND_UI_RANGE (ID_OLE_VERB_FIRST,
ID_OLE_VERB_LAST, CRICHEDITDOC :: OnUpdateObjectverbmenu)
END_MESSAGE_MAP ()
///
// CMYWORDDOC Construction / Destruction
CMYWORDDOC :: CMYWORDDOC ()
{
}
CMYWORDDOC :: ~ CMYWORDDOC ()
{
}
Bool CMYWORDDOC :: OnNewDocument ()
{
IF (! cricheditdoc :: onnewdocument ())
Return False;
Return True;
}
CRICHEDITCNTRITEM * CMYWORDDOC :: CreateClientItem (Reobject * preo) Const
{
Return New CMYwordcntritem (preo, (cmyworddoc *);
}
///
// CMYWORDDOC Serialization
Void CMYWORDDOC :: Serialize (CARCHIVE & A)
{
Cricheditdoc :: serialize (ar);
}
///
// CMYWORDDOC DIAGNOSTICS
#ifdef _Debug
Void CMYWORDDOC :: AssertValid () Const
{
Cricheditdoc :: assertvalid ();
}
Void CMYWORDDOC :: Dump (CDumpContext & DC) Const
{
Cricheditdoc :: Dump (DC);
}
#ENDIF / / _ Debug
///
// CMYWORDDOC CommANDS
MywordView.h // mywordview.h: interface of the cmywordview class
//
///
#if! defined (
AFX_MYWORDVIEW_H__C85C908D_A154_11D2_8E53_006008A82731__included_)
#define AFX_MYWORDVIEW_H__C85C908D_A154_11D2_8E53_006008A82731__included_
#if _MSC_VER> 1000 # Pragma ONCE
#ENDIF / / 100 m _ _ _
Class CMYWORDCNTRITEM;
Class CMYWORDVIEW: PUBLIC CRICHEDITVIEW
{
protected: // Create from Serialization Only
CMYWORDVIEW ();
Declare_DyncReate (CMYWORDVIEW)
// attributes
PUBLIC:
CMYWORDDOC * GETDocument ();
// Operations
PUBLIC:
Void getFontInfo (LPTSTSTSTSTSTSTSZZFACENAME, INT & NSIZE);
Void Changefont (LPCTSTR PSZFACENAME);
Void Changefontsize; INT NSize
// Overrides
// ClassWizard Generated Virtual Function Overrides
// {{AFX_VIRTUAL (CMYWORDVIEW)
PUBLIC:
Virtual Bool PrecreateWindow (CreateStruct & Cs);
protected:
Virtual void OnInitialUpdate (); // Called First Time After Construct
//}} AFX_VIRTUAL
// Implementation
PUBLIC:
Virtual ~ cmywordview ();
#ifdef _Debug
Virtual void assertvalid () const;
Virtual Void Dump (CDumpContext & DC) Const;
#ENDIF
protected:
// generated message map functions
protected:
// {{AFX_MSG (CMYWORDVIEW)
AFX_MSG void onDestroy ();
AFX_MSG void oncharbold ();
AFX_MSG void oncharital ();
AFX_MSG void oncharunderline ();
AFX_MSG void onparaleft ();
AFX_MSG void onparacnter ();
AFX_MSG void onpararight ();
AFX_MSG Void OnUpdateCharBold (ccmdui * pcmdui);
AFX_MSG Void OnupdateCharital (CCMDUI * PCMDUI);
AFX_MSG void onupdatecharunderline (ccmdui * pcmdui);
AFX_MSG Void OnUpdateParaleft (ccmdui * pcmdui);
AFX_MSG Void OnUpdateParacenter (CCMDUI * PCMDUI);
AFX_MSG Void OnupdatePararight (ccmdui * pcmdui);
//}} AFX_MSG
AFX_MSG Void Onupdatelinenumber (CCMDUI * PCMDUI);
Declare_message_map ()
}
#ifndef _debug // debug version in MywordView.cpp
Inline CMYWORDDOC * CMYWORDVIEW :: getDocument ()
{Return (CMYWORDDOC *) m_pdocument;
#ENDIF
///
// {{AFX_INSERT_LOCATION}}
// Microsoft Visual C Will Insert Additional Declarations // Immediately Before The Previous Line.
#ENDIF
//! Defined (
// AFX_MYWORDVIEW_H__C85C908D_A154_11D2_8E53_006008A82731__included_)
MywordView.cpp // mywordview.cpp: Implementation of the cmywordView Class
//
#include "stdafx.h"
#include "myword.h"
#include "myworddoc.h"
#include "cntritem.h"
#include "mywordview.h"
#ifdef _Debug
#define new debug_new
#undef this_file
Static char this_file [] = __file__;
#ENDIF
///
// CMYWordView
Implement_dyncreate (CMYWORDVIEW, CRICHEDITVIEW)
Begin_MESSAGE_MAP (CMYWORDVIEW, CRICHEDITVIEW)
// {{AFX_MSG_MAP (CMYWORDVIEW)
ON_WM_DESTROY ()
ON_COMMAND (ID_CHAR_BOLD, ONCHARBOLD)
ON_COMMAND (ID_CHAR_ITALIC, ONCHARITIC)
ON_COMMAND (ID_CHAR_UNDERLINE, OnCHARUNDERLINE)
ON_COMMAND (ID_PARA_LEFT, ONPARALEFT)
ON_COMMAND (ID_PARA_CENTER, OONPARACENTER)
ON_COMMAND (ID_PARA_RIGHT, ONPARARight)
ON_UPDATE_COMMAND_UI (ID_CHAR_BOLD, ONUPDATECHARBOLD)
ON_UPDATE_COMMAND_UI (id_char_italic, onupdatecharital)
ON_UPDATE_COMMAND_UI (ID_CHAR_UNDERLINE, ONUPDATECHARUNDERLINE)
ON_UPDATE_COMMAND_UI (id_para_left, onupdateparaaleft)
ON_UPDATE_COMMAND_UI (ID_PARA_CENTER, ONUPDATEPARACENTER)
ON_UPDATE_COMMAND_UI (ID_PARA_RIGHT, ONUPDATEPARARIGHT)
//}} AFX_MSG_MAP
ON_UPDATE_COMMAND_UI (id_indicator_line, onupdatelinenumber)
END_MESSAGE_MAP ()
///
// CMYWordView Construction / Destruction
CMYWORDVIEW :: CMYWORDVIEW ()
{
}
CMYWORDVIEW :: ~ CMYWORDVIEW ()
{
}
Bool CMYWORDVIEW :: PrecreateWindow (CreateStruct & Cs)
{
Return CricheditView :: PrecreateWindow (CS);
}
Void cMywordView :: onInitialupdate ()
{
Cricheditview :: oninitialupdate ();
CharFormat CF;
Cf.cbsize = sizeof (charformat);
Cf.dwmask = cfm_bold | cfm_italic | cfm_underline | cfm_protaced | cfm_strikeout | cfm_face | cfm_size;
Cf.dweffects = 0;
Cf.YHEight = 240; // 240 twips == 12 Points
:: lstrcpy (cf.szfacename, _t ("Times New Roman");
SetcharFormat (CF);
}
Void CMYWordView :: ONDESTROY ()
{
// deactivate the item on destruction; this is importantant
// When a splitter view is being used.
CricheditView :: ONDESTROY ();
ColeClientItem * PactiveItem = getDocument () -> GetInplaceActiveItem (this);
IF (PACTIVEITEM! = null && pactiveItem-> getActiveView () == this)
{
PACTIVEITEM-> deActivate ();
Assert (GetDocument () -> GetInplaceActiveItem (this) == null);
}
}
///
// CMYWORDVIEW DIAGNOSTICS
#ifdef _Debug
Void CMYWORDVIEW :: assertvalid () const
{
Cricheditview :: assertvalid ();
}
Void CMYWORDVIEW :: Dump (CDumpContext & DC) Const
{
CRICHEDITVIEW :: DUMP (DC);
}
CMYWORDDOC * CMYWORDVIEW :: getDocument () // Non-debug version is inline
{
Assert (m_pdocument-> iskindof (runtime_class (cmywordddoc));
Return (CMYWORDDOC *) m_pdocument;
}
#ENDIF / / _ Debug
///
// CMYWordView Message Handlers
Void CMYWordView :: oncharbold ()
{
CharFormat CF;
Cf = getcharformatselection ();
IF (! (cf.dwmask & cfm_bold) ||! (cf.dweffects & cfe_bold))
Cf.dweffects = cfe_bold;
Else
Cf.dweffects = 0;
Cf.dwmask = cfm_bold;
SetcharFormat (CF);
}
Void CMYWordView :: oncharital ()
{
CharFormat CF;
Cf = getcharformatselection ();
IF (! (cf.dwmask & cfm_italic) ||! (cf.dweffects & cfe_italic))
Cf.dweffects = cfe_ital;
Else
Cf.dweffects = 0;
Cf.dwmask = cfm_italic;
SetcharFormat (CF);
}
Void CMYWordView :: oncharunderline ()
{
CharFormat CF;
Cf = getcharformatselection (); if (! (cf.dwmask & cfm_underline) ||! (cf.dweffects & cfe_underline))
Cf.dweffects = cfe_underline;
Else
Cf.dweffects = 0;
Cf.dwmask = CFM_UNDERLINE;
SetcharFormat (CF);
}
Void CMYWordView :: onpaaleft ()
{
OnpaAlign (PFA_LEFT);
}
Void CMYWordView :: onpaacenter ()
{
ONPARAALIGN (PFA_CENTER);
}
Void cMywordView :: onpaRight ()
{
ONPARAALIGN (PFA_RIGHT);
}
Void CMYwordView :: onupdatecharbold (ccmdui * pcmdui)
{
OnUpdateChareffect (PCMDUI, CFM_BOLD, CFE_BOLD);
}
Void CMYWORDVIEW :: OnupdateCharitalic (ccmdui * pcmdui)
{
OnupdateChareffect (PCMDUI, CFM_ITALIC, CFE_ITALIC);
}
Void CMYWORDVIEW :: OnUpdateCharunderline (ccmdui * pcmdui)
{
OnUpdateChareffect (PCMDUI, CFM_UNDERLINE, CFE_UNDERLINE);
}
Void CMYWordView :: OnUpdateParaleft (ccmdui * pcmdui)
{
OnUpdateparaalign (PCMDUI, PFA_LEFT);
}
Void CMYWordView :: onupdateparacter (ccmdui * pcmdui)
{
OnUpdateparaalign (PCMDUI, PFA_Center);
}
Void CMYwordView :: onupdatePararight (ccmdui * pcmdui)
{
OnupdateParaalign (PCMDUI, PFA_RIGHT);
}
Void CMYWordView :: onupdatelinenumber (ccmdui * pcmdui)
{
Int nline = getricheditctrl () .LineFromchar (-1) 1;
CString string;
String.Format (_T ("line% d"), nline);
PCMDUI-> Enable (TRUE);
PCMDUI-> setText (String);
}
Void CMYWordView :: Changefont (LPCTSTR PSZFACENAME)
{
CharFormat CF;
Cf.cbsize = sizeof (charformat);
Cf.dwmask = cfm_face;
:: lstrcpy (cf.szfaceename, pszfacename);
SetcharFormat (CF);
}
Void CMYWordView :: Changefontsize (int nsize)
{
CharFormat CF;
Cf.cbsize = sizeof (charformat);
Cf.dwmask = cfm_size;
Cf.YHEight = nsize;
SetcharFormat (CF);
}
Void CMYWordView :: getFontInfo (LPTSTSTSTINFA (INT & NSIZE) {
Charformat cf = getcharformatselection ();
:: lstrcpy (pszfacename,
Cf.dwmask & cfm_face? cf.szfacename: _t (""));
nsize = cf.dwmask & cfm_size? cf.YHEight: -1;
}
STYLEBAR.H # ix! Defined (
AFX_STYLEBAR_H__C85C9099_A154_11D2_8E53_006008A82731__included_)
#define AFX_StyleBar_H__C85C9099_A154_11D2_8E53_006008A82731__included_
#iF _MSC_VER> 1000
#pragma overce
#ENDIF / / 100 m _ _ _
// stylebar.h: Header File
//
///
// cStylebar Command Target
Class CStylebar: Public CToolbar
{
// attributes
PUBLIC:
// Operations
PUBLIC:
Static int Callback EnumfontNameProc (Enumlogfont * LPelf,
NewTextMetric * LPNTM, INT NFONTTYPE, LPARAM LPARAM;
// Overrides
// ClassWizard Generated Virtual Function Overrides
// {{AFX_VIRTUAL (CStyleBar)
//}} AFX_VIRTUAL
Virtual void onupdatecmdui (cframewnd * ptarget,
Bool bdisableifnohndler;
// Implementation
protected:
Void InitTypefacelist (CDC * PDC);
CFont M_Font;
CCOMBOBOX M_WNDFONTNAMES;
CCOMBOBOX M_WNDFONTSIZES;
// generated message map functions
// {{AFX_MSG (cStylebar)
AFX_MSG Int Oncreate (LPCReatestruct LPCreateStruct);
//}} AFX_MSG
AFX_MSG VOID ONSELECTFONT ();
AFX_MSG VOID ONSELECTSIZE ();
AFX_MSG void onCloseup ();
Declare_message_map ()
}
///
// {{AFX_INSERT_LOCATION}}
// Microsoft Visual C Will Insert Additional Declarations
// Immediately Before The Previous Line.
#ENDIF
//! Defined (
// afX_StyleBar_H__C85C9099_A154_11D2_8E53_006008A82731__included_)
Stylebar.cpp // stylebar.cpp: importation file
//
#include "stdafx.h"
#include "myword.h"
#include "myworddoc.h"
#include "mywordview.h"
#include "stylebar.h" #ifdef _debug
#define new debug_new
#undef this_file
Static char this_file [] = __file__;
#ENDIF
///
// cStylebar
Begin_MESSAGE_MAP (CStylebar, Ctoolbar)
// {{AFX_MSG_MAP (cStylebar)
ON_WM_CREATE ()
//}} AFX_MSG_MAP
ON_CBN_SELENDOK (IDC_FontNames, OnsectFont)
ON_CBN_SELENDOK (IDC_FONTSIZES, ONSELECTSIZE)
ON_CBN_CLOSEUP (IDC_FontNames, OnCloseup)
ON_CBN_CLOSEUP (IDC_FONTSIZES, ONCLOSEUP)
END_MESSAGE_MAP ()
///
// cStylebar Message Handlers
INT CStylebar :: OnCreate (lpcreatestruct lpcreatestruct)
{
Static int nfontsizes [] = {
8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 32, 36, 48, 72
}
IF (ctoolbar :: oncreate (lpcreatestructure) == -1)
Return -1;
//
// load the Toolbar.
//
if (! loadingtoolbar (idr_style_bar))
Return -1;
//
// Create An 8-Point MS Sans Serif Font for the Combo Boxes.
//
CClientDC DC (this);
M_Font.createPointFont (80, _T ("MS Sans Serif");
CFont * PoldFont = Dc.selectObject (& m_font);
TextMetric TM;
Dc.getTextMetrics; & TM);
INT cxchar = tm.tmavecharwidth;
INT cychar = tm.tmheight tm.tmexternalleading;
Dc.selectObject (PoldFont);
//
// add the font name Combo Box to the Toolbar.
//
SetButtonInfo (8, IDC_FontNames, TBBS_SEPARATOR, CXCHAR * 32);
CRECT RECT;
GetItemRect (8, & Re);
Rect.bottom = Rect.top (Cychar * 16);
IF (! m_wndfontnames.create (ws_child | ws_visible | WS_VSCROLL |
CBS_DROPDOWNLIST | CBS_SORT, RECT, THIS, IDC_FONTNAMES)))
Return -1;
M_WndFontNames.SetFont (& m_font);
INITTYPEFACELIST (& DC);
//
// Add the font size combo box to the toolbar.
//
SetButtonInfo (10, IDC_FONTSIZES, TBBS_SEPARATOR, CXCHAR * 12);
GetItemRect (10, & Re);
Rect.bottom = Rect.top (CYCHAR * 14); if (! m_wndfontsizes.create (ws_child | ws_visible | WS_VSCROLL |
CBS_DROPDOWNLIST, RECT, THIS, IDC_FONTSIZES))))
Return -1;
M_WndFontSizes.SetFont (& m_font);
CString string;
Int ncount = sizeof (nfontsizes) / sizeof (int);
For (int i = 0; i String.format (_t ("% d"), nfontsizes [i]); m_wndfontsizes.addstring (String); } Return 0; } Void cStylebar :: OnsectFont () { Tchar SzFacename [lf_facesize]; INT NINDEX = M_WndFontNames.getcursel (); M_WndFontNames.getlbtext (NINDEX, SZFACENAME); CMYWORDVIEW * PVIEW = (CMYWORDVIEW *) ((cframewnd *) AFXGETMAINWND ()) -> getActiveView (); PView-> Changefont (Szfacename); } Void cStylebar :: OnseTsize () { Tchar szsize [8]; Int nindex = m_wndfontsizes.getcursel (); M_WndFontSizes.getlbtext (NINDEX, SZSIZE); INT nsize = atoi (szsize) * 20; // NEED TWIPS CMYWORDVIEW * PVIEW = (CMYWORDVIEW *) ((cframewnd *) AFXGETMAINWND ()) -> getActiveView (); PView-> Changefontsize (nsize); } Void cStylebar :: onCloseup () { ((Cframewnd *) AFXGETMAINWND ()) -> getActiveView () -> setfocus (); } Void cStylebar :: InitTypefaceList (CDC * PDC) { :: EnumfontFamilies (PDC-> M_HDC, NULL, (FontenumProc) EnumfontNameProc, (LPARAM) THIS } INUMFONTNAMEPROC (EnumfontNameProc) NewTextMetric * LPNTM, int NFONTTYPE, LPARAM LPARAM) { CStylebar * PWnd = (cStylebar *) LPARAM; IF (NFONTTYPE & TRUETYPE_FONTTYPE) PWND-> m_wndfontnames.addstring (lppelf-> elflogfont.lffacename); Return 1; } Void cStylebar :: onupdatecmdui (cframewnd * ptarget, bool bdisableifnohndler) { Ctoolbar :: onupdatecmdui (PTARGET, BDISABLEIFNOHNDLER); CWND * PWND = getfocus (); if ((PWND == & M_WndFontNames) || (PWND == & M_WndFontsizes)) Return; // // Get the font name and size. // int NTWIPS; Tchar SzFacename [lf_facesize]; CMYWORDVIEW * PVIEW = (CMYWORDVIEW *) ((cframewnd *) AFXGETMAINWND ()) -> getActiveView (); PView-> GetFontInfo (SZFACENAME, NTWIPS); // // Update the font name Combo Box. // Tchar szselection [lf_facesize]; M_WndFontNames.GetWindowText (SzseLection, SizeOf (SzseLection) / sizeof (tchar)); IF (: lstrcmp (szfaceename, szselection)! = 0) { IF (SZFACENAME [0] == 0) m_wndfontnames.setcurseel (-1); Else { IF (m_wndfontnames.selectstring (-1, szfacename) == CB_ERR) m_wndfontnames.setcurseel (-1); } } // // Update the font size combo box. // Tchar szsize [4]; m_wndfontsizes.getWindowText (szsize, Sizeof (szsize) / sizeof (tchar)); INT nsizefromcomboBOX = ATOI (szsize); INT nsizefromview = ntwips / 20; IF (nsizefromcomboBox! = nsizefromview) { IF (NTWIPS == -1) m_wndfontsizes.setcursel (-1); Else { CString string; String.Format (_t ("% d"), nsizefromview; IF (m_wndfontsizes.selectstring (-1, string) == CB_ERR) m_wndfontsizes.setcursel (-1); } } } The main Toolbar MyWord's main toolbar is a standard CToolBar that's created along with the style bar and status bar in CMainFrame :: OnCreate. After the main toolbar is created, the styles CBRS_TOOLTIPS, CBRS_FLYBY, and CBRS_SIZE_DYNAMIC are added and CToolBar :: EnableDocking is called with a CBRS_ALIGN_ANY parameter so that the toolbar can be docked to any side of the frame window. DockControlBar is called to dock the toolbar in its default location at the top of the window so that it can be detached and floated. The call to LoadBarState in CMainFrame :: OnCreate restores the toolbar to its previous location if the application has been run before.Handlers for all the buttons on the main toolbar-and for all the items in myWord's menus, for that matter-are provided by the framework. As usual, CWinApp provides Handlers for the New, Open, And Exit Commands in The File Menu, And CDocument Handles The Save and Save As Commands. CricheditView Provides Handlers for The Items in The Edit Menu (All Prewired Into th e message map, of course), and CFrameWnd handles the commands in the View menu. CRichEditView also provides update handlers for Edit commands, which explains why the Cut, Copy, Paste, and Undo buttons in the toolbar are automatically enabled and disabled in response to actions performed by the user. to see what I mean, type a line or two of text and highlight a few characters to form a selection. The Cut and Copy buttons will light up when the first character is selected and blink out again when the Selection is canledled. Updates Are Automatic Because of the Following Entries in CricheditView's Message Map: ON_UPDATE_COMMAND_UI (ID_EDit_cut, onupdateneedsel) ON_UPDATE_COMMAND_UI (id_edit_copy, onupdateneedsel) Scan the cricheditview message map in the mfc source code file viewrich.cpp to see the full of commists for which crichditview provides default Command and update handlers.the style bar MyWord's style bar is an instance of the CToolBar-derived class CStyleBar. The style bar is constructed when the frame window is constructed and created in CMainFrame :: OnCreate, but it also contains its own OnCreate handler that creates and initializes the font name and font . size combo boxes Other CStyleBar member functions include OnSelectFont, which applies typefaces selected from the font name combo box; OnSelectSize, which applies sizes selected from the font size combo box; OnCloseUp, which restores the input focus to the view when either combo box's drop -down list box is closed; InitTypefaceList and EnumFontNameProc, which work together to enumerate fonts and add their names to the font name combo box; and OnUpdateCmdUI, which updates the combo boxes so that the font name and the font size shown in the style bar Are consistent with the character at the care or the characters in a selection. MYWORD'S VIEW CLASS Provides Command and Update Handlers for the Buttons In The Style Bar. Clicking The Bold Button, for Example, Activates CMYWORDVIEW :: OnCharBold, Which IS IMPLEMENTED AS FOLLOWS: Void CMYWordView :: oncharbold () { CharFormat CF; Cf = getcharformatselection (); IF (! (cf.dwmask & cfm_bold) ||! (cf.dweffects & cfe_bold)) Cf.dweffects = cfe_bold; Else Cf.dweffects = 0; Cf.dwmask = cfm_bold; SetcharFormat (CF); } GetCharFormatSelection is a CRichEditView function that returns a CHARFORMAT structure containing information about the text that is currently selected in the view or, if there is no selection, about the default character format. SetCharFormat is another CRichEditView function that applies the text attributes described in a CHARFORMAT structure to the selected text. If no text is currently selected, SetCharFormat sets the view's default character format.Boldface text is toggled on or off by setting the CFM_BOLD bit in the dwMask field of the CHARFORMAT structure passed to SetCharFormat and either setting or clearing the CFE_BOLD bit in the structure's dwEffects field. To determine the proper setting for the CFE_BOLD flag, OnCharBold inspects both the CFM_BOLD and CFE_BOLD flags in the CHARFORMAT structure returned by GetCharFormatSelection. The CFM_BOLD flag is clear if the current selection includes a mix of bold and nonbold Text. if cfm_bold is set, Either The Selection Consists Enti rely of bold or nonbold text or no text is currently selected. In either case, the CFE_BOLD flag indicates whether the selected (or default) text is bold or nonbold. OnCharBold can be called in five possible scenarios. The following table describes each set of . Circumstances Under Which OnCharBold Is CalleddwMask & CFM_BOLDdwEffects & CFE_BOLDAction Taken by OnCharBoldOne or more characters are selected; the selection contains a mix of bold and nonbold text.0UndefinedMakes all characters in the selection bold.One or more characters are selected; the selection consists entirely of bold text.NonzeroNonzeroMakes all characters in the selection nonbold.One or more characters are selected; the selection consists entirely of nonbold text.Nonzero0Makes all characters in the selection bold.No text is selected; the default character format is bold.NonzeroNonzeroSets the default character format to nonbold.No text is selected; the default character format is nonbold.Nonzero0Sets the default character format to bold.The handlers for the paragraph alignment buttons are simpler because their actions do not depend on the current paragraph alignment CRichEditView provides a convenient OnParaAlign. Function for Setting The Paragraph Alignment To Left, Right, O (unfortunately, neither a cricheditview nor the rich edit control trory) the widtified text trusts the width pETWEEN Both margins.) The Statement OnpaAlign (PFA_LEFT); in OnParaLeft selects left-aligned text. If no text is selected in the view, OnParaAlign reformats the paragraph that contains the caret. If text is selected, all paragraphs touched by the selection are transformed so that the text in them is left aligned. Each button in the style bar is mapped to an update handler that calls either CRichEditView :: OnUpdateCharEffect or CRichEditView :: OnUpdateParaAlign. In addition to checking and unchecking the buttons as appropriate, these CRichEditView functions also set a button to the indeterminate state when a selection includes a mix of character formats or paragraph alignments. For a simple demonstration, try this test. First enter some text if you have not already. Then highlight some characters, click the Italic button to italicize the selection, and select a range of characters that includes both italicized and nonitalicized text. Because OnUpdateCharItalic calls OnUpdateCharEffect, the Italic button will become half-grayed, indicating that the selection contains a mix of character formats. and because each style bar button is assigned an update handler, the buttons behave like check Push Buttons and Radio Push Buttons Even Though None Is Assigned The Tbbs_Checkbox or Tbbs_CheckGroup Style.when a font name or a font size is selected from the combo boxes, the style bar retrieves the font name or font size and calls a public member function of the view class to implement the change. Selecting a font name activates CStyleBar :: OnSelectFont, which . passes the new typeface name to the view through CMyWordView :: ChangeFont ChangeFont, in turn, changes the font in the view by setting the CFM_FACE flag in a CHARFORMAT structure's dwMask field, copying the typeface name to the structure's szFaceName field and calling SetCharFormat: Void CMYWordView :: Changefont (LPCTSTR PSZFACENAME) { CharFormat CF; Cf.cbsize = sizeof (charformat); Cf.dwmask = cfm_face; :: lstrcpy (cf.szfaceename, pszfacename); SetcharFormat (CF); } CStyleBar :: OnSelectSize uses a similar procedure to change the font size through the view's ChangeFontSize member function. Font sizes passed to CRichEditViews are expressed in twips, where 1 twip equals 1/20 of a point. Therefore, OnSelectSize multiplies the point size retrieved from The Combo Box by 20 to Convert Points To Twips Before Calling Changefontsize. Which brings up a question: Because the command message generated when an item is selected from a combo box is subject to command routing, why does not MyWord let the view handle combo box notifications directly Actually, that would be ideal But it would?. also pose a problem. Because the combo boxes are protected members of the style bar class, the view would have no way of retrieving the selected item from the combo box. We could fix that by making the combo boxes public data members and the style bar a public data member of the frame window class, but protected data members provide stricter encapsulation. Letting the style bar handle combo box notifications and pass the information to the view through public member functions allows the style bar to hide its data yet still communicate style changes To the view. So that the items selected in the combo boxes will match the character format in the view as the caret is moved through the document and selections are made, CStyleBar overrides the OnUpdateCmdUI function it inherits from CToolBar and updates the combo boxes based on information obtained from the view. After verifying that neither of the combo boxes has the input focus so that the combo boxes will not flicker if OnUpdateCmdUI is called while a drop-down list box is displayed, OnUpdateCmdUI calls CMyWordView :: GetFontInfo to get the current font name and size. If the font name obtained from the view does not match the font name selected in the font name combo box, OnUpdateCmdUI changes the combo box selection. Similarly, the selection is updated in the font size combo box if the size shown in the Combo box doesn't match the size reported by getFontinfo. Leaving the current selection intact if it isn't change prevents the Combo Boxes from Flickering As a Result of Repeated (and Unnecessary) updates. The update handler is also smart enough to blank the combo box selection if the font name or font size obtained from GetFontInfo does not match any of the items in the combo box or if the text selected in the view contains a mixture of typefaces OR font sizes. One thing CStyleBar does not do is update the list of typefaces in the font name combo box if the pool of installed fonts changes while MyWord is running. When fonts are added or deleted, Windows sends all top-level windows a WM_FONTCHANGE message notifying them of the change. to respond to changes in font availability while an application is running, include an ON_WM_FONTCHANGE entry in the frame window's message map and an OnFontChange handler to go with it. The message-map entry and handler must be members of the frame window class because WM_FONTCHANGE messages are not routed, whereas command messages are.To simplify the logic for updating the selection in the font size combo box, myWord's style bar lists TrueType fonts only. If the font name combo box included raster fonts as well, the font SIZE Combo Box Would NEED TO BE REINITIALIZED EACH TIME THE SELECTION CHENED IN THE IN A LIMITED NUMBER OF SIZES. LIMITING THE USER's Choice of FON ts to TrueType only makes the point sizes listed in the font size combo box independent of the typeface selected in the font name combo box because TrueType fonts can be accurately rendered in any point size from 1 through 999. More about cricheditview Most of MyWord's functionality comes from CRichEditView, which is built around the powerful rich text edit control provided in the common controls library MFC's CRichEditView class does not act alone in encapsulating the features of a rich text edit control;. Help comes from CRichEditDoc and CRichEditCntrItem . CRichEditDoc represents the data stored in a CRichEditView, which can include linked and embedded OLE objects, and CRichEditCntrItem represents OLE objects contained in a CRichEditView.When you derive a view class from CRichEditView, you must also derive a document class from CRichEditDoc and override CRichEditDoc :: CreateClientItem, Which Is Pure Virtual. Myword's CMYWORDDOC Document Class Implements CreateClientIntItem By Creating a cricheditcntritem Object and return a Pointer: CRICHEDITCNTRITEM * CMYWORDDOC :: CreateClientItem (Reobject * preo) Const { Return New CMYwordcntritem (preo, (cmyworddoc *); } This simple override enables the Paste and Paste Special commands in the Edit menu to paste OLE items into the document. For a demonstration, copy a picture created with the Windows Paint applet to the clipboard and paste it into a MyWord document. Then double-click the embedded image in myWord, and Paint will merge its menus and toolbars with myWord's menus and toolbars so that you can edit the picture in place. If the document is saved, the embedded Paint object is saved, too, so that it will come back Up Just As You Left Ithen You Reload The Document. In case you had not noticed, MyWord is fully capable of saving the documents you create and loading them back in It can even read RTF files created by other word processors and serialize OLE objects Yet CMyWordDoc :: Serialize contains just one statement..: Cricheditdoc :: serialize (ar); You will not find any other serialization code in CMyWordDoc because CRichEditDoc can handle serialization on its own. CRichEditDoc :: Serialize streams data to and from a CRichEditView by calling the view's Serialize function, which in turn relies on the streaming capabilities built into a rich text edit control. (for more information, see the documentation for the EM_STREAMIN and EM_STREAMOUT messages that can be sent to a rich text edit control and the equivalent StreamIn and StreamOut function members of MFC's CRichEditCtrl class.) It's relatively easy to write an SDK application that saves and loads documents in a rich text edit control, but it's downright simple to do it in MFC because CRichEditDoc and CRichEditView work together with other components of the framework to handle all phases of the serialization process for you.