domingo, 27 de fevereiro de 2022

C++ Builder - estilos e funções nativas do win32


O programador que utiliza o C++ Builder,
e que possui pelo menos conhecimentos
intermediário nesta excelente IDE,
está repleto de opções para a criação
de interfaces modernas e de recursos avançados,
exibindo estilos profissionais em seus programas.
Como meus programas são em sua maioria programas
didáticos nunca me preocupei de incorporar
estilos na interface gráfica.
O C++ Builder possui estilos de interfaces
prontos para serem inseridos por seus usuários,
mas se isto não for suficiente, existem empresas
que criam pacotes de interfaces para aplicações
em programas em Delph ou C++, e com preços interessantes.
Mas o programador pode criar suas próprias interfaces
personalizadas, e o único limite nisto tudo só depende
do nível de conhecimento próprio.
As interfaces personalizadas são criadas e salvas
com a extensão .vsf, e pode ser editadas ou reutilizadas por
outros programas quando for necessário.
Um outro recurso importante do C++ Builder
é a possibilidade de utilização das funções nativas
do Win32, e suporte completo das bibliotecas gráfica gdiplus.
Para demonstrar um dos vários estilos prontos do C++ Builder,
e para utilizar algumas funções do Win32, criei este programa,
que faz cálculo do fatorial dos dez primeiros números naturais.
O programa calcula os fatoriais e armazena num vetor 
de estilo C de dez posições.



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

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
#include <gdiplusheaders.h>
#include <gdipluseffects.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")
#include <Gdiplus.h>

#include <sstream>
#include <iostream>
#include <iomanip>

using namespace std;

using std::setw;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
// ---------------------------------------------------------------------------
void Label_Manual ( ) {

	Form1 -> Label1 -> Font->Size = 12;
	Form1 -> Label1 -> Font->Name = "Arial";
	Form1 -> Label1 -> Font->Color = clBlue;
	//Form1 -> Label1 -> Width = 30;
	//Form1 -> Label1 -> Height = 20;
	Form1 -> Label1 -> Left = 50;
	Form1 -> Label1 -> Top = 40;

	Form1 -> Label2 -> Font->Size = 12;
	Form1 -> Label2 -> Font->Name = "alarm clock";
	Form1 -> Label2 -> Font->Color = clBlack;
	//Form1 -> Label2 -> Width = 30;
	//Form1 -> Label2 -> Height = 20;
	Form1 -> Label2 -> Left = 105;
	Form1 -> Label2 -> Top = 65;

	Form1 -> Label3 -> Font->Size = 12;
	Form1 -> Label3 -> Font->Name = "alarm clock";
	Form1 -> Label3 -> Font->Color = clRed;
	//Form1 -> Label2 -> Width = 30;
	//Form1 -> Label2 -> Height = 20;
	Form1 -> Label3 -> Left = 105;
	Form1 -> Label3 -> Top = 65;

	Form1 -> BitBtn1 -> Font -> Size = 12;
	Form1 -> BitBtn1 -> Font -> Color = clBlue;
	Form1 -> BitBtn1 -> Font -> Style = TFontStyles ( ) << fsItalic;
	Form1 -> BitBtn1 -> Top = 260;
	Form1 -> BitBtn1 -> Left = 150;
	Form1 -> BitBtn1 -> Height = 23;
	Form1 -> BitBtn1 -> Width = 50;
	Form1 -> BitBtn1 -> Caption = "Sair";
}
 //---------------------------------------------------------------------------
