Você está na página 1de 14

DICAS DE PROGRAMAÇÃO EM DELPHI

SUMÁRIO
 ACESSANDO ARQUIVOS PARADOX EM REDE
 CONFIRMAR DIRETÓRIO
 HINT COM QUEBRA DE LINHA
 TESTE SE HÁ DISCO NO DRIVE "A"
 VERIFICA SE O FORM, JÁ ESTA ATIVO
 PEGANDO O NOME DO USUÁRIO E A EMPRESA DO WINDOWS
 COMO CRIAR UMA TELA DE ABERTURA (SPLASH SCREEN)
 COMO VALIDAR A ENTRADA EM UMA CAIXA DE TEXTO
 CONFIGURANDO A TECLA "ENTER" PARA FUNCIONAR COMO "TAB"

ACESSANDO ARQUIVOS PARADOX EM REDE

Arquivos Paradox podem ser compartilhados em rede. Para que isto ocorra devemos :
 Adicionar o DATABASE ENGINE CONFIGURATION (BDE CONFIG)
 Selecionar a página DRIVERS
 Selecionar o driver PARADOX e alterar o parâmetro NET DIR para o local onde serão gravados os
arquivos de controle para compartilhamento. Por exemplo, "G:\MEUAPLIC", onde G : corresponde
ao drive de rede e MEUAPLIC, o diretório aonde está o aplicativo (executável)
 Depois selecionar a página SYSTEM
 Alterar o parâmetro LOCAL SHARE para TRUE. Após isto o BDE controlará o compartilhamento
de arquivos PARADOX em rede.
Topo

CONFIRMAR DIRETÓRIO

procedure TForm1.Button1Click(Sender: TObject);


begin
if DirectoryExists(Edit1.Text) then
Label1.Caption := Edit1.Text + ' exists'
else Label1.Caption := Edit1.Text + ' does not exist';
end;
Topo

HINT COM QUEBRA DE LINHA

Para incluir mais de uma linha no Hint você deve utilizar o evento OnMouseMove
de cada componente. Veja abaixo como ficará o código em um Edit por exemplo.
procedure TForm1.Edit1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
Edit1.hint := 'Primeira Linha'+#13+'Segunda Linha'+#13+ 'Terceira Linha'+#13+'Quarta Linha';
end;
Obs. Não esquecer de mudar para TRUE o evento ShowHint.
Topo
TESTE SE HÁ DISCO NO DRIVE "A"

function TForm1.TemDiscoNoDrive(const drive : char): boolean;


var
DriveNumero : byte;
EMode : word;
begin
result := false;
DriveNumero := ord(Drive);
if DriveNumero >= ord('a') then
dec(DriveNumero,$20);
EMode := SetErrorMode(SEM_FAILCRITICALERRORS);
try
if DiskSize(DriveNumero-$40) <> -1 then
Result := true else messagebeep(0);
finally
SetErrorMode(EMode);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if TemDiscoNoDrive('a') then
ShowMessage('Tem disco no drive A:')
else ShowMessage('Não tem disco no drive A:');
end;
Topo

VERIFICA SE O FORM, JÁ ESTA ATIVO

procedure TForm1.Button1Click(Sender: TObject);


var
Found : Integer;
begin
Found := -1;
for i := 0 to Screen.FormCount - 1 do
if Screen.Forms[i] is TForm2 then Found := i;
if Found >= 0 then Screen.Forms[Found].Show
else
begin
Form2 := TForm2.Create(Self);
Form2.Show;
end;
end;
Topo

PEGANDO O NOME DO USUÁRIO E A EMPRESA DO WINDOWS

