11.04.2014 Views

Advanced MFC Programming

Advanced MFC Programming

Advanced MFC Programming

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Chapter 9. Font<br />

width of different characters may vary, we need to make careful calculation before moving the caret to the<br />

next position.<br />

Every class derived from the CWnd supports caret, the steps of implementing caret are as follows: 1)<br />

Create a caret with specific style. 2) Show the caret. 3) Destroy the caret before the window is destroyed.<br />

The following three member functions can be used to create a caret:<br />

void CWnd::CreateSolidCaret(int nWidth, int nHeight);<br />

void CWnd::CreateGrayCaret(int nWidth, int nHeight);<br />

void CWnd::CreateCaret(CBitmap *pBitmap);<br />

The first member function allows us to create a solid caret, here parameters nWidth and nHeight<br />

specify the dimension of the caret. Similarly, the second function can be used to create a gray caret. The<br />

last function can create a caret from a bitmap so that the caret can have a custom pattern.<br />

After the caret is created, we can call function CWnd::ShowCaret() to display the caret or call function<br />

CWnd::HideCaret() to hide the caret.<br />

The difficult thing on managing caret is to set its position. Because every character may have a<br />

different width, when the user presses arrow keys, we can not advance the caret with fixed distance each<br />

time. We must move the caret forward or backward according to the width of the character located before<br />

(or after) the caret. In order to do this, we can either calculate the new caret position each time, or we can<br />

store the starting position of each character in a table and obtain the caret position from it whenever the<br />

caret needs to be moved. In the sample, the latter solution is used.<br />

Sample<br />

Sample 9.5\GDI demonstrates how to implemnt caret. It is based on sample 9.4\GDI.<br />

First, some new variables and functions are added to class CGDIDoc for caret implementation:<br />

class CGDIDoc : public CDocument<br />

{<br />

protected:<br />

CGDIDoc();<br />

DECLARE_DYNCREATE(CGDIDoc)<br />

CString m_szText;<br />

CFont m_ftDraw;<br />

CDWordArray m_arCaret;<br />

int m_nCaretIndex;<br />

int m_nCaretVerSize;<br />

……<br />

public:<br />

CString GetText(){return m_szText;}<br />

CFont *GetFont(){return &m_ftDraw;}<br />

void ForwardCaret();<br />

void BackwardCaret();<br />

POINT GetCaretPosition();<br />

int GetCaretVerSize(){return m_nCaretVerSize;}<br />

CGDIView *CGDIDoc::GetCGDIView();<br />

//{{AFX_VIRTUAL(CGDIDoc)<br />

public:<br />

};<br />

Two variables m_nCaretIndex and m_nCaretVerSize are added. The first variable is the index<br />

indicating the position of the caret. The second variable is the caret’s vertical size. This is necessary<br />

because for fonts with different sizes, we need to create different carets, whose vertical size should be the<br />

same with the current font’s height.<br />

Five functions are added to the class, among them, function CGDIDoc::GetCaretVerSize() provides<br />

us a way of obtaining the current caret’s vertical size in class CGDIView; and function CGDIDoc::<br />

GetCaretPosition() converts the caret index to a position within the client window (The function returns<br />

a POINT type value). It is implemented as follows:<br />

POINT CGDIDoc::GetCaretPosition()<br />

{<br />

252

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!