Antes de avançar para maneiras documentadas de criar seqüências compostas, precisamos nos familiarizar com um objeto como um parágrafo. É um bloco de texto formatado automaticamente, composto por várias linhas. Nesta lição, examinaremos a construção de parágrafos simples.

O conteúdo da série de lições “Trabalhando com a API COMPASS-3D”
- O básico
- Desenho de desenho
- Conexão correta com o KOMPAS
- Inscrição principal
- Primitivas gráficas
- Salvando um documento em vários formatos
- Conhecendo as configurações
- Métodos de escrita mais sofisticados no bloco de título
- Lendo células de legenda
- Caracteres especiais, incluindo uma sequência
- Etiquetas de texto simples
- Cordas compostas
- Parágrafos
- Texto de várias linhas
Parâmetros de parágrafo ( ksParagraphParam )
Um parágrafo é descrito pela interface
ksParagraphParam . Para obtê-lo, você precisa usar o método
GetParamStruct da interface
KompasObject , para isso, você deve passar a constante
ko_ParagraphParam (
0x0000001B ) para ele. Considere as propriedades da interface
ksParagraphParam .
ang - o ângulo do texto em graus. Está atrasado da linha horizontal no sentido anti-horário. Semelhante ao parâmetro
ang do método
ksText .
height - a altura do parágrafo em milímetros.
hFormat - formatação de texto horizontalmente. Esta propriedade é usada quando o texto não cabe no parágrafo em largura. Os valores válidos estão listados na tabela abaixo.
estilo - estilo do texto (descrito na
lição 11 ).
vFormat - formatar texto verticalmente. Esta propriedade é usada quando o texto não cabe no parágrafo em altura. Os valores válidos estão listados na tabela abaixo.

Há duas
coisas a serem
lembradas ao trabalhar com a propriedade
vFormat :
- De acordo com a documentação do KOMPAS, os valores válidos da propriedade vFormat são 0 e -1 , mas não é assim. Os valores válidos são 0 e 1 .
- COMPASS não altera a altura dos caracteres. Apenas altera a distância entre as linhas. Se a altura das linhas for menor que a altura do parágrafo, elas poderão se sobrepor. Um exemplo dessa sobreposição está na figura abaixo.
width - a largura do parágrafo em milímetros.
As propriedades
height ,
hFormat ,
vFormat e
width nos permitem resolver o problema de colocar texto em um determinado retângulo. Esse método é muito mais confiável e eficiente do que o método
ksGetTextLength discutido na
Lição 11 .
x e
y são as coordenadas do ponto de ancoragem. A posição do parágrafo em relação ao ponto de ancoragem ao longo do eixo horizontal é ajustada pelo método
ksSetTextAlign da interface
ksDocument2D (embora essa possibilidade não esteja documentada). O ponto de ancoragem vertical sempre corresponde à parte inferior da primeira linha do parágrafo. Este comportamento não pode ser alterado.
A interface
ksParagraphParam possui apenas um método:
Init () . Inicializa os valores da propriedade da interface. Não possui parâmetros de entrada. Se for bem-sucedido, retorna
verdadeiro .
Construção de parágrafo
A criação de um parágrafo consiste em três etapas seqüenciais.
- Declaração do início do parágrafo. Para fazer isso, o método ksParagraph da interface ksDocument2D é chamado . Como único parâmetro, esse método aceita a interface ksParagraphParam , que define os parâmetros do parágrafo. Se for bem-sucedido, o método ksParagraph retorna um e, em caso de erro, retorna zero .
- Preenchendo o parágrafo. Para cada linha exibida em um parágrafo, o método ksTextLine da interface ksDocument2D é chamado . Como único parâmetro, ele aceita a interface ksTextItemParam ou ksTextLineParam (discutida nas lições anteriores do loop) que descrevem a sequência. Observe que as linhas de saída não devem conter os caracteres @ , $ , & , ~ , ^ e # , pois são caracteres de controle. O trabalho com eles será considerado nas próximas lições do ciclo.
- Fim do parágrafo. Para fazer isso, o método ksEndObj () da interface ksDocument2D é chamado . Não possui parâmetros de entrada e, se for bem-sucedido, retorna um ponteiro inteiro para o objeto criado (parágrafo). Em caso de erro, ele retorna zero .
Um exemplo O parágrafo mais simples
Abaixo está o código fonte do programa, demonstrando a construção de um parágrafo simples.// 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();
Como sempre, aqui, por simplicidade, o código responsável pela criação e execução do documento é omitido (este tópico foi discutido nas lições anteriores).
Neste exemplo, o próprio COMPASS determina o tamanho do parágrafo com base em seu conteúdo. A figura abaixo mostra o parágrafo gerado.