Uses Registry;
Procedure GetUserCompany; var reg: TRegIniFile;
begin
reg := TRegIniFile.create('SOFTWARE\MICROSOFT\MS SETUP (ACME)\');
Edit1.Text := reg.ReadString('USER INFO','DefName','');
Edit2.Text := reg.ReadString('USER INFO','DefCompany','');
reg.free;
end;
Topo

COMO CRIAR UMA TELA DE ABERTURA (SPLASH SCREEN)

Após ter criado o formulário principal, crie um Formulário para a Splah Screen. que iremos chamar de
FormAbertura (dê o nome que você quiser).
 Depois de criar os dois forms, clique no menu View, na opção Project Source. Encontrando a linha
em que o form de abertura é criado e apague-a.
Linha que deve ser apagada:
begin
Application.CreateForm(TFormabertura, FormAbertura); {Esta linha deve ser apagada}
end;
 Agora insira as linhas abaixo antes da criação dos demais form do seu aplicativo:
begin
AberturaForm:=TFormAbertura.Create(Application);
AberturaForm.show; {Os outros form devem ser criados a partir daqui}
FormAbertura.Hide; {Esconde o FormAbertura}
FormAbertura.Free; {Libera Memória}
Application.Run;
End;
Topo

COMO VALIDAR A ENTRADA EM UMA CAIXA DE TEXTO

procedure Edit1KeyPress(Sender: TObject; var Key: Char);


begin
If not(key in['0'..'9',#8]) then
begin
beep;{somente delphi 2.0 ou 3.0} key:=#0;
end;
end
Topo

CONFIGURANDO A TECLA "ENTER" PARA FUNCIONAR COMO "TAB"

obs.:(1) a propriedade KEYPREVIEW do form será igual TRUE;


obs.:(2) a propriedade DEFAULT dos botões será igual FALSE;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);


begin
If Key = #13 then
Begin
Key:=#0;
If (Sender is TEdit) and (Sender is TComboBox) then
TEdit(Sender).Perform(WM_KeyDown,VK_Tab,0)
Else
Perform(Wm_NextDlgCtl,0,0);
End;
Topo

Dicas
1ª) Alterando a Data do Sistema
procedure TForm1.Button1Click(Sender: TObject);
begin
SetNewTime(1998,2,10,18,07);
end;
function SetNewTime(Ano, Mes, Dia, hour, minutes: word): Boolean;
var
st:TSYSTEMTIME;
begin
GetLocalTime(st);
st.wYear := Ano;
st.wMonth := Mes;
st.wDay := Dia;
st.wHour := hour;
st.wMinute := minutes;
if not SetLocalTime(st) then
Result := False
else
Result := True;
end;
2ª) Veja como carregar um cursor animado em sua aplicação
procedure TForm1.Button3Click(Sender: TObject);
const
NovoCursor = 1;
begin
Screen.Cursors[ NovoCursor ] :=
LoadCursorFromFile(‘c:\windows\cursors\globe.ani’ );
Cursor := NovoCursor;
end;
OBS. Para descarregar o cursor animado troque a string ‘c:\windows\cursors\globe.ani’ por ‘OCR_NORMAL’.
3ª) Bloquear a tecla Ctrl+Del do DBGrid
procedure TForm1.DBGrid1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if ((Shift = [ssCtrl]) and (key = vk_delete)) THEN
Abort;
end;
4ª) Fechar um aplicativo Delphi a partir de outro aplicativo Delphi
procedure TForm1.Button1Click(Sender: TObject);
var
Win : THandle;
begin
Win := FindWindow(nil,’Form1');
if Win <> 0 then
PostMessage(Win,WM_CLOSE,0,0)
else
ShowMessage(‘Programa não encontrado’);
end;
Obs. No exemplo acima foi utilizado o POSTMESSAGE para enviar uma mensagem WM_CLOSE para a janela
principal.
5ª) Verifica se o Form já está ativo, Delphi1, Delphi2 e Delphi3
procedure TForm1.Button1Click(Sender: TObject);
var Found,i : Integer;
begin
Found := -1;
for i := 0 to Screen.FormCount - 1 do
if Screen.Forms[i] is TForm2 then
Found := i;
if Found >= 0 then
Screen.Forms[Found].Show
else begin
Form2 := TForm2.Create(Self);
Form2.Show;
end;
end;
6ª) Veja como retornar a coluna ativa do DBGrid
procedure TForm1.DBGrid1ColEnter(Sender: TObject);
begin
Caption := DBGrid1.SelectedField.FieldName;
end;
7ª) A função abaixo mostra como adquirir a data e hora de um arquivo
function GetFileDate(Arquivo: String): String;
var
FHandle: integer;
begin
FHandle := FileOpen(Arquivo, 0);
try
Result := DateTimeToStr(FileDateToDateTime(FileGetDate(FHandle)));
finally
FileClose(FHandle);
end;
end;
8ª) Alterar as cores do título de um DBGrid em tempo execução
procedure TForm1.DBGrid1TitleClick(Column: TColumn);
var
I : integer;
begin
for i:=0 to DBGrid1.Columns.count-1 do begin
DBGrid1.Columns[i].Title.Color := clBtnFace;
DBGrid1.Columns[i].Title.Font.Color := clBlack;
DBGrid1.Columns[i].Title.Font.Style := [];
end;
Column.Title.color := ClYellow;
Column.Title.Font.Style := [ fsBold, fsItalic];
Column.Title.Font.Color := clRed;
end;
9ª) Como definir seu próprio hotkey (Tecla Quente)
Primeiro fixe a propriedade KeyPreview do Form para TRUE
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if (ssCtrl in Shift) and (chr(Key) in [‘A’, ‘a’]) then
ShowMessage(‘Ctrl-A’);
end;
10ª) Criando 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;
11ª) Enviando um arquivo para a lixeira
uses ShellAPI;
Function DeleteFileWithUndo(sFileName : string ) : boolean;
var fos : TSHFileOpStruct;
begin
FillChar( fos, SizeOf( fos ), 0 );
With fos do begin
wFunc := FO_DELETE;
pFrom := PChar( sFileName );
fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION or FOF_SILENT;
end;
Result := ( 0 = ShFileOperation( fos ) );
end;
12ª) A função Delay do turbo pascal
procedure TForm1.Delay(msecs:integer);
var FirstTickCount : longint;
begin
FirstTickCount:=GetTickCount;
repeat
Application.ProcessMessages;
until ((GetTickCount-FirstTickCount) >= Longint(msecs));
end;
13ª) Lendo o volume do HD
Function ExtractDiskSerial(Drive:String):String;
Var Serial : DWord;
DirLen, Flags : DWord;
DLabel : Array[0..11] of Char;
begin
GetVolumeInformation(PChar(Drive+':\'),dLabel,12,@Serial,DirLen,Flags,nil,0);
Result := IntToHex(Serial,8);
end;
14ª) Executando uma única cópia do aplicativo
Se você quiser executar uma única copia do aplicativo, o código de inicializacao do arquivo fonte do PROJETO
pode ser escrito conforme segue:
program Project1;
uses
Forms,
Windows,
Dialogs,
Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}
Var HprevHist : HWND;
begin
Application.Initialize;
HprevHist := FindWindow(Nil, PChar('TheProgrammer'));
if HprevHist = 0 then begin
Application.Title := 'TheProgrammer';
Application.CreateForm(TForm1, Form1);
Application.Run;
end else
MessageDlg('Você não pode executar outra cópia do aplicativo', mtInformation, [mbOK], 0);
Com esse código o usuário pode iniciar uma nova copia do aplicativo somente se não houver outra anterior. Caso
contrario é exibido uma mensagem para o usuário.
15ª) Escondendo janelas filhas minimizadas
Para esconder janelas filhas minimizadas, basta capturar a mensagem WM_Size, desta maneira:
type
TForm1 = class(TForm)
public
procedure WMSize(var M : TWMSIZE);Message WM_Size;
end;
implementation
procedure TForm1.WMSize(var M:TWMSIZE);
begin
if M.SizeType=Size_Minimized then
ShowWindow(Handle,Sw_Hide);
end;
16ª) Conectando uma unidade de rede
procedure TForm1.Button1Click(Sender: TObject);
var NRW: TNetResource;
begin
with NRW do begin
dwType := RESOURCETYPE_ANY;
lpLocalName := 'G:';
lpRemoteName := '\\servidor\c';
lpProvider := '';
end;
WNetAddConnection2(NRW, 'MyPassword', 'MyUserName', CONNECT_UPDATE_PROFILE);
end;
17ª) Copiando Arquivos Via Programação
Function CopiaArquivo(scrname,destname:string):byte;
var
source,destination:file;
buffer:array[1..1024] of byte;
readcnt,writecnt:word;
pname,dname,fname,ename:String;
{ USO: R:=COPIAARQUIVO('C:\diretorio\FILE.EXT','C:\diretorio\FILE.EXT'); Devolve 0=Ok, 1=Erro no
Origem, 2=Erro no
Destino, 3=Disco Cheio }
begin
AssignFile(source,scrname);
Try
Reset(source,1);
Except
CopiaArquivo:=1;
Exit;end;If destname[length(destname)]='\' then
begin
pname:=scrname;
destname:=destname+separa(scrname,'\',Ocorre(scrname,'\')+1);
end;
AssignFile(destination,destname);
Try
Rewrite(destination,1);
Except
CopiaArquivo:=2;
Exit;
end;
Repeat
BlockRead(source,buffer,sizeof(buffer),readcnt);
Try
BlockWrite(destination,buffer,readcnt,writecnt);
Except
CopiaArquivo:=3; {Disco Cheio?}
Exit;
end;
until (readcnt=0) or (writecnt<>readcnt);
CloseFile(destination);
CloseFile(source);
CopiaArquivo:=0;
end;
18ª) Traduzindo a mensagem: "Delete Record?"
procedure TForm1.Table1BeforeDelete(DataSet:TDataSet);
begin
if MessageDlg('Eliminar o Registro?',mtConfirmation,[mbYes,mbNo],0)<>mrYes then
Abort;
end;
19ª) Obtendo o diretório corrente da aplicação
Caminho := ExtractFilePath(Application.ExeName);
20ª) Utilizando a tecla <Enter> para saltar de campo
Insira este código no evento OnKeyPress de um controle de edição:
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
If Key = #13 Then begin
SelectNext(Sender as tWinControl, True, True );
Key := #0;
end;
end;
21ª) Interceptando as teclas de função no seu programa
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = VK_F5 then
showMessage('A Tecla F5 foi Pressionada');
end;
22ª) Função que retorna o nome do usuário logado na rede
Uses BDE;
function TForm1.dgGetUserName : String;
Var UserNameBuff : array[0..255] of char;
pUserName : Pchar;
begin
Result := '';
pUserName := @UserNameBuff;
Check(DbiGetNetUserName(pUserName));
Result := StrPas(pUserName);
end;
23ª) Função que retorna o nome do Computador
Uses Registry;
function TForm1.Getcomputer : string;
var registro : tregistry;
begin
registro:=tregistry.create;
registro.RootKey:=HKEY_LOCAL_MACHINE;
registro.openkey('System\CurrentControlSet\Services\VXD\VNETSUP',false);
result:=registro.readstring('ComputerName');
end;
24ª) Rolar um form usando pgUP and pgDn
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
const
PageDelta = 10;
begin
With VertScrollbar do
if Key = VK_NEXT then
Position := Position + PageDelta
else if Key = VK_PRIOR then
Position := Position - PageDelta;
end;
25ª) Preenche com quantidade determinada de zeros o lado esquerdo de uma string
unit Zero;
interface
function RetZero(ZEROS:string;QUANT:integer):String;
implementation
function RetZero(ZEROS:string;QUANT:integer):String;
var
I,Tamanho:integer;
aux: string;
begin
aux:=zeros;
Tamanho:=length(ZEROS);
ZEROS:='';
for I:=1 to quant-tamanho do
ZEROS:=ZEROS+'0';
aux:=zeros+aux;
RetZero:=aux;
end;
end.

