quarta-feira, 15 de janeiro de 2025

Como converter decimal para romanos em Delphi

function DecToRoman( Decimal: LongInt ): String;

{Converte um numero decimal em algarismos romanos}

const

    Romans: Array[1..13] of String = ( 'I', 'IV', 'V', 'IX', 'X','XL', 'L', 'XC', 'C', 'CD', 'D', 'CM', 'M' );

    Arabics: Array[1..13] of Integer =( 1, 4, 5, 9, 10, 40, 50, 90,100, 400, 500, 900, 1000);

var

    i: Integer;

    scratch: String;

begin

  scratch := '';

  for i := 13 downto 1 do

  while ( Decimal >= Arabics[i] ) do

  begin

  Decimal := Decimal - Arabics[i];

  scratch := scratch + Romans[i];

  end;

  Result := scratch;

end;

Colocar uma ProgressBar numa StatusBar

Coloque uma StatusBar no form e adicione dois painéis a ela (propriedade Panels). Ajuste as propriedades do primeiro painel comoStyle = psOwnerDraw e Width = 150. Coloque uma ProgressBar no form e mude sua propriedade Visible para false. No evento OnDrawPanel da StatusBar digite o código abaixo:

procedure TForm1.StatusBar1DrawPanel(StatusBar: TStatusBar;

Panel: TStatusPanel; const Rect: TRect);

begin

  { Se for o primeiro painel... }

  if Panel.Index = 0 then begin

      { Ajusta a tamanho da ProgressBar de acordo com o tamanho do painel }

      ProgressBar1.Width := Rect.Right - Rect.Left +1;

      ProgressBar1.Height := Rect.Bottom - Rect.Top +1;

      { Pinta a ProgressBar no DC (device-context) da StatusBar }

      ProgressBar1.PaintTo(StatusBar.Canvas.Handle, Rect.Left, Rect.Top);

  end;

end;

ColoqueumButtonnoform

DigitenoeventoOnClickdoButtonocódigoabaixo:

procedure TForm1.Button1Click(Sender: TObject);

var

  I: integer;

begin

  for I := ProgressBar1.Min to ProgressBar1.Max do begin

  { Atualiza a posição da ProgressBar }

  ProgressBar1.Position := I;

  { Repinta a StatusBar para forçar a atualização visual }

  StatusBar1.Repaint;

  { Aguarda 50 milisegundos }

  Sleep(50);

  end;

  { Aguarde 500 milisegundos }

  Sleep(500);

  { Reseta (zera) a ProgressBar }

  ProgressBar1.Position := ProgressBar1.Min;

  { Repinta a StatusBar para forçar a atualização visual }

  StatusBar1.Repaint;

end;

Execute e clique no botão para ver o resultado.


Colocar os bitmaps na DLL

 Por vezes, quando iniciamos um projeto, temos uma preocupação: fazer uma aplicação pequena em delphi. Bem, a solução pode passar por colocar todos os bitmaps que vamos utilizar numa DLL. Então vamos lá começar:

Deve usar o Image Editor, criar uma nova Resource File (.res), neste ficheiro vamos colocar os bitmaps e icons (ambos funcionam da mesma forma) que queremos na nossa aplicação, clique com a tecla direita do mouse na nova resource file e crie um novo bitmap, depois desenhe ou cole do clipboard um bitmap, finalmente guarde o ficheiro com o nome images.res. Depois disto estar feito vá ao IDE do Delphi e no File menu clique New... e escolha DLL depois cole o código abaixo, não se esqueça de adicionar uma unit vazia ao projeto. Guarde o projeto da dll no mesmo diretório do ficheiro image.res, finalmente faça o build da DLL (não se esqueça, que não se pode correr (executar) uma DLL!)

Código da DLL:

library ImageRes; {nome da dll}

uses DummyUnit; {DummyUnit é uma unit vazia, que é necessária}