Observe: o texto é exibido como uma única linha. Como não especificamos a largura do parágrafo, o KOMPAS aumenta automaticamente conforme necessário. Se a largura fosse definida, o comportamento COMPASS seria determinado pelo valor da propriedade
hFormat da interface
ksParagraphParam .
Para formar um texto composto por várias linhas e linhas, você precisa usar os recursos de desenho discutidos parcialmente na lição anterior.
Um exemplo Texto de várias linhas
Para
quebrar explicitamente em uma nova linha, use o sinalizador
NEW_LINE (
0x1000 ).
A seguir, é apresentado um exemplo de programa que demonstra a construção de um parágrafo com várias linhas usando esse sinalizador. // 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();
Neste exemplo, um parágrafo de três linhas é criado. A primeira linha é exibida como de costume. Para o segundo, o sinalizador
NEW_LINE está
definido . Ele fala sobre o início de uma nova linha. O terceiro é exibido normalmente, mas o sinalizador
NEW_LINE ainda está ativo, pois estamos trabalhando com a mesma instância da interface
ksTextItemParam . A figura abaixo mostra o parágrafo gerado por este programa.

Agora as linhas são exibidas corretamente.
Desafios para trabalhar com parágrafos
Alinhamento de texto
O alinhamento do texto é definido pelo método
ksSetTextLineAlign da interface
ksDocument2D . Ele possui apenas um parâmetro inteiro - ajuste o alinhamento. Seus valores válidos estão listados na tabela abaixo.

Se for bem-sucedido, o método
ksSetTextLineAlign retorna o sinalizador de alinhamento anterior e, em caso de erro, retorna
-1 .
Observe que o método
ksSetTextLineAlign pode ser usado apenas dentro do bloco (no nosso caso, é usado dentro do parágrafo). Isso significa que ele não pode ser usado para definir o alinhamento da saída de texto pelo método
ksText . Essa limitação se deve ao fato de que, neste caso, o KOMPAS não sabe com relação a quais limites o texto precisa ser alinhado.
Outro ponto importante está relacionado ao escopo do método
ksSetTextLineAlign - quais linhas de saída ele afeta. Considere um exemplo (uma sintaxe muito simplificada é usada aqui em comparação com seus originais):
ksSetTextLineAlign(1); ksTextLine(“ ”); ksSetTextLineAlign(2); ksTextLine(“ ”);
Como as linhas serão alinhadas? Ao contrário de nossas expectativas, ambas as linhas serão alinhadas à direita. Porque O fato é que o método
ksSetTextLineAlign altera primeiro o alinhamento da última linha de saída. Aqui está o que acontece em nosso exemplo: a primeira linha define o alinhamento central. Como não há linha de saída anterior, esta chamada altera o alinhamento padrão (esquerda).
Em seguida, imprimimos a linha "Centro". Inicialmente, ele usa o alinhamento central definido anteriormente.
Na terceira linha, alteramos novamente o alinhamento. Primeiro de tudo, o método altera o alinhamento da linha anterior ("Centro"). Portanto, está alinhado à direita, e não ao centro, como planejamos. O mesmo alinhamento fica alinhado por padrão.
Exibimos a linha "Direita". Como o método
ksSetTextLineAlign não
é mais chamado, ele usa o alinhamento definido anteriormente (à direita).
Assim, as duas linhas estão alinhadas à direita. Agora vamos mudar um pouco o exemplo:
ksSetTextLineAlign(1); ksTextLine(“ ”); ksTextLine(“”); ksSetTextLineAlign(2); ksTextLine(“ ”);
Tudo o que mudamos foi adicionar a saída de uma string vazia sem alterar o alinhamento. Agora as linhas são exibidas corretamente. Isso acontece porque a saída de uma sequência vazia "absorve" o alinhamento correto definido. A segunda chamada para o método
ksSetTextLineAlign afeta uma linha vazia e não afeta a linha central de forma alguma.
O exemplo abaixo mostra o alinhamento correto sem exibir uma sequência vazia.
ksTextLine(“ ”); ksSetTextLineAlign(1); ksTextLine(“ ”); ksSetTextLineAlign(2);
As chamadas
ksTextLine e
ksSetTextLineAlign são trocadas. Como o método
ksSetTextLineAlign afeta principalmente a última linha exibida, os alinhamentos são definidos corretamente e as linhas são exibidas como desejávamos.
Exemplo
A seguir, é apresentado o código fonte de um programa que demonstra o alinhamento do texto em um parágrafo. // 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();
Neste exemplo, além do alinhamento do texto, também é demonstrado o uso das propriedades
width e
hFormat da interface
ksParagraphParam . Eles são usados para limitar sua largura. Se não os mudássemos, o KOMPAS aumentaria a largura do parágrafo e não veríamos alinhamento à esquerda e à largura.
Linhas em branco são exibidas para melhorar a legibilidade do parágrafo. Eles não afetam o alinhamento correto.
A figura abaixo mostra o parágrafo gerado por este programa.

