因为TextOut是不能使用/n进行多行输出的,它的每一个行的位置都是由坐标决定的,所以要实现多行输出就要自己算每行的位置,所以就要知道每行的高度(在不考虑会超出右边界的情况下)。
程序取得行高的方法是从hdc句柄中得到每个字的高度。使用函数如下:
tm是一个TEXTMETRIC结构,需要自己定义。调用这个函数需要hdc句柄而计算行高之类的操作一般在程序创建的时候进行,所以用GetDC取得句柄。
TEXTMETRIC之中包含来很多信息,不过不用担心记不住,在VC++中,当输入完tm.之后,后面的所有属性都会显示出来,只要记得前面几个字母就可以立即输入完毕了。这个也是VC++看起来很难,要记的东西很多的原因吧:)有用的有这么几个:
{
LONG tmHeight ; // 文字高度
LONG tmAscent ; // 文字上部高度
LONG tmDescent ; // 文字下部高度
LONG tmInternalLeading ; // 重音符号出现的地方
LONG tmExternalLeading ; // 行间距
LONG tmAveCharWidth ; // 文字平均宽度
LONG tmMaxCharWidth ;
其它结构字段
}
TEXTMETRIC, * PTEXTMETRIC ;
只要对照这张图看看就知道了,上面标注了一个字母各个部分的高度是怎么划分的:
另外,大写字母宽度一般是tmAveCharWidth的1.5倍。所以文字宽度一般就是tmAveCharWidth,高度就是tmHeight+tmExternalLeading
所以,一般的初始化代码就是这样的(来自MSDN[Platform SDK>MSDN Library>用户界面的设计和开发>Windows Controls>Individual Control Information>Scroll Bars>Using Scroll Bars]的示例)
// Get the handle to the client area's device context.
hdc = GetDC (hwnd);
// Extract font dimensions from the text metrics.
GetTextMetrics (hdc, & tm);
xChar = tm.tmAveCharWidth;
xUpper = (tm.tmPitchAndFamily & 1 ? 3 : 2 ) * xChar / 2 ;
yChar = tm.tmHeight + tm.tmExternalLeading;
// Free the device context.
ReleaseDC (hwnd, hdc);
// Set an arbitrary maximum width for client area.
// (xClientMax is the sum of the widths of 48 average
// lowercase letters and 12 uppercase letters.)
xClientMax = 48 * xChar + 12 * xUpper;
return 0 ;
MSDN地址:ms-help://MS.MSDNQTR.2003FEB.2052/shellcc/platform/commctls/scrollbars/usingscrollbars.htm
然后,每一行就是这样子的:
x,y是指第x各字符和第y行。使用wsprintf函数的好处是,它的返回值就是字符串的长度,而且在里面用了TEXT就可以使用%i之类的东东进行格式化了。说白了wsprintf就是在预格式化到了szBuffer这个缓冲区。不过记得先定义szBuffer就是了(TCHAR szBuffer [40] ;)
-----------------------------------------------------------
好了,终于可以动手了,这回要弄点东西进行输出了:
显示可以从GetSystemMetrics呼叫中取得的信息!这个函数时这么用的:
GetSystemMetrics (「索引」),所谓的索引呢,就是一个整数,告诉这个函数我们要知道什么。因为这个函数索引众多(废话,不多怎么练习我们的多行输出),所以定义了一个.h的文件,直接调用这个结构就可以了。具体程序就不列出来了,书上有,建议除了SYSMETS.H外,其他部分自己写(注意书上的有点小错误哦)
下面是这个示例的工程打包(其实就是昨天那个,把那个MessageBox函数去掉就行了):
http://dl2.csdn.net/down4/20070706/06104222215.rar
到这里你会发现有些东西没有显示出来。这就要用到滚动条了。。。。。。