VOID Moldura ( HDC hdc, int left, int top, int right, int bottom,
	 int bewel, int a, int r, int g, int b ) {

	Gdiplus::Graphics graphics(hdc);

	Gdiplus::Graphics* myGraphics;
	GraphicsPath myGraphicsPath;

	Pen penJoin1 ( Color ( a, r, g, b ), bewel );
	penJoin1.SetLineJoin ( LineJoinBevel );

	graphics.DrawRectangle ( &penJoin1, Gdiplus::Rect ( left, top, right, bottom ) );
	graphics.DrawPath ( &penJoin1, &myGraphicsPath );
}
//----------------------------------------------------------------------------
VOID Informe_2 ( HDC hdc, int x, int y, int a_1, int a_2, int a_3, int a_4,
	int b_1, int b_2, int b_3, int b_4, int c_1, int c_2, int c_3, int c_4,
	LPCWSTR font, FontStyle style, int fontTam ) {

	Gdiplus::Graphics graphics(hdc);

	SolidBrush solidBrush_1 ( Color ( a_1, a_2, a_3, a_4 ) );
	SolidBrush solidBrush_2 ( Color ( b_1, b_2, b_3, b_4 ) );
	SolidBrush solidBrush_3 ( Color ( c_1, c_2, c_3, c_4 ) );

	FontFamily fontFamily ( font );
	Font font1 ( &fontFamily, fontTam, style, UnitPixel );

	Gdiplus::PointF pointF ( x, y );

	const WCHAR* string_1 = L"Por: ";
	const WCHAR* string_2 = L"Samuel Lima";
	const WCHAR* string_3 = L"sa_sp10@hotmail.com";

	graphics.DrawString ( string_1, 4, &font1, Gdiplus::PointF ( x, y ), &solidBrush_1 );
	graphics.DrawString ( string_2, 12, &font1, Gdiplus::PointF ( x + 40, y ), &solidBrush_2 );
	graphics.DrawString ( string_3, 20, &font1, Gdiplus::PointF ( x, y + 18 ), &solidBrush_3 );
}
 //---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint ( TObject *Sender ) {

	Gdiplus::GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR  gdiplusToken;
	// Inicializando GDI+.
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	HDC hdc = Canvas -> Handle;

	static HFONT hFont;

		 HFONT holdFont;
		 HFONT m_newFont;

		 hFont = CreateFont (
	18,                       // nHeight
	8,                        // nWidth
	0,                        // nEscapement
	0,                        // nOrientation
	FW_NORMAL,                // nWeight
	TRUE,                    // bItalic
	FALSE,                    // bUnderline
	0,                        // cStrikeOut
	ANSI_CHARSET,             // nCharSet
	OUT_DEFAULT_PRECIS,       // nOutPrecision
	CLIP_DEFAULT_PRECIS,      // nClipPrecision
	DEFAULT_QUALITY,          // nQuality
	DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
	_T ( "Times New Roman" ) );
				m_newFont = CreateFont ( 80, 0, 0, 0,
        FW_THIN, FALSE, TRUE, FALSE,
        ANSI_CHARSET, OUT_DEFAULT_PRECIS,
		CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
		DEFAULT_PITCH | FF_DONTCARE, _T ( "Times" ) );

		SelectObject ( hdc, hFont );
		DeleteObject ( hFont );

	SetTextColor ( hdc, RGB ( 255, 0, 0 ) );
	SetBkColor ( hdc, RGB ( 0, 0, 0 ) );
	TextOutA ( hdc, 100, 10, "C++ BUILDER - ARMAZENANDO FATORIAL EM VETOR", 43 );

	Moldura ( hdc, 5, 5, 590, 290, 10, 255, 0, 0, 255 );

		Informe_2 (
		hdc, 230, 250,
		255, 255, 0, 0,
		255, 0, 0, 255,
		255, 0, 255, 0,
		L"Times New Roman",
		FontStyleItalic, 14 );
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow ( TObject *Sender ) {
	Label_Manual ( );

	string str_1;
	string str_2;
	string str_3;

	const  char *Conv_1;
	const  char *Conv_2;
	const  char *Conv_3;

	int vet_fat [ 10 ];

	int val, fatorial = 1;

	stringstream sst;
	sst << setw ( 29 ) << "Posição" << setw ( 29 ) << "Fatorial" << endl;
	str_1 += sst.str ( );

	//Convertendo std::string em const  char
	Conv_1 = str_1.c_str ( );
	Label1 -> Caption += ( Conv_1 );

	for ( int i = 1; i <= 10; i++ ) {
		//stringstream deve ser declarado aqui
		stringstream sst_1;
		stringstream sst_2;

		val = i;
		if ( val > 1 ) {
			fatorial = fatorial * val;
			val--;
		}

		vet_fat [ i ] =  fatorial;
		sst_1 << setw ( 7 ) << i << + "°" << endl;
		str_2 += sst_1.str ( );

		//Convertendo std::string em const  char
		Conv_2 = str_2.c_str ( );
		Label2 -> Caption = ( Conv_2 );

		sst_2 << setw ( 23 ) << vet_fat [ i ] << endl;
		str_3 += sst_2.str ( );

		//Convertendo std::string em const  char
		Conv_3 = str_3.c_str ( );
	}

	Label3 -> Caption += ( Conv_3 );

}
//---------------------------------------------------------------------------
void __fastcall TForm1::BitBtn1Click ( TObject *Sender ) {
			   Close ( );
}
//---------------------------------------------------------------------------