Dicas
26ª) Criando uma rotina para pegar todos os erros do programa.
Procedure MostraErro;
Begin
ShowMessage('Ocorreu algum erro!');
end;
TForm1.Create;
Begin
Application.OnException:=MostraErro;
end;
27ª) Capturando conteúdo do desktop.
procedure TForm1.FormResize(Sender: TObject);
var
R : TRect;
DC : HDc;
Canv : TCanvas;
begin
R := Rect( 0, 0, Screen.Width, Screen.Height );
DC := GetWindowDC( GetDeskTopWindow );
Canv := TCanvas.Create;
Canv.Handle := DC;
Canvas.CopyRect( R, Canv, R );
ReleaseDC( GetDeskTopWindow, DC );
end;
28ª) Obtendo número do registro atual
Function Recno(Dataset: TDataset): Longint;
var
CursorProps: CurProps;
RecordProps: RECProps;
begin
Result := 0;
with Dataset do begin
if State = dsInactive then DBError(SDataSetClosed);
Check(DbiGetCursorProps(Handle, CursorProps));
UpdateCursorPos;
try
Check(DbiGetRecord(Handle, dbiNOLOCK, nil, @RecordProps));
case CursorProps.iSeqNums of
0: Result := RecordProps.iPhyRecNum; { dBASE }
1: Result := RecordProps.iSeqNum; { Paradox }
end;
except
on EDBEngineError do
Result := 0;
end;
end;
end;
29ª) Jogar uma imagem direto para um campo da tabela.
procedure TForm1.Button1Click(Sender: TObject);
var BMP: TBitMap;
begin
BMP := TBitMap.Create;
if OpenPictureDialog1.Execute then begin
if Table1.State in [dsInsert, dsEdit] then begin
BMP.LoadFromFile(OpenPictureDialog1.FileName);
Table1Graphic.Assign( BMP );
end;
end;
end;
30ª) Saindo do Windows
{ Reinicia o Windows }
ExitWindowsEx(EWX_REBOOT, 0);
{ Desliga o Windows }
ExitWindowsEx(EWX_SHUTDOWN, 0);
{ Força todos os programa a desligarem-se }
ExitWindowsEx(EWX_FORCE, 0);
31ª) Modificando/Obtendo a posição do cursor em um Memo
Modificando a posição:
ActiveControl:=Memo1;
MemoCursorTo(Memo1,2,3);
Obtendo a Posição:
GetMemoLineCol(Memo1,Linha,Coluna);
32ª) Mostrando o HINT num Panel.
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnHint := DisplayHint;
end;
procedure TForm1.DisplayHint(Sender: TObject);
begin
Panel1.Caption := Application.Hint;
end;
33ª) Escrevendo um Texto na Diagonal usando o Canvas
procedure TForm1.Button1Click(Sender: TObject);
var
lf : TLogFont;
tf : TFont;
begin
with Form1.Canvas do begin
Font.Name := 'Arial';
Font.Size := 24;
tf := TFont.Create;
tf.Assign(Font);
GetObject(tf.Handle, sizeof(lf), @lf);
lf.lfEscapement := 450;
lf.lfOrientation := 450;
tf.Handle := CreateFontIndirect(lf);
Font.Assign(tf);
tf.Free;
TextOut(20, Height div 2, 'Texto Diagonal!');
end;
end;
34ª) Fundo do texto transparente
procedure TForm1.Button1Click(Sender: TObject);
var
OldBkMode : integer;
begin
with Form1.Canvas do begin
Brush.Color := clRed;
FillRect(Rect(0, 0, 100, 100));
Brush.Color := clBlue;
TextOut(10, 20, 'Não é Transparente!');
OldBkMode := SetBkMode(Handle, TRANSPARENT);
TextOut(10, 50, 'É Transparente!');
SetBkMode(Handle, OldBkMode);
end;
end;
35ª) Formatação de Casas Decimais
procedure TForm1.Button1Click(Sender: TObject);
var num : integer;
begin
num:=12450;
Edit1.text:=formatfloat('###,###,##0.00', num)
end;
36ª) Escondendo/Mostrando o botão Iniciar
procedure EscondeIniciar(Visible:Boolean);
Var taskbarhandle,
buttonhandle : HWND;
begin
taskbarhandle := FindWindow('Shell_TrayWnd', nil);
buttonhandle := GetWindow(taskbarhandle, GW_CHILD);
If Visible=True Then Begin
ShowWindow(buttonhandle, SW_RESTORE); {mostra o botão}
End Else Begin
ShowWindow(buttonhandle, SW_HIDE); {esconde o botão}
End;
end;
37ª) Criando uma janela não retangular
Você deve criar uma Região do Windows e usar a função da API SetWindowRgn, desta maneira
var
hR : THandle;
begin {cria uma Reigião elíptica}
hR := CreateEllipticRgn(0,0,100,200);
SetWindowRgn(Handle,hR,True);
end;
38ª) Retornar o nome do usuário que está com a tabela Exclusiva
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
try
Table1.Close;
Table1.Exclusive := True;
Table1.Open;
except on E:EDBEngineError do
if E.Errors[0].ErrorCode = 10243 then begin
ShowMessage('Mensagem de erro'+E.Errors[0].Message );
ShowMessage( 'Arquivo com erro'+E.Errors[1].Message );
ShowMessage( 'Nome do usuario'+ E.Errors[2].Message );
end;
end;
end;
39ª) Colocar um componente ComboBox em um componente StringGrid.
Inclua no seu Form um componente ComboBox e um componente StringGrid.
type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
ComboBox1: TComboBox;
procedure FormCreate(Sender: TObject);
procedure ComboBox1Change(Sender: TObject);
procedure ComboBox1Exit(Sender: TObject);
procedure StringGrid1SelectCell(Sender: TObject; Col, Row: Integer; var CanSelect: boolean);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
// Evento OnCreate do Form
procedure TForm1.FormCreate(Sender: TObject);
begin
{Ajusta a altura do ComboBox com a altura da linha do StringGrid}
StringGrid1.DefaultRowHeight := ComboBox1.Height;
{Esconde o ComboBox}
ComboBox1.Visible := False;
end;
// Evento OnChange do componente ComboBox
procedure TForm1.ComboBox1Change (Sender: TObject);
begin
StringGrid1.Cells[StringGrid1.Col,StringGrid1.Row] := ComboBox1.Items[ComboBox1.ItemIndex];
ComboBox1.Visible := False;
StringGrid1.SetFocus;
end;
// Evento OnExit do componente ComboBox
procedure TForm1.ComboBox1Exit (Sender: TObject);
begin
StringGrid1.Cells[StringGrid1.Col,StringGrid1.Row] := ComboBox1.Items[ComboBox1.ItemIndex];
ComboBox1.Visible := False;
StringGrid1.SetFocus;
end;
// Evento OnSelectCell do componente StringGrid
procedure TForm1.StringGrid1SelectCell(Sender: TObject; Col, Row: Integer; var CanSelect: Boolean);
var
R: TRect;
begin
if ((Col = 3) AND (Row <> 0)) then
begin
R := StringGrid1.CellRect(Col, Row);
R.Left := R.Left + StringGrid1.Left;
R.Right := R.Right + StringGrid1.Left;
R.Top := R.Top + StringGrid1.Top;
R.Bottom := R.Bottom + StringGrid1.Top;
ComboBox1.Left := R.Left + 1;
ComboBox1.Top := R.Top + 1;
ComboBox1.Width := (R.Right + 1) - R.Left;
ComboBox1.Height := (R.Bottom + 1) - R.Top;
ComboBox1.Visible := True;
ComboBox1.SetFocus;
end;
CanSelect := True;
end;
40ª) Incluir o evento onClick no DBgrid
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids, DBGrids, DB,
DBTables;
type
thack = class(tcontrol);
TForm1 = class(TForm)
Table1: TTable;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
THack(dbgrid1).controlstyle := THack(dbgrid1).controlstyle + [csClickEvents];
THack(dbgrid1).OnClick := Form1.OnClick;
end;
procedure TForm1.FormClick(Sender: TObject);
begin
ShowMessage('Teste');
application.processmessages;
end;
end.
Voltar