在继续使用记录的方法来创建复合字符串之前,我们需要熟悉一个对象(例如段落)。 它是由几行组成的自动格式化的文本块。 在本课程中,我们将研究构建简单的段落。

课程系列“使用KOMPAS-3D API的工作”的内容
- 基础知识
- 图纸设计
- 正确连接到KOMPAS
- 主题词
- 图形图元
- 以各种格式保存文档
- 了解设置
- 标题栏中更复杂的书写方法
- 读取字幕单元
- 特殊字符,包括字符串
- 简单文字标签
- 复合弦
- 段落
- 多行文字
段落参数( ksParagraphParam )
ksParagraphParam接口描述了一个段落。 要获取它,您需要使用
KompasObject接口的
GetParamStruct方法,为此您需要将常量
ko_ParagraphParam (
0x0000001B )传递给它。 考虑
ksParagraphParam接口的属性。
ang-文本的角度,以度为单位。 它从水平线逆时针延迟。 类似于
ksText方法的
ang参数。
height-段落的高度,以毫米为单位。
hFormat-水平格式化文本。 当文本的宽度不适合段落宽度时,使用此属性。 有效值在下表中列出。
style-文本样式(在第
11节中进行了介绍 )。
vFormat-垂直格式化文本。 当文本不适合段落的高度时,使用此属性。 有效值在下表中列出。

使用
vFormat属性时,要记住两
件事 :
- 根据KOMPAS文档, vFormat属性的有效值为0和-1 ,但事实并非如此。 有效值为0和1 。
- COMPASS不会更改字符的高度。 它仅更改线之间的距离。 如果线条的高度小于段落的高度,则它们可以重叠。 下图是此类叠加层的示例。
width-段落的宽度,以毫米为单位。
属性
height ,
hFormat ,
vFormat和
width允许我们解决将文本放置在给定矩形中的问题。 该方法比
第11课中讨论的
ksGetTextLength方法更加可靠和高效。
x和
y是锚点的坐标。 段落相对于锚点沿水平轴的位置由
ksDocument2D接口的
ksSetTextAlign方法调整(尽管未记录这种可能性)。 垂直锚点始终与段落第一行的底部匹配。 此行为无法更改。
ksParagraphParam接口只有一种方法:
Init() 。 它初始化接口的属性值。 没有输入参数。 如果成功,则返回
true 。
段落建设
创建一个段落包含三个连续步骤。
- 本段开头的声明。 为此, 调用 ksDocument2D接口的ksParagraph方法。 作为唯一参数,此方法接受ksParagraphParam接口,该接口设置段落的参数。 如果成功,则ksParagraph方法返回1,如果发生错误,则返回0 。
- 填充段落。 对于段落中显示的每一行,都会调用 ksDocument2D接口的ksTextLine方法。 作为唯一参数,它接受描述字符串的ksTextItemParam或ksTextLineParam接口 (在循环的上一课中讨论过)。 请注意,输出行不得包含@ , $ , & , 〜 , ^和#字符,因为它们是控制字符。 在本周期的下一课中将考虑与他们合作。
- 段末。 为此, 调用 ksDocument2D接口的ksEndObj()方法。 它没有输入参数,如果成功,则返回指向创建的对象(段落)的整数指针。 如果发生错误,它将返回零 。
一个例子。 最简单的段落
下面是该程序的源代码,演示了一个简单段落的构造。// ksTextItemParam TextItemParamPtr textItemParam; textItemParam = static_cast<TextItemParamPtr>(kompas->GetParamStruct(ko_TextItemParam)); // ParagraphParamPtr paragraphParam; paragraphParam = static_cast<ParagraphParamPtr>(kompas->GetParamStruct(ko_ParagraphParam)); paragraphParam->Init(); paragraphParam->set_x(100.0); paragraphParam->set_y(100.0); // Document2D->ksParagraph(paragraphParam); // BSTR str = SysAllocString(L" "); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); str = SysAllocString(L" "); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); // Document2D->ksEndObj(); paragraphParam.Unbind(); textItemParam.Unbind();
与往常一样,这里为了简单起见,省略了负责创建和执行文档的代码(在上一课程中讨论了该主题)。
在此示例中,KOMPAS本身根据其内容确定段落的大小。 下图显示了生成的段落。

