11.04.2014 Views

Advanced MFC Programming

Advanced MFC Programming

Advanced MFC Programming

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Chapter 9. Font<br />

}<br />

dc.SelectObject(ptrFtOld);<br />

m_nCaretIndex=nIndex;<br />

GetCGDIView()->RedrawCaret();<br />

In order to find out all the possible caret positions, we need to obtain the dimension of different substrings.<br />

For example, the caret positions of text “abcde” can be calculated from the dimensions of following<br />

sub-strings: “a”, “ab”, “abc”, “abcd”, “abcde”. In the above function, first a DC that does not belong to any<br />

window is created, then the current font is selected into this DC, and function CDC::GetTextExtent(…) is<br />

called to obtain the dimension of each sub-string. Because we have only one line text, only the horizontal<br />

size is meaningful to us.<br />

A loop is implemented to do the comparison. For the nth loop, we create a sub-string that contains<br />

text’s first character to nth character, obtain its dimension, and calculate the distance from the position of<br />

the last character of the sub-string to the current position of mouse cursor. After the loop finishes, we<br />

choose the smallest distance and set m_nCaretIndex to the corresponding caret index.<br />

Cursor Shape<br />

For a text editor, when the mouse is over its editable area, usually the mouse cursor should be changed<br />

to an insertion cursor. This indicates that the user can input text at this time. This feature can also be<br />

implemented in our sample application.<br />

To set mouse cursor’s shape, we need to call API function ::SetCursor(…). The input parameter to<br />

this function is an HCURSOR type handle.<br />

A cursor can be prepared as a resource and then be loaded before being used. After the cursor is<br />

loaded, we can pass its handle to function ::SetCursor(…) to change the current cursor shape. Besides the<br />

cursor prepared by the user, there also exist some standard cursors that can be loaded directly.<br />

We can call function CWinApp::LoadCursor(…) to load a user-defined cursor, and call function<br />

CWinApp::LoadStandardCursor(…) to load a standard cursor. The following table lists some of the<br />

standard cursors:<br />

Cursor ID<br />

IDC_ARROW<br />

IDC_IBEAM<br />

IDC_WAIT<br />

IDC_CROSS<br />

Meaning<br />

Arrow cursor<br />

Text-insertion cursor<br />

Hourglass cursor<br />

Cross-hair cursor<br />

In the sample, an HCURSOR type variable is declared in class CGDIView, and the insertion cursor is<br />

loaded in function CGDIView::OnInitialUpdate():<br />

……<br />

……<br />

class CGDIView : public CScrollView<br />

{<br />

protected:<br />

HCURSOR m_hCur;<br />

}<br />

void CGDIView::OnInitialUpdate()<br />

{<br />

}<br />

m_hCur=AfxGetApp()->LoadStandardCursor(IDC_IBEAM);<br />

We need to respond to WM_SETCURSOR message in order to change the cursor shape. By handling this<br />

message, we have a chance to customize the default cursor when it is within the client window of the<br />

application. Upon receiving this message, we can check if the mouse position is over the editable text. If so,<br />

we need to change the cursor by calling API function ::SetCursor(…). In this case, we need to return a<br />

TRUE value and should not call the default message handler. If the cursor should not be changed, we need<br />

to call the default message handler to let the cursor be set as usual.<br />

262

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

Saved successfully!

Ooh no, something went wrong!