Ativar ou desativar o estilo
Na
11ª lição do ciclo, examinamos os sinalizadores que controlam o estilo (
ITALIC_ON ,
ITALIC_OFF ,
BOLD_ON ,
UNDERLINE_ON e
UNDERLINE_OFF ). Em seguida, os examinamos em relação ao método
ksText . Uma diferença importante entre o uso em um parágrafo é que a ação não se limita a chamar o método
ksTextLine , mas se estende ao parágrafo inteiro. Vejamos alguns exemplos.
TextItemFont->SetBitVectorValue(BOLD_ON, true); TextItemParam->s = SysAllocString(L” ”); Document2D->ksTextLine(TextItemParam); TextItemFont->Init(); TextItemParam->s = SysAllocString(L” ”); Document2D->ksTextLine(TextItemParam);
A primeira linha será exibida em negrito. Não há perguntas com isso. Mas como a segunda linha será exibida? A bandeira
BOLD_ON foi redefinida para ela. Portanto, podemos assumir que ele será exibido em fonte regular. Mas isso não é verdade. Tendo cumprido o sinalizador
BOLD_ON , o KOMPAS entende o comando da seguinte maneira: todas as linhas subseqüentes deste parágrafo são exibidas em negrito. Portanto, todas as linhas subseqüentes são exibidas em negrito até o parágrafo ser concluído ou o KOMPAS encontrar o sinalizador
BOLD_OFF associado a ele . Considere um exemplo:
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);
A primeira linha é exibida em negrito. Para a segunda linha,
limpamos o sinalizador
BOLD_ON e posicionamos o sinalizador BOLD_OFF
associado a ele , o que cancela o estilo negrito. Por esse motivo, a segunda e a terceira linhas são exibidas sem negrito.
Esse comportamento se aplica aos sinalizadores
ITALIC_ON ,
ITALIC_OFF ,
UNDERLINE_ON e
UNDERLINE_OFF , mas não se aplica ao sinalizador
NEW_LINE , pois não possui um par de sinalizadores de substituição.
Exemplo
A seguir está o código fonte do programa, mostrando a saída de texto com estilos diferentes usando parágrafos. // 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();
A parte mais importante deste programa é a configuração adequada de sinalizadores para as linhas de saída. Vamos analisá-lo em mais detalhes (as linhas correspondentes do programa são marcadas com um par de caracteres “
// ”).
A primeira linha é exibida sem nenhuma alteração. Portanto, nenhum sinalizador está definido para ele.
A segunda linha deve ser exibida sem inclinação e com uma nova linha. Portanto, os sinalizadores são definidos para ele:
NEW_LINE (inicie em uma nova linha) e
ITALIC_OFF (desative o
itálico ).
A terceira linha deve aparecer em itálico e negrito. Para isso,
exibimos os sinalizadores:
NEW_LINE ,
ITALIC_ON (
ativar itálico) e
BOLD_ON (
ativar faces em negrito). Todos os outros sinalizadores são redefinidos.
A quarta linha deve ser impressa em itálico, sublinhada e não em negrito. Para fazer isso,
exibimos os sinalizadores:
NEW_LINE ,
BOLD_OFF (desative negrito, deixado na linha anterior) e
UNDERLINE_ON (ative sublinhado).
Se houvesse mais linhas no parágrafo, elas seriam exibidas em fonte sublinhada em itálico. Para desativar o estilo sublinhado, você deve limpar o sinalizador UNDERLINE_ON e armar o sinalizador
UNDERLINE_OFF .
A figura abaixo mostra o resultado deste programa.

Separando informações da apresentação
Se você seguir a estrutura de seus programas, provavelmente notou uma séria desvantagem do exemplo anterior: o código responsável por gerar a saída é misturado ao código responsável por implementar sua saída. Com um bom estilo de programação, é habitual separar as informações da sua apresentação.
Se as informações de saída consistirem em várias linhas de
ksTextItemParam , elas poderão ser combinadas em uma interface
ksTextLineParam . O método
ksTextLine pode manipular essas duas interfaces. Mas essa abordagem tem uma limitação desagradável: se o método
ksTextLine aceitar a interface
ksTextLineParam , os sinalizadores
NEW_LINE (e
SPECIAL_SYMBOL_END ) serão ignorados. Ou seja, todas as informações serão exibidas em uma linha, mesmo se o sinalizador
NEW_LINE estiver
definido para algumas
instâncias do ksTextItemParam . Para contornar essa limitação, você deve chamar manualmente
ksTextLine para cada linha.
A seguir, é apresentado o código fonte de um exemplo que demonstra essa técnica. // 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();
Neste exemplo, as linhas de saída são gravadas primeiro no
DynamicArray e somente depois são exibidas no parágrafo. Isso permite que você separe as informações de sua apresentação. Se o sinalizador
NEW_LINE não foi usado em nosso exemplo, poderíamos
conviver com uma chamada para o método
ksTextLine .
O resultado deste programa é semelhante ao resultado do exemplo anterior.
ConclusãoNesta lição, vimos como criar um parágrafo e como usá-lo para exibir texto de várias linhas. Também aprendemos a separar as informações de sua apresentação. Infelizmente, a saída correta do texto de várias linhas requer a passagem manual de uma matriz de seqüências de caracteres. Isso não é muito conveniente. Na próxima lição, mostrarei como resolver esse problema.
Para continuar, acompanhe as notícias do blog.
Sergey Norseev, Ph.D., autor do livro "Application Development for COMPAS in Delphi".