请注意:文本显示为一行。 我们没有指定段落的宽度,因此KOMPAS会根据需要自动将其增加。 如果设置了宽度,则COMPASS行为将由
ksParagraphParam接口的
hFormat属性的值确定。
要形成多行和复合文本,您需要使用上一课中部分讨论的图形功能。
一个例子。 多行文字
要显式
换行,请使用
NEW_LINE标志(
0x1000 )。
下面是一个示例程序,演示了使用此标志构建多行段落。 // ksTextItemParam TextItemParamPtr textItemParam; textItemParam = static_cast<TextItemParamPtr>(kompas->GetParamStruct(ko_TextItemParam)); // ParagraphParamPtr paragraphParam; paragraphParam = static_cast<ParagraphParamPtr>(kompas->GetParamStruct(ko_ParagraphParam)); paragraphParam->Init(); paragraphParam->set_x(100.0); paragraphParam->set_y(100.0); // Document2D->ksParagraph(paragraphParam); // BSTR str = SysAllocString(L" "); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); TextItemFontPtr textItemFont; textItemFont = static_cast<TextItemFontPtr>(textItemParam->GetItemFont()); textItemFont->SetBitVectorValue(NEW_LINE, true); str = SysAllocString(L" "); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); textItemFont.Unbind(); str = SysAllocString(L" "); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); // Document2D->ksEndObj(); paragraphParam.Unbind(); textItemParam.Unbind();
在本示例中,将创建一个三行段落。 第一行照常显示。 第二,设置
NEW_LINE标志。 他谈到新生产线的开始。 第三行照常显示,但是
NEW_LINE标志仍处于活动状态,因为我们正在使用
ksTextItemParam接口的相同实例。 下图显示了此程序生成的段落。

现在,这些行已正确显示。
使用段落的挑战
文字对齐
文本对齐方式是通过
ksDocument2D接口的
ksSetTextLineAlign方法设置的。 它只有一个整数参数-设置对齐方式。 下表列出了其有效值。

如果成功,则
ksSetTextLineAlign方法将返回上一个对齐标记,如果发生错误,则返回
-1 。
请注意,
ksSetTextLineAlign方法只能在块内使用(在我们的示例中,它在段落内使用)。 这意味着它不能用于设置
ksText方法输出的文本的
对齐方式。 这种限制是由于这样的事实,在这种情况下,KOMPAS不知道需要对齐哪个边框。
另一个要点与
ksSetTextLineAlign方法的范围有关-它影响输出的行。 考虑一个示例(与原始示例相比,此处使用了非常简化的语法):
ksSetTextLineAlign(1); ksTextLine(“ ”); ksSetTextLineAlign(2); ksTextLine(“ ”);
线条将如何对齐? 与我们的预期相反,两条线将向右对齐。 怎么了 事实是,
ksSetTextLineAlign方法首先会更改最后一条输出线的对齐方式。 这是我们示例中发生的情况:第一行设置中心对齐。 由于没有先前的输出行,因此此调用将更改默认对齐方式(左)。
然后我们打印“中心”行。 最初,它使用先前的中心对齐设置。
在第三行中,我们再次更改对齐方式。 首先,该方法更改前一行(“中心”)的对齐方式。 因此,它按照我们的计划在右侧而不是在中心对齐。 默认情况下,相同的对齐方式将对齐。
我们显示“右”行。 由于不再调用
ksSetTextLineAlign方法,因此它使用先前设置的对齐方式(在右侧)。
因此,两条线都向右对齐。 现在让我们稍微更改一下示例:
ksSetTextLineAlign(1); ksTextLine(“ ”); ksTextLine(“”); ksSetTextLineAlign(2); ksTextLine(“ ”);
我们所做的只是在不更改对齐方式的情况下添加空字符串的输出。 现在,这些行已正确显示。 这是因为空字符串的输出“吸收”了设置的右对齐。 对
ksSetTextLineAlign方法的第二次调用会影响空行,并且不会以任何方式影响中心线。
下面的示例显示正确的对齐方式,而不显示空字符串。
ksTextLine(“ ”); ksSetTextLineAlign(1); ksTextLine(“ ”); ksSetTextLineAlign(2);
调用
ksTextLine和
ksSetTextLineAlign被交换。 由于
ksSetTextLineAlign方法主要影响最后显示的行,因此正确设置了对齐方式,并根据需要显示了行。
例子
以下是演示段落中文本对齐方式的程序的源代码。 // ksTextItemParam TextItemParamPtr textItemParam; textItemParam = static_cast<TextItemParamPtr>(kompas->GetParamStruct(ko_TextItemParam)); // ParagraphParamPtr paragraphParam; paragraphParam = static_cast<ParagraphParamPtr>(kompas->GetParamStruct(ko_ParagraphParam)); paragraphParam->Init(); paragraphParam->set_x(100.0); paragraphParam->set_y(100.0); paragraphParam->set_width(60.0); paragraphParam->set_hFormat(2); // Document2D->ksParagraph(paragraphParam); // BSTR str = SysAllocString(L" "); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); TextItemFontPtr textItemFont; textItemFont = static_cast<TextItemFontPtr>(textItemParam->GetItemFont()); textItemFont->SetBitVectorValue(NEW_LINE, true); str = SysAllocString(L""); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); textItemFont.Unbind(); str = SysAllocString(L" "); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); Document2D->ksSetTextLineAlign(1); str = SysAllocString(L""); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); str = SysAllocString(L" "); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); Document2D->ksSetTextLineAlign(3); // Document2D->ksEndObj(); paragraphParam.Unbind(); textItemParam.Unbind();
在此示例中,除了文本对齐方式以外,还演示了
ksParagraphParam接口的
width和
hFormat属性的使用。 它们用于限制其宽度。 如果我们不更改它们,KOMPAS将增加该段落的宽度,并且看不到左侧和宽度的对齐方式。
显示空白行以提高段落的可读性。 它们不会影响正确的对齐方式。
下图显示了此程序生成的段落。