{$R images.res} {nome da resource file, que deve estar no mesmo caminho da dll}

begin

end.

Código da DummyUnit:

unit DummyUnit;

interface

implementation

end.


Colocando bitmaps num ComboBox

Ajuste a propriedade Style do ComboBox para csOwnerDrawVariable

var

  Form1: TForm1;

  Bmp1, Bmp2, Bmp3: TBitmap;

implementation

 {$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);

begin

    Bmp1:=TBitmap.Create;

    Bmp.Loadfromfile('c:\chip16.bmp');

    Bmp1:=TBitmap.Create;

    Bmp.Loadfromfile('c:\zoom.bmp');

    Bmp1:=TBitmap.Create;

    Bmp.Loadfromfile('c:\disk.bmp');

    ComboBox1.Items.AddObject('Chip',Bmp1);

    ComboBox1.Items.AddObject('Zoom',Bmp2);

    ComboBox1.Items.AddObject('Disk',Bmp3);

end;

procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOWnerDrawState);

var

  Bitmap: TBitmap;

  Offset: Integer;

begin

  with (Control as TComboBox).Canvas do

  begin

      FillRect(Rect); Bitmap:= TBitmap(ComboBox1.Items.Objects[index]);

      if Bitmap nil then begin

        BrushCopy(Bounds(Rect.Left + 2, Rect.Top + 2, Bitmap.Width,

        Bitmap.Height), Bitmap, Bounds(0, 0, Bitmap.Width, Bitmap.Height), clRed);

        Offset: Bitmap.width + 8;

      end;

      TextOut(Rect.Left + Offset, Rect.Top, ComboBox1.Items[index]);

  end;

end;

procedure TForm1.ComboBox1MeasureItem(Control: TWinControl; Index: Integer; var Height: Integer);

begin

  Height:=20;

end;

segunda-feira, 21 de setembro de 2015

Como usar a propriedade Eof para verificar se estamos no último registro do TClientDataSet


Em algumas situações gostaríamos de verificar se já estamos no último registro do TClientDataSet, ou seja, estamos percorrendo todos os registros do dataset e queremos saber se já estamos no último. Para isso podemos usar a propriedade Eof da classe TClientDataSet. Esta propriedade retorna true se estivermos no último registro e false em caso contrário.

Veja um trecho de código no qual usamos um laço while para percorrer todos os registros de um TClientDataSet. Note o uso da propriedade Eof para finalizar as iterações do laço:

procedure TForm3.Button4Click(Sender: TObject);
begin
  // vamos percorrer todos os registros do TClientDataSet
  ClientDataSet1.First; // vamos para o primeiro registro
  // e agora disparamos um laço While
  while not ClientDataSet1.Eof do
    begin
      // vamos mostrar em um TMemo os valores do
      // campo id de cada registro
      Memo1.Lines.Add(ClientDataSet1.FieldByName('id').AsString);
      // vamos mover para o próximo registro
      ClientDataSet1.Next;
    end;
end;


A propriedade Eof é verdadeira quando:

a) Abrimos um dataset vazio. 

b) Efetuamos uma chamada ao método Last do dataset.

c) Chamamos o método Next do dataset e a chamada falha porque o registro atual já é o último registro no dataset.

d) Efetuamos uma chamada ao método SetRange em uma faixa de dados ou dataset vazio.

Como obter o número do registro atual em um TClientDataSet


Em algumas situações gostaríamos de obter o número do registro atual enquanto navegamos pelos registros de um TClientDataSet. Isso pode ser feito por meio da propriedade RecNo (implementada na classe TDataSet e reimplementada na classe TClientDataSet). O retorno da propriedade é sempre um valor inteiro representando o registro atual. Na implementação da classe TClientDataSet, esta propriedade retorna o valor -1 se o componente estiver no estado (State) dsInsert (um novo registro estiver sendo inserido).

Veja um trecho de código no qual usamos o evento OnClick de um botão para exibir o número do registro atual em um TClientDataSet: 

