Topic : Using Fonts in MFC
Author : Unknown
Page : << Previous 8  
Go to page :

the caret to be updated.

The following shows the modifications made to inline function CGDIDoc::ResetSelection():

Old Version:

(Code omitted)

New Version:

(Code omitted)

Flag HINT_UNSELECTION will cause only the selected area to be updated. Because both m_nSelIndexBgn and m_nSelIndexEnd should be set to -1 to indicate that there is no selected text anymore, we need to use two other variables (m_nSelIndexBgnOld and m_nSelIndexEndOld) to store the old selection indices.

Overriding CView::OnUpdate(...)

On the view side, function OnUpdate(...) can be added through using Class Wizard. In this function, we need to know the current values of CGDIDoc::m_nSelIndexBgn, CGDIDoc::m_nSelIndexEnd, CGDIDoc:: m_nSelIndexBgnOld, CGDIDoc::m_nSelIndexEndOld and CGDIDoc::m_nCaretIndex in order to decide which part of the text should be updated. We also need to obtain the current font and text string in order to calculate the actual rectangle for implementing update.

If parameter lHint is NULL, it means that all client area needs to be updated. In this case, we call the default implementation of this function and return. The following is a portion of funciton CGDIView:: OnUpdate(...) which implements this:

(Code omitted)

If parameter lHint is non-null, we need to obtain the current font, text string and selection indices from the document, and calculate the area that should be updated. Here variable rect stores a rectangle that covers all of the text (within the window).

In the case when hint is one of HINT_DELCHAR_AFTER, HINT_PASTE and HINT_INPUT, we need to update all the characters after the caret:

(Code omitted)

The caret index is retrieved from the document and stored to variable nIndex. Then the sub-string before the caret is extracted and stored to variable szText. Its dimension is calculated by calling function CDC::GetTextExtent(...), and the left border of rect is changed so that it covers only the characters after the caret. Finally, function CWnd::InvalidateRect(...) is called and rect is passed to one of its parameters.

If the hint is HINT_DELCHAR_BEFORE, we need to update the character before the caret and all the characters after the caret:

(Code omitted)

If the hint is HINT_DELETE_SELECTION, we need to update the selected text as well as the characters after the selection:

(Code omitted)

If the hint is HINT_UNSELECTION, we need to update only the selected text. Since both CGDIDoc:: m_nSelIndexBgn and CGDIDoc::m_nSelIndexEnd are -1 now, we must use CGDIDoc::m_nSelIndexBgnOld and CGDIDoc::m_nSelIndexEndOld to calculate the rectangle:

(Code omitted)

If the hint is HINT_SELECTION, we must check if CGDIDoc::nSelIndexEndOld is -1 or not. If it is -1, it means that the area needed to be updated is between CGDIDoc::nSelIndexBgn and CGDIDoc::nSelIndexEnd; if not, the area needed to be updated is between CGDIDoc::nSelIndexEnd and CGDIDoc::nSelIndexEndOld (See Figure 9-6):

(Code omitted)

If we pass FALSE to the second parameter of CWnd::InvalidateRect(...), the client area will be updated without being erased. This can further reduce flickering.


1) Font can be created from structure LOGFONT. We need to provide the following information when creating a special font: face name, font size (height and width). To add special effects to the text, we need to know if the font is bolded, italic, underlined or strikeout. Also, we can change character's orientation by setting font's escapement.

2) All the fonts contained in the system can be enumerated by calling function ::EnumFontFamilies(...). We need to provide a callback function to receive information for each type of font.

3) Function CDC::ExtTextOut(...) can output a text string within a specified rectangle, the area outside the rectangle will not be affected no matter what the text size is. When we call this function, all the area not covered by the text within the rectangle is treated as the background of the text.

4) To implement caret within a window, first we need to create the caret by using one of the following functions: CWnd::CreateSolidCaret(...), CWnd::CreateGrayCaret(...), CWnd::CreateCaret(...). Then we can show or hide the caret by calling either function CWnd::ShowCaret() or CWnd::HideCaret().

5) Keyboard input events can be trapped by handling WM_KEYDOWN or WM_CHAR message.

6) Mouse cursor can be changed by handling message WM_SETCURSOR. We can load a user designed cursor resource by calling function CWinApp::LoadCursor(...). We can also load a standard cursor by calling function CWinApp::LoadStandardCursor(...).

7) If we call function CDC::SetTextAlign(...) using TA_UPDATECP flag, the window origin will be updated to the end of the text each time funciton CDC::TextOut(...) is called.

8) To use global memory, we need to call ::GlobalAlloc(...) to allocate the buffers, call ::GlobalLock(...) to lock the memory before accessing it, call ::GlobalUnlock(...) to stop accessing the memory, and call ::GlobalFree(...) to release the memory.

9) To access the clipboard, we need to call CWnd::OpenClipboard(...) to open the clipboard, call ::EmptyClipboard() to clear any existing data, call ::SetClipboardData() to put data to the clipboard, and call ::CloseClipboard() to close the clipboard. To get data from the clipboard, after opening it, we need to call function ::GetClipboardData() to obtain a global memory handle, which can be used for accessing the data contained in the clipboard.

10) We can pass hints to function CDocument::UpdateAllViews(...) to indicate different updating situations. The hint can be received in function CView::OnUpdate(...). If we want only a portion of the client window to be updated, we can specify the area with a CRect type variable and use it to call function CWnd::InvalidateRect(...) instead of default function CWnd::Invalidate(...).

Page : << Previous 8