打开或关闭样式
在本
周期的
第11课中,我们检查了控制样式的标志(
ITALIC_ON ,
ITALIC_OFF ,
BOLD_ON ,
UNDERLINE_ON和
UNDERLINE_OFF )。 然后,我们针对
ksText方法检查了它们。 它们在段落中的应用之间的重要区别是,该操作不仅限于调用
ksTextLine方法,还可以扩展到整个段落。 让我们看几个例子。
TextItemFont->SetBitVectorValue(BOLD_ON, true); TextItemParam->s = SysAllocString(L” ”); Document2D->ksTextLine(TextItemParam); TextItemFont->Init(); TextItemParam->s = SysAllocString(L” ”); Document2D->ksTextLine(TextItemParam);
第一行将以粗体显示。 毫无疑问。 但是第二行将如何显示? 标志
BOLD_ON已为她重置。 因此,我们可以假定它将以常规字体显示。 但是事实并非如此。 遇到
BOLD_ON标志后,KOMPAS将按以下方式理解命令:该段的所有后续行均以粗体显示。 因此,所有后续行均以粗体显示,直到该段落完成或COMPASS不会遇到
与其配对的
BOLD_OFF标志。 考虑一个例子:
TextItemFont.SetBitVectorValue(BOLD_ON, true); TextItemParam.s = SysAllocString(L” ”); Document2D.ksTextLine(TextItemParam); TextItemFont.Init(); TextItemFont.SetBitVectorValue(BOLD_OFF, true); TextItemParam.s = SysAllocString(L“ ”); Document2D.ksTextLine(TextItemParam); TextItemFont.Init(); TextItemParam.s = SysAllocString(L” ”); Document2D.ksTextLine(TextItemParam);
第一行以粗体显示。 对于第二行,我们
清除BOLD_ON标志,并将与之
配对的BOLD_OFF标志终止,这将取消粗体样式。 因此,第二和第三行显示为不加粗。
此行为适用于标志
ITALIC_ON ,
ITALIC_OFF ,
UNDERLINE_ON和
UNDERLINE_OFF ,但不适用于
NEW_LINE标志,因为它没有一对覆盖标志。
例子
以下是程序的源代码,使用段落显示了不同样式的文本输出。 // ksTextItemParam TextItemParamPtr textItemParam; textItemParam = static_cast<TextItemParamPtr>(kompas->GetParamStruct(ko_TextItemParam)); // ParagraphParamPtr paragraphParam; paragraphParam = static_cast<ParagraphParamPtr>(kompas->GetParamStruct(ko_ParagraphParam)); paragraphParam->Init(); paragraphParam->set_x(100.0); paragraphParam->set_y(100.0); // Document2D->ksParagraph(paragraphParam); // BSTR str = SysAllocString(L" "); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); TextItemFontPtr textItemFont; textItemFont = static_cast<TextItemFontPtr>(textItemParam->GetItemFont()); textItemFont->set_bitVector(NEW_LINE | ITALIC_OFF); // str = SysAllocString(L" "); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); textItemFont->set_bitVector(NEW_LINE | ITALIC_ON | BOLD_ON); // str = SysAllocString(L" "); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); textItemFont->set_bitVector(NEW_LINE | BOLD_OFF | UNDERLINE_ON); // str = SysAllocString(L" "); textItemParam->set_s(str); Document2D->ksTextLine(textItemParam); SysFreeString(str); // Document2D->ksEndObj(); paragraphParam.Unbind(); textItemFont.Unbind(); textItemParam.Unbind();
该程序最重要的部分是正确设置输出线的标志。 让我们更详细地分析它(程序的相应行用一对字符“
// ”标记)。
显示的第一行没有任何更改。 因此,没有为其设置标志。
第二行应显示为没有斜率,并以新行显示。 因此,将为其设置标志:
NEW_LINE (从新行开始)和
ITALIC_OFF (禁用
斜体 )。
第三行应以斜体和粗体显示。 为此,我们将标记设置为:
NEW_LINE ,
ITALIC_ON (
启用斜体)和
BOLD_ON (
启用粗体)。 所有其他标志均被重置。
第四行应以斜体显示,带下划线,而不要加粗。 为此,我们对以下标志进行翘起:
NEW_LINE ,
BOLD_OFF (禁用粗体,从上一行开始保留)和
UNDERLINE_ON (启用带下划线的)。
如果段落中有更多行,它们将以斜体带下划线的字体显示。 要禁用带下划线的样式,必须清除UNDERLINE_ON标志,并旋开
UNDERLINE_OFF标志。
下图显示了该程序的结果。

从演示中分离信息
如果遵循程序的结构,您可能会注意到上一个示例的严重缺陷:负责生成输出的代码与负责实现其输出的代码混合在一起。 具有良好的编程风格,习惯上将信息与其表示分开。
如果输出信息由几行
ksTextItemParam组成 ,则可以将它们组合到一个接口
ksTextLineParam中 。
ksTextLine方法可以处理这两个接口。 但是这种方法有一个令人不愉快的局限性:如果
ksTextLine方法接受
ksTextLineParam接口,则将忽略
NEW_LINE (和
SPECIAL_SYMBOL_END )标志。 也就是说,即使为某些
ksTextItemParam 实例设置了
NEW_LINE标志,所有信息也将显示在一行上。 要变通解决此限制,您必须为每行手动调用
ksTextLine 。
以下是演示此技术的示例的源代码。 // DynamicArrayPtr dynamicArray; dynamicArray = static_cast<DynamicArrayPtr>(kompas->GetDynamicArray(TEXT_ITEM_ARR)); dynamicArray->ksClearArray(); // ksTextItemParam TextItemParamPtr textItemParam; textItemParam = static_cast<TextItemParamPtr>(kompas->GetParamStruct(ko_TextItemParam)); // BSTR str = SysAllocString(L" "); textItemParam->set_s(str); dynamicArray->ksAddArrayItem(-1, textItemParam); SysFreeString(str); TextItemFontPtr textItemFont; textItemFont = static_cast<TextItemFontPtr>(textItemParam->GetItemFont()); textItemFont->set_bitVector(NEW_LINE | ITALIC_OFF); str = SysAllocString(L" "); textItemParam->set_s(str); dynamicArray->ksAddArrayItem(-1, textItemParam); SysFreeString(str); textItemFont->set_bitVector(NEW_LINE | ITALIC_ON | BOLD_ON); str = SysAllocString(L" "); textItemParam->set_s(str); dynamicArray->ksAddArrayItem(-1, textItemParam); SysFreeString(str); textItemFont->set_bitVector(NEW_LINE | BOLD_OFF | UNDERLINE_ON); str = SysAllocString(L" "); textItemParam->set_s(str); dynamicArray->ksAddArrayItem(-1, textItemParam); SysFreeString(str); // ParagraphParamPtr paragraphParam; paragraphParam = static_cast<ParagraphParamPtr>(kompas->GetParamStruct(ko_ParagraphParam)); paragraphParam->Init(); paragraphParam->set_x(100.0); paragraphParam->set_y(100.0); // Document2D->ksParagraph(paragraphParam); // for(unsigned int i = 0; i < dynamicArray->ksGetArrayCount(); ++i) { dynamicArray->ksGetArrayItem(i, textItemParam); Document2D->ksTextLine(textItemParam); } // Document2D->ksEndObj(); // textItemFont.Unbind(); textItemParam.Unbind(); paragraphParam.Unbind(); dynamicArray->ksDeleteArray(); dynamicArray.Unbind();
在此示例中,首先将输出行写入
DynamicArray ,然后才将其输出到段落。 这使您可以将信息与其表示分开。 如果在我们的示例中未使用
NEW_LINE标志,则只需调用
ksTextLine方法就可以解决。
该程序的结果类似于上一个示例的结果。
结论在本课程中,我们研究了如何构建段落以及如何使用它显示多行文本。 我们还学会了将信息与演示分开。 不幸的是,多行文本的正确输出需要手动遍历字符串数组。 这不是很方便。 在下一课中,我将展示如何解决此问题。
要继续,请关注博客新闻。
Sergey Norseev博士,《在Delphi中进行COMPAS的应用程序开发》一书的作者。