Trabalhar com a API KOMPAS-3D → Lição 13 → Parágrafos

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”


  1. O básico
  2. Desenho de desenho
  3. Conexão correta com o KOMPAS
  4. Inscrição principal
  5. Primitivas gráficas
  6. Salvando um documento em vários formatos
  7. Conhecendo as configurações
  8. Métodos de escrita mais sofisticados no bloco de título
  9. Lendo células de legenda
  10. Caracteres especiais, incluindo uma sequência
  11. Etiquetas de texto simples
  12. Cordas compostas
  13. Parágrafos
  14. 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 :

  1. 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 .
  2. 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.

  1. 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 .
  2. 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.
  3. 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ão

Nesta 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".

Source: https://habr.com/ru/post/pt434336/


All Articles