⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 05.1.1 创建文本插入符.txt

📁 网上第一本以TXT格式的VC++深入详解孙鑫的书.全文全以TXT格式,并每一章节都分了目录,清晰易读
💻 TXT
字号:
5.1.1 创建文本插入符
在程序中想要创建插入符,可以利用 CWnd类的 CreateSolidCaretO函数来完成,该函数的原型声明如下: 
void CreateSolidCaret( int nWidth, int nHeight ); 
该函数各个参数的含义如下所述: 
. nWidth 
指定插入符的宽度(逻辑单位)。如果该参数的值为 0,那么系统将其设置为系统定义的窗口边界的宽度。 
. nHeight 
指定插入符的高度(逻辑单位〉。如果该参数的值为 0,那么系统将其设置为系统定义的窗口边界的高度。下面我们利用这个函数在程序窗口中创建一个插入符,首先请读者按照第 3章介绍的步骤创建一个单文档类型的 MFCAppWizard (exe)工程,取名为 Text。
插入符需要在窗口上创建,单文档类型的工程有两个窗口,即框架类窗口和视类窗口,我们应该选择哪一个窗口来创建插入符呢?第4章曾介绍过,视类窗口始终位于框架类窗口之上,对窗口客户区的鼠标和键盘操作实际上都是在视类窗口上进行的,因此应该在视类窗口上创建插入符。
插入符的创建应该在窗口创建之后进行,可以在 WM_CREATE消息的响应函数 OnCreate中 (在创建窗口的代码之后)添加创建插入符的代码。MFC AppWizard所生成的 CTextView类中没有OnCreate函数,我们需要手动添加。为CTextView类添加WM CREATE 消息的响应函数OnCreate.然后在此函数中创建一个宽度为20、高度为 100的插入符,代码如例5-1所示。 
int CTextView: :OnCreate(LPCREATESTRUCT lpCreateStruct) 

i f (CView: :OnCreate(lpCreateStruct) -1) return -1; 
// TODO: Add your special工zed creation code here 
CreateSolidCaret(20 , 100) ; 
return 0 ; 
Build并运行Text程序,发现程序窗口中并没有出现刚才我们创建的插入符。这是为什么呢?实际上. CreateSolidCaret函数创建插入符以后,该插入符初始时是隐藏的,必须调用ShowCaret函数来显示它。因此,在上述例子1所示代码中调用CreateSolidCaret函数之后,应再添加下面这句代码: 
ShowCaret() ; 
Build并运行Text程序,创建的插入符终于显示在程序窗口中了,程序运行结果如图 
5.1所示。

图 5.1插入符显示结果

显然,这个插入符看起来不太正常,太高也太宽了。我们使用Word时,都有这样的经验,插入符的大小会根据当前所选的字号来变化,如果选择了比较大的字号,例如三号,那么插入符也会相应的增大。对Text程序来说,如何才能够让插入符适合于当前字体的大小呢?首先我们需要得到设备描述表中当前字体的信息,也就是文本的信息,然后根据宇
体的信息来调整插入符的大小。调用CDC类的GetTextMetrics成员函数可以得到设备描述表中当前字体的度量信息。该函数的原型声明如下所示: 
BOOL GetTextMetrics( LPTEXTMETRIC lpMetrics ) const; 
可以看到,该函数的参数要求是一个TEXTMETRIC结构体的指针,也就是说,我们可以定义一个TEXTMETRIC结构体类型的变量,然后将该变量的地址传递给这个参数。通过GetTextMe国cs这个函数调用,它会用设备描述表中当前字体的信息来填充这个结构体。 
TEXTMETRIC结构体的定义如下: 
typedef struct tagTEXTMETRIC 1* tm *1 
int t mHeight; 
int tmAscent; 
, 	int tmDescent; 
int tmInternalLeading; ì
int tmExternalLeading; 
int tmAveCharWidth; 
int tmMaxCharWidth; 
int tmWeight; 
BYTE tmltalic ;
 BYTE tmUnderlined; 
BYTE tmStruCkOut ; 
BYTE tmFirstChar; 
BYTE tmLastChar; 
BYTE tmDefaultChar ; 
BYTE t mBreakChar; 
BYTE tmPitchAndFamilY; 
BYTE tmCharSet ; 
int tmOverhang; 
int tmDigitizedAspectX; 
int tmDigitizedAspectY; 
TEXTMETRIC; 
可以发现TEXTMETRIC这个结构体的信息比较多,但实际上常用的只有几个。为了更好地理解TEXTMETRIC结构体中 tmAscent和 tmDescent成员的含义,先来看看图5.2所示的字体信息示意图。 
tmAscent tmDescent 
…........... ...1……μ … base line 
图 5.2字体信息示意图

从图 5.2中可以看到,对英文字符来说, g和 h的高度明显是不一样的。每一种字体

都有一条基线 ( base line ),基线以上到图中 h字符最高点之间的高度称为升序高度 ( trnAscent),基线以下到图中 g字符最底点之间的高度称为降序高度 (tmDescent)。升序高度加上降序高度就是字体的高度 (tmHeight)。这样,当我们在文本程序窗口中输入文字时,下一行的文字才不会覆盖上-行的文字部分。
和字符的高度一样,英文字符的宽度也是不同的。读者可以在任意文本处理程序中输入一个w和i字符,将会很明显地看到这两个字符的宽度是不一样的,显然w要比i宽。因此,字体并没有一个具体的宽度值,只有一个平均宽度 ( tmAveCharWidth)。另外, TEXTMETRIC结构体中还定义了宇体的最大字符宽度 (trnMaxCharWidth)。
得到了字体的信息,我们就可以利用字体的高度和平均宽度来计算插入符的高度和宽度。例5-2是具体的实现代码: 
int CTextView : :OnCreate(LPCREATESTRUCT lpCreateStruct) { 
if (CView : :OnCreate(lpCreateStruct) -1) 
return -1; 

//创建设备描述表 
CClientDC dc(this) ; 
//定义文本信息结构体变量 
TEXTMETRIC tm; 
//获得设备描述表中的文本信息 
dc . GetTextMetrics(&tm) ; 
//根据字体大小,创建合适的插入符 
CreateSolidCaret(tm.tmAveCharWidth/8, tm . tmH eight) ; 
//显示插入符 

ShowCaret() ; 
return 0 ; 
读者可能要提出这样的疑问,为什么上述例5-2所示代码在创建插入符时,要将字体平均宽度除以8呢?这是-个经验值,读者可以试试其他数值,看看结果是否符合自己的需要。 
Build并运行Text程序,这时在应用程序窗口的左上角就出现了一条闪烁的竖线,而且其大小也比较符合常规。程序运行结果如图5.3所示。 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -