Reduzindo o tempo de carga de um programa Delphi
É comum acontecer um sensível aumento do tempo de carga de um aplicativo desenvolvido em Delphi à medida que este aplicativo cresce e adquire mais e mais formulários. Às vezes o tempo de carga se torna totalmente insuportável.
Os programas se tornam lentos principalmente devido à grande quantidade de formulários que são criados e inicializados logo no início da execução do programa. Antes de ser efetivamente utilizado, todo formulário precisa ser criado. A criação do formulário também provoca a criação de todos os componentes incluidos nele. Além disto, o código que o programador escreveu para o evento FormCreate é executado.
Sempre que você adiciona um novo formulário ao sistema, o IDE do Delphi providencia código para que ele seja criado automaticamente. Isto simplifica a vida do programador que não precisará se preocupar com este detalhe.
O aumento do tempo de carga do aplicativo pode ser resolvido pela simples remoção do código que o Delphi gerou para a criação do formulário. Entretanto isto cria um problema. Antes de efetivamente mostrar o formulário na tela (ou antes de usar e/ou alterar qualquer componente contido nele), nós deveremos incluir manualmente o código para criá-lo.
Para remover o código que o Delphi criou automaticamente, selecione Project|Options no menu. Selecione a aba 'Forms'. Aponte para um dos formulários e clique no botão '>'. Isto faz com que o formulário passe do painel 'Auto-create forms' para o painel 'Available forms'. Isto também retira o código que o Delphi criou.
Se você quer saber onde está este código, clique em View|Units (ou use Ctrl-F12) e selecione o seu projeto na lista de units que aparecerá. O código que cria formulários é algo mais ou menos como se segue:
Application.CreateForm(TForm1, Form1);
Cada formulário auto-criado terá uma linha como esta. Quando o formulário passa para o painel de 'Available forms', a linha correspondente é removida. Você também pode simplesmente remover a linha manualmente, usando o editor de textos.
Tipicamente usar um formulário significa mostrá-lo na tela. Isto é feito invocando-se os métodos Show ou ShowModal do formulário conforme o estilo do aplicativo. Agora que o formulário não é mais criado automaticamente, isto se torna um pouco mais complicado. Mostrar o formulário agora requer uma codificação como a que se segue:
if Form1 = nil then
Form1 := TForm1.Create ( Application );
Form1.Show; { ou Form1.ShowModal; }
Alternativamente você poderia escrever assim:
if Form1 = nil then
Application.CreateForm ( TForm1, Form1 );
Form1.Show; { ou Form1.ShowModal; }
O efeito é o mesmo, mas eu, pessoalmente, prefiro a primeira forma.
Você deve ter extremo cuidado ao usar esta técnica. Se você tirar o código de criação automática do formulário e tentar executar o Show ou ShowModal você vai receber um erro do tipo 'Access violation'. Tome cuidado e faça isto um formulário por vez.
Atenção! Não faça isto para o seu formulário principal. O formulário principal precisa ser o primeiro formulário a ser criado. Assim é melhor mantê-lo como auto-criado.
Esta técnica efetivamente 'distribui' o tempo de carga e inicialização do aplicativo pela execução do programa. Os formulários agora são carregados 'sob-demanda'. Formulários nunca utilizados nunca serão criados. Isto também melhora o uso de memória e é benéfico ao seu computador (e à sua rede, eventualmente) como um todo.
Como saber o estado das teclas Num lock, Caps lock e Scroll lock
Para saber o estado das teclas acima citadas, utilize a função getkeystate em conjunto com o código das teclas, ela retorna 0 se a tecla estiver OFF e 1 se a tecla estiver ON, assim:
If getkeystate(vk_numlock) = 0 then // Num lock está OFF
If getkeystate(vk_numlock) = 1 then // Num lock está ON
If getkeystate(vk_scroll) = 0 then // Scroll lock está OFF
If getkeystate(vk_scroll) = 1 then // Scroll lock está ON
If getkeystate(vk_CAPITAL) = 0 then // Caps lock está OFF
If getkeystate(vk_CAPITAL) = 1 then // Caps lock está ON
Como extrair o ícone de um executável
Inclua a unit Shellapi na cláusula uses do seu form.
Image1.Picture.Icon.Handle:= ExtractIcon(Handle,PChar('c:\windows\calc.exe'),0);
Como criar um alias dinamicamente na memória
procedure TForm1.FormCreate(Sender: TObject);
begin
if not Session.IsAlias('Teste') then
session.AddStandardAlias('Teste',
ExtractFilePath(Application.ExeName),'PARADOX');
end;
Desabilitando um RadioButton num RadioGroup
TRadioButton(RadioGroup1.Controls[1]).
Enabled := False;
Ativar a proteção de tela do Windows Inclua na seção uses: Windows
{ Ativa a proteção de tela do Windows, se estiver configurada. }
SendMessage(Application.Handle, WM_SYSCOMMAND, SC_SCREENSAVE, 0);
Desligar/Ligar monitor
Inclua na seção uses: Windows
No Win95 podemos desligar o monitor afim de economizar energia elétrica. Normalmente este recurso é controlado pelo próprio Windows. Porém sua aplicação Delphi também pode fazer isto. O exemplo abaixo desliga o monitor, aguarde 5 segundos e re-liga monitor.
SendMessage(Application.Handle, WM_SYSCOMMAND,
SC_MONITORPOWER, 0);
Sleep(5000); { Aguarde 5 segundos }
SendMessage(Application.Handle, WM_SYSCOMMAND,
SC_MONITORPOWER, -1);
Observações
Este recurso pode não funcionar dependendo da configuração do sistema
Impedir que o form seja arrastado para fora das margens da tela
- Na seção Private declare a procedure abaixo:
private
procedure WMMove(var Msg: TWMMove); message WM_MOVE;
- Abaixo da palavra implementation escreva a procedure abaixo:
procedure TForm1.WMMove(var Msg: TWMMove);
begin
if Left < 0 then
Left := 0;
if Top < 0 then
Top := 0;
if Screen.Width - (Left + Width) < 0 then
Left := Screen.Width - Width;
if Screen.Height - (Top + Height) < 0 then
Top := Screen.Height - Height;
end;
Para testar:
- Execute o programa e tente arrastar o form para fora das margens da tela e veja o que acontece.
Criar sub-diretório no diretório do EXE
Inclua na seção uses: FileCtrl, SysUtils
function CriaSubDir(const NomeSubDir: string): boolean;
var
Caminho: string;
begin
Caminho := ExtractFilePath(ParamStr(0)) + NomeSubDir;
if DirectoryExists(Caminho) then
Result := true
else
Result := CreateDir(Caminho);
end;
Exemplo de uso:
- Chame a função no evento OnCreate do form:
procedure TForm1.FormCreate(Sender: TObject);
begin
if not CriaSubDir('MeuSubDir') then
ShowMessage('Não foi possível criar o sub-diretório MeuSubDir.');
end;
Mudar a cor de um DBEdit dentro de um DBCtrlGrid de acordo com uma condição
- Monte o form normalmente colocando DataSource, Table, DBCtrlGrid e os DBEdit's, DBText's, etc.
- Escreva no manipulador do evento OnPaintPanel do DBCtrlGrid conforme abaixo:
procedure TForm1.DBCtrlGrid1PaintPanel(DBCtrlGrid: TDBCtrlGrid;
Index: Integer);
begin
if Table.FieldByName('NomeDoCampo').AsFloat < 0 then
DBEdit1.Font.Color := clRed
else
DBEdit1.Font.Color := clBlue;
end;
Observações
Neste exemplo mudamos a cor da fonte do componente DBEdit, Porém, pode-se também mudar a cor do próprio componente (DBEdit1.Color).
Configurar linhas de diferentes alturas em StringGrid
- Coloque o StringGrid no form.
- No evento OnCreate do form coloque o código abaixo:
procedure TForm1.FormCreate(Sender: TObject);
begin
StringGrid1.RowHeights[0] := 15;
StringGrid1.RowHeights[1] := 20;
StringGrid1.RowHeights[2] := 50;
StringGrid1.RowHeights[3] := 35;
end;
Observações
Cuidado para não especificar uma linha inexistente.
Adicionar o evento OnClick do DBGrid
- Monte seu form normalmente, colocando o DBGrid e demais componentes;
- Vá na seção "private" da unit e declare a procedure abaixo:
private
procedure DBGridClick(Sender: TObject);
- Logo após a palavra "implementation", escreva a procedure:
implementation
{$R *.DFM}
procedure TForm1.DBGridClick(Sender: TObject);
begin
ShowMessage('Clicou no DBGrid.');
end;
- Coloque as instruções abaixo no evento OnCreate do Form:
procedure TForm1.FormCreate(Sender: TObject);
begin
DBGrid1.ControlStyle :=
DBGrid1.ControlStyle + [csClickEvents];
TForm(DBGrid1).OnClick := DBGridClick;
end;
- E pronto. Execute e teste.
Observações
O segredo principal desta dica está OnCreate do Form. A primeira instrução ativa o evento OnClick. A segunda instrução acessa o manipulador do evento OnClick. Para isto precisamos tratar o DBGrid como se fosse Form, pois o evento OnClick está declarado como protegido (protected) na classe TDBGrid.
Criar caixas de diálogo em tempo de execução
Inclua na seção uses: Forms, StdCtrls, Buttons
A função abaixo demonstra a criação de uma caixa de diálogo que pode ser usada para permitir ao usuário digitar o seu nome:
{ Esta função retorna true se for pressionado OK e false em caso contrário. Se for OK, o texto digitado pelo usuário será copiado para a variável Nome }
function ObterNome(var Nome: string): boolean;
var
Form: TForm; { Variável para o Form }
Edt: TEdit; { Variável para o Edit }
begin
Result := false; { Por padrão retorna false }
{ Cria o form }
Form := TForm.Create(Application);
try
{ Altera algumas propriedades do Form }
Form.BorderStyle := bsDialog;
Form.Caption := 'Atenção';
Form.Position := poScreenCenter;
Form.Width := 200;
Form.Height := 150;
{ Coloca um Label }
with TLabel.Create(Form) do begin
Parent := Form;
Caption := 'Digite seu nome:';
Left := 10;
Top := 10;
end;
{ Coloca o Edit }
Edt := TEdit.Create(Form);
with Edt do begin
Parent := Form;
Left := 10;
Top := 25;
{ Ajusta o comprimento do Edit de acordo com a largura
do form }
Width := Form.ClientWidth - 20;
end;
{ Coloca o botão OK }
with TBitBtn.Create(Form) do begin
Parent := Form;
{ Posiciona de acordo com a largura do form }
Left := Form.ClientWidth - (Width * 2) - 20;
Top := 80;
Kind := bkOK; { Botão Ok }
end;
{ Coloca o botão Cancel }
with TBitBtn.Create(Form) do begin
Parent := Form;
Left := Form.ClientWidth - Width - 10;
Top := 80;
Kind := bkCancel; { Botão Cancel }
end;
{ Exibe o form e aguarda a ação do usuário. Se for OK... }
if Form.ShowModal = mrOK then begin
Nome := Edt.Text;
Result := true;
end;
finally
Form.Free;
end;
end;
Para chamar esta função siga o exemplo abaixo:
procedure TForm1.Button1Click(Sender: TObject);
var
S: string;
begin
if ObterNome(S) then
Edit1.Text := S;
end;
Observações
Os componentes Label, Edit (var Edt) e BitBtn's (botões) não são destruídos explicitamente (Componente.Free). Isto não é necessário, pois ao criá-los informei como proprietário o Form (ex: TLabel.Create(Form)). Neste caso, estes componentes são destruídos automaticamente ao destruir o Form (Form.Free).
Mostrar uma mensagem durante um processamento
- Crie um form com a mensagem. Um pequeno form com um Label já é suficiente. Aqui vou chamá-lo de FormMsg.
- Vá em Project|Options e passe o FormMsg de "Auto-create forms" para "Available forms".
- Abaixo vou simular um processamento demorado, usando a API Sleep:
procedure TForm1.Button1Click(Sender: TObject);
var
Form: TFormMsg;
I: integer;
begin
Form := TFormMsg.Create(Self);
try
Form.Label1.Caption := 'Processamento demorado...';
Form.Show;
for I := 1 to 5 do begin
Form.UpDate;
Sleep(1000); { Aguarda um segundo }
end;
finally
Form.Free;
end;
end;
Observações
A função Sleep é uma API do Windows e serve para paralisar a aplicação por um determinado dempo. Este tempo é em milisegundos.
Obter o endereço IP do Dial-Up
Inclua na seção uses: WinSock
{ Esta função retorna o endereço IP do Dial-Up. }
function GetLocalIP : string;
type
TaPInAddr = array [0..10] of PInAddr;
PaPInAddr = ^TaPInAddr;
var
phe : PHostEnt;
pptr : PaPInAddr;
Buffer : array [0..63] of char;
I : Integer;
GInitData : TWSADATA;
begin
WSAStartup($101, GInitData);
Result := '';
GetHostName(Buffer, SizeOf(Buffer));
phe :=GetHostByName(buffer);
if phe = nil then Exit;
pptr := PaPInAddr(Phe^.h_addr_list);
I := 0;
while pptr^[I] <> nil do begin
result:=StrPas(inet_ntoa(pptr^[I]^));
result := StrPas(inet_ntoa(pptr^[I]^));
Inc(I);
end;
WSACleanup;
end;
Observações
Se o endereço IP for designado pelo servidor, a cada conecção teremos um endereço IP diferente e, obviamente, se não estivermos conectados, não conseguiremos obtê-lo.