本节中的示例来自简单的文字处理应用程序。它包括代码,使用户可以通过单击文本行上的任意位置来设置插入符的位置,并通过双击行中的任何位置来选择(突出显示)一行文本。
LRESULT APIENTRY MainWndProc(hwndMain,uMsg,wParam,lParam)en
HWND hwndMain;
UINT uMsg;
WPARAM wParam;
LPARAM 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 highlight */
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 */
开关(uMsg){
case WM_CREATE:
/ *获取当前字体的指标。*/
hdc = GetDC(hwndMain);
GetTextMetrics(hdc, &tm);
ReleaseDC(hwndMain, hdc);
/ *保存平均字符宽度和高度。*/
dwCharX = tm.tmAveCharWidth;
dwLineHeight = tm.tmHeight;
/ *分配缓冲区以存储键盘输入。*/
pchInputBuf = (LPSTR) GlobalAlloc(GPTR,
BUFSIZE * sizeof(TCHAR));
return 0;
case WM_CHAR:
开关(wParam){
case 0x08: /* backspace */
case 0x0A: /* linefeed */
case 0x1B: /* escape */
MessageBeep(0xFFFFFFFF);
return 0;
case 0x09: /* tab */
/ *将标签转换为四个连续空格。*/
for (i = 0; i < 4; i++)
SendMessage(hwndMain, WM_CHAR, 0x20, 0);
return 0;
case 0x0D: /* carriage return */
/*
记录回车,并定位
*在新行开始的插入符号。
*/
pchInputBuf[cch++] = 0x0D;
nCaretPosX = 0;
nCurrentLine += 1;
break;
默认值:/ *可显示字符* /
ch = (char) wParam;
HideCaret(hwndMain);
/*
*检索字符的宽度,并显示
*性格。
*/
hdc = GetDC(hwndMain);
GetCharWidth32(hdc,(UINT)wParam,(UINT)wParam,
&nCharWidth);
TextOut(hdc,nCaretPosX,
nCurrentLine * dwLineHeight, &ch, 1);
ReleaseDC(hwndMain, hdc);
/ *将字符存储在缓冲区中。*/
pchInputBuf[cch++] = ch;
/*
*计算新的水平位置
*插入符号。如果新职位超过了
*最大,插入回车和
*在开始时重新设置插入符号
*下一行。
*/
nCaretPosX += nCharWidth;
如果((DWORD)nCaretPosX > dwMaxCharX){
nCaretPosX = 0;
pchInputBuf[cch++] = 0x0D;
++nCurrentLine;
}
ShowCaret(hwndMain);
break;
}
SetCaretPos(nCaretPosX, nCurrentLine * dwLineHeight);
nLastLine = max(nLastLine, nCurrentLine);
break;
.
./ *处理其他消息。*/
.
case WM_LBUTTONDOWN:
/*
*如果当前高亮显示一行文本,请重新绘制
*文字删除突出显示。
*/
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;
}
/ *保存当前鼠标光标坐标。*/
ptsCursor = MAKEPOINTS(lParam);
/*
*确定光标所在的行,并保存
*行号。不允许行数更大
*比最后一行的文字数。该
*行数乘以平均高度
*的当前字体。结果用于设置
*插入符号的y坐标。
*/
nCurrentLine = min((int)(ptsCursor.y / dwLineHeight),
nLastLine);
/*
*解析文本输入缓冲区以查找第一个
*所选文字行中的字符。每
*线以回车方式结束,所以有可能
*计数回车查找所选的
*行。
*/
cCR = 0;
nBegLine = 0;
if (nCurrentLine != 0) {
for (i = 0; (i < cch) &&
(cCR < nCurrentLine); i++) {
if (pchInputBuf[i] == 0x0D)
++cCR;
}
nBegLine = i;
}
/*
*从所选行的开头开始,
*测量每个字符的宽度,求和
*宽度与每个字符测量。停止时
* sum大于光标的x坐标。
*总和用于设置插入符号的x坐标。
*/
hdc = GetDC(hwndMain);
nCaretPosX = 0;
for (i = nBegLine;
(pchInputBuf[i] != 0x0D) && (i < cch); i++) {
ch = pchInputBuf[i];
GetCharWidth32(hdc, (int) ch, (int) ch, &nCharWidth);
if((nCaretPosX + nCharWidth)> ptsCursor.x)
break;
其他
nCaretPosX += nCharWidth;
}
ReleaseDC(hwndMain, hdc);
/ *将插入符号设置为用户选择的位置。*/
SetCaretPos(nCaretPosX, nCurrentLine * dwLineHeight);
break;
case WM_LBUTTONDBLCLK:
/ *将选定的文本行复制到缓冲区。*/
for (i = nBegLine, j = 0; (pchInputBuf[i] != 0x0D) &&
(i < cch); i++)
szHilite[j++] = pchInputBuf[i];
szHilite[j] = '\0';
/*
*隐藏插入符号,反转背景和前景
*颜色,然后重画所选行。
*/
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;
.
./ *处理其他消息。*/
.
默认:
return DefWindowProc(hwndMain, uMsg, wParam, lParam);
}
return NULL;
}