The example in this section is taken from a simple word processing application. It includes code that allows the user to set the position of the caret by clicking anywhere on a line of text, and to select (highlight) a line of text by double-clicking anywhere on the line.
LONG APIENTRY MainWndProc(hwndMain, uMsg, wParam, lParam)
HWND hwndMain;
UINT uMsg;
UINT wParam;
LONG lParam;
{
HDC hdc; /* handle of device context */
TEXTMETRIC tm; /* font size data */
int i, j; /* loop counters */
int cCR = 0; /* count of carriage returns */
char ch; /* character from input buffer */
static int nBegLine; /* beginning of selected line */
static int nCurrentLine = 0; /* currently selected line */
static int nLastLine = 0; /* last text line */
static int nCaretPosX = 0; /* x-coordinate of caret */
static int cch = 0; /* number of characters entered */
static int nCharWidth = 0; /* exact width of a character */
static char szHilite[128]; /* text string to hilite */
static DWORD dwCharX; /* average width of characters */
static DWORD dwLineHeight; /* line height */
static POINTS ptsCursor; /* coordinates of mouse cursor */
static COLORREF crPrevText; /* previous text color */
static COLORREF crPrevBk; /* previous background color */
static PTCHAR pchInputBuf; /* address of input buffer */
static BOOL fTextSelected = FALSE; /* text-selection flag */
switch (uMsg) {
case WM_CREATE:
/* Get metrics of current font. */
hdc = GetDC(hwndMain);
GetTextMetrics(hdc, &tm);
ReleaseDC(hwndMain, hdc);
/* Save the average character width and height. */
dwCharX = tm.tmAveCharWidth;
dwLineHeight = tm.tmHeight;
/* Allocate a buffer to store keyboard input. */
pchInputBuf = (LPSTR) GlobalAlloc(GPTR,
BUFSIZE * sizeof(TCHAR));
return 0;
.
. /* Process other messages. */
.
case WM_LBUTTONDOWN:
/*
* If a line of text is currently highlighted, redraw
* redraw the text to remove the highlighting.
*/
if (fTextSelected) {
hdc = GetDC(hwndMain);
SetTextColor(hdc, crPrevText);
SetBkColor(hdc, crPrevBk);
TextOut(hdc, 0, nCurrentLine * dwLineHeight,
szHilite, lstrlen(szHilite));
ReleaseDC(hwndMain, hdc);
ShowCaret(hwndMain);
fTextSelected = FALSE;
}
/* Save the current mouse-cursor coordinates. */
ptsCursor = MAKEPOINTS(lParam);
/*
* Determine which line the mouse cursor is on and save
* the line number. Don't allow line numers greater
* than the number of the last line of text. Later, the
* line number will be multiplied by the average height
* of the current font. The result will be used to set
* y-coordinate of the caret.
*/
for (i = 1; (i * dwLineHeight) <= ptsCursor.y; i++);
nCurrentLine = min(i - 1, nLastLine);
/*
* Parse the text input buffer to find the first
* character in the selected line of text. Each
* line ends with a carriage return, so it's possible
* to count the carriage returns to find the selected
* line.
*/
cCR = 0;
nBegLine = 0;
if (nCurrentLine != 0) {
for (i = 0; (i < cch) && (cCR < nCurrentLine); i++)
if (pchInputBuf[i] == 0x0D)
++cCR;
nBegLine = i;
}
/*
* Starting at the beginning of the selected line,
* measure the width of each character, summing the
* width with each character measured. Stop when the
* sum is greater than the x-coordinate of the mouse
* cursor. The sum will be used to set the x-coordinate
* of the caret.
*/
hdc = GetDC(hwndMain);
nCaretPosX = 0;
for (i = nBegLine;
(pchInputBuf[i] != 0x0D) && (i < cch); i++) {
ch = pchInputBuf[i];
GetCharWidth(hdc, (int) ch, (int) ch, &nCharWidth);
if ((nCaretPosX + nCharWidth) > ptsCursor.x)
break;
else
nCaretPosX += nCharWidth;
}
ReleaseDC(hwndMain, hdc);
/* Set the caret to the user-selected position. */
SetCaretPos(nCaretPosX, nCurrentLine * dwLineHeight);
break;
case WM_LBUTTONDBLCLK:
/* Copy the selected line of text to a buffer. */
for (i = nBegLine, j = 0; (pchInputBuf[i] != 0x0D) &&
(i < cch); i++)
szHilite[j++] = pchInputBuf[i];
szHilite[j] = '\0';
/*
* Hide the caret, invert the background an foreground
* colors, then redraw the selected line.
*/
HideCaret(hwndMain);
hdc = GetDC(hwndMain);
crPrevText = SetTextColor(hdc, RGB(255, 255, 255));
crPrevBk = SetBkColor(hdc, RGB(0,0,0));
TextOut(hdc, 0, nCurrentLine * dwLineHeight, szHilite,
lstrlen(szHilite));
SetTextColor(hdc, crPrevText);
SetBkColor(hdc, crPrevBk);
ReleaseDC(hwndMain, hdc);
fTextSelected = TRUE;
break;
.
. /* Process other messages. */
.
default:
return (DefWindowProc(hwndMain, uMsg, wParam, lParam));
}
return NULL;
}