procedure TForm3.Button3Click(Sender: TObject);
var
  nRegistro: Integer;
begin
  // obtém o número do registro atual no TClientDataSet
  nRegistro := ClientDataSet1.RecNo;

  // mostra o resultado
  ShowMessage('O número do registro atual é: ' + IntToStr(nRegistro));
end;

Ao executar o código e clicar no botão você verá uma mensagem parecida com:

"O número do registro atual é: 5".

Esta dica foi escrita e testada no Delphi 2009.

Aprenda a usar a propriedade Active da classe TClientDataSet


A propriedade Active de um controle TClientDataSet pode ser definida em tempo de design (pelo Object Inspector) ou em tempo de execução. Se o valor for True os dados armazenados no TClientDataSet podem ser lidos e manipulados. Se o valor for False, o client dataset está fechado (closed) e não podemos acessar nem manipular os dados contidos nele.

Veja no trecho de código abaixo como definir o valor da propriedade Active em tempo de execução:

procedure TForm3.Button3Click(Sender: TObject);
begin
  // vamos ativar o client dataset
  ClientDataSet1.Active := True;

  // vamos testar se o client dataset foi mesmo ativado
  if ClientDataSet1.Active then
    ShowMessage('O ClientDataSet está ativo')
  else
    ShowMessage('O ClientDataSet  NÃO está ativo')
end;

Ao clicar no botão nós "ativamos" o client dataset e em seguida testamos o valor da propriedade Active para informar se o controle foi realmente ativado. É preciso ter muito cuidado. Tentar manipular os dados de um client dataset fechado pode resultar em uma exceção do tipo EDatabaseError com mensagens parecidas com:

Project Projeto.exe raised exception class EDatabaseError with message 'ClientDataSet1: Cannot perform this operation on a closed dataset'.

Ao definirmos o valor True para a propriedade Active as seguintes ações ocorrem:

1) O client dataset é preenchido com dados. Dependendo das propriedades do controle, estes dados podem vir de três formas diferentes: a) Do arquivo especificado na propriedade FileName; b) Do provider especificado na propriedade ProviderName ou por meio do método SetProvider. (algumas classes derivadas de TCustomClientDataSet possuem um componente interno que faz o papel do provider); c) Os dados que estavam ativos quando o client dataset foi desativado (somente se a aplicação foi executada durante um certo período depois que o dataset foi desativado).

2) O evento BeforeOpen é disparado. 

3) O valor dsBrowse é atribuído à propriedade State do dataset. 

4) Abre e posiciona um cursor no primeiro registro do conjunto de dados.

5) Dispara o evento AfterOpen. 

Se o client dataset nunca foi ativado, atribuir o valor True para a propriedade Active faz com que a estrutura (metadata) do client dataset seja definida. Esta estrutura é obtida juntamente com o pacote de dados a partir do provider ou armazenado em disco. Se não houver pacote de dados, tal estrutura é construída usando o valor atual da propriedade FieldDefs ou a partir dos componentes de campos persistentes listados na propriedade Fields.

Se um erro ocorrer durante a abertura do dataset, seu estado (State) é definido como dsInactive e o cursor de navegação é fechado.

Ao definirmos o valor False para a propriedade Active as seguintes ações ocorrem:

1) O evento BeforeClose é disparado. 

2) O valor para a propriedade State é definido como dsInactive. 

3) O cursor de navegação é fechado, salvando os dados atuais em disco se a propriedade FileName estiver definida e salvando o pacote de dados atual em cache de forma que o mesmo possa ser restaurado mais tarde quando o dataset for reaberto.

4) O evento AfterClose é disparado. 

Importante: Uma chamada ao método Open do TClientDataSet define a propriedade Active como True, enquanto uma chamada ao método Close a define como False.

Esta dica foi escrita e testada no Delphi 2009.

Curso de Delphi: 7.Consultas SQL