sábado, 22 de maio de 2021

FMX - criando um novo cadastro num arquivo


No último post, nos responsabilizamos de fazer
um programa para criar cadastros num arquivo,
mas o programa tinha que ser capaz de saber
se existem cadastros vazios,
se existem, o programa deverá preencher
estes cadastros, se não houver cadastros vazios,
ou se todos já foram preenchidos o programa
deveria acrescentar um novo cadastro abaixo
do último registrado.
Na verdade tudo o que iriámos
precisar já foram feitos nos programas anteriores,
mas por falta de tempo passamos alguns
dias sem programar.
Para fazer este programa, criamos algumas
funções com retorno para string e inteiro,
e com alocação dinâmica, visto que os cadastros
tende à aumentar de acordo com uso.
O programa está apto à calcular o total
de cadastros, o total de linhas, e o tamanho em bytes
do arquivo e isto tudo em tempo de execução.
O funcionamento básico se resume na remoção
de um cadastro, ou na criação de um novo.
Quando um cadastro é removido,
o programa escreve no cadastro a palavra "Vazio",
e quando o usuário escolhe no menu a opção
criar cadastro, o programa pesquisa automaticamente,
por cadastros vazios utilizando a palavra
que ele mesmo escreveu (Vazio), se for encontrado,
é nesta posição que o novo cadastro será criado.
Na verdade até um ponto já seria suficiente
para isto, ou alguns caracteres em branco.
Para testar o funcionamento, vamos começar
com um arquivo totalmente vazio,
depois daremos uma pausa no vídeo,
e acrescentaremos manualmente vários outros cadastros,
para que o vídeo não fique tão extenso.
Depois iremos apagar e criar alguns.
Assistam o vídeo por favor.



//------------------------------------------------------------------------------
void T_Memo ( int X, int Y, int W, int H ) {
   Form5 -> Memo1 -> Position -> X = X;
   Form5 -> Memo1 -> Position -> Y = Y;
   Form5 -> Memo1 -> Width = W;
   Form5 -> Memo1 -> Height = H;
   Form5 -> Memo1 -> ShowScrollBars = True;
   Form5 -> Memo1 -> Size -> PlatformDefault = False;
   Form5 -> Memo1 -> TextSettings -> Font -> Family = "Consolas";
   Form5 -> Memo1 -> TextSettings -> Font -> Size = 14;
   Form5 -> Memo1 -> TextSettings -> Font -> Style = TFontStyles ( ) << fsBold << fsItalic;
   Form5 -> Memo1 -> TextSettings -> FontColor = claBlack;
}
//------------------------------------------------------------------------------
void T_Memo_1 ( int X, int Y, int W, int H ) {
   Form1 -> Memo1 -> Position -> X = X;
   Form1 -> Memo1 -> Position -> Y = Y;
   Form1 -> Memo1 -> Width = W;
   Form1 -> Memo1 -> Height = H;
   Form1 -> Memo1 -> ShowScrollBars = True;
   Form1 -> Memo1 -> Size -> PlatformDefault = False;
   Form1 -> Memo1 -> TextSettings -> Font -> Family = "Consolas";
   Form1 -> Memo1 -> TextSettings -> Font -> Size = 14;
   Form1 -> Memo1 -> TextSettings -> Font -> Style = TFontStyles ( ) << fsBold << fsItalic;
   Form1 -> Memo1 -> TextSettings -> FontColor = claBlue;
}
//------------------------------------------------------------------------------
void func ( bool val ) {
if ( val == false ) {
T_Text2 ( 150, 253, 170, 18, 1 );
Form5 -> Text2 -> Text = "Remover cadastro de Nº";
}
if ( val == true ) {
T_Text2 ( 150, 250, 270, 18, 3 );
Form5 -> Text2 -> Text = "O Cadastro foi removido com sucesso";
}
}
//------------------------------------------------------------------------------
void func_2 ( bool val ) {
  if ( val == false ) {
T_Rect ( 150, 60, 260, 18, 1, 2 );
T_Text ( 150, 60, 260, 18, 16, false, 1, 0, "Leitura de todos os cadastros" );
  }
  if ( val == true ) {
T_Rect ( 150, 60, 260, 18, 5, 4 );
T_Text ( 150, 60, 260, 18, 16, false, 5, 0, "Leitura de todos os cadastros" );
  }
}
//------------------------------------------------------------------------------


quarta-feira, 28 de abril de 2021

FMX - Abrindo imprimindo e alterando um arquivo

No último post, há alguns dias atrás,
criamos um programa no C++ builder,
que fazia leitura, pesquisa individual,
e remoção de um cadastro criado manualmente
num arquivo.
E como ficou determinado que no post seguinte,
nós faríamos alterações num cadastro dentro
de um arquivo de texto, aqui está cumprido.
Pena que por falta de tempo suficiente
não fizemos isto antes, mas conseguimos
reservar algumas horas para programar.
Sempre que temos que fazer alterações num
arquivo, optamos por trabalhar com a abertura
de dois e de nomes diferentes, isto é óbvio,
sendo um como leitura e outro como escrita.
No arquivo que abrimos como escrita,
fizemos as alterações, mas ele precisa
assumir o nome do arquivo que foi aberto 
como leitura, sendo que o arquivo,
que foi aberto como leitura precisa
ser destruído, e o arquivo que foi aberto
como escrita e que recebeu as alterações,
agora é o arquivo principal.
Para fazer este processo conheço
duas maneiras, uma é a clássica, usando,
as funções da biblioteca padrão do C,
à saber, as funções rename ( ..., ... );
e remove ( ... ); e a outra maneira,
pouco usada, acredito assim, mas que estamos
usando neste programa e no programa do post
anterior, que é na força bruta, com comandos
do dos, e que funciona perfeitamente ainda hoje.
Na opção de alterar cadastro, preferi manter,
o que foi configurado no programa anterior,
isto é, apagar um cadastro deixando o espaço
em branco, para isto basta clicar no botão
"Editar", sem que nada tenha sido escrito,
nos campos do componente de edição.
Mesmo nós tendo criado manualmente 29 cadastros,
O programa está pronto para selecionar um cadastro,
entre centenas ou milhares, porque a pesquisa
é eficiente e não falha, e sabemos muito bem
do que estamos falando.
Então, nos posts anteriores, fizemos leitura,
fizemos precisa pesquisa, fizemos remoção,
e agora alteração de cadastros em arquivo.
Pergunta:
Podemos fazer um programa para criar cadastros,
onde um foi removido com sucesso,
ou se não houver cadastros vazios, inserir
com precisão abaixo do último cadastro?
ora, o programa terá de ser inteligente
o suficiente para detectar cadastros vazios,
e inserir o novo cadastro no primeiro vago
que encontrar, e se não houver cadastros vazios,
ele automaticamente irá inserir depois do último.
Vamos queimar nossos miolos?
Até breve, se Deus quiser. 
Assistam o vídeo por favor.
Se precisarem de ajuda com o C++ builder,
entre em contato comigo.




//-----------------------------------------------------------------------
//FormCreate está funcionando com um evento OnClick do Button1
void __fastcall TForm2::FormCreate ( TObject *Sender ) {
   Label_Manual ( Sender );

   ScrollBox1 -> Visible = false;
   Button1 -> Visible = false;
   //pos X, pos Y, Width, Height, Size, Bool, Color,String
   T_Text ( 50, 35, 500, 20, 17, true, 2, 3, "ARQUIVO - ABRINDO IMPRIMINDO E ALTERANDO" );

   Imprime_Arquivo ( Sender );

   Button1 -> Visible = true;
   x++;

   if (  x == 2 && Form2 -> Edit1 -> Text == "" ) {
Beep ( 500, 500 );
Form2 -> Show ( );
Form3 -> Hide ( );
Form1 -> Hide ( );
                        x = 1;
   }

   if ( x == 2 ) {
   int c = 0;
   c = Contador ( );
   T_Text ( 100, 60, 270, 17, 14, true, 3, 1, "Alterando o cadastro de Nº: " );
   T_Rect ( 340, 60, 20, 17, 3, 4 );
   T_Text ( 340, 60, 20, 17, 14, true, 3, 0, c );
   Form2 -> Terceira_janela ( Sender );
   x = 1;
   }
}
//---------------------------------------------------------------------------