sábado, 5 de abril de 2008

Plotando gráficos no Borland C++ Builder

 

Convém praticar o desenvolvimento do projeto "Desenhando em Cpp Builder" publicado em:


 http://www.cbrasil.org/wiki/index.php?title=Desenhando_em_Cpp_Builder, por Wanderley Caloni.


No projeto acima são abordados os conceitos básicos para plotagem de elementos gráficos diretamente na região de um formulário (objeto Form1 instanciado da classe TForm1) e a persistência e reconstituição dos elementos plotados quando o formulário é redesenhado ao retomar o foco do gerenciador de janelas (evento FormPaint).

Toda a lógica está orientada aos eventos:

  • FormMouseDown: fixar a posição da caneta para plotagem de linha (Canvas->PenPos) relativa à posição corrente do mouse;
  • FormMouseMove: traçar linha até o ponto relativo à posição corrente do mouse;
  • FormMouseUp: desligar flag (mouseDown) que controla a plotagem;
  • FormPaint: reconstituir a plotagem quando o formulário retoma o foco do gerenciador de janelas;

A classe TForm1 (Form1), por herança da classe TForm, agrega a classe TCanvas (definida na biblioteca Graphics.hpp). O objeto canvas do formulario disponibiliza diversos métodos e propriedades para plotagem gráfica:

  • Canvas->PenPos : fixar a posição da caneta para plotagem de linha em um ponto (x1, y1);
  • Canvas->LineTo : traçar linha do ponto (x1, y1) até um ponto (x2, y2), deixando a caneta nesta nova posição;
  • Canvas->Draw : plotar um objeto do tipo bitmap (de área retangular) a partir do canto superior esquerdo deste na posição inicial definida pelo ponto (x, y) ;

Objetos da classe Graphics::TBitmap também disponibizam um canvas, permitindo construir todo um conteúdo a ser plotado primeiramente em formato bitmap e, numa etapa posterior, poderemos usar estes bitmaps para plotar em objetos como formulario (TForm), paintbox (TPaintPox) , image (TImage) e até mesmo em outro objeto bitmap (TBitmap).

A partir do projeto do Wanderley Caloni, foi desenvolvida uma versão usando a classe Graphics::TBitmap (graphics.hpp) e, para reforçar os conceitos de orientação a objetos, foi proposta a construção de uma classe denominada Quadrado para realizar a plotagem das arestas de quadrados desejados diretamente em um bitmap.

Começando pela interface gráfica do projeto, temos:

image

 

Destacamos os seguintes eventos para tratamento "PaintBox1Paint":

image

e "Button1Click":

image

 

O código para o "Unit1.h" do formulário ficou assim:

 

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H

//---------------------------------------------------------------------------

#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>

#include "Unit2.h"

//---------------------------------------------------------------------------

class TForm1 : public TForm
{
__published:    // IDE-managed Components

        TLabel *Label1;
        TEdit *Edit1;
        TLabel *Label2;
        TEdit *Edit2;
        TLabel *Label3;
        TEdit *Edit3;
        TButton *Button1;
        TPaintBox *PaintBox1;

        void __fastcall Button1Click(TObject *Sender);
        void __fastcall PaintBox1Paint(TObject *Sender);

private:    // User declarations

        Graphics::TBitmap *figura;

public:        // User declarations

        __fastcall TForm1(TComponent* Owner);       // construtor
        __fastcall ~TForm1( void );                         // destrutor

};

//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------

#endif

 

E aqui o código para o "Unit1.cpp":

 

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)
#pragma resource "*.dfm"

TForm1 *Form1;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)  // construtor
{
        this->figura = new Graphics::TBitmap();

        this->figura->Width = this->PaintBox1->Width ;
        this->figura->Height = this->PaintBox1->Height;

}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1()                                                   // destrutor
{
        delete this->figura;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)


       
// Os valores fornecidos para X, Y e L não foram considerados nesta
        // versão preliminar, apenas para mostrar o uso de
        // múltiplos construtores da classe Quadrado.

        Quadrado *q1, *q2, *q3;

        q1 =  new Quadrado();
       
q1->Plotar( this->figura );
       

q2 =  new Quadrado( 400, 100 );
q2->Plotar( this->figura );


q3 =  new Quadrado( 50, 50, 20);
q3->Plotar( this->figura );

        this->PaintBox1->Repaint() ;

        delete q1;
        delete q2;
        delete q3;

}
//---------------------------------------------------------------------------

void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
        this->PaintBox1->Canvas->Draw( 0, 0, this->figura );
}
//---------------------------------------------------------------------------

 

E agora o código para a classe Quadrado, começando pelo "Unit2.h":

 

//---------------------------------------------------------------------------

#ifndef Unit2H
#define Unit2H

#include <graphics.hpp>

class Quadrado
{
        private:

                int x;
                int y;
                int largura;

        public:

                Quadrado();                                       // construtor default
                Quadrado( int, int );                            // construtor
                Quadrado( int, int, int );                       // construtor

                void Plotar( Graphics::TBitmap * );

                ~Quadrado();                                    // destrutor

};

//---------------------------------------------------------------------------

#endif

 

E finalmente o "Unit2.cpp" para a classe Quadrado:

 

//---------------------------------------------------------------------------

#pragma hdrstop

#include "Unit2.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

Quadrado :: Quadrado( )                               // construtor default
{
        this->x = 100;
        this->y = 200;
        this->largura = 90;
}

Quadrado :: Quadrado( int a, int b )                 // construtor
{
        this->x = a;
        this->y = b;
        this->largura = 50;
}

Quadrado :: Quadrado( int a, int b, int c)           // construtor
{
        this->x = a;
        this->y = b;
        this->largura = c;
}

void Quadrado :: Plotar( Graphics::TBitmap *tmp )
{
        tmp->Canvas->PenPos = TPoint( this->x, this->y );

        tmp->Canvas->LineTo( this->x + this->largura, this->y  );

        tmp->Canvas->LineTo( this->x + this->largura, this->y + this->largura );

        tmp->Canvas->LineTo( this->x, this->y + this->largura  );

        tmp->Canvas->LineTo( this->x, this->y  );

}

Quadrado :: ~Quadrado()
{
}

 

E então, aqui temos a execução do programa quando do clique no botão Plotar:

 

image

 

Próxima tarefa: complementar o código que falta para plotar o quadrado conforme localização e largura indicadas.

 

Até mais.

Nenhum comentário: