Você está na página 1de 168

Coleo de Dicas sobre programao Delphi.

Retiradas do E-Zine Grandes Dicas em Delphi

Por Ramos de Souza Janones

www.ramosdainformatica.com.br

ndice
1 ndice ............................................................................................................................ 2 Descobrindo o cdigo ASCII de uma tecla .................................................................. 6 Funo - Retornando o prximo dia til....................................................................... 6 DBGrid - Colocando em Letras maisculas uma coluna selecionada.......................... 7 DBGrid - Mostrando todo contedo de um campo Memo........................................... 7 Crtica de datas no objeto Edit sem mensagem de erro do Delphi ............................. 10 Preenchimento de zeros para completar a data........................................................... 14 Multimdia - Fazendo suas aplicaes Delphi falar ................................................... 14 Multimdia - Toque um som quando o mouse passar por cima de um boto............. 15 Hints com multiplas linhas ......................................................................................... 15 Multimdia - Usando cursores animados .................................................................... 16 Detectando a verso do Internet Explorer .................................................................. 16 QuickReport - Filtrando registros............................................................................... 17 Evitando efeito de maximizao................................................................................. 17 Calcula a quantidade de dias no ms .......................................................................... 18 Calculando abono salrial de modo progressivo ........................................................ 18 Checa se um processo est rodando ........................................................................... 19 Checa se um diretrio est vazio ................................................................................ 20 dbExpress - Passando parmetros com CommandText via programao.................. 20 Corrigindo problemas de instalao do Borland Data Provider For Firebird............. 21 Lendo texto de um arquivo PDF ................................................................................ 21 Deixando seu EXE mais enxuto e rpido e, mais seguro contra decompilao......... 24 Copiando (Upload) um diretrio para um servidor FTP ............................................ 26 Trabalhando com arquivos texto no Delphi ............................................................... 29 Criando uma conexo ao DBExpress em tempo de execuo.................................... 31 ActiveX - Pegar um texto selecionado no Internet Explorer...................................... 32 Cria um efeito na apresentao de um formulrio...................................................... 33 Criando um Menu transparente .................................................................................. 34 Checa se um diretrio est vazio ................................................................................ 36 Mostra multiplas linhas de texto em um ComboBox ................................................. 37 Criando atalhos no Windows pelo Delphi.................................................................. 38 Faa suas aplicaes Falar.......................................................................................... 39 Imprimindo arquivos PDF sem abrir-los .................................................................... 39 Ler arquivos PDF ....................................................................................................... 39 Inno Setup - Script para criao de conexo OBDC DSN ......................................... 40 Colocar cursor no final do Edit ao receber o foco...................................................... 42 Mudar a cor de fundo de um Hint............................................................................... 42 Fazer um executvel ser executado somente se chamado por um determinado executvel ................................................................................................................... 42 DBGrid - Focando a clula selecionada mudando sua cor......................................... 43 Verificando a verso do Windows ............................................................................. 43 Rave Report - Alterar a impressora padro ................................................................ 44 Atribundo efeitos para abertura de formulrios......................................................... 44 API do Windows - Funo para excluir uma pasta e todos arquivos desta pasta....... 45 Inno Setup - Verificando se existe determinada Chave no Registro do Windows..... 46 Controlando o PowerPoint no Delphi......................................................................... 46 Rave Report - Indicar pgina inicial........................................................................... 48 2

InnoSetup - Adicionar um programa no iniciar do Windows .................................... 48 Validando endereo de e-mail no Delphi em aplicaes Win32, .Net e Asp.Net ...... 49 Memo redondo............................................................................................................ 50 Colocar Banners em Menus........................................................................................ 50 Usando a WebCam no Delphi .................................................................................... 51 Colocando imagens em um ComboBox ..................................................................... 52 Importando e Exportando Registro ............................................................................ 53 DBGrid - Colocar um ComboBox num DBGrid........................................................ 54 Enviando mensagens HTML com imagens anexadas ................................................ 54 Mostrando dicas balo para caixas de edio wm WindowsXP ................................ 56 CheckLisBox - Trocar a cor das linhas ...................................................................... 57 Windows - Verificar a impressora padro.................................................................. 58 RichEdit - Pesquisar um texto, posicionar sobre ele e mostrar ao usurio................. 58 ActiveControl - Envia um valor para Edit que estiver em foco ................................. 59 Registro do Windows - Retorna portas seriais ........................................................... 59 Verifica se um programa est aberto, caso contrrio, abre......................................... 60 Funo que verifica a velocidade do processador ...................................................... 60 DBGrid - Ao clicar no campo no DBGrid ordenar os registros ................................. 61 Criando um lista Push and Pop em Delphi ................................................................. 61 Rave Report - Imprimindo cdigo de barras em modo de programao.................... 64 Gerar planilhas no Excel atravs de uma Query......................................................... 64 Rave Report - Somar valores...................................................................................... 65 Colorir componente focado - Preservando sua cor original ....................................... 66 ActiveControl - Envia valor para Edit que tiver em foco........................................... 67 TFields - Adiciona Fields no Fields Editors em tempo de execuo ......................... 67 ListBox - Colorir ........................................................................................................ 69 Associando um extenso de arquivo a um executvel ............................................... 69 Retornar as contas de E-Mail...................................................................................... 70 HKEY, Registry ......................................................................................................... 71 Criar e ler chave.......................................................................................................... 72 Retornar lista de hardware via registry....................................................................... 73 Verificar se um valor existe dentro de uma Chave..................................................... 73 Quick Report - Selecionando itens do ComboBox para PapeSize ............................. 74 ListBox - Pesquisa incremental .................................................................................. 74 Acertar data e hora com o servidor............................................................................. 75 QuickReport - Access Violation no Windows 2000 e XP ......................................... 75 DBGrid - Alterar as cores do ttulo em tempo de execuo....................................... 75 Testa se a impressora est funcionando...................................................................... 76 Como implementar um AutoComplete num Edit comum.......................................... 76 Como adicionar um CheckBox em um StringGrig .................................................... 78 Abreviao automtica de nomes ............................................................................... 80 Compilando a aplicao pelo MS-DOS ..................................................................... 81 Colorao gradiente no Form ..................................................................................... 82 Usar perfeitamente o LookupComboBox................................................................... 83 Como colocar um codigo para que a aplicacao feche apos XX segundos sem atividades no teclado ou sem cliques do mouse. ........................................................ 83 Escondendo a barra de tarefas do Windows............................................................... 85 Pega todos os erros do Sistema, captura tela do erro, grava em arquivo e envia por email ............................................................................................................................. 85 Detectando o tipo de Conexo com a internet............................................................ 86

Funo de potenciao - Juros.................................................................................... 87 Para trocar as cores dos botoes do radiogroup ........................................................... 87 Como criar uma figura do tipo marca d' gua ............................................................ 88 Criptografando Imagens ............................................................................................. 88 Alterar a fonte de determinado registro num DBGrid................................................ 89 Alinhar ttulo da barra de titulos do Form a esquerda ou direita................................ 89 Alterar fonte do Hint................................................................................................... 90 Criando arquivo Texto................................................................................................ 91 Como selecionar tudo (Ctrl+A) em um TMemo/TDBMemo..................................... 92 Mudando o IP da mquina via API do Windows ....................................................... 93 Texto na diagonal e girando ....................................................................................... 93 Criar um alias dinamicamente na memria ................................................................ 94 Rodar videos em um panel ......................................................................................... 94 Como colocar uma coluna do DBGrid em maiuscula ................................................ 95 DBGrid - Alinhando texto conforme condio .......................................................... 95 DBGrid - Colocando CheckBox no grid .................................................................... 96 RichEdit - Como fazer uma pesquisa e substituio em um RichEdit ....................... 97 TForm - Criando formulrios transparentes ............................................................... 98 TList - Ordenando os itens ......................................................................................... 99 3 formas de dar um shutdown................................................................................... 100 QuickReport e FastReport - Gerando um PDF......................................................... 103 SetVolumeLabel - Mudando o Label do HD............................................................ 104 Memo - Rolagem vertical ......................................................................................... 105 Como adicionar o evento OnClick no DBGrid ........................................................ 106 Alterando a cor dos TabSheet de um PageControl................................................... 107 Como chamar uma home page utilizando o seu browse padro............................... 107 Como alterar o caption da janela de preview do quickreport ................................... 107 Como passar parmetros entre 2 forms .................................................................... 108 Como reduzir o tempo e carga de um programa ...................................................... 109 Escondendo o Programa de Ctrl+Alt+Del................................................................ 110 Verifica se o BDE est instalado .............................................................................. 112 Verificando se um alias est instalado...................................................................... 114 Como prevenir a movimentao do mouse para fora do form? ............................... 114 Como criar hints customizados?............................................................................... 114 Como capturar a tela? ............................................................................................... 116 Como mostrar um TMenuItem alinhado direita? .................................................. 121 Como mover o form clicando em qualquer lugar? ................................................... 121 Como mostrar um texto de vrias linhas em um TCombobox? ............................... 122 Como criar tooltips com bales? .............................................................................. 124 Mostra o total de pginas.......................................................................................... 144 InnoSetup Verificando a verso do software, se inferior, ento, no instalar ....... 144 InnoSetup Manipulao de arquivos texto ............................................................ 145 Finalizando processos do Windows via programao.............................................. 146 Gravando CDs .......................................................................................................... 147 Quick Report - Obtendo a lista de papeis disponveis.............................................. 147 DBGrid - Como fazer quebra de linhas .................................................................... 148 Arquivo: Verificar se est ReadOnly........................................................................ 150 Treeview Foco ....................................................................................................... 151 Rave Report Indicar pgina inicial ........................................................................ 151 Desktop do Windows auto-arranjar icones............................................................ 152

Clculo de Parcelas................................................................................................... 153 Porta Serial Como verificar se uma porta est em uso .......................................... 154 GIF Como converter uma imagem GIF para BMP ............................................... 155 Veja como criar atalhos no menu iniciar do Windows............................................. 155 Como mover um componente em Run-time............................................................. 158 Como apresentar o nmero da linha e coluna em um DBGrid?............................... 159 Como implementar um log de todos os erros gerados na aplicao?....................... 160 Printers - Como retornar informaes das impressoras instaladas na mquina ....... 161 IP Como retornar o hostname a partir de um endereo IP..................................... 163 Windows Como criar grupos e subgrupos de programas no menu iniciar............ 164 Windows Como desabilitar uma combinao de teclas genericamente ................ 165

Descobrindo o cdigo ASCII de uma tecla


Para descobrir o cdigo ASCII de uma determinada tecla voc pode criar a seguinte aplicao. 1. Insira um componente Label no form (Label1); 2. Mude a propriedade KeyPreview do form para true; 3. Altere o evento OnKeyDown do form como abaixo: procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin Label1.Caption := Format(O cdigo da tecla pressionada : %d, [Key]); end; Para testar execute e observe o Label enquanto pressiona as teclas desejadas.

Funo - Retornando o prximo dia til


Obtendo o prximo dia til caso a data informada caia em um fim de semana function ProximoDiaUtil(dData : TDateTime) : TDateTime; begin if DayOfWeek(dData) = 7 then dData := dData + 2 else if DayOfWeek(dData) = 1 then dData := dData + 1; Result := dData; end;

DBGrid - Colocando em Letras maisculas uma coluna selecionada


procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char); begin if DBGrid1.SelectedField.FieldName='NOME' THEN Key := AnsiUpperCase(Key)[Length(Key)]; end;

DBGrid - Mostrando todo contedo de um campo Memo


Desenvolvedores em geral utilizam o componente DBGrid para apresentar os dados de uma tabela ou banco de dados. Os problemas surgem a partir do momento em que necessrio apresentar o contedo de um campo Memo. Porm, existe um jeito fcil de resolver este problema. O que iremos fazer que, ao usurio clicar sobre o contedo de algum campo Memo no DBGrid, seja apresentada uma janela com todas informaes contidas neste memo. Primeiro desenvolvida uma funo que realiza este processo: function TForm1.MostraMemo(Dts: TDataSource; Dbg: TDBGrid; Fld: TField): Boolean; var Frm: TForm; Ret: Boolean; Mem: TDBMemo; begin Ret := False; if Dts.DataSet.RecordCount > 0 then if Dbg.SelectedField = Fld then begin Ret := True; Frm := TForm.Create(nil); try Frm.Width := 240; Frm.Height := 120; Frm.Top := Mouse.CursorPos.Y; Frm.Left := Mouse.CursorPos.X; Frm.BorderStyle := bsToolWindow; Frm.Caption := Fld.DisplayLabel; Mem := TDBMemo.Create(nil); try Mem.Parent := Frm; Mem.Align := alClient;

Mem.DataSource := Dts; Mem.DataField := Fld.FieldName; Mem.ReadOnly := True; Mem.ScrollBars := ssVertical; Frm.ShowModal; finally Mem.Free; end; finally Frm.Free; end; end; Result := Ret; end;

Uma vez desenvolvida nossa funo, preciso colocar em prtica, no evento OnCellClick do DBGrid, insira o cdigo a seguir:

procedure TForm1.DBGrid1CellClick(Column: TColumn); begin MostraMemo(DBGrid1.DataSource, DBGrid1, DBGrid1.SelectedField); end; Confira como ficou todo exemplo: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Grids, DBGrids, DB, DBTables, StdCtrls, DBCtrls; type TForm1 = class(TForm) Table1: TTable; DataSource1: TDataSource; DBGrid1: TDBGrid; procedure DBGrid1CellClick(Column: TColumn); private function MostraMemo(Dts: TDataSource; Dbg: TDBGrid; Fld: TField): Boolean; { Private declarations } public { Public declarations } end;

var Form1: TForm1; implementation {$R *.dfm} function TForm1.MostraMemo(Dts: TDataSource; Dbg: TDBGrid; Fld: TField): Boolean; var Frm: TForm; Ret: Boolean; Mem: TDBMemo; begin Ret := False; if Dts.DataSet.RecordCount > 0 then if Dbg.SelectedField = Fld then begin Ret := True; Frm := TForm.Create(nil); try Frm.Width := 240; Frm.Height := 120; Frm.Top := Mouse.CursorPos.Y; Frm.Left := Mouse.CursorPos.X; Frm.BorderStyle := bsToolWindow; Frm.Caption := Fld.DisplayLabel; Mem := TDBMemo.Create(nil); try Mem.Parent := Frm; Mem.Align := alClient; Mem.DataSource := Dts; Mem.DataField := Fld.FieldName; Mem.ReadOnly := True; Mem.ScrollBars := ssVertical; Frm.ShowModal; finally Mem.Free; end; finally Frm.Free; end; end; Result := Ret; end;

procedure TForm1.DBGrid1CellClick(Column: TColumn); begin MostraMemo(DBGrid1.DataSource, DBGrid1, DBGrid1.SelectedField); end; end.

Crtica de datas no objeto Edit sem mensagem de erro do Delphi


Fazer o tratamento de mensagens de erro em campos de data fundamental. Neste exemplo, para ilustrar, so inseridos dois componentes Edit. O componente Edit1 o componente onde sero inseridos as datas e o componente Edit2 apenas para que possamos fazer a transio entre os componentes. No evento OnExit do Edit1 foi inserido o cdigo a seguir: No evento OnExit do objeto procedure TForm1.Edit1Exit(Sender: TObject); var Data : string; begin Data := Edit1.text; CriticaData(Data); // Se no for um campo vlido, a procedure devolve a varivel data vazia; if Data = '' then Edit1.SetFocus else Edit1.text := DateToStr(StrToDate(Edit1.text)); end; Foi criado uma procedure para fazer o tratamento das mensagens de erro. Esta procedure ter o nome de Criticadata: procedure TForm1.CriticaData(var Data: string); //Sem controle dos caracteres digitados no objeto Edit1 var I, J, Dia, Mes, Ano : Integer; Barras, Barra1, Barra2 : Integer; // Verifica a posio das barras; K, M : Array Of Integer; Num : Array Of String; Caracter, Erro : String; begin Erro:='n'; //Em princpio o campo considerado como correto(vlido). // Cria-se os Arrays K e M com 13 campos dos quais usaremos do 1 ao 12 SetLength (K, 13); SetLength (M, 13);

10

// A matriz M preenchida com o ltimo dia de cada ms // A matriz K preenchida com 1. A posio relativa de cada caracter do campo // data, dentro da matriz K, ser prenchida com zero se o caracter for vlido. // Caso contrrio ser setado Erro igual a s for I := 1 to 12 do begin K[I] := 1; M[I] := 31; end; M[4] := 30; M[2] := 28; M[6] := 30; M[9] := 30; M[11] := 30; //Num contm os nmeros e / para controle do campo data. SetLength (Num, 11); for I := 0 to 9 do Num[I] := IntToStr(I); Num[10] := '/'; // Barra controla a posio das duas // do campo data Barras := 0; // Verifica a quantidade de barras digitadas Barra1 := 0; // Posio da 1 barra (pode ser 2 ou 3) Barra2 := 0; // Posio da 2 barra (pode ser 4, 5 ou 6) for I := 1 to length(Data) do begin Caracter := copy(Data,I,1); if Caracter = '/' then begin Barras := Barras + 1; if Barra1 = 0 then Barra1 := I else Barra2 := I; end; for J := 0 to 10 do if Num[J] = Caracter then K[I] := 0; end; //Se Algum elemento da varivel Data no for vlido // seta o erro com s for J := 1 to length(Data) do if K[J] = 1 then Erro := 's'; if (length(data) < 6) or (length(data) > 10) then Erro := 's';//or // (length(data) = 9) then Erro := 's'; if Barras > 2 then Erro := 's'; if (Barra1 > 3) or (Barra1 < 2) then Erro := 's'; if (Barra2 > 6) or (Barra2 < 4) then Erro := 's'; // At aqui j sabemos que a data est em formato vlido com barras if Erro = 'n' then begin Caracter := Copy(Data,(Barra2 + 1),4); if length(Caracter) < 4 then begin Caracter := '20' + Caracter; // Se a data entrar no formato dd/mm/aa // fazemos a data ficar dd/mm/20aa Data := Copy(Data,1,Barra2)+Caracter; end;

11

// Podemos converter as posies da string em inteiros sem receio de recebermos // aquela mensagem de erro do delphi. Dia := StrToInt(Copy(Data,1,(Barra1 - 1))); Mes := StrToInt(Copy(Data,(Barra1+1),(Barra2 - Barra1 - 1))); Ano := StrToInt(Copy(Data,(Barra2 + 1),4)); // Verifica se o ano bissexto para a crtica do dia se o ms for fevereiro. J := Ano mod 4; if J = 0 then M[2] := 29 else M[2] := 28; // Critica o mes if (mes < 1) or (mes >12) then Erro := 's'; // Critica o dia if Erro = 'n' then if (dia < 1) or (dia > M[Mes]) then Erro := 's'; // critica o ano (Se quiser) if ano < 2003 then Erro := 's'; end; if Erro = 's' then begin Data := ''; messageDlg('Data inconsistente!!!',mtError, // Esta ser a nica mensagem mostrada. [mbOk],0); end; end;

A mesma procedure CriticaData, mais enxuta, porm, com o controle dos caracteres feito no evento OnKeyPress: procedure TForm1.CriticaData(var Data: string); //Com controle dos caracteres //digitados no objeto Edit1 atravs do evento OnKeyPress var I, J, Dia, Mes, Ano : Integer; Barras, Barra1, Barra2 : Integer; // Verifica a posio das barras; M : Array Of Integer; Caracter, Erro : String; begin Erro:='n'; //Em princpio o campo considerado como correto(vlido). // Cria-se o Array M com 13 campos dos quais usaremos do 1 ao 12 SetLength (M, 13); // A matriz M preenchida com o ltimo dia de cada ms for I := 1 to 12 do begin M[I] := 31; end; M[4] := 30; M[2] := 28; M[6] := 30; M[9] := 30; M[11] := 30; // Barra controla a posio das duas // do campo data Barras := 0; // Verifica a quantidade de barras digitadas

12

Barra1 := 0; // Posio da 1 barra (pode ser 2 ou 3) Barra2 := 0; // Posio da 2 barra (pode ser 4, 5 ou 6) for I := 1 to length(Data) do begin Caracter := copy(Data,I,1); if Caracter = '/' then begin Barras := Barras + 1; if Barra1 = 0 then Barra1 := I else Barra2 := I; end; end; if (length(data) < 6) or (length(data) > 10) then Erro := 's'; if Barras > 2 then Erro := 's'; if (Barra1 > 3) or (Barra1 < 2) then Erro := 's'; if (Barra2 > 6) or (Barra2 < 4) then Erro := 's'; // Aqui j sabemos se a data numrica e se est em formato vlido com barras if Erro = 'n' then begin Caracter := Copy(Data,(Barra2 + 1),4); if length(Caracter) < 4 then begin Caracter := '20' + Caracter; // Se a data entrar no formato dd/mm/aa // fazemos a data ficar dd/mm/20aa Data := Copy(Data,1,Barra2)+Caracter; end; // Podemos converter as posies da string em inteiros sem receio de recebermos // aquela mensagem de erro do delphi. Dia := StrToInt(Copy(Data,1,(Barra1 - 1))); Mes := StrToInt(Copy(Data,(Barra1+1),(Barra2 - Barra1 - 1))); Ano := StrToInt(Copy(Data,(Barra2 + 1),4)); // Verifica se o ano bissexto J := Ano mod 4; if J = 0 then M[2] := 29 else M[2] := 28; // Critica o mes if (mes < 1) or (mes >12) then Erro := 's'; // Critica o dia if Erro = 'n' then if (dia < 1) or (dia > M[Mes]) then Erro := 's'; // critica o ano (Se quiser) if ano < 2003 then Erro := 's'; end; if Erro = 's' then begin Data := ''; messageDlg('Data inconsistente!!!',mtError, [mbOk],0); end;

No evento onKeyPress do Edit1 inserido cdigos para que possa controlar os caracteres digitados:

13

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char); begin if not (Key = Chr(vk_Back)) then // Este if habilita a tecla Backspace para correo do objeto if not (Key in ['0'..'9','/']) then // Este if permite a digitao somente de nmeros e da barra / abort; end;

Preenchimento de zeros para completar a data


Usurios podem no colocar os zeros de dias e meses menores que dez forando um erro de digitao de data. Para resolver este problema, no evento OnCreate do formulrio insira o cdigo a seguir: procedure TForm1.FormCreate(Sender: TObject); begin ShortDateFormat := 'dd/mm/yyyy'; // pode-se usar dd/mm/yy para exibio no formato curto end;

Multimdia - Fazendo suas aplicaes Delphi falar


H um tempo atrs inserimos uma dica ensinando o Delphi a falar, no entanto era com sutaque "americado portugus". Saiu o SAPI 4.0 com a opo de Portugus Brasil. A seguir, links com downloads e exemplos: Para SAPI 4.0 http://www.microsoft.com/msagent/downloads/user.asp Em Text-to-speech engines, escolha o idioma Portugus Brasil E mais embaixo faa o download do SAPI 4.0 runtime support No site http://bdn.borland.com/article/0,1410,29582,00.html voc tem exemplos para delphi usando o SAPI 4.0. Download dos exemplos: http://codecentral.borland.com/codecentral/ccWeb.exe/listing?id=19509 Para SAPI 5.1 tem o site http://bdn.borland.com/article/0,1410,29583,00.html tambm com exemplos, mas no sei onde encontrar engine em portugues para esta versao. Um exemplo simples para fazer o seu Delphi falar este: Primeiro declarada na clusula uses ComObj. Em seguida, no evento onClick do boto inserido o cdigo a seguir: procedure TForm1.Button1Click(Sender: TObject);

14

var voice: OLEVariant; begin voice := CreateOLEObject('SAPI.SpVoice'); voice.Rate := 0; voice.Volume := 100; voice.Speak('Ramos da Informtica',0); voice := unassigned; end;

Multimdia - Toque um som quando o mouse passar por cima de um boto


Neste exemplo iremos utilizar CM_MOUSEENTER quando o mouse entrar no objeto e CM_MOUSELEAVE quando sair do objeto, a rotina deve ficar assim:

uses MMSystem; TYourObject = class(TAnyControl) ... private procedure CMMouseEnter(var AMsg: TMessage); message CM_MOUSEENTER; procedure CMMouseLeave(var AMsg: TMessage); message CM_MOUSELEAVE; ... end; implementation procedure TYourObject.CMMouseEnter(var AMsg: TMessage); begin sndPlaySound('c:\win\media\ding.wav',snd_Async or snd_NoDefault); end; procedure TYourObject.CMMouseLeave(var AMsg: TMessage); begin sndPlaySound(nil,snd_Async or snd_NoDefault); end;

Hints com multiplas linhas


muito simples, no evento OnCreate do formulrio insira o cdigo a seguir: procedure TForm1.FormCreate(Sender: TObject); begin Button1.Hint:='Ramos da'+#13+'Informtica'; end; 15

Multimdia - Usando cursores animados


Cursores animados existem aos montes pela internet, voc pode utilizar estes cursores em suas aplicaes, neste pequeno exemplo inserimos o cdigo no evento OnCreate do formulrio, acompanhe: procedure TForm1.FormCreate(Sender: TObject); const MyCursor=1; begin Screen.Cursors[MyCursor]:=LoadCursorFromFile('C:\Shuttle.ani'); Screen.Cursor:=MyCursor; end;

Detectando a verso do Internet Explorer


Para detectar a verso do Internet Explorer, basta consultar uma chave do registro cujo endereo : HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Internet Explorer Existem 3 chaves neste local que determinam a verso do IE: - IVer disponvel no IE 1, 2 e 3 - Build disponvel a partir do IE 2 - Version disponvel a partir do IE 4.0 possvel consultar a verso do IE atravs da verso da Shdocvw.dll, porm essa DLL s est disponvel a partir da verso 3.0. A chave IVer contm os seguintes valores: 100 - IE 1.0 101 - IE para NT 4.0 102 - IE 2.0 103 - IE 3.0 A chave Version contm o nmero da verso por extenso que no corresponde ao nmero da verso que o usurio v. Na pgina abaixo tem uma lista detalhada que relaciona um valor com o outro: http://www.codeproject.com/shell/detectie.asp E finalmente, o cdigo da funo que obtm a verso: function GetIEVersion: string; var Reg: TRegistry; 16

begin Reg := TRegistry.Create; try Reg.RootKey := HKEY_LOCAL_MACHINE; Reg.OpenKey('Software\\Microsoft\\Internet Explorer', False); try Result := Reg.ReadString('Version'); if (Result='') then Result := Reg.ReadString('IVer'); except Result := ''; end; Reg.CloseKey; finally Reg.Free; end; end; Atravs da verso do IE determina-se qual ActiveX poder ser carregado para fazer OLE com o IE. At a verso 3.0 o componente o TWebBrowser_V1 e a partir do IE 4.0, o componente o TWebBrowser.

QuickReport - Filtrando registros


procedure TForm1.QuickReport1Filter(var PrintRecord:Boolean); begin PrintRecord:= ( Table1.fieldbyname ('idade').value > 21 ); end;

Evitando efeito de maximizao


Se voc j desenvolveu uma aplicao MDI com um formulrio MDIChild que tem que ser exibido em estado Maximizado (WindowState=wsMaximized), provavelmente voc j se deparou com aquele deselegante problema em que o usurio acompanha a maximizao do seu formulrio. Para evitar isto, faa o seguinte: Antes de criar o seu formulrio para a exibio, utilize LockWindowUpdate(Handle); Aps a criao do formulrio, utilize LockWindowUpdate(0); Com isto, voc dar um efeito mais profissional s suas aplicaes. Exemplo: procedure MainForm.ItemArqCadFor(Sender: TObject); begin LockWindowUpdate(Handle); with TFrmCadFor.Create(self) do Show; LockWindowUpdate(0); end;

17

Calcula a quantidade de dias no ms


function DaysInMonth: Integer; var Year, Month, Day: Word; begin DecodeDate(Now, Year, Month, Day); Result := MonthDays[IsLeapYear(Year), Month]; end; Exemplo de uso: procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage(IntToStr(DaysInMonth)); end;

Calculando abono salrial de modo progressivo


function Abono (S, F, A1, A2: Double) : Double; Begin If S>=F then begin Result:=S+A2 end else begin If S>F-A1 then Result:=(100-(((F-S)/A1)*100))*A2/100+F else Result:=S+A1 end; end;

Onde S = Salrio (No nosso exemplo R$ 290,00 ou R$ 300,00). F= Faixa do Abono (No nosso exemplo R$ 300,00). A1= 1 Abono (Valor mais alto, no nosso exemplo R$ 50,00). A2= 2 Abono (Valor mais baixo, no nosso exemplo R$ 30,00). Result= Retorno da funo com o calculo do novo salrio.

Para executar basta declarar as variveis ou campos do banco de dados exatamente na ordem acima em modo Double.

18

Esta uma funo para calcular de modo progressivo um abono (por exemplo, folha de pagamento) sem cometer injustia. Expl: Digamos que queremos que todos os funcionrios que ganham at R$ 299,99 recebam um abono de R$ 50,00 e acima deste valor um abono de R$ 30,00. Se no aplicarmos a formula o que vai acontecer quem ganha, por exemplo, R$ 290,00 recebera R$ 340,00 (o correto seria ganhar R$ 324,00) passando a ganhar mais de quem ganhava R$ 300,00, pois este ter apenas um abono de R$ 30,00 percebendo R$ 330,00. A funo acima corrige estas distores, e pode ser aplicada num banco de dados para diversas faixas salariais.

Checa se um processo est rodando


{ .... } uses TlHelp32; { .... }

function processExists(exeFileName: string): Boolean; var ContinueLoop: BOOL; FSnapshotHandle: THandle; FProcessEntry32: TProcessEntry32; begin FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); FProcessEntry32.dwSize := SizeOf(FProcessEntry32); ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32); Result := False; while Integer(ContinueLoop) <> 0 do begin if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) = UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) = UpperCase(ExeFileName))) then begin Result := True; end; ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32); end; CloseHandle(FSnapshotHandle); end;

// Exemplo: procedure TForm1.Button1Click(Sender: TObject); begin if processExists('calc.exe') then ShowMessage('Processo em execuo') else 19

ShowMessage('O processo NO est em execuo'); end;

Checa se um diretrio est vazio


function DirectoryIsEmpty(Directory: string): Boolean; var SR: TSearchRec; i: Integer; begin Result := False; FindFirst(IncludeTrailingPathDelimiter(Directory) + '*', faAnyFile, SR); for i := 1 to 2 do if (SR.Name = '.') or (SR.Name = '..') then Result := FindNext(SR) <> 0; FindClose(SR); end;

// Exemplo: procedure TForm1.Button1Click(Sender: TObject); begin if DirectoryIsEmpty('C:\test') then Label1.Caption := 'empty' else Label1.Caption := 'not empty'; end;

dbExpress - Passando parmetros com CommandText via programao


O parametro no adicionado quando criamos o CommandText via programao, portanto devemos cri-lo da seguinte forma: procedure TForm1.Button1Click(Sender: TObject); begin SQLClientdataSet1.Close; SQLClientdataSet1.Params.Clear; SQLClientdataSet1.CommandText := 'select * from CLIENTE where CODIGO = :COD'; SQLClientdataSet1.Params.CreateParam(ftInteger, 'COD', ptInput).AsInteger := 1; SQLClientdataSet1.Open; end;

20

Corrigindo problemas de instalao do Borland Data Provider For Firebird


Em alguns casos, o Borland Data Provider For Firebird tm apresentado problemas de instalao, abaixo segue algumas dicas para tentar auxiliar na resoluo dos mesmos: 1. Verificar se o D8 est atualizado com Update Pack#2; 2. Se o BDP For Firebird foi instalado 'antes' do D8 ter sido atualizado,desinstalar, atualizar o D8 e aps isso instalar o BDP For Firebird novamente; 3. Efetuar testes diretamente via 'Data Explorer' a fim de verificar se a conexo ocorre sem problemas; 4. Copiar o arquivo 'FirebirdSql.Data.Bdp' para a pasta: C:\Arquivos de programas\Arquivos comuns\Borland Shared\BDS\Shared\Assemblies\2.0 5. No projeto, acesse 'Project Manager' | 'References' e adicione a referncia ao 'Firebirdsql.Data.Bdp'

Lendo texto de um arquivo PDF


o seguinte, esta dica peguei em um site Alemo, fiz aqui sua traduo e alguns testes e funciou. Para quem precisa criar algum sistema que leia o contedo de texto de um arquivo PDF. No lembro quem havia pedido, mas aqui est a soluo: {++++++++++++++++++++++++++++++++++++++++++++++++++ Esta uma rotina para ler informaes de arquivos PDF. No formulrio adicione um TMemo, 5 TLabel, 1 TButton e um OpenDialog. S um detalhe, v oa menu do Delphi e na opo "Import TypeLibrary" escolha a opo do Adobe Acrobat, seno, no ir funcionar. Bem, o cdigo completo da aplicao este que segue: +++++++++++++++++++++++++++++++++++++++++++++++++++} unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, OleCtrls, acrobat_tlb; type TForm1 = class(TForm) Button1: TButton; 21

Memo1: TMemo; OpenDialog1: TOpenDialog; GroupBox1: TGroupBox; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end;

var Form1: TForm1; implementation uses ComObj; {$R *.dfm} {$TYPEDADDRESS OFF} // preciso dazer esta chamada var PDDoc: Acrobat_TLB.CAcroPDDoc; PDPage: Variant; PDHili: Variant; PDTextS: Variant; acrobat: Variant; Result: Boolean; NTL, i, j, Pagecount: Integer; zeilen: string; stichwortcounter: Integer; Size: Integer; gesamtstring: AnsiString; zwreal: Real; procedure TForm1.Button1Click(Sender: TObject); function removecrlf(workstring: string): string; var i: Integer; begin removecrlf := ''; for i := 0 to Length(workstring) do begin if workstring[i] = #13 then workstring[i] := ' '; if workstring[i] = #10 then

22

workstring[i] := ' '; end; removecrlf := workstring; end; begin if not opendialog1.Execute then Exit; memo1.Clear; gesamtstring := ''; stichwortcounter := 0; Size := 0; try acrobat := CreateOleObject('AcroExch.pdDoc'); //Identifica arquivos PDF atravs do OLE Result := acrobat.Open(opendialog1.FileName);

if Result = False then begin messagedlg('O arquivo no pode ser aberto', mtWarning, [mbOK], 0); Exit; end; for j := 0 to acrobat.GetNumPages - 1 do begin memo1.Lines.Add('----------------------------------------------'); //Primeira pgina do documento ativa PDPage := acrobat.acquirePage(j); PDHili := CreateOleObject('AcroExch.HiliteList'); Result := PDHili.Add(0, 4096); //Marca sobre o texto PDTextS := PDPage.CreatePageHilite(PDHili); ntl := PDTextS.GetNumText; for i := 0 to ntl - 1 do begin zeilen := PDTextS.GetText(i); if (Length(zeilen) > 0) and (zeilen <> '') then memo1.Lines.Add(removecrlf(zeilen)); gesamtstring := gesamtstring + removecrlf(zeilen); //Apenas para estatstica Size := Size + SizeOf(zeilen); Inc(stichwortcounter);

23

Application.ProcessMessages; end; //Depois libera pdhili := Unassigned; pdtextS := Unassigned; pdpage := Unassigned; label2.Caption := IntToStr(stichwortcounter); label4.Caption := IntToStr(Size); label2.Refresh; label4.Refresh; end;

except on e: Exception do begin messagedlg('Erro: ' + e.Message, mtError, [mbOK], 0); Exit; end; end; if Size > 1024 then begin zwreal := Size / 1024; str(zwreal: 2: 1,zeilen); label4.Caption := zeilen; label5.Caption := 'KB'; end; memo1.Lines.SaveToFile(Extractfilepath(Application.exename) + '\debug.txt'); end; end.

Deixando seu EXE mais enxuto e rpido e, mais seguro contra decompilao
Geralmente, arquivos EXE criados com Delphi so maiores que os criados com outras linguagens de programao. O motivo disso so as VCL (Claro que VCL tem muitas vantagens e devem ser usadas). Porm, possvel deixar os executveis menores e, consequentemente, mais rpidos de serem abertos, fcil de distribuio pela Web (mesmo na era da banda larga), fica mais difcil de piratas de cdigos abrir seus softwares, etc. Ento apresento aqui, 10 passos (ou dicas) para deixar seu executvel mais enxuto: 01) Use um EXE-Packer (UPX, ASPack,...) 02) Use o KOL.

24

03) O que puder ser desenvolvido sem o uso de VCL deve ser feito, pois quanto maior a quantidade de VCLs, maior ser o executvel, mas as VCL devem ser usadas, ok. 04) Use a ACL (API Controls Library) 05) Use StripReloc. 06) Desative a opo remote debugging information e TD32 do Delphi. 07) You might want to put code in a dll. 08) No coloque imagens em Formulrios. De preferncia, leia em tempo de execuo. 09) Use imagens compactas, como por exemplo JPG ao invs de BMP. ****************************************************** 01) UPX um software freeware, Compactao de alto desempenho em linha de comando (sem interface grfica). Em testes, alguns arquivos chegaram a ficar com apenas 22% de seu tamanho original. A descompresso tambm muito veloz: mais de 10 MB por segundo em um pentium 133. http://upx.sourceforge.net/ ASPack um Compressor de arquivos executveis Win32, capaz de reduzir o tamanho de programas Windows 32-bit em mais de 70% (bem melhor que o padro industrial ZIP, que fica em torno de 10 a 20%). Torna menores os programas e suas bibliotecas, diminuindo o tempo de transferncia atravs de rede e o tempo de download a partir da Internet. Tambm protege os programas contra engenharia reversa por hackers no profissionais. Os programas comprimidos pelo ASPack rodam da mesma maneira que rodavam antes, sem perda de performance do tempo de execuo.

http://www.aspack.com/aspack.htm {****************************************************************} 02) KOL - Key Objects Library um conjunto de objetos para desenvolvimento de poderosas aplicaes Windows 32 bit GUI usando Delphi sem o uso de VCL. distribudo livremente e com o cdigo fonte http://bonanzas.rinet.ru/ {****************************************************************} 03) nonVCL Delphi possibilita muitos caminhos. Se voc quer um executvel pequeno, ento no uso a VCL. Isso possvel usando 100% chamadas APIs, standards resources, etc. Alguns sites que podem ajudar: http://nonvcl.luckie-online.de http://www.erm.tu-cottbus.de/delphi/stuff/Tutorials/nonVCL/index.html http://www.angelfire.com/hi5/delphizeus/ http://www.tutorials.delphi-source.de/nonvcl/

25

{****************************************************************} 04) ACL (API Controls Library) Voc tambm pode usar a ACL, o que facilita o uso de APIs, para mais informaes visite este site: http://www.apress.ru/pages/bokovikov/delphi/index.html/ {****************************************************************} 05) StripReloc Este programa remove a seo de recolocao (".reloc") dos executvies Win32 PE, reduzindo o tamanho deles. A maioria do compiladores/linkeditores (inclusive o do Delphi) insere esta seo no executvel e uma seo que nunca ser usada e no tem outra finalidade seno desperdiar espao na memria e em disco. http://www.jrsoftware.org/striprlc.php {****************************************************************} 06) Desativando o Debug Information Exclusa qualquer informao de debug no final indo ao menu do Delphi Project / Pptions Compiler - Debugging e Project / Options: Linker EXE e DLL options. {****************************************************************} 08 e 09) Sobre imagens Formulrios com muitas imagens anexadas so criadas junto ao executvel, deixando ele muito grande e sempre que executado o tamanho original multiplicado, o que torna invivel. O melhor anexar as imagens e enviar junto ao executvel pois assim no h esta multiplicao. Use arquivos JPEG ao invs de BMP. Isso ajuda a reduzir o tamanho do EXE. {****************************************************************} Essas so apenas algums dicas, no preciso fazer todas elas, mas caso precise...

Copiando (Upload) um diretrio para um servidor FTP


Oferecer uma opo de backup para clientes, ou at mesmo alguma outra aplicao, sempre um diferencial. Para esta rotina necessrio ter o componente Indy instalado em seu Delphi. procedure UploadPerFTP; procedure GetDir(dir: string); 26

var SearchRec: TSearchRec; details, nodetails: TStringList; k: Integer; begin //Pega direito o diretrio if FindFirst(dir + '*.*', faAnyFile, SearchRec) = 0 then begin repeat if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then begin //Se acharmos a pasta if (SearchRec.Attr and faDirectory) = faDirectory then begin //Pega a pasta que contm do FTP. um com detalhes e outro sem details := TStringList.Create; nodetails := TStringList.Create; FTPClient.List(details, '', True); FTPClient.List(nodetails, '', False); for k := details.Count - 1 downto 0 do begin if details.Strings[k] <> '' then begin if (details.Strings[k][1] <> 'd') or (nodetails.Strings[k] = '.') or (nodetails.Strings[k] = '..') then begin details.Delete(k); nodetails.Delete(k); end; end; end; //Se o diretrio no existe no servidor, ento cria if nodetails.IndexOf(SearchRec.Name) = -1 then begin FTPClient.MakeDir(SearchRec.Name); end; //Muda o diretrio no servidor FTPClient.ChangeDir(SearchRec.Name); details.Free; nodetails.Free; //Se achou, vai para o prximo sub-siretrio GetDir(dir + SearchRec.Name + '\'); //Temos que ir a um diretrio a cima

27

FTPClient.ChangeDirUp; end else begin //Se apenas um arquivo, upload o diretrio atual FTPClient.Put(dir + SearchRec.Name, SearchRec.Name); end; end; until FindNext(SearchRec) <> 0; FindClose(SearchRec); end; end; var dir: string; details, nodetails: TStringList; k: Integer; begin //Seta as configuraes para acesso ao servidor de FTP(TIdFTPClient) with FTPClient do begin Host := 'your_server.com'; // Coloque host Username := 'your_username'; // Colque senha Password := 'your_password'; // Adjust your data here Passive := True; end; FTPClient.Connect; //Se for de um computador remoto, ou na rede, faa isso dir := StringReplace('your/remote_directory', '\', '/', [rfReplaceAll]); if dir <> '' then begin if dir[1] = '/' then Delete(dir, 1, 1); if dir[Length(dir)] <> '/' then dir := dir + '/'; while Pos('/', dir) > 0 do begin details := TStringList.Create; nodetails := TStringList.Create; FTPClient.List(details, '', True); FTPClient.List(nodetails, '', False); for k := details.Count - 1 downto 0 do begin if details.Strings[k] <> '' then begin if (details.Strings[k][1] <> 'd') or

28

(nodetails.Strings[k] = '.') or (nodetails.Strings[k] = '..') then begin details.Delete(k); nodetails.Delete(k); end; end; end; if nodetails.IndexOf(Copy(dir, 1, Pos('/', dir) - 1)) = -1 then begin FTPClient.MakeDir(Copy(dir, 1, Pos('/', dir) - 1)); end; FTPClient.ChangeDir(Copy(dir, 1, Pos('/', dir) - 1)); Delete(dir, 1, Pos('/', dir)); details.Free; nodetails.Free; end; end; dir := 'C:\your\local\directory\'; if dir[Length(dir)] <> '\' then dir := dir + '\'; GetDir(dir); FTPClient.Disconnect; end;

Trabalhando com arquivos texto no Delphi


Para trabalhar com arquivo texto: Existem vrios mtodos em Delphi para gravar arquivos texto a partir de informaes gravadas em bases de dados ou para ler arquivos texto e armazen-los em bases de dados. Esta dica apresenta um destes mtodos: o uso de TextFiles. TextFile um tipo de dado pr-definido no Delphi e corresponde ao tipo Text do Turbo Pascal e do Object Pascal. Inicialmente para acessar um arquivo de texto, voc precisa definir uma varivel tipo TextFile, no local que voc achar mais apropriado, da seguinte forma: var arq: TextFile; Vamos precisar tambm de uma varivel tipo string para armazenar cada linha lida do arquivo: var linha: String;

29

Antes de se iniciar a leitura do arquivo, precisamos associar a variavel TextFile com um arquivo fisicamente armazenado no disco: AssignFile ( arq, 'C:\AUTOEXEC.BAT' ); Reset ( arq ); A rotina AssignFile faz a associao enquanto Reset abre efetivamente o arquivo para leitura. AssignFile corresponde Assign do Turbo Pascal. Em seguida necessrio fazer uma leitura ao arquivo, para isto utilizaremos a procedure ReadLn: ReadLn ( arq, linha ); O comando acima l apenas uma linha de cada vez, assim precisamos de um loop para efetuar vrias leituras at que o arquivo acabe. Para verificar o fim do arquivo, utilizaremos a funo Eof: while not Eof ( arq ) do Agora uma rotina quase completa para fazer a leitura de um arquivo texto. Esta rotina recebe como parmetro o nome do arquivo que ser lido: procedure percorreArquivoTexto ( nomeDoArquivo: String ); var arq: TextFile; linha: String; begin AssignFile ( arq, nomeDoArquivo ); Reset ( arq ); ReadLn ( arq, linha ); while not Eof ( arq ) do begin { Processe a linha lida aqui. } { Para particionar a linha lida em pedaos, use a funo Copy. } ReadLn ( arq, linha ); end; CloseFile ( arq ); end; E tambm uma rotina quase completa para gravao de um arquivo texto. Esta rotina recebe como parmetro o nome do arquivo que ser gravado e uma tabela (TTable) de onde os dados sero lidos: procedure gravaArquivoTexto ( nomeDoArquivo: String; tabela: TTable ); var arq: TextFile; linha: String; begin AssignFile ( arq, nomeDoArquivo ); Rewrite ( arq ); tabela.First; while not tabela.Eof do begin Write ( arq, AjustaStr ( tabela.FieldByName ( 'Nome' ).AsString, 30 ) ); Write ( arq, FormatFloat ( '00000000.00', tabela.FieldByName ( 'Salario' ).AsFloat ) );

30

WriteLn ( arq ); tabela.Next; end; CloseFile ( arq ); end; Note nesta segunda rotina, a substituio de Reset por Rewrite logo aps o AssignFile. Rewrite abre o arquivo para escrita, destruindo tudo que houver l anteriormente . Note tambm o uso de Write e WriteLn para gravar dados no arquivo texto. Finalmente note o uso de AjustaStr e FormatFloat para garantir que campos string e numericos sejam gravados com um nmero fixo de caracteres. FormatFloat uma rotina do prprio Delphi enquanto AjustaStr est definida abaixo: function AjustaStr ( str: String; tam: Integer ): String; begin while Length ( str ) < tam do str := str + ' '; if Length ( str ) > tam then str := Copy ( str, 1, tam ); Result := str; end; O uso da funo AjustaStr fundamental quando voc estiver gravando arquivos texto com registros de tamanho fixo a partir de bases de dados Paradox que usualmente no preenchem campos string com espaos no final.

Criando uma conexo ao DBExpress em tempo de execuo


{ O caminho normal para se criar uma conexo com o DBExpress no Delphi e no Kylix o desenvolvedor colocar um componente TSQLConnection no formulrio de com um duplo clique no componente abrir o editor de conexo e setar os parmetros (drive, caminho do banco de dados, nome da conexo, etc) para indicar a conexo. Veja agora como fazer isso em tempo de execuo. } procedure TVCLScanner.PostUser(const Email, FirstName, LastName: WideString); var Connection: TSQLConnection; DataSet: TSQLDataSet; begin Connection := TSQLConnection.Create(nil); with Connection do begin

31

ConnectionName := 'VCLScanner'; DriverName := 'INTERBASE'; LibraryName := 'dbexpint.dll'; VendorLib := 'GDS32.DLL'; GetDriverFunc := 'getSQLDriverINTERBASE'; Params.Add('User_Name=SYSDBA'); Params.Add('Password=masterkey'); Params.Add('Database=milo2:D:\ramosinfo\webservices\umlbank.gdb'); LoginPrompt := False; Open; end; DataSet := TSQLDataSet.Create(nil); with DataSet do begin SQLConnection := Connection; CommandText := Format('INSERT INTO kings VALUES("%s","%s","%s")', [Email, FirstN, LastN]); try ExecSQL; except end; end; Connection.Close; DataSet.Free; Connection.Free; end;

ActiveX - Pegar um texto selecionado no Internet Explorer


Em defesa do Ctrl+C, Ctrl+V: Eu bem que queria saber quem que teve a pssima idia de condenar a cpia intelectual deslavada, deixando a gente com essa sensao desconfortvel de ter que fazer as coisas por si mesmo. O sujeito que inventou a patente era obviamente um chato e provavelmente se chamava Lazinho. Nestes tempos de subjetivismo, de dinmicas de grupo e de cursos de gesto, as pessoas so pagas para serem originalssimas. Estamos na era da tirania da criatividade. A quantidade de bobagem, de feira e de chatice que isso gerou incalculvel. por isso que, sempre que posso, tento privar o mundo de minhas desinteressantssimas particularidades. Penso que melhor ter um pouco mais de pudor e no sair mostrando as originalidades pra todo mundo no. Mais ou menos como barriga de mulher: se feia, melhor nem mostrar. Pensando nisso, que tal uma rotina que pega textos selecionados do IE? Pode ser bastante til: uses SHDocVw_TLB; // http://www.euromind.com/iedelphi Se voc no tiver esta unit, visite este site.

32

function GetSelectedIEtext: string; var x: Integer; Sw: IShellWindows; IE: HWND; begin IE := FindWindow('IEFrame', nil); sw := CoShellWindows.Create; for x := SW.Count - 1 downto 0 do if (Sw.Item(x) as IWebbrowser2).hwnd = IE then begin Result := variant(Sw.Item(x)).Document.Selection.createRange.Text; break; end; end;

Cria um efeito na apresentao de um formulrio


procedure TForm1.animin(Sender: TObject); procedure delay(msec: Longint); var start, stop: Longint; begin start := GetTickCount; repeat stop := GetTickCount; Application.ProcessMessages; until (stop - start) >= msec; end; var maxx, maxy: Integer; MyHand: HWND; MyDc: HDC; MyCanvas: TCanvas; hal, hat, hak, haa: Integer; begin maxx := (Sender as TForm).Width; maxy := (Sender as TForm).Height; hal := 2; hat := 2; MyHand := GetDesktopWindow; MyDc := GetWindowDC(MyHand); MyCanvas := TCanvas.Create; MyCanvas.Handle := MyDC; MyCanvas.Brush.Color := (Sender as TForm).Color;

33

repeat if hat + (maxy div 24) >= maxy then begin hat := maxy end else begin hat := hat + (maxy div 24); end; if hal + (maxx div 24) >= maxx then begin hal := maxx end else begin hal := hal + (maxx div 24); end; hak := (Sender as TForm).Left + ((Sender as TForm).Width div 2) - (hal div 2); haa := (Sender as TForm).Top + ((Sender as TForm).Height div 2) - (hat div 2); MyCanvas.Rectangle(hak, haa, hak + hal, haa + hat); delay(10); until (hal = maxx) and (hat = maxy); (Sender as TForm).Show; end;

procedure TForm1.Button1Click(Sender: TObject); begin animin(form2); end; procedure TForm1.Button2Click(Sender: TObject); begin animin(form3); end;

Criando um Menu transparente


Que tal brincar um pouco com suas aplicaes: var hHookID: HHOOK; // Funo para criar um menu transarente function MakeWndTrans(Wnd: HWND; nAlpha: Integer = 10): Boolean; type

34

TSetLayeredWindowAttributes = function(hwnd: HWND; crKey: COLORREF; bAlp ha: Byte; dwFlags: Longint): Longint; stdcall; const // Use crKey para definir a cor como transparente LWA_COLORKEY = 1; // Use bAlpha para determinar a opacidade do layer do windows LWA_ALPHA = 2; WS_EX_LAYERED = $80000; var hUser32: HMODULE; SetLayeredWindowAttributes: TSetLayeredWindowAttributes; i : Integer; begin Result := False; // imnportante usarmos a DLL USER32.DLL e distribuir na aplicao. hUser32 := GetModuleHandle('USER32.DLL'); if hUser32 <> 0 then begin @SetLayeredWindowAttributes := GetProcAddress(hUser32,'SetLayeredWindowAtt ributes'); if @SetLayeredWindowAttributes <> nil then begin SetWindowLong(Wnd, GWL_EXSTYLE, GetWindowLong(Wnd, GWL_EXST YLE) or WS_EX_LAYERED); SetLayeredWindowAttributes(Wnd, 0, Trunc((255 / 100) * (100 nAlpha)), LWA_ALPHA); Result := True; end; end; end; // hook procedure function HookCallWndProc(nCode: Integer; wParam, lParam: Longint): Longint; stdca ll; const MENU_CLASS = '#32768'; N_ALPHA = 60; var cwps: TCWPStruct; lRet: THandle; szClass: array[0..8] of char; begin if (nCode = HC_ACTION) then begin CopyMemory(@cwps, Pointer(lParam), SizeOf(CWPSTRUCT)); case cwps.message of WM_CREATE: begin GetClassName(cwps.hwnd, szClass, Length(szClass)-1);

35

// Window name for menu is #32768 if (lstrcmpi(szClass, MENU_CLASS) = 0) then begin MakeWndTrans(cwps.hwnd, N_ALPHA {Alphablending}); end; end; end; end; Result := CallNextHookEx(WH_CALLWNDPROC, nCode, wParam, lParam); end; // Coloque no evento OnCreate do form procedure TForm1.FormCreate(Sender: TObject); var tpid: DWORD; begin tpid := GetWindowThreadProcessId(Handle, nil); hHookID := SetWindowsHookEx(WH_CALLWNDPROC, HookCallWndProc, 0, tpi d); end; // Pare o processo no evento OnDestroy procedure TForm1.FormDestroy(Sender: TObject); begin if (hHookID <> 0) then // Remove o menu transparente UnhookWindowsHookEx(hHookID); end;

Checa se um diretrio est vazio


function DirectoryIsEmpty(Directory: string): Boolean; var SR: TSearchRec; i: Integer; begin Result := False; FindFirst(IncludeTrailingPathDelimiter(Directory) + '*', faAnyFile, SR); for i := 1 to 2 do if (SR.Name = '.') or (SR.Name = '..') then Result := FindNext(SR) <> 0; FindClose(SR); end;

// Exemplo de uso: procedure TForm1.Button1Click(Sender: TObject);

36

begin if DirectoryIsEmpty('C:\test') then Label1.Caption := 'empty' else Label1.Caption := 'not empty'; end;

Mostra multiplas linhas de texto em um ComboBox


procedure TForm1.ComboBox1MeasureItem(Control: TWinControl; Index: Integer; var Height: Integer); var ItemString: string; MyRect: TRect; MyImage: TImage; MyCombo: TComboBox; begin if (Index > -1) then begin MyCombo := TComboBox(Control); // Create a temporary canvas to calculate the height MyImage := TImage.Create(MyCombo); try MyRect := MyCombo.ClientRect; ItemString := MyCombo.Items.Strings[Index]; MyImage.Canvas.Font := MyCombo.Font; // Calc. using this ComboBox's font size Height := DrawText(MyImage.Canvas.Handle, PChar(ItemString), - 1, MyRect, DT_CALCRECT or DT_WORDBREAK); finally MyImage.Free; end; end; end; Modo de usar: procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); var ItemString: string; begin TComboBox(Control).Canvas.FillRect(Rect); ItemString := TComboBox(Control).Items.Strings[Index]; DrawText(TComboBox(Control).Canvas.Handle, PChar(ItemString), - 1, Rect, DT_WORDBREAK); end;

37

Criando atalhos no Windows pelo Delphi


implementation uses ShlObj, ActiveX, ComObj; {$R *.dfm} procedure CriaShortCut(aNome, aFileName: string; aLocation: integer); var IObject : IUnknown; ISLink : IShellLink; IPFile : IPersistFile; PIDL : PItemIDList; InFolder : array[0..MAX_PATH] of Char; TargetName : String; LinkName,s : WideString; begin TargetName := aFileName; IObject := CreateComObject(CLSID_ShellLink); ISLink := IObject as IShellLink; IPFile := IObject as IPersistFile; with ISLink do begin SetPath(pChar(TargetName)); SetWorkingDirectory(pChar(ExtractFilePath (TargetName))); end; SHGetSpecialFolderLocation (0, aLocation, PIDL); SHGetPathFromIDList(PIDL, InFolder); s := InFolder; LinkName := s + '\' + aNome + '.LNK'; if FileExists(LinkName) then ShowMessage('Atalho j existe!') else IPFile.Save(PWChar(LinkName), false); end; // Para utilizar: CriaShortCut('Calculadora', 'c:\windows\system32\calc.exe', CSIDL_DESKTOP);

38

Faa suas aplicaes Falar


Um exemplo que demonstra o uso dos objetos de fala da Microsoft para fazer suas aplicaes tornarem-se falantes. Para fazer suas aplicaes em Delphi FALAR basta baixar o pacote Speech SDK no site da microsoft. http://www.microsoft.com/speech Feito isso, use o seguinte cdigo para falar "Hello World". uses Comobj; procedure TForm1.Button1Click(Sender: TObject); var objVoice: OLEVariant; begin objVoice := CreateOLEObject('SAPI.SpVoice'); objVoice.Speak('Hello World',0); objVoice := unassigned; end; Veja outros exemplos: http://www.blong.com/Conferences/DCon2002/Speech/SAPI51/SAPI51.htm

Imprimindo arquivos PDF sem abrir-los


Implementation Uses shellApi; {$R *.DFM} procedure Tform1.Button1Click(Sender: Tobject); begin ShellExecute(Handle, 'print', Pchar('C;\Pasta\Leiame.pdf'), nil,nil,SW_SHOW); End;

Ler arquivos PDF


Tem que ter o Acrobat instalado no computador. 1.) Coloque um opendialog e um button. 39

2.) V em Project + Import Type Library. 3.) Selecione Acrobat Control para ActveX..... + install ........... 4.) Aparcer uma tela, clique em compilar...... 5.) V depois na palheta ActiveX e escolha o componente PDF 6.) Faa as devidos ajuste e digite no button: if opendialog1.execute then pdf1.src:=opendialog1.filename;

Inno Setup - Script para criao de conexo OBDC DSN


[Setup] AppName=ODBC2 AppVerName=ODBC2 Uninstallable=false UpdateUninstallLogAppName=false DisableDirPage=false DisableProgramGroupPage=true DefaultDirName={pf}\ODBC2 DisableStartupPrompt=true CreateAppDir=false [_ISTool] EnableISX=true [Tasks] Name: cfgdsndlg; Description: Config DSN with dialog; GroupDescription: Configuration:; Flags: unchecked [Code] function SQLConfigDataSource(hwndParent: LongInt; fRequest: LongInt; lpszDriver: String; lpszAttributes: String): LongInt; external 'SQLConfigDataSource@ODBCCP32.DLL stdcall'; const ODBC_ADD_DSN = 1; // Add data source ODBC_CONFIG_DSN = 2; // Configure (edit) data source ODBC_REMOVE_DSN = 3; // Remove data source ODBC_ADD_SYS_DSN = 4; // add a system DSN ODBC_CONFIG_SYS_DSN = 5; // Configure a system DSN ODBC_REMOVE_SYS_DSN = 6; // remove a system DSN

function CreateDSN( showdlg: Boolean) : LongInt; var hwnd : LongInt; var

40

strDriver, strAttributes, NewLine : String; begin // if it is not auto configuration, setting HWND of wizard let show // DSN setup dialog with attributes specified if not showdlg then hwnd := 0 else hwnd := StrToInt(ExpandConstant('{wizardhwnd}')); // MYSQL Sample { strDriver := 'MySQL'; NewLine := Chr(0); strAttributes := 'SERVER=localhost' + NewLine + 'DESCRIPTION=MySQL Driver DSN' + NewLine + 'DSN=SAMPLE_DSN' + NewLine + 'DATABASE=test' + NewLine + 'UID=username' + NewLine + 'PASSWORD=password' + NewLine + 'PORT=3306' + NewLine + 'OPTION=3' + NewLine; } Result := SQLConfigDataSource( hwnd, ODBC_ADD_SYS_DSN, strDriver, strAttributes); end;

function NextButtonClick(CurPage: Integer): Boolean; var showdlg : Boolean; begin // by default go to next page Result := true; // if curpage is wpSelectTasks check config DSN if CurPage = wpSelectTasks then begin showdlg := ShouldProcessEntry( '','cfgdsndlg') = srYes ; if CreateDSN( showdlg ) = 0 then MsgBox( 'DSN not done.', mbError, MB_OK ) else MsgBox( 'DSN Created !', mbInformation, MB_OK ); end; end;

41

Colocar cursor no final do Edit ao receber o foco


No evento OnEnter do TEdit coloque: procedure TForm1.Edit1Enter(Sender: TObject); begin Edit1.Selstart:= Length(Edit1.text); end;

Mudar a cor de fundo de um Hint


Application.HintColor := clBlack;

Fazer um executvel ser executado somente se chamado por um determinado executvel


Inclua na seo uses: Windows Problema: Gostaria que um determinado programa (Prog1.EXE) fosse executado apenas atravs de outro programa (Prog2.EXE). Soluo: Antes da linha "Application.Initialize;" de Prog1.dpr (programa a ser chamado), coloque o cdigo abaixo: if ParamStr(1) <> 'MinhaSenha' then begin { Para usar ShowMessage, coloque Dialogs no uses } ShowMessage('Execute este programa atravs de Prog2.EXE'); Halt; { Finaliza } end; No Form1 de Prog2 (programa chamador) coloque um boto e escreva o OnClick deste boto como abaixo: procedure TForm1.Button1Click(Sender: TObject); var Erro: Word; begin Erro := WinExec('Pro2.exe MinhaSenha', SW_SHOW); if Erro <= 31 then { Se ocorreu erro... } ShowMessage('Erro ao executar o programa.'); end; Observaes: Aqui o parmetro passado foi 'MinhaSenha'. Voc dever trocar 'MinhaSenha' por algo que apenas voc saiba (uma senha). Caso uma pessoa conhea 42

esta senha, ser possvel chamar este programa passando-a como parmetro. Neste caso sua "trava" estar violada.

DBGrid - Focando a clula selecionada mudando sua cor


possvel fazer um tratamento no evento onDrawDataCell do DBGrid e verificar a clula em foco alterando a cor da mesma, veja abaixo simples exemplo: procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect; Field: TField; State: TGridDrawState); begin if (gdSelected in State) then begin with DBGrid1.Canvas do begin Brush.Color := clAqua; Font.Color := clNavy; FillRect( Rect ); TextOut(Rect.Left, Rect.Top, Field.AsString); end; end; end; Obs. Para que toda a linha fica selecionada voc dever alterar a propriedade Options -> dgRowSelect para True;

Verificando a verso do Windows


Neste exemplo apresentamos uma rotina para verificar qual a verso do Windows. O que diferencia esta rotina de outras j apresentadas que ela consegue distinguir entre todas as verses do Windows, ou seja, se Windows 95, 98, ME, NT 4, 2000 ou XP. function GetWinVersion: String; begin case Win32MajorVersion of 3: Result := Windows NT 3.51; // NT 3.51 4: // WIn9x/ME, NT 4 case Win32MinorVersion of 0: Result := Windows 95; 10: Result := Windows 98; 90: Result := Windows ME; else if (Win32Platform and VER_PLATFORM_WIN32_NT) <> 0 then Result := Windows NT 4.0 else Result := SO desconhecido; end;

43

5: // Win2K, XP case Win32MinorVersion of 0: Result := Windows 2000; 1: Result := Windows XP or .NET server; else Result := SO desconhecido; end; else Result := SO desconhecido; end; end; // Chamada: { mostrar em um label } OSVersion.Caption := GetWinVersion;

Rave Report - Alterar a impressora padro


Basta informar o ndice da impressora da seguinte forma: uses RpDevice, Printers; procedure TForm1.Button1Click (Sender: TObject); begin Printer.PrinterIndex := 0; RPDev.DeviceIndex := Printer.PrinterIndex; rvTestes.ExecuteReport(Rep_Employee); end;

Atribundo efeitos para abertura de formulrios


Existe uma funo chamada AnimateWindow. Veja a seguir como chamar: procedure TForm1.Button1Click(Sender: TObject); begin Form2.BringToFront; AnimateWindow(Form2.Handle, 3000, AW_BLEND); Form2.Show; { No terceiro parmetro da funo voc pode utilizar uma das opes abaixo AW_BLEND : Uses a fade effect AW_SLIDE : Uses slide animation. AW_ACTIVATE : Activates the window AW_HIDE : Hides the window. 44

AW_CENTER : Makes the window appear to collapse inward AW_HOR_POSITIVE : Animates the window from left to right. AW_HOR_NEGATIVE : Animates the window from right to left AW_VER_POSITIVE : Animates the window from top to bottom AW_VER_NEGATIVE : Animates the window from bottom to top } end;

API do Windows - Funo para excluir uma pasta e todos arquivos desta pasta
implementation uses ShellApi; {$R *.dfm} procedure DeleteDir(hHandle: THandle; Const sPath : String; Confirm: boolean); var OpStruc: TSHFileOpStruct; FromBuffer, ToBuffer: Array[0..128] of Char; begin FillChar( OpStruc, Sizeof(OpStruc), 0 ); FillChar( FromBuffer, Sizeof (FromBuffer), 0 ); FillChar( ToBuffer, Sizeof(ToBuffer), 0 ); StrPCopy( FromBuffer, sPath); With OpStruc Do Begin Wnd:= hHandle; wFunc:=FO_DELETE; pFrom:= @FromBuffer; pTo:= @ToBuffer; if not confirm then begin fFlags:= FOF_NOCONFIRMATION; end; fAnyOperationsAborted:=False; hNameMappings:=nil; End; ShFileOperation(OpStruc); end; Usando a Funo: procedure TForm1.Button1Click(Sender: TObject); begin DeleteDir(Self.Handle,C:\TESTE,True) 45

end; end.

Inno Setup - Verificando se existe determinada Chave no Registro do Windows


O Inno Setup o instalador oficial do nosso site. Aqui trazemos mais uma dica deste fantstico gerador de instalaes, onde demonstramos como verificar se uma determinada chave existe no registro do Windows: [Setup] AppName=VerificaChave AppVerName=VerificaChave DefaultDirName={pf}\VerificaChave DisableStartupPrompt=true Uninstallable=false DisableDirPage=true OutputBaseFilename=VerificaChave [Code] function InitializeSetup(): Boolean; begin if RegKeyExists(HKEY_LOCAL_MACHINE, SOFTWARE\Firebird Project\Firebird Server) then begin MsgBox( No posso instalar! , mbInformation, MB_OK ); Result := false; end else Result := true; end; Isso muito interessante, por exemplo, para verificar se uma determinada aplicao j existe no computador do cliente.

Controlando o PowerPoint no Delphi


Seguindo a linha da automao OLE Office, veja agora como controlar o powerpoint em uma aplicao delphi uses comobj; procedure TForm1.Button1Click(Sender: TObject); 46

var PowerPointApp: OLEVariant; begin try PowerPointApp := CreateOleObject('PowerPoint.Application'); except ShowMessage('Error...'); Exit; end; // Torna o Powerpoint visivel PowerPointApp.Visible := True; // Mostra verso do PowerPoint ShowMessage(Format('Powerpoint version: %s',[PowerPointApp.Version])); // Abre uma apresentao PowerPointApp.Presentations.Open('c:\\windows\\desktop\\teste.ppt', False, False, True); // SMostra o nmero de slides ShowMessage(Format('%s slides.',[PowerPointApp.ActivePresentation.Slides.Count])); // Roda a apresentao PowerPointApp.ActivePresentation.SlideShowSettings.Run; // Vai para o prximo slide PowerPointApp.ActivePresentation.SlideShowWindow.View.Next; // Vai para slide 2 PowerPointApp.ActivePresentation.SlideShowWindow.View.GoToSlide(2); // Vai para o slide anterior PowerPointApp.ActivePresentation.SlideShowWindow.View.Previous; // Vai para o ltimo slide PowerPointApp.ActivePresentation.SlideShowWindow.View.Last; // Mostra o nome do Slide corrente ShowMessage(Format('Current slidename: %s',[PowerPointApp.ActivePresentation.SlideShowWindow.View.Slide.Name])); // Fecha o Powerpoint PowerPointApp.Quit; PowerPointApp := UnAssigned; end;

47

Rave Report - Indicar pgina inicial


O Rave Reports permite ter vrias pginas de relatrio (cada pgina com um layout) para um mesmo relatrio. Neste exemplo, iremos demonstrar como definir via programao qual pgina ser apresentada como inicial. uses RVClass, RVProj, RVCsStd; procedure TForm1.btnChamaRelClick (Sender: TObject); var Pagina: TRavePage; Report: TRaveReport; QualPagina: String; begin // Nome da pgina dentro do projeto Rave. QualPagina := Page2; // Abre RvProject. RvProject1.Open; // Pega referncia do Report // dentro do projeto Rave. Report := RvProject1.ProjMan.ActiveReport; // Pega referncia da Page dentro do Report. Pagina := RvProject1.ProjMan.FindRaveComponent (Report1.+QualPagina,nil) as TRavePage; // Indica a pgina inicial. Report.FirstPage := Pagina; // Executa o relatrio. RvProject1.Execute; end;

InnoSetup - Adicionar um programa no iniciar do Windows


O InnoSetup uma gerador gratuito de instalaes que vm dia-a-dia se popularizando meio a comunidade Delphi. A seguir, apresentamos uma dica para adicionar sua aplicao para iniciar junto com o Windows. [Code] [Setup] AppName=Adicionar no iniciar. AppVerName= Adicionar no iniciar. DefaultDirName={pf}\ Adicionar no iniciar. DisableStartupPrompt=true Uninstallable=false DisableDirPage=true OutputBaseFilename=Adicionar no iniciar. 48

[Files] Source: C:\teste.exe; DestDir: {userstartup}; DestName: teste.exe Veja que o segredo est no diretrio de destino da aplicao ou atalho da mesma, o qual dever ser destinado para {userstartup} que representa um path especial que o Windows ir buscar no momento que estiver iniciando.

Validando endereo de e-mail no Delphi em aplicaes Win32, .Net e Asp.Net


{ Exemplo: If IsValidEMail(Edit1.Text) then ShowMessage('Valid E-Mail!') Else ShowMessage('Invalid E-Mail!'); } Function OcorrenciasEm(De, NoTexto:String):LongInt; Var h,CONT:LongInt; TEMP:String; Begin TEMP:=AnsiReplaceText(NoTexto, '|', ''); TEMP:=AnsiReplaceText(TEMP, De, '|'); CONT:=0; For h:=1 to Length(TEMP) do If TEMP[h] = '|' then CONT:=CONT+1; Result:=CONT; End; Function IsValidEMail(EMail:String):Boolean; Var h,A_POS:LongInt; OK:Boolean; TEMP:String; Begin OK:=True; TEMP:=UpperCase(EMail); For h:=1 to Length(TEMP) do Begin If Not ((ORD(TEMP[h]) >= 64) and (ORD(TEMP[h]) <= 90)) and Not (ORD(TEMP[h]) = 95) and Not (ORD(TEMP[h]) = 46) then OK:=False; End;

49

A_POS:=Pos('@', EMail); If (A_POS = 0) or (A_POS < 3) then OK:=False; If Pos('.', Copy(EMail, A_POS, Length(EMail)-A_POS)) = 0 then OK:=False; If OcorrenciasEm('@', EMail) > 1 then OK:=False; If Pos('..', EMail) > 0 then OK:=False; If Pos('@.', EMail) > 0 then OK:=False; If Email[1] = '.' then OK:=False; If Email[Length(EMail)] = '.' then OK:=False; If Length(Email) > 250 then OK:=False; Result:=OK; End;

Memo redondo
Pensando no carnaval, que tal montar o Rei Memo? Veja a rotina: procedure TForm1.Button1Click(Sender: TObject); procedure MemoRedondo(QueMemo: TMemo); var rect : TRect; rgn : HRGN; begin rect := QueMemo.ClientRect; rgn := CreateRoundRectRgn( rect.Left, rect.top, rect.right, rect.bottom, 20, 20); QueMemo.BorderStyle := bsNone; QueMemo.Perform(EM_GETRECT, 0, lparam(@rect)); InflateRect(rect, -5, -5); QueMemo.Perform(EM_SETRECTNP, 0, lparam(@rect)); SetWindowRgn(QueMemo.Handle, rgn, true); end; Como usar: begin MemoRedondo(Memo1); end;

Colocar Banners em Menus


Vamos adicionar em um menu, uma imagem no estilo banner. Para isso, adicione no formulrio um Image e carregue uma imagem de sua preferncia. Selecione todos os itens do menu e no evento OnDrawItem digite o seguinte cdigo:

50

procedure TForm1.Exit1DrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect; Selected: Boolean); begin ACanvas.FillRect(ARect); ACanvas.TextOut(ARect.Left+48, ARect.Top, StripHotkey((Sender as TMenuItem).Caption)); ACanvas.Draw(0, 0, Image1.Picture.Graphic); ImageList1.Draw(ACanvas, ARect.Left+30, ARect.Top, (Sender as TMenuItem).ImageIndex); end;

Usando a WebCam no Delphi


Recebo constantemente e-mails pedindo informaes de como usar a WebCam no Delphi. O primeiro passo baixar o SDK do fabricante da WebCam. Neste exemplo, que segue, estou utilizando o Quick Cam SDK, que pode ser encontrado no site do fabricante, que neste caso : http://developer.logitech.com/ O exemplo a seguir mostra como usar o mtodo PictureToMemory da biblioteca Quick Cam SDK. No site do fabricante tambm h documentaes de como usar a SDK. type TMemoryStream = class(Classes.TMemoryStream); var MS : TMemoryStream; lSize : LongInt; pBuffer : ^Byte; begin MS := TMemoryStream.Create; bitmap1 := TBitmap.Create; try if VideoPortal1.PictureToMemory(0,24,0,lSize,'') = 1 then begin pBuffer := AllocMem(lSize); if VideoPortal1.PictureToMemory(0,24,integer(pBuffer),lSize,'') = 1 then begin MS.SetPointer(pBuffer,lSize); bitmap1.loadfromstream(MS); end; end; finally MS.Free; FreeMem(pBuffer);

51

end; end;

Colocando imagens em um ComboBox


Inicialmente, necessrio setar a propriedade "Style" do ComboBox para "csOwnerDrawVariable". Desta forma teremos a liberdade para desenharmos o que quisermos dentro do ComboBox. Imaginemos que o nosso ComboBox possui trs tens. E para cada tem colocaremos uma imagem diferente. Para isso, criaremos um vetor que ter um nmero de elementos correspondente a quantidade de tens de nosso ComboBox. No nosso exemplo, sero trs elementos. Este vetor deve ser criado como uma varivel "private" (em "private declarations" do form). private Img: Array[0..2] of TBitmap; A seguir, no evento "OnCreate" do nosso formulrio colocaremos o seguinte: procedure TForm1.FormCreate(Sender: TObject); begin Img[0] := TBitmap.Create; Img[0].LoadFromFile('edit.bmp'); ComboBox1.Items.AddObject('Edit', Img[0]); Img[1] := TBitmap.Create; Img[1].LoadFromFile('delete.bmp'); ComboBox1.Items.AddObject('Delete', Img[1]); Img[2] := TBitmap.Create; Img[2].LoadFromFile('export.bmp'); ComboBox1.Items.AddObject('Export', Img[2]); end; Agora o trabalho no evento "OnDrawItem" do ComboBox que dever ter o seguinte: procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); var Bmp: TBitmap; Off: Integer; Cmb: TComboBox;

52

begin Cmb := (Control as TComboBox); with Cmb.Canvas do begin FillRect(Rect); Off := 0; Bmp := TBitmap(ComboBox1.Items.Objects[Index]); if Bmp <> nil then begin BrushCopy(Bounds(Rect.Left+2, Rect.Top+2, Bmp.Width, Bmp.Height), Bmp, Bounds(0, 0, Bmp.Width, Bmp.Height), clOlive); Off := Bmp.Width+8; end; TextOut(Rect.Left + Off, Rect.Top, ComboBox1.Items[Index]); end; end; E, finalmente, no evento "OnMeasureItem" do ComboBox: procedure TForm1.ComboBox1MeasureItem(Control: TWinControl; Index: Integer; var Height: Integer); begin Height := 20; end; Alguma explicao: O evento "OnDrawItem" o responsvel por "desenhar" cada tem do ComboBox quando clicamos no cone para abr-lo. Simplesmente aproveitamos isto para desenhar a nossa imagem antes do texto. Neste mesmo evento fizemos uma chamada a funo "BrushCopy", onde o ltimo parmetro a cor que deseja que fique transparente. Como eu utilizei imagens que vem com o Delphi, a cor de fundo destas imagens o amarelo escuro (clOlive). Da pra frente testar com imagens diferentes, porm, uma sugesto que todas tenham o mesmo tamanho para que se mantenha um padro dentro do seu ComboBox.

Importando e Exportando Registro


Um tcnica bem simples para exportar/importar o registry em arquivos no formato .REG. Function ExportRegistry(FileName:String; ExportKey:String):Boolean; Begin ShellExecute(0,nil,'REGEDIT.EXE',PChar('/SC /E '+FileName+' "'+ExportKey+'"'),nil,sw_hide);

53

Result := FileExists(FileName); End; Function ImportRegistry(FileName:String; ExportKey:String):Boolean; Begin Result := FileExists(FileName); If Result Then Begin ShellExecute(0,nil,'REGEDIT.EXE',PChar('/SC /C '+FileName),nil,sw_hide); End; End; Exemplo: procedure TForm1.Button1Click(Sender: TObject); begin ExportRegistry('c:\\windows\\desktop\\teste.reg','HKEY_CURRENT_USER\\Software\\ Borland'); end;

DBGrid - Colocar um ComboBox num DBGrid


As colunas da DBGrid tem uma propriedade chamada PickList, que permite colocar as opes numa lista, que sero mostradas quando a coluna editada. Para preench-la, basta abrir o editor de colunas da DBGrid, selecionar a coluna desejada, abrir o editor da PickList e colocar as opes para aquela coluna. Assim, ao editar a coluna, abre-se a combobox.

Enviando mensagens HTML com imagens anexadas


Para se enviar uma mensagem html com os componentes Indy basta usar a propriedade ContentType de TIdMessage, configurando-a para text/html. Quando se quer mandar uma imagem nesta mensagem, uma maneira que pode ser usada colocar um link externo para ela: <img src="http://www.meusite.com/imagem.jpg">. Isto, alm de gerar um trfego desnecessrio no site, tende a ser desabilitado nos mailers, por ser um risco de segurana. Outra maneira embutir a imagem na mensagem como anexo e ligar o link a ela. Porm, como fazer isso ? Qual o link para a mensagem anexa ? Este link dado pelo Content-Id da imagem. Ao chamar o link para a imagem, faz-se algo como <img src="cid:minhaimagem">. minhaimagem o content-id da imagem, que definido quando colocamos a mensagem como anexo:

54

Imagem := TIdAttachment.Create(MessageParts, 'c:\windows\cafezinho.bmp'); // Aqui estou preenchendo o Content-ID Imagem.ExtraHeaders.Values['Content-ID'] := '<minhaimagem>'; Imagem.ContentType := 'image/jpeg'; Desta maneira, a imagem vai na mensagem e aberta sem problemas. Ao executar o programa da postagem, notamos um problema: a mensagem enviada corretamente, com a imagem em anexo, porm o html no gerado corretamente, aparecendo como texto normal. Analisando o cabealho da mensagem, vemos que o content-type da mensagem est como text/plain, mesmo tendo especificado text/html. O que ocorre que a mensagem, quando tem um anexo, transformada em multipart e isso faz que o contedo seja enviado como texto. Uma soluo para isto enviar o texto da mensagem como uma parte de texto, com contedo html. Isto feito criando-se uma varivel do tipo TIdText, que ser preenchida com o texto que queremos. Na realidade, iremos criar duas partes de texto na mensagem: uma normal, no html, que ser mostrada em leitores de e-mail no html, e outra html. Isto feito da seguinte maneira:

// configura para multipart ContentType := 'Multipart/Alternative'; // parte de texto normal idText := TIdText.Create(MessageParts,nil); idText.ContentType := 'text/plain'; idText.Body.Add('Esta parte texto puro e no mostra a imagem'); // parte de texto html idText := TIdText.Create(MessageParts,nil); idText.ContentType := 'text/html'; idText.Body.Text := '<html><body>Esta mensagem html tem '+ 'imagens<br />'+ 'A imagem est como anexo, e no est fora da mensagem:<br />'+ '<img src="cid:MinhaImagem"></body></html>'; // Configura anexos Imagem := TIdAttachment.Create(MessageParts, 'c:\windows\cafezinho.bmp'); Imagem.ExtraHeaders.Values['Content-ID'] := '<minhaimagem>'; Imagem.ContentType := 'image/jpeg'; Desta maneira, temos a mensagem com anexos formatada corretamente, podendo ser vista tanto em leitores texto como html.

55

Mostrando dicas balo para caixas de edio wm WindowsXP


Para mostrar uma dica balo para uma caixa de edio, devemos mandar uma mensagem EM_SHOWBALLOONTIP para ela. O texto, ttulo e cone da dica so mandados prenchendo um record do tipo TEditBalloonTip, definida como: TEditBalloonTip = packed record cbStruct: DWORD ; pszTitle: LPCWSTR ; pszText: LPCWSTR; ttiIcon: Integer; end; Uma vez preenchido record, passamos como o terceiro parmetro para a funo SendMessageW: procedure ShowBalloonTip(Window : HWnd; Texto, Titulo : PWideChar;Tipo : Integer); var EditBalloonTip : TEditBalloonTip; begin EditBalloonTip.cbStruct := SizeOf(TEditBalloonTip); EditBalloonTip.pszText := Texto; EditBalloonTip.pszTitle := Titulo; EditBalloonTip.ttiIcon := Tipo; SendMessageW(Window, EM_SHOWBALLOONTIP, 0, Integer(@EditBalloonTip)); end; O cdigo completo das funes que mostram e escondem a dica o seguinte: TEditBalloonTip = packed record cbStruct: DWORD ; pszTitle: LPCWSTR ; pszText: LPCWSTR; ttiIcon: Integer; end; const ECM_FIRST = $1500; EM_SHOWBALLOONTIP = (ECM_FIRST + 3); EM_HIDEBALLOONTIP = (ECM_FIRST + 4); TTI_NONE = 0; TTI_INFO = 1; TTI_WARNING = 2; TTI_ERROR = 3; var Form1: TForm1; implementation 56

{$R *.dfm}

procedure ShowBalloonTip(Window : HWnd; Texto, Titulo : PWideChar;Tipo : Integer); var EditBalloonTip : TEditBalloonTip; begin EditBalloonTip.cbStruct := SizeOf(TEditBalloonTip); EditBalloonTip.pszText := Texto; EditBalloonTip.pszTitle := Titulo; EditBalloonTip.ttiIcon := Tipo; SendMessageW(Window, EM_SHOWBALLOONTIP, 0, Integer(@EditBalloonTip)); end; procedure HideBalloonTip(Window : HWnd); begin SendMessageW(Window, EM_HIDEBALLOONTIP, 0, 0) end; procedure TForm1.Button1Click(Sender: TObject); begin ShowBalloonTip(Edit1.Handle,'Texto a ser mostrado', 'Ttulo da janela',TTI_INFO); end; procedure TForm1.Button2Click(Sender: TObject); begin HideBalloonTip(Edit1.Handle); end; Nota: Esta dica s funciona com os estilos do XP ativados. Assim, voc precisa colocar um componente TXpManifest na sua Form.

CheckLisBox - Trocar a cor das linhas


Existe uma forma simples de fazer este tipo de trabalho. Inclua alguns itens no seu CheckListBox, v at a propriedade Style e altere para lbOwnerDrawVariable, agora v at ao evento OnDrawItem e inclua o cdigo abaixo: CheckListBox1.Canvas.FillRect(Rect); if not (odFocused in State) then begin if CheckListBox1.Checked[index] then begin CheckListBox1.Canvas.Font.Color := clRed; CheckListBox1.Canvas.Brush.Color := clWhite; end

57

else begin CheckListBox1.Canvas.Font.Color := clBlack; CheckListBox1.Canvas.Brush.Color := clWhite; end; end; CheckListBox1.Canvas.TextOut(Rect.Left+2,Rect.Top,CheckListBox1.Items.Strings[In dex]);

Windows - Verificar a impressora padro


implementation uses Printers; {$R *.dfm} function GetDefaultPrinter: string; var ResStr: array[0..255] of Char; begin GetProfileString('Windows', 'device', '', ResStr, 255); Result := StrPas(ResStr); end; procedure TForm1.Button1Click(Sender: TObject); begin Caption := GetDefaultPrinter; end;

RichEdit - Pesquisar um texto, posicionar sobre ele e mostrar ao usurio


No Windows XP somente utilizar o SelStart no mostrou a linha encontrada ao usurio, foi necessrio utilizar o perform para mostrar a linha onde est o texto encontrado. procedure TForm1.SpeedButton1Click(Sender: TObject); var nPos, Linha: Integer; begin With RichEdit1 do begin SetFocus; { Pega a linha atual } Linha := Perform(EM_LINEFROMCHAR, SelStart, 0); nPos := FindText(Edit1.Text, 0, Length(RichEdit1.Text), []); { Posiciona o cursor sobre o texto encontrado na pesquisa } 58

SelStart := nPos; SelLength := Length(Edit1.Text); { Pega a quantidade de linhas que separa a ltima linha para essa nova linha posicionada } Linha := Perform(EM_LINEFROMCHAR, SelStart, 0)-Linha; { Visualiza a nova linha } Perform(EM_LINESCROLL, Linha, Linha); end; end;

ActiveControl - Envia um valor para Edit que estiver em foco


Verifica se o componente que est com o foco da classe do TEdit, se for envia um Texto para esse componente. procedure TForm1.SpeedButton1Click(Sender: TObject); begin if (ActiveControl is TEdit) then (ActiveControl as TEdit).Text := 'Teste'; end; Funciona para outros componentes, trocando a propriedade Text utilizado neste exemplo pela propriedade do outro componente.

Registro do Windows - Retorna portas seriais


procedure TForm1.Button1Click(Sender: TObject); var Reg: TRegistry; ts : TStrings; i : Integer; begin Reg := TRegistry.Create; Reg.RootKey := HKEY_LOCAL_MACHINE; Reg.OpenKey('HARDWARE\DEVICEMAP\SERIALCOMM', False); ts := TStringList.Create; Reg.GetValueNames(ts); for i := 0 to ts.Count -1 do ListBox1.Items.Add(Reg.ReadString(ts.Strings[i])); ts.Free; Reg.CloseKey; Reg.Free; end;

59

Verifica se um programa est aberto, caso contrrio, abre


Existe uma forma que pegando o nome da janela. Veja o exemplo abaixo que trabalha com a calculadora do Windows. procedure TForm1.Button1Click(Sender: TObject); var TheWindow: HWND; begin {find a handle to the Windows Explorer window} TheWindow:=FindWindow(nil,'Calculadora'); if TheWindow <> 0 then // Chama calculadora se j estiver carregada SetForegroundWindow(TheWindow) else // Carrega calculadora se estiver fechada ShellExecute(Handle, 'Open', 'Calc.exe', nil, 'c:\windows', end;

sw_shownormal);

Funo que verifica a velocidade do processador


function GetCPUSpeed: Double; const DelayTime = 500; var TimerHi, TimerLo: DWORD; PriorityClass, Priority: Integer; begin PriorityClass := GetPriorityClass(GetCurrentProcess); Priority := GetThreadPriority(GetCurrentThread); SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS); SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL); Sleep(10); asm dw 310Fh // rdtsc mov TimerLo, eax mov TimerHi, edx end; Sleep(DelayTime); asm dw 310Fh // rdtsc sub eax, TimerLo sbb edx, TimerHi mov TimerLo, eax mov TimerHi, edx end; SetThreadPriority(GetCurrentThread, Priority); SetPriorityClass(GetCurrentProcess, PriorityClass); 60

Result := TimerLo / (1000.0 * DelayTime); end; procedure TForm1.Timer1Timer(Sender: TObject); var CPUSpeed: Double; begin CPUSpeed := GetCPUSpeed; Label1.Caption := FormatFloat('0.00 MHz', CPUSpeed); end;

DBGrid - Ao clicar no campo no DBGrid ordenar os registros


Temos na tabela 04 campos: Empresa, Inscricao, Contador e Telefone No Evento OnTitleClick do dbgrid: var campo:string; begin campo:=column.fieldname; application.processmessages; query1.sql.clear; query1.sql.add('select * from Contribuinte order by '+campo); if not query1.Prepared then query1.Prepare; query1.Open; if campo='Nome' then label12.caption:='Consulta por ordem de Empresa'; // campo Empresa if campo='Inscricao' then label12.caption:='Consulta por ordem de Inscrio'; // campo Inscrio if campo='Contador' then label12.caption:='Consulta por ordem de Contador'; // campo Contador if campo='Telefone' then label12.caption:='Consulta por ordem de Telefone' // campo Telefone // Ao clicar em cada campo os registros so ordenados

Criando um lista Push and Pop em Delphi


Veja como implementar uma lista Push and Pop (Last In First Out) usando Array e TList. Demonstra ainda a tcnica do uso de Arrays em um TList.

61

Type TInfo = Record Nome : String; End; PInfo = ^TInfo; //============================================================= ================= // Coloca itens na lista //============================================================= ================= Procedure PushItem(List:TList; Nome:String); Var Info : PInfo; Begin New(Info); Info.Nome := Nome; List.Add(Info); End; //============================================================= ================= // Retira o ultimo item da lista //============================================================= ================= Procedure PopItem(List:TList; Var Nome:String); Begin If List.Count>0 then Begin Nome := PInfo(List[List.Count-1]).Nome; Dispose(PInfo(List[List.Count-1])); List.Delete(List.Count-1); End Else Begin Nome := ''; End; End; //============================================================= ================= // Retorna um item a partir de sua posicao //============================================================= ================= Procedure GetItem(List:TList; Var Info:PInfo; RecordNumber:Integer); Begin Info := PInfo(List[RecordNumber]); End; //============================================================= ================= // Cria o objeto de lista //============================================================= =================

62

Procedure CreateList(Var List:TList); Begin If not Assigned(List) then List := TList.Create Else List.Clear; End; //============================================================= ================= // Destroi a lista e remove os ponteiros //============================================================= ================= Procedure DestroyList(List:TList); Var I : Integer; Begin for i := 0 to List.Count-1 do Dispose(PInfo(List[i])); List.Free; End; //============================================================= ================= // Exemplo de Uso da lista //============================================================= ================= procedure TForm1.Button1Click(Sender: TObject); Var List : TList; i : Integer; Info : PInfo; Nome : String; begin CreateList(List); // Empilha itens PushItem(List,'Adenilton'); PushItem(List,'Ana'); PushItem(List,'Roberto'); PushItem(List,'Marta'); PushItem(List,'Silvia'); PushItem(List,'Pedro'); // Remove itens comecando pelo ultimo inserido PopItem(List,Nome); ShowMessage('Retirando '+Nome+' da lista '); PopItem(List,Nome); ShowMessage('Retirando '+Nome+' da lista '); PopItem(List,Nome); ShowMessage('Retirando '+Nome+' da lista ');

63

PushItem(List,'Carlos'); // Mostra os demais Itens de baixo para cima for i := List.Count-1 downto 0 do Begin GetItem(List,Info,i); ShowMessage(Info.Nome); End; // Destroi a lista DestroyList(List); end;

Rave Report - Imprimindo cdigo de barras em modo de programao


// Uses rpBars procedure TForm1.RvSystem1Print(Sender: TObject); begin With TRPBars2of5.Create(Sender as TBaseReport) do Begin BarHeight := 1.5; BarWidth := 0.065; WideFactor := BarWidth; Text := '27596000000000000000902900000124000341010150'; PrintXY(1,1); Free; end; end;

Gerar planilhas no Excel atravs de uma Query


Procedimento que recebe um Query e gera um planilha do Excel. procedure GerarExcel(Consulta:TQuery); var coluna, linha: integer; excel: variant; valor: string; begin try excel:=CreateOleObject('Excel.Application'); excel.Workbooks.add(1); except Application.MessageBox ('Verso do Ms-Excel'+

64

'Incompatvel','Erro',MB_OK+MB_ICONEXCLAMATION); end; Consulta.First; try for linha:=0 to Consulta.RecordCount-1 do begin for coluna:=1 to Consulta.FieldCount do // eliminei a coluna 0 da relao do Excel begin valor:= Consulta.Fields[coluna-1].AsString; excel.cells [linha+2,coluna]:=valor; end; Consulta.Next; end; for coluna:=1 to Consulta.FieldCount do // eliminei a coluna 0 da relao do Excel begin valor:= Consulta.Fields[coluna-1].DisplayLabel; excel.cells[1,coluna]:=valor; end; excel.columns.AutoFit; // esta linha para fazer com que o Excel dimencione as clulas adequadamente. excel.visible:=true; except Application.MessageBox ('Aconteceu um erro desconhecido durante a converso'+ 'da tabela para o Ms-Excel','Erro',MB_OK+MB_ICONEXCLAMATION); end; end;

Rave Report - Somar valores


Existe um componente chamado "CalcTotal" o qual faz praticamente as mesmas operaes que o QRExpr. Para utilizar, faa o seguinte: 1. Adicione um CalcOp em sua banda de totalizao; 2. Configure suas propriedades: - DataView, apontando para seu DataView - DataField, campo a ser totalizado - Controller, banda "detalhe" - DestPIVar, uma varivel criada na propriedade PIVars da "page" - CalcType, ctSum 3. Adicione um componente DataText e configure sua propriedade DataField apontando para a varivel que recebeu o valor no item acima. Com isso, o ser efetuada a soma do campo e apresentado no referido DataText.

65

Colorir componente focado - Preservando sua cor original


public procedure ColorControl(Sender: TObject); end;

type TControlaCor = Record Objeto: TComponent; Cor: TColor; end;

var Form1: TForm1; ControlaCor: TControlaCor;

implementation {$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject); begin Screen.OnActiveControlChange := ColorControl; end;

{Procedure que altera a cor} procedure TForm1.ColorControl(Sender: TObject); begin if Screen.ActiveControl is TForm then Exit; if (ControlaCor.Objeto = Nil) or (not TComboBox(ControlaCor.Objeto).Showing) then begin ControlaCor.Objeto := Screen.ActiveControl; ControlaCor.Cor := TComboBox(Screen.ActiveControl).Color; end; With Screen.ActiveForm do begin TComboBox(ControlaCor.Objeto).Color := ControlaCor.Cor; ControlaCor.Objeto := Screen.ActiveControl; ControlaCor.Cor := TComboBox(Screen.ActiveControl).Color; TComboBox(Screen.ActiveControl).Color := clInfoBk end; end; 66

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin Screen.OnActiveControlChange := Nil; end;

ActiveControl - Envia valor para Edit que tiver em foco


Verifica se o componente que est com o foco da classe do TEdit, se for envia um Texto para esse componente. procedure TForm1.SpeedButton1Click(Sender: TObject); begin if (ActiveControl is TEdit) then (ActiveControl as TEdit).Text := 'Teste'; end; Funciona para outros componentes, trocando a propriedade Text utilizado neste exemplo pela propriedade do outro componente.

TFields - Adiciona Fields no Fields Editors em tempo de execuo


{ Primeiramente temos que ter declarado as variveis onde sero criado os Objetos Fields. } public Table1Name: TStringField; Table1Capital: TStringField; Table1Continent: TStringField; Table1Area: TFloatField; Table1Population: TFloatField; { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} { Agora criamos os Objetos e configuramos suas propriedades } procedure TForm1.Button1Click(Sender: TObject); begin Table1.Close; Button1.Enabled := False; Button2.Enabled := True; 67

Table1Name := TStringField.Create(Table1); Table1Name.FieldName := 'Name'; Table1Name.DataSet := Table1; Table1Name.FieldKind := fkData; Table1Name.Size := 24; Table1Capital := TStringField.Create(Table1); Table1Capital.FieldName := 'Capital'; Table1Capital.DataSet := Table1; Table1Capital.FieldKind := fkData; Table1Capital.Size := 24; Table1Continent := TStringField.Create(Table1); Table1Continent.FieldName := 'Continent'; Table1Continent.DataSet := Table1; Table1Continent.FieldKind := fkData; Table1Continent.Size := 24; Table1Area := TFloatField.Create(Table1); Table1Area.FieldName := 'Area'; Table1Area.DataSet := Table1; Table1Population := TFloatField.Create(Table1); Table1Population.FieldName:= 'Population'; Table1Population.DataSet := Table1; Table1.Open; end; { Aqui destruimos todos os objetos Fields criados } procedure TForm1.Button2Click(Sender: TObject); begin Table1.Close; Button1.Enabled := True; Button2.Enabled := False; Table1Name.Free; Table1Capital.Free; Table1Continent.Free; Table1Area.Free; Table1Population.Free; Table1.Open; end; { Um simples exemplo de como configurar a mscara via programao } procedure TForm1.Button3Click(Sender: TObject); begin try Table1.Close; Table1Area.DisplayFormat := '###,###,##0'; Table1Population.DisplayFormat := '###,###,##0';

68

Table1.Open; except ShowMessage('Adicione os campos...') end; end;

ListBox - Colorir
procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); begin if StrToInt(ListBox1.Items[Index]) > 5 then begin ListBox1.Canvas.Font.Color := clBlue; ListBox1.Canvas.Font.Style := [fsBold]; ListBox1.Canvas.Brush.Color := clYellow; end; ListBox1.Canvas.FillRect(Rect); ListBox1.Canvas.TextOut(Rect.Left, Rect.Top, Listbox1.Items[Index]); end; *** Alterar a propriedade Style para onDrawVariable

Associando um extenso de arquivo a um executvel


{ necessrio declarar a unit abaixo } Registry procedure CriaChave(const Chave, Nome, Valor: string); var K: TRegistry; begin K := TRegistry.Create; try K.RootKey := HKEY_CLASSES_ROOT; K.OpenKey(Chave, true); K.WriteString(Nome, Valor); finally K.Free; end; end;

procedure CriaAssociacao(const NomeDoc, NomeApp, NomeEXE, NomeIcone, Ext: string); begin CriaChave(NomeDoc, , NomeApp); 69

CriaChave(Ext, , NomeDoc); CriaChave(NomeDoc+\shell\open\command,,NomeEXE); CriaChave(NomeDoc + \DefaultIcon,, NomeIcone); end;

procedure TForm1.Button1Click(Sender: TObject); begin Button1.Enabled := false; Try // EdDoc.Text = Nome do arquivo Exemplo: Doc01 // EdNome.Text = Nome do programa Exemplo:NotePad // EdExe.Text = Executvel Exemplo: // c:\windows\notepad.exe %1 // EdIcone.Text = cone Exemplo: // c:\windows\notepad.exe // EdExt.Text = Extenso Exemplo: .xxx // CriaAssociacao(EdDoc.Text, EdNome.Text, // EdEXE.Text, EdIcone.Text, EdExt.Text); finally Button1.Enabled := true; end; end;

Retornar as contas de E-Mail


Nesta dica iremos demonstrar como obter as contas de email registradas na Mquina, verificando as informaes armazenadas do registrador do Windows. Neste exemplo iremos utilizar um componente TListBox e um TButton... implementation uses Registry; {$R *.DFM} { Evento OnShow do Formulrio } procedure TForm1.FormShow(Sender: TObject); var Reg: TRegistry; begin Reg := TRegistry.Create; try Reg.RootKey := HKEY_CURRENT_USER; Reg.OpenKey(\Software\Microsoft\Internet Account Manager\Accounts, False); Reg.GetKeyNames(ListBox1.Items); finally

70

Reg.CloseKey; Reg.Free; end; end; { evento OnClick do TButton } procedure TForm1.Button1Click(Sender: TObject); var Reg: TRegistry; sKey : String; begin if ListBox1.ItemIndex = -1 then Exit; Reg := TRegistry.Create; try Reg.RootKey := HKEY_CURRENT_USER; sKey := \Software\Microsoft\Internet Account Manager\Accounts\; sKey := sKey + ListBox1.Items[ListBox1.ItemIndex]; Reg.OpenKey(sKey, False); if Reg.ValueExists(SMTP Server) then ShowMessage( O SMTP da conta selecionada :+#13+ Reg.ReadString(SMTP Server) ) else ShowMessage(SMTP no existe para esta conta); finally Reg.CloseKey; Reg.Free; end; end;

HKEY, Registry
implementation uses registry;

{ Atribui um informacao para o Registry } procedure TForm1.BitBtn2Click(Sender: TObject); Var Reg : TRegistry; begin Reg := Tregistry.Create; With TRegistry.Create do begin RootKey:= HKEY_USERS; OpenKey(RamosInformatica\curso\teste', True); WriteString('Teste_Reg1','Teste Teste'); Free; end;

71

end; { Recupera um valor do Registry } procedure TForm1.BitBtn7Click(Sender: TObject); Var Reg : TRegistry; Value : string; begin Reg := Tregistry.Create; With TRegistry.Create do begin RootKey:= HKEY_USERS; OpenKey('Ramosinformatica\curso\teste', True); Caption := ReadString('Teste_Reg1'); Free; end; end;

Criar e ler chave


procedure TForm1.Button1Click(Sender: TObject); var Reg: TRegistry; S: String; begin Reg := TRegistry.Create; Reg.RootKey := HKey_Classes_Root; if Reg.Openkey('RamosDaInformatica',True) then { Cria ou Abre a chave principal } begin Reg.CreateKey('Empresa'); { Cria Sub-Chave dentro de RamosDaInformatica} Reg.CreateKey('Chave'); { Cria Sub-Chave dentro de RamosDaInformatica} ShowMessage('Chave Criada...') end else ShowMessage('Erro na criao da Chave...'); // S := Reg.ReadString('(Padro)'); Reg.free; end;

//L informaes da Empresa cadastrado na mquina procedure TForm1.Button1Click(Sender: TObject); var Info: TRegDataInfo; Reg: TRegistry; begin Reg := TRegistry.Create; Reg.RootKey := HKEY_LOCAL_MACHINE;

72

if not Reg.OpenKey('\SOFTWARE\Microsoft\Windows\CurrentVersion', FALSE) then Reg.GetDataInfo('RegisteredOrganization', Info); Label1.Caption := 'Empresa...: ' + Reg.ReadString('RegisteredOrganization'); Label2.Caption := 'Usuario...: ' + Reg.ReadString('RegisteredOwner'); end;

Retornar lista de hardware via registry


var Reg: TRegistry; Chs, tmp: TStringList; i, t: integer; begin Chs := TStringList.Create; tmp := TStringList.Create; Reg := TRegistry.Create; Reg.RootKey := HKEY_LOCAL_MACHINE; Reg.OpenKey('hardware\devicemap\', false); Reg.GetKeyNames(Chs); for i := 0 to Chs.Count -1 do begin Reg.Free; Reg := TRegistry.Create; Reg.RootKey := HKEY_LOCAL_MACHINE; Reg.OpenKey('hardware\devicemap\' + Chs[i], false); Reg.GetKeyNames(tmp); if tmp.Count = 0 then Reg.GetValueNames(tmp); Memo1.Lines.Add('---> ' + Chs[i]); Memo1.Lines.Add(tmp.Text); Memo1.Lines.Add('------------------------'); end; Chs.Free; tmp.Free; Reg.CloseKey; Reg.Free; end;

Verificar se um valor existe dentro de uma Chave


implementation uses Registry; {$R *.DFM} 73

procedure TForm1.Button1Click(Sender: TObject); var Reg: TRegistry; begin Reg := TRegistry.Create; Reg.RootKey := HKEY_LOCAL_MACHINE; Reg.OpenKey('\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo\', False); if Reg.ValueExists('DSQUERY') then Showmessage('Existe!'); end;

Quick Report - Selecionando itens do ComboBox para PapeSize


procedure TForm1.ComboBox1Click(Sender: TObject); var i : integer; begin //Atribui o item selecionado no ComboBox a prop. PaperSize For i := 1 to ComboBox1.Items.Count-1 do begin if ComboBox1.Items[ComboBox1.ItemIndex] = 'Letter' then QuickRep1.Page.PaperSize := Letter else if ComboBox1.Items[ComboBox1.ItemIndex] = 'Custom' then QuickRep1.Page.PaperSize := Custom else if ComboBox1.Items[ComboBox1.ItemIndex] = 'A4' then QuickRep1.Page.PaperSize := A4; end; end;

procedure TForm1.FormCreate(Sender: TObject); begin // Atribui os nomes ao ComboBox ComboBox1.Items.ADD('Letter'); ComboBox1.Items.ADD('Custom'); ComboBox1.Items.ADD('A4'); end;

ListBox - Pesquisa incremental


Para fazer uma pesquisa incremental no ListBox voc ir precisar tambm de um componente Edit. Inclua o cdigo abaixo no evento OnChange do componente Edit. 74

procedure TForm1.Edit1Change(Sender: TObject); var S: Array[0 ..255] of char; begin StrPCopy(S, Edit1.Text); with ListBox1 do ItemIndex := Perform(LB_SELECTSTRING, 0, LongInt(@S)); if (ListBox1.ItemIndex < 0) or (ListBox1.Items[ListBox1.ItemIndex] <> Edit1.Text) then ListBox1.ItemIndex := -1; end;

Acertar data e hora com o servidor


No Windows NT/2000/XP existem APIs especficas para obter a data e hora de um Servidor, porm com Windows 9x no encontramos APIs com o mesmo efeito, porm possvel implementar via um utilitrio DOS e com isso acertar a data e hora de uma mquina com outra da rede. procedure AcertaHora(ServerName: String); begin WinExec(PChar(net time + ServerName + /set /yes), 0); end;

QuickReport - Access Violation no Windows 2000 e XP


Ocorre devido ao tamanho do caminho do diretrio temporrio do Windows. V em Control Panel -> System -> Clique na aba Advanced -> Clique no boto Environment Variables. Altere o caminho da varivel TMP para um caminho menor, como por exemplo c:\temp. Confirme se este diretrio j est criado.

DBGrid - Alterar as cores do ttulo em tempo de execuo.


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;

75

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;

Testa se a impressora est funcionando


function PrinterOK(Lpt: Word): Boolean; const PrnStInt : Byte = $17; StRq : Byte = $02; var nResult : Byte; begin asm mov ah,StRq; mov dx,Lpt; Int $17; mov nResult,ah; end; Result := (nResult and $80) = $80; end; Modo de utilizao: if PrinterOK(0) then ShowMessage('Impressora OK') else ShowMessage('Impressora sem papel ou desligada'); O parmetro da funo equivale ao nmero da porta da impressora. 0- LPT1 1- LPT2

Como implementar um AutoComplete num Edit comum


Esta dica vou publicar sem traduo, primeiro porque no original bem melhor e segundo para no haver erros.

76

// To add auto-complete capability to a TEdit component // 1) Declare a global TStringlist object // 2) Create it on the form create event // 3) Free it on the form destroy event // 4) Add new entry to it on the TEdit exit event // 5) Do the auto-complete on the TEdit keyUp event // 6) Add a TCheckbox control for enable/disable // If desired, initialize the list from a database, ini file etc. procedure TForm1.FormCreate(Sender: TObject); begin listValues := TStringList.create; listValues.sorted := true; listValues.Duplicates := dupIgnore; end; procedure TForm1.FormDestroy(Sender: TObject); begin listValues.free; end; procedure TForm1.edtListExit(Sender: TObject); begin listValues.add(edtList.text); end; procedure TForm1.edtListKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); var theText: string; i, p: integer; begin if not ckbxList.checked then exit; // User can enable/disable with edtList do case key of 8, 13, 46, 37..40: ; // No backspace, enter, delete, or arrows else begin // Search for unselected portion at start of text p := selStart; // cursor position theText := copy(text, 0, p); // Excludes searched portion // Match entered text portion for i := 0 to listValues.count-1 do begin // Keep case of listed item if pos(upperCase(theText), upperCase(listValues[i]))=1 then if compareText(theText, listValues[i]) < 0 then begin text := listValues[i]; selStart := p;

77

SelLength := length(text) - selStart; break; // Match found, so quit search end; end; // for end; // case end; // with end;

Como adicionar um CheckBox em um StringGrig


Esta uma maneira bem simples de adicionar um checkbox, ou qualquer outro objeto, num StringGrid Para fazer este exemplo, adicione TPanel, e um StringGrid,com 5 colunas e 4 linhas, no Painel .

procedure TForm1.CheckBox1Click(Sender: TObject); begin ShowMessage('Aqui'); end; procedure TForm1.FormCreate(Sender: TObject); begin StringGrid1.Cells[0,0] := 'Uma Maneira'; StringGrid1.Cells[1,0] := 'Simples'; StringGrid1.Cells[2,0] := 'Para'; StringGrid1.Cells[3,0] := 'Fazer'; StringGrid1.Cells[4,0] := 'Marcar'; AdicionarCheckBoxes; //rotina que adiciona os Check end; procedure TForm1.AdicionarCheckBoxes; var i: Integer; NovoCheckBox: TCheckBox; begin limpaBuffer; // bom no esquecer de limpar controles no utilizados for i := 1 to 4 do begin StringGrid1.Cells[0,i] := 'a'; StringGrid1.Cells[1,i] := 'b'; StringGrid1.Cells[2,i] := 'c'; StringGrid1.Cells[3,i] := 'd'; NovoCheckBox := TCheckBox.Create(Application); NovoCheckBox.Width := 0; NovoCheckBox.Visible := false; NovoCheckBox.Caption := 'OK'; NovoCheckBox.Color := clWindow;

78

NovoCheckBox.Tag := i; NovoCheckBox.OnClick := CheckBox1.OnClick; //Associar um evento OnClick j existente para o Novo CheckBox NovoCheckBox.Parent := Panel1; StringGrid1.Objects[4,i] := NovoCheckBox; StringGrid1.RowCount := i; end; AlinhaCheck; // agora vamos alinhar o check na celular end; Procedure TForm1.Limpabuffer; var NovoCheckBox: TCheckBox; i: Integer; begin for i := 1 to StringGrid1.RowCount do begin NovoCheckBox := (StringGrid1.Objects[4,i] as TCheckBox); if NovoCheckBox <> nil then // o objeto deve existir para poder ser destrudo begin NovoCheckBox.Visible := false; StringGrid1.Objects[4,i] := nil; end; end; end; Procedure TForm1.AlinhaCheck; var NovoCheckBox: TCheckBox; Rect: TRect; i: Integer; begin for i := 1 to StringGrid1.RowCount do begin NovoCheckBox := (StringGrid1.Objects[4,i] as TCheckBox); if NovoCheckBox <> nil then begin Rect := StringGrid1.CellRect(4,i); // aqui descobrimos a posio da celula para utilizarmos no check NovoCheckBox.Left := StringGrid1.Left + Rect.Left+2; NovoCheckBox.Top := StringGrid1.Top + Rect.Top+2; NovoCheckBox.Width := Rect.Right - Rect.Left; NovoCheckBox.Height := Rect.Bottom - Rect.Top; NovoCheckBox.Visible := True; end; end; end; procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);

79

begin if not (gdFixed in State) then AlinhaCheck; end;

Abreviao automtica de nomes


Abrevia nomes extensos pegando a primeira letra do nome e acrescentando ponto no final. timo para impresso de etiquetas. function AbreviaNome(Nome: String): String; var Nomes: array[1..20] of string; i, TotalNomes: Integer; begin Nome := Trim(Nome); Result := Nome; {Insere um espao para garantir que todas as letras sejam testadas} Nome := Nome + #32; {Pega a posio do primeiro espao} i := Pos(#32, Nome); if i > 0 then begin TotalNomes := 0; {Separa todos os nomes} while i > 0 do begin Inc(TotalNomes); Nomes[TotalNomes] := Copy(Nome, 1, i - 1); Delete(Nome, 1, i); i := Pos(#32, Nome); end; if TotalNomes > 2 then begin {Abreviar a partir do segundo nome, exceto o ltimo.} for i := 2 to TotalNomes - 1 do begin {Contm mais de 3 letras? (ignorar de, da, das, do, dos, etc.)} if Length(Nomes[i]) > 3 then {Pega apenas a primeira letra do nome e coloca um ponto aps.} Nomes[i] := Nomes[i][1] + '.'; end; Result := ''; for i := 1 to TotalNomes do Result := Result + Trim(Nomes[i]) + #32; Result := Trim(Result); end;

80

end; end;

Compilando a aplicao pelo MS-DOS


Apenas a ttulo de curiosidade, este texto explica como criar um programa em Delphi a partir do zero, usando somente o compilador do Delphi utilizado na linha de comando (dcc32) e o prompt do dos. Para fazer o programa, voc precisar criar dois arquivos : teste.pas (o programa propriamente dito) e teste.dfm (definicoes do formulario). Primeiro, crie o programa teste.pas e teste.dfm. ARQUIVO: teste.pas ------------------------------------------------------program teste; uses windows,sysutils,classes,forms,stdctrls; type tfrm = class(tform) button1 : tbutton; constructor create(aowner:tcomponent);override; procedure button1click(sender:tobject); end; constructor tfrm.create(aowner:tcomponent); begin inherited create(aowner); left:=(screen.width div 2)-width div 2; top:=(screen.height div 2)-height div 2; end; procedure tfrm.button1click(sender:tobject); begin if button1.caption = 'Clique' then button1.caption:='Aperte' else button1.caption:='Clique'; end; {$R *.dfm} var frm : tfrm; begin application.initialize; application.createform(tfrm,frm); application.run; end. -------------------------------------------------------

81

ARQUIVO: teste.dfm ------------------------------------------------------object frm: tfrm width = 350 height = 290 caption = 'programa teste' object button1: tbutton caption = 'Clique' left = 20 top = 20 width = 100 height = 30 onclick = button1click end end ------------------------------------------------------Pense no arquivo .dfm como se fosse a janela de propriedades do objeto. Caso voc queira alterar cor, alinhamento, etc, etc e etc, s colocar no .dfm. Para compilar, simplesmente digite na linha do prompt : dcc32 teste Pronto. Voc ter, no mesmo diretrio, um arquivo chamado teste.exe, que nada mais que o seu projeto compilado.

Colorao gradiente no Form


procedure TForm1.FormPaint(Sender: TObject); var altura, coluna: Word; begin altura := (ClientHeight + 255) div 256; for coluna := 0 to 255 do with Canvas do begin Brush.Color := RGB(coluna, 0, 0); { Modifique para obter cores diferentes } FillRect(Rect(0, coluna * altura, ClientWidth, (coluna + 1) * altura)) ; end; end; procedure TForm1.FormResize(Sender: TObject); begin Invalidate; end;

82

Usar perfeitamente o LookupComboBox


O componente DBLookupComboBox utilizado para seleciona registros de uma tabela e gravar em outra tabela. As propriedades necessrias para a utilizao so: DataSource - Ligar a DataSource da Tabela ao qual vai receber o valor do registro selecionado; DataField - Ligar o campo de ligao entre as duas tabelas, ao qual vai receber o valor do registro selecionado; ListSource - Ligar a DataSource da Tabela ao qual vai Ter o registro selecionado; ListField - Ligar o campo que ser listado quando o usurio abrir a janela para seleo do registro; KeyField - Ligar o campo de ligao entre as duas tabelas, ao qual ter o seu valor enviado para gravao. O campo de ligao entre as duas tabelas pode ser um campo cdigo, pois este campo que manter os valores iguais entre as duas tabelas.

Como colocar um codigo para que a aplicacao feche apos XX segundos sem atividades no teclado ou sem cliques do mouse.
Ol Ramos, enviei uma duvida no forum do Ramos e nao esperava ter tido tanta discussao, mas depois que consegui a resposta ninguem mais comentou sobre o assunto. De qualquer forma apesar de ter postado no forum a resposta que recebi de outro camarada, abaixo segue de novo um exemplo de como colocar um codigo para que a aplicacao feche apos XX segundos sem atividades no teclado ou sem cliques do mouse. Este codigo deve ser colocado no Form principal e fazer os devidos ajustes. Nao esquecer de colocar o timer. Esta dica foi enviada por Cristiano Menusi- Oeste - SC e ele tambem havia encontrado na Net

unit Unit1; interface

83

uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls; type TForm1 = class(TForm) Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); private procedure AppIdle(Sender: TObject; var Done: Boolean); procedure AppMessage(var Msg: TMsg; var Handled: Boolean); public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} { TForm1 } procedure TForm1.AppIdle(Sender: TObject; var Done: Boolean); begin Timer1.Enabled := True; end; procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean); begin Case Msg.message of WM_LBUTTONDOWN,WM_RBUTTONDOWN,WM_KEYDOWN :Timer1.Enabled := False; end; end; procedure TForm1.FormCreate(Sender: TObject); begin Application.OnMessage := AppMessage; Application.OnIdle := AppIdle; end; procedure TForm1.Timer1Timer(Sender: TObject); begin Application.Terminate; end;

84

Escondendo a barra de tarefas do Windows


var Jan: HWnd; begin Jan:= FindWindow(Nil,'Nome_do_projeto'); if Jan <> 0 then ShowWindow(Jan,SW_Hide); end;

Pega todos os erros do Sistema, captura tela do erro, grava em arquivo e envia por e-mail
Como montar uma rotina para pegar todos os erros do sistema e capturar tela do erro e gravar em arquivo para futura inspecao ou envio por e-mail. Coloque esta rotina no menu principal de seu sistema. unit Form_Menu; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Menus, DB, ComCtrls, ExtCtrls, StdCtrls,Buttons, Mask, DBTables, DBIPROCS, DBITypes, DBIErrs, Gauges, ImgList, ToolWin, jpeg, ExtDlgs; type TFrm_Menu = class(TForm) MainMenu1: TMainMenu; PRIVATE { Private declarations } Procedure ManipulaExcecoes(Sender: TObject; E: Exception); public { Public declarations } end; var Frm_Menu: TFrm_Menu; implementation //------------------------------------// //...Rotina de manipulaco de erros // //------------------------------------//

85

Procedure TFrm_Menu.ManipulaExcecoes(Sender: TObject; E: Exception); Var BitMap : TBitmap; Begin //...Captura e salva a tela atual do erro. BitMap := TBitmap.Create; BitMap := CaptureScreenRect(Bounds(0,0,Screen.Width,Screen.Height)); BitMap.SaveToFile(ExtractFilePath(Application.ExeName)+'erro.bmp') ; BitMap.Free; //...Messagem de erro do sistema MessageDlg(E.Message + #13#13 +'Suporte tcnico:'#13 +'aceinfo@starknet.com.br',mtError, [mbOK], 0); end; {$R *.DFM} procedure TFrm_Menu.FormCreate(Sender: TObject); Begin Application.OnException := ManipulaExcecoes; end; End.

Detectando o tipo de Conexo com a internet


uses Wininet function ConnectionKind: Boolean; var flags: DWORD; begin Result := InternetGetConnectedState(@flags, 0); if Result then begin if (flags and INTERNET_CONNECTION_MODEM) = INTERNET_CONNECTION_MODEM then ShowMessage('Modem'); if (flags and INTERNET_CONNECTION_LAN) = INTERNET_CONNECTION_LAN then ShowMessage('LAN'); if (flags and INTERNET_CONNECTION_PROXY) = INTERNET_CONNECTION_PROXY then ShowMessage('Proxy'); if (flags and INTERNET_CONNECTION_MODEM_BUSY) = INTERNET_CONNECTION_MODEM_BUSY then

86

ShowMessage('Modem Busy'); end; end; procedure TForm1.Button1Click(Sender: TObject); begin ConnectionKind; end;

Funo de potenciao - Juros


Segue abaixo uma funo para efetuar a potenciao. til para compor formulas financeiras, como a de VP ("PV" valor presente) VF ("FV" valor futuro) Exemplo: Calcular o valor de um produto para o prazo de 30 dias com a taxa de juros de 5% ms. var i: Real; // taxa de juros valor: Real; // valor base para calculo do valor futuro. pz: Integer // prazo em dias begin i := 5//100; valor:= 1000.00 pz := 30 Result:= valor*( Pot( (1+i), (pz/30) ) //Resultado 1.050,00 end; no excel a Pot substituda pelo sinal ^ Ex. =E18*((1+C19)^(C20/30)) Function Pot( base, expoente: real ):real; // Potenciao begin { utiliza a funo de exponencial e de logaritmo } Result:= Exp((expoente * Ln( base ))); end; Dica: No amplie o nome da funo, pois as funes financeiras costumam ser bem extensas.

Para trocar as cores dos botoes do radiogroup


No Object Inspector na propriedade Font coloque a cor verde. procedure TForm1.RADIOGROUP1Click(Sender: TObject); Var i : Integer;

87

begin // Para trocar as cores dos botoes do RadioGroup for i := 0 to RADIOGROUP1.Items.Count-1 do begin TRadioButton(RADIOGROUP1.Controls[i]).Font.Color := clGreen; TRadioButton(RADIOGROUP1.Controls[i]).Font.Style := [fsBold]; end; TRadioButton(RADIOGROUP1.Controls[RADIOGROUP1.ItemIndex]).Font.Color := clRed; TRadioButton(RADIOGROUP1.Controls[RADIOGROUP1.ItemIndex]).Font.Style := [fsBold]; end;

Como criar uma figura do tipo marca d' gua


procedure TForm1.Button1Click(Sender: TObject); var X, Y : Integer; begin brush.style := bsClear; for y:=0 to image1.height-1 do for x:=0 to image1.width-1 do begin if (x mod 2)=(y mod 2) then image1.canvas.pixels[x,y]:=clWhite; end; end;

Criptografando Imagens
procedure cripto(const BMP: TBitmap; Key: Integer); var BytesPorScan: Integer; w, h: integer; p: pByteArray; begin try BytesPorScan := Abs(Integer(BMP.ScanLine[1]) Integer(BMP.ScanLine[0])); except raise Exception.Create('Erro !'); end; RandSeed := Key; for h := 0 to BMP.Height - 1 do begin P := BMP.ScanLine[h]; for w := 0 to BytesPorScan - 1 do 88

P^[w] := P^[w] xor Random(256); end; end; Agora vamos ao evento onclick do Button chamar a nossa procedure cripto, basta digitar o seguinte cdigo: procedure TForm1.Button1Click(Sender: TObject); begin cripto(Image1.Picture.Bitmap, 1); Image1.Refresh; end; Ao chamar a rotina passamos como parmetro o caminho da imagem que no exemplo foi utilizado o componente image e 1 como um valor inteiro para retornamos a imagem normal, logo aps a execuo da nossa procedure atualizamos o image para que ele possa exibir nossa imagem criptografada.

Alterar a fonte de determinado registro num DBGrid


Para trocar a fonte de um DBGrid, utilize a rotina abaixo no evento OnDrawDataCell: if Tabela.FieldByName ('Salario').Value >= 10000 then begin DbGrid1.Canvas.Font.Color := clRed; DbGrid1.Canvas.Font.Style := [fsBold]; end; DbGrid1.DefaultDrawDataCell(Rect, Field, State); No caso, somente os registros com salrio maior que R$ 10.000,00 ficaro com cor vermelha e em negrito. Nota: No necessrio mover o ponteiro da tabela para colorir os registros.

Alinhar ttulo da barra de titulos do Form a esquerda ou direita


//Deve ser usada assim: //Procedure TForm1.Titulo(Titulo: Pchar;pos,wParam: Integer); //e declarada na clausua private. procedure Titulo(Titulo: Pchar;pos,wParam: Integer); var DC: THandle; R1, R2: TRect; begin DC := GetWindowDC(Handle); 89

try SetWindowText(Handle, nil); GetWindowRect(Handle, R2); R1.Left := GetSystemMetrics(SM_CXSIZE) + GetSystemMetrics(SM_CXBORDER) + GetSystemMetrics(SM_CXFRAME); R1.Top := GetSystemMetrics(SM_CYFRAME); R1.Right := R2.Right - R2.Left - R1.Left - 2 * GetSystemMetrics(SM_CXSIZE); R1.Bottom := R1.Top + GetSystemMetrics(SM_CYSIZE); if wParam = 1 then begin SetBkColor(DC, GetSysColor(COLOR_ACTIVECAPTION)); end else begin SetBkColor(DC, GetSysColor(COLOR_INACTIVECAPTION)); end; SetTextColor(DC, GetSysColor(COLOR_CAPTIONTEXT)); if pos = 1 then begin DrawText(DC, Titulo, -1, R1, DT_LEFT or DT_VCENTER); end else begin DrawText(DC, Titulo, -1, R1, DT_RIGHT or DT_VCENTER); end; finally ReleaseDC(Handle, DC); end; end;

Alterar fonte do Hint


Para testar este exemplo inclua no seu form alguns componentes. Nestes componentes coloque informaes na propriedade Hint de cada componente e altere a propriedade ShowHint para True. unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Edit1: TEdit;

90

Edit2: TEdit; Edit3: TEdit; procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } procedure MyShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: THintInfo); end; var Form1: TForm1; implementation {$R *.DFM} // Funo que ir alterar a fonte do Hint procedure TForm1.MyShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: HintInfo); var i : integer; begin for i := 0 to Application.ComponentCount - 1 do if Application.Components[i] is THintWindow then with THintWindow(Application.Components[i]).Canvas do begin Font.Name := 'Arial'; Font.Size := 18; Font.Style := [fsBold]; HintInfo.HintColor := clWhite; end; end; // Evento OnCreate do Form procedure TForm1.FormCreate(Sender: TObject); begin // Ativa a funo que ir alterar o formato do Hint Application.OnShowHint := MyShowHint; end;

Criando arquivo Texto


Veja abaixo os passos bsicos para criao de arquivos texto: Var

91

F:TextFile; Begin AssignFile(f,'c:\qq_arquivo.txt'); Rewrite(f); //abre o arquivo para escrita Writeln(f,'Testando'); escreve no arquivo e desce uma linha Write(f,'Linha de Cdigo - www.linhadecodigo.com.br'); //escreve no arquivo sem descer a linha Closefile(f); //fecha o handle de arquivo End; ///Rotina para ler de um arquivo texto: var f:TextFile; linha:String; begin AssignFile(f,'c:\qq_arquivo.txt'); Reset(f); //abre o arquivo para leitura; While not eof(f) do begin Readln(f,linha); //le do arquivo e desce uma linha. O contedo lido transferido para a varivel linha Memo1.lines.add(linha); End; Closefile(f); end;

Como selecionar tudo (Ctrl+A) em um TMemo/TDBMemo


Voc pode selecionar todo o contedo de um TMemo ou TDBMemo utilizando as teclas de atalho Crtl+A adicionando no evento OnKeyDownEvent destes componentes o cdigo a seguir: procedure OnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState) ; begin if (Key = Ord('A')) and (ssCtrl in Shift) then begin TMemo(Sender).SelectAll; Key := 0; end; end;

92

Mudando o IP da mquina via API do Windows


{Como posso mudar meu IP? via API? A resposta para essa pergunta no neste artigo estou unsando o Delphi 7, mas pode ser feito com qualquer outra verso do delphi. nos Windows 2000 e XP existe um aplicativo chamado NETSH que faz essa mudana para ns sem que precisemos reiniciar o computador. bem vamos por a mo na massa e brincarmos um pouco com as configuraes de IP. Mudando a Configurao para DHCP: Crie uma aplicao no Delphi, NEW -> Application no FormDesigner ponha um TButton e no evento OnClick escreva o seguinte cdigo:}

if Win32Plataform = VER_PLATAFORM_WIN32_NT then WinExec('cmd /c netsh interface ip set address "Conexo local" DHCP', SW_SHOWNORMAL) else MessageBox(Handle, 'esse Comando no pode ser rodado fora da plataforma NT', 'NETSH', MB_ICONWARNING); {onde verifico se a plataforma do Programa uma plataforma NT, caso contrrio informo ao usurio que esse comando no pode ser rodado fora de uma plataforma NT. Mudando as Configuraes dos IPs da mquina, menos os DNS: Na mesma aplicao do exemplo acima Ponha outro TButton e no Evento OnClick dele escreva:} if Win32Plataform = VER_PLATAFORM_WIN32_NT then WinExec('cmd /c netsh interface ip set address "Conexo local" static 192.168.10.104 255.255.255.0 192.168.10.1 1', SW_SHOWNORMAL) else MessageBox(Handle, 'esse {Comando no pode ser rodado fora da plataforma NT', 'NETSH', MB_ICONWARNING);

Pronto seu IP, SubnetMask e Gateway foram mudados. Para maiores informaes sobre o NETSH visite o site da Microsoft: Suporte Microsoft.

Texto na diagonal e girando


Procedure TForm1.Button1Click(Sender: TObject); 93

var lf : TLogFont; tf : TFont; i : integer; begin with Form1.Canvas do begin Font.Name := 'Verdana'; Font.Size := 16; tf := TFont.Create; tf.Assign(Font); GetObject(tf.Handle, sizeof(lf), @lf); lf.lfOrientation := 1000; end; For i:= 50000 Downto 1 do Begin lf.lfEscapement := i; tf.Handle := CreateFontIndirect(lf); Form1.Canvas.Font.Assign(tf); Form1.Canvas.TextOut(200, Height div 2, 'Ramos da Informtica'); //Sleep(10); Este pode cria um Delay na execuo end; tf.Free; end;

Criar um alias dinamicamente na memria


procedure TForm1.FormCreate(Sender: TObject); begin if not Session.IsAlias(Teste) then session.AddStandardAlias(Teste, ExtractFilePath(Application.ExeName),PARADOX); end;

Rodar videos em um panel


begin if opendialog1.execute then begin mediaplayer1.filename:= opendialog1.filename; mediaplayer1.open; mediaplayer1.Perform (wm_lbuttondown,0,$00090009); mediaplayer1.Perform (wm_lbuttonup,0,$00090009); end; end;

94

Como colocar uma coluna do DBGrid em maiuscula


procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char); begin if DBGrid1.SelectedField.FieldName='NOME' THEN Key := AnsiUpperCase(Key)[Length(Key)]; end;

DBGrid - Alinhando texto conforme condio


Aqui iremos demonstrar como colorir e alinhar o texto de uma coluna do DBGrid com base em uma condio. Estamos utilizando a tabela COUNTRY do alias DBDemos e verificamos o contedo do campo Continent. Caso seja North America iremos mudar a cor da fonte para verde e o alinhamento do texto para direita, o qual ser redesenhado atravs da API DrawText. Este tratamento ser feito no evento OnDrawColumnCell do prprio DBGrid, acompanha o cdigo abaixo: { constantes para o alinhamento } const FmtCentered = DT_SingleLine or DT_VCenter or DT_NoClip or DT_Center; FmtLeft = DT_SingleLine or DT_VCenter or DT_NoClip or DT_Left; FmtRight = DT_SingleLine or DT_VCenter or DT_NoClip or DT_Right; implementation implementation {$R *.DFM} procedure TForm1.gridCountryDrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); var Format: integer; R: TRect; begin if (tabCountryContinent.AsString = 'North America') and (DataCol = 1) then begin gridCountry.Canvas.Font.Color := clGreen; R := Rect; Format := FmtRight; { poder utilizar: FmtCentered, FmtLeft, FmtRight } gridCountry.Canvas.FillRect(Rect); DrawText(gridCountry.Canvas.Handle, PChar(Column.Field.AsString), Length Column.Field.AsString), R, Format); end; if (tabCountryContinent.AsString = 'South America') and (DataCol = 1) then begin 95

gridCountry.Canvas.Font.Color := clRed; R := Rect; Format := FmtCentered; { poder utilizar: FmtCentered, FmtLeft, FmtRight } gridCountry.Canvas.FillRect(Rect); DrawText(gridCountry.Canvas.Handle, PChar(Column.Field.AsString), Length Column.Field.AsString), R, Format); end; end;

DBGrid - Colocando CheckBox no grid


Frequentemente e-mail de nossos visitantes sobre como colocar um CheckBox em uma coluna referente um campo lgico apresentada no DBGrid. Aqui irei demonstrar uma abordagem bem simples que desenha uma imagem que ir imitar um CheckBox e caso o contedo do campo seja verdadeiro, mostraremos uma imagem checada e do contrrio uma imagem desmarcada. Neste exemplo, o campo lgico possui o nome de situacao. No evento OnDrawColumnCell verificamos se a coluna atual situacao e conforme o valor do referido campo desenhamos a imagem correspondente. No evento OnCellClick permitimos a alterao do valor do campo que, quando estiver = true ir receber false e vice-versa. E finalizando, no evento OnEnter do DBGrid efetuamos um tratamento para no permitir a edio direta na coluna referente o campo lgico. Neste exemplo iremos codificar os eventos: OnDrawColumnCell, OnCellClick e OnEnter do DBGrid, alm ainda de um componente ImageList que ser responsvel em armazenar e fornecer as imagens que sero desenhada referida coluna. procedure TForm1.grdExemploDrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); begin { Desenha CheckBox } if Column.FieldName = 'Situacao' then begin grdExemplo.Canvas.FillRect(Rect); Imagens.Draw(grdExemplo.Canvas, Rect.Left+10, Rect.Top+1, 0); if not cdsExemploSituacao.IsNull then if cdsExemploSituacao.AsBoolean then Imagens.Draw(grdExemplo.Canvas, Rect.Left+10, Rect.Top+1, 2) else Imagens.Draw(grdExemplo.Canvas, Rect.Left+10, Rect.Top+1, 1); end; end; procedure TForm1.grdExemploCellClick(Column: TColumn); begin { Quando clicar, alterna o valor True/False } if Column.FieldName = 'Situacao' then begin

96

if cdsExemplo.State = dsBrowse then cdsExemplo.Edit; cdsExemploSituacao.AsBoolean := not cdsExemploSituacao.AsBoolean; end; end; procedure TForm1.grdExemploEnter(Sender: TObject); begin { No permite edio na clula do CheckBox } with grdExemplo do begin if SelectedField = cdsExemploSituacao then Options := Options - [dgEditing] else Options := Options + [dgEditing]; end; end; procedure TForm1.cdsExemploNewRecord(DataSet: TDataSet); begin cdsExemploSituacao.AsBoolean := True; end;

RichEdit - Como fazer uma pesquisa e substituio em um RichEdit


O cdigo abaixo procurar por uma string e a substituir. Tenha certeza que voc tem o RichEdit1 em seu Form1. procedure TForm1.RearchAndReplace (InSearch, InReplace: string) ; var X, ToEnd : integer; oldCursor : TCursor; begin oldCursor := Screen.Cursor; Screen.Cursor := crHourglass; with RichEdit1 do begin X := 0; ToEnd := length(Text) ; X := FindText(inSearch, X, ToEnd, []) ; while X <> -1 do begin SetFocus; SelStart := X; SelLength := length(inSearch) ; SelText := InReplace; X := FindText(inSearch, 97

X + length(InReplace), ToEnd, []) ; end; end; Screen.Cursor := oldCursor; end; procedure TForm1.Button1Click (Sender: TObject) ; var SearchText, ReplaceText: string; begin SearchText := Pascal; ReplaceText := Delphi; RearchAndReplace(SearchText, ReplaceText) ; end;

TForm - Criando formulrios transparentes


private { Private declarations } FullRgn, ClientRgn, CtlRgn: THandle; procedure MakeTransparent; procedure UndoTransparent; end; {...} implementation {...} procedure TForm1.MakeTransparent; var AControl: TControl; A, Margin, X, Y, CtlX, CtlY: Integer; begin Margin := (Width - ClientWidth) div 2; FullRgn := CreateRectRgn(0, 0, Width, Height); X := Margin; Y := Height - ClientHeight - Margin; ClientRgn := CreateRectRgn(X, Y, X + ClientWidth, Y + ClientHeight); CombineRgn(FullRgn, FullRgn, ClientRgn, RGN_DIFF); for A := 0 to ControlCount - 1 do begin AControl := Controls[A]; if (AControl is TWinControl) or (AControl is TGraphicControl) then with AControl do begin if Visible then begin

98

CtlX := X + Left; CtlY := Y + Top; CtlRgn := CreateRectRgn(CtlX, CtlY, CtlX + Width, CtlY + Height); CombineRgn(FullRgn, FullRgn, CtlRgn, RGN_OR); end; end; end; SetWindowRgn(Handle, FullRgn, True); end; procedure TForm1.UndoTransparent; begin FullRgn := CreateRectRgn(0, 0, Width, Height); CombineRgn(FullRgn, FullRgn, FullRgn, RGN_COPY); SetWindowRgn(Handle, FullRgn, True); end; Para usar: // Teste: procedure TForm1.Button1Click(Sender: TObject); begin MakeTransparent end; procedure TForm1.Button1Click(Sender: TObject); begin UndoTransparent end;

TList - Ordenando os itens


Quando voc est trabalhando com um objeto TList e quer ordenar os itens baseados um critrio seu, pode usar o cdigo abaixo. O exemplo a seguir mostra como ordenar os itens em ordem alfabtica baseado nos nomes. Ele assume que a lista contm apenas referncias para as variveis do tipo TMyListItem, onde TMyListItem definida como: type TMyListItem = record Points : Integer; Name: string[255] ; end; A funo CompareNames faz as comparaes entre os objetos da lista. A lista ordenada quando o usurio clicar no boto.

99

function CompareNames (Item1, Item2: Pointer): Integer; begin Result := CompareText((Item1 as TMyListItem).Name, (Item2 as TMyListItem).Name) ; end; procedure TForm1.Button1Click (Sender: TObject) ; begin List1.Sort(@CompareNames) ; end;

{ Note: the Sort method needs a pointer to a custom function (with the signature below) that indicates how the items are to be ordered. type TListSortCompare = function (Item1, Item2: Pointer): Integer; Your sorting / comparison function should return a positive value if Item1 is less than Item2, 0 if they are equal, and a negative value if Item1 is greater than Item2. }

3 formas de dar um shutdown


Existem 3 formas distintas de fazer a mesma coisa, so elas: //------------- Forma 1-----------------

procedure TForm1.Button1Click(Sender: TObject); begin ExitWindowsEx(EWX_FORCE and EWX_SHUTDOWN,0); //EWX_SHUTDOWN para shutdown //EWX_REBOOT para reboot //EWX_LOGOFF para logoff end;

//------------- Forma 2-----------------

100

Executando o programa shutdown.exe do Windows: run %Windir%\system32\shutdown.exe Example : procedure TForm1.Button1Click(Sender: TObject); begin WinExec('shutdown.exe -s -f -t 0' , SW_HIDE); end;

//------------- Forma 3-----------------

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} function SetPrivilege1 (sPrivilegeName: string; bEnabled: Boolean) : Boolean; var TPPrev, TP : TTokenPrivileges; Token : THandle; dwRetLen : DWORD; begin

101

result := False; OpenProcessToken (GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, Token); TP.PrivilegeCount := 1; if LookupPrivilegeValue (nil, PChar (sPrivilegeName), TP.Privileges[0].LUID) then begin if bEnabled then TP.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED else TP.Privileges[0].Attributes := 0; dwRetLen := 0; result := AdjustTokenPrivileges (Token, False, TP, SizeOf (TPPrev), TPPrev, dwRetLen) end; CloseHandle (Token) end;

function WinExit1 (iFlags: integer) : Boolean; begin result := true; if SetPrivilege1 ('SeShutdownPrivilege', true) then begin if (not ExitWindowsEx (iFlags, 0)) then begin result := False end; SetPrivilege1 ('SeShutdownPrivilege', False) end else begin result := False end; end;

procedure TForm1.Button1Click(Sender: TObject); begin // 0= Logoff // 1= Shutdown WinExit1(1); end; end.

102

QuickReport e FastReport - Gerando um PDF


Esse componente ExportQR foi criado para trabalhar com o QuickReport e com o FastReport, mas aqui vou dar exemplo apenas do QuickReport. Caso algum queira pegar a verso que tambm trabalha com o FastReport recomendo que acesse o site do fabricante no seguinte link: http://usuarios.lycos.es/isma A instalao desse componente bastante simples, abra o arquivo ExPackD6.dpk (Delphi 6) ou ExPackD7.dpk (Delphi 7) atravs do delphi e em seguida compile e instale. Esse componente j est trazendo os dois componentes utilizados no primeiro exemplo, isso , o componente TNPDV e o componente de compactao. Aps efetuar a instalao acesse o menu Tools, do Delphi, e depois a opo Environment Options. Selecione a aba Library e depois acesse o boto da Library path. Na janela que ser aberta indique o caminho onde esto os arquivos .pas do componente e depois clique em Add e em seguida em Ok. Agora estando com o componente instalado podemos coloc-lo no form do nosso projeto que contem o relatrio criado no QuickReport e depois atravs de um boto colocar a instruo que ir fazer a exportao. A instruo do boto para exportao ficar da seguinte forma: procedure TMainForm.BtnExportQRClick(Sender: TObject); begin { Liga o componente do QuickReport ao componente de exportao } EXQR.Report := Rep; { Faz a exportao } EXQR.ExportQR; end; Este componente tambm nos permite exportar relatrios a partir do componente QRPreview que o componente ao qual criamos preview personalizado no QuickReport. Para isso podemos colocar um boto no form de preview e neste boto colocar a seguinte instruo: procedure TFPreviewQR.TBSaveClick(Sender: TObject); begin { Faz a ligao do QRPreview com o componente } EXQR.Preview := Preview; { Faz a exportao do relatrio } EXQR.ExportQRFromPreview; end; Esses cdigos acima podem ser encontrados no projeto de Exemplo1 que acompanha o componente ExportQR.

103

Outros formatos: A exportao dos relatrios para os demais formatos bastante simples tambm, veja abaixo as sintaxes utilizadas para cada tipo: PDF com Alta Compresso: EXQR.ExportQRPDF(edFileName.Text, True); PDF com Baixa Compresso EXQR.ExportQRPDF(edFileName.Text, False); JPG EXQR.ExportQRJPG(edFileName.Text); BMP EXQR.ExportQRBMP(edFileName.Text); WMF EXQR.ExportQRWMF(edFileName.Text); EMF EXQR.ExportQREMF(edFileName.Text); Esses cdigos acima podem ser encontrados no projeto de Exemplo3 que acompanha o componente ExportQR.

SetVolumeLabel - Mudando o Label do HD


A seguir a rotina completa: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Label1: TLabel; Label2: TLabel; Button1: TButton; ComboBox1: TComboBox; Edit1: TEdit; procedure FormCreate(Sender: TObject);

104

procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin SetVolumeLabel(pansichar(ComboBox1.Text), pchar(Edit1.Text)); end; procedure TForm1.FormCreate(Sender: TObject); var i:Integer; begin for i:=Ord('A') to Ord('Z') do begin if GetDriveType(pchar(char(i)+':\'))=3 then ComboBox1.Items.Add(char(i)+':\'); end; ComboBox1.Text:=ComboBox1.Items.Strings[0]; Button1Click(Self); end; end.

Memo - Rolagem vertical


Inclua na seo uses: Windows Problema: Gostaria que o meu programa rolasse automaticamente o contedo de um TMemo, simulando o deslizamento da barra de rolagem vertical. Isto possvel no Delphi? Soluo: Sim. Utilizando mensagens do Windows isto fcil. Vejamos algums exemplos: SendMessage(Memo1.Handle, WM_VSCROLL, SBPAGEDOWN, 0); Onde: 105

Memo1.Handle = manipulador da janela do Memo1. WM_VSCROLL = Mensagem do Windows - rolagem vertical. SB_PAGEDOWN = Comanndo de rolagem - pgina para baixo. Outros exemplos: { Pgina para cima } SendMessage(Memo1.Handle, WM_VSCROLL, SBPAGEUP, 0); { Linha para baixo } SendMessage(Memo1.Handle, WM_VSCROLL, SBLINEDOWN, 0); { Linha para cima } SendMessage(Memo1.Handle, WM_VSCROLL, SBLINEUP, 0); Observaes: Alm desta tcnica existem API's do Windows que fazem um trabalho equivalente.

Como adicionar o evento OnClick no DBGrid


O componente DBGrid no tem o evento OnClick no Object Inspector. Mas podemos utiliz-lo atravs de uma instancia da classe THack. Inclua as duas linhas abaixo da seo Implementation: type THack = class(TControl); Depois na seo Private declare a nova procedure que utilizaremos no evento OnClick: private { Private declarations } procedure DBGridClick(Sender: TObject); Agora crie a procedure que declaramos na seo private. procedure TForm1.DBGridClick (Sender: TObject); begin ShowMessage(O contedo desta clula +TDBGrid(Sender).SelectedField.AsString); end; Para utilizarmos esta procedure temos que fazer a sua ligao no evento OnCreate do form. Veja o cdigo abaixo: procedure TForm1.FormCreate(Sender: TObject); begin THack(dbgrid1).controlstyle := THack(dbgrid1).controlstyle + [csClickEvents]; THack(dbgrid1).OnClick := DBGridClick; end;

106

Alterando a cor dos TabSheet de um PageControl


Coloque um PageControl no Form. - Adicione 6 TabSheet (New Page). - Agora basta implementar o codigo abaixo no evento OnDrawTab.

procedure TForm1.PageControl1DrawTab(Control: TCustomTabControl; TabIndex: Integer; const Rect: TRect; Active: Boolean); begin case TabIndex of 0: Control.Canvas.Font.Color := clGreen; 1: Control.Canvas.Font.Color := clRed; 2: Control.Canvas.Font.Color := clBlue; 3: Control.Canvas.Font.Color := clYellow; 4: Control.Canvas.Font.Color := clMaroon; 5: Control.Canvas.Font.Color := clWhite; end; Control.Canvas.TextOut(Rect.left+5, Rect.top+3,PageControl1.Pages [TabIndex].Caption); PageControl1.Pages[TabIndex].Font.Color := Control.Canvas.Font.Color; end; Obs.: No esquea de alterar a propriedade OwnerDraw para True.

Como chamar uma home page utilizando o seu browse padro


uses UrlMon; procedure TForm1.Button1Click(Sender: TObject); begin HlinkNavigateString(nil, http://www.theclub.com.br); end;

Como alterar o caption da janela de preview do quickreport


Para mudar o ttulo da barra de ttulo da janela de Preview de seus relatrios, use o seguinte comando: QRPrinter.PreviewCaption := Visualizao do Relatrio; Como colocar Captions no DBNavigator 107

type TDBNewNavigator = class(TDBNavigator); procedure TForm1.FormCreate(Sender: TObject); var B: TNavigateBtn; begin for B := Low(TNavigateBtn) to High(TNavigateBtn) do with TDBNewNavigator(DBNavigator1).Buttons[B] do begin Case Index of nbFirst : Caption := Inicio; nbPrior : Caption := Anterior; nbNext : Caption := Prximo; nbLast : Caption := ltimo; nbInsert : Caption := Novo; nbDelete : Caption := Apagar; nbEdit : Caption := Alterar; nbPost : Caption := Gravar; nbCancel : Caption := Cancelar; nbRefresh: Caption := Atualizar; End; Hint := Caption; ShowHint := True; end; end; end;

Como passar parmetros entre 2 forms


Suponha que voc esteja no Form1 e precise chamar o Form2 passando dois parametros ("Verde" e "Amarelo"). 1. Crie as variveis de instncia do Form2 que recebero os dois parmetros. 2. Reescreva o Construtor desse form, de forma a receber os parmetros e atribu-los s suas variveis de instncia: type TForm2 = class(TForm) private Parametro1 : String; Parametro2 : String; public constructor Create(AOwner : TComponent; pPar1, pPar2 : String); end; var

108

Form2: TForm2; implementation constructor TForm2.Create(AOwner : TComponent; pPar1, pPar2 : String); begin inherited Create(AOwner); Parametro1 := pPar1; Parametro2 := pPar2; end; Agora no seu form1, abra o form2 com a seguinte sintaxe: With TForm2.Create(self, Verde, Amarelo) do Begin ShowModal; Free; End; No evento OnShow inclua a seguinte linha: procedure TForm2.FormShow(Sender: TObject); begin Caption := Parametro1 + - + Parametro2; end; Obs: No deixe o Delphi criar automaticamente o formulrio. Crie-o (e o destrua) manualmente.

Como reduzir o tempo e carga de um programa


comum acontecer um sensvel aumento de tempo de carga de um aplicativo desenvolvido em Delphi medida que este aplicativo cresce e adquire mais e mais formulrios. s vezes o tempo de carga se torna totalmente insuportvel. Os programas se tornam lentos principalmente devido a grande quantidade de formulrios que so criados e inicializados logo no incio da execuo do programa. Antes de ser efetivamente utilizado, todo formulrio precisa ser criado. A criao do formulrio acontece sempre que voc adiciona um novo formulrio ao sistema, o IDE do Delphi providencia cdigo para que ele seja criado automaticamente. Isto simplifica a vida do programador que no precisar se preocupar com este detalhe. O aumento do tempo de carga do aplicativo pode ser resolvido pela simples remoo do cdigo que o Delphi gerou para a criao do formulrio. Para remover o cdigo que o Delphi criou automaticamente, selecione Project|Options no menu. Selecione a aba Forms. Aponte para um dos formulrios e clique no boto >. Isto faz com que o formulrio passe do painel Auto-create forms para o painel Available forms.

109

Se voc quer saber onde est este cdigo, clique em View|Units (ou use Ctrl-F12) e selecione o seu projeto na lista de units que aparecer. O cdigo que cria formulrios algo mais ou menos como se segue: Application.CreateForm(TForm1, Form1); Cada formulrio auto-criado ter uma linha como esta. Quando o formulrio passa para o painel de Available forms, a linha correspondente removida. Voc tambm pode simplesmente remover a linha manualmente, usando o editor de textos. Normalmente usar um formulrio significa mostr-lo na tela. Isto feito invocando-se os mtodos Show ou ShowModal do formulrio conforme o estilo do aplicativo. Agora que o formulrio no mais criado automaticamente, isto se torna um pouco mais complicado, por exemplo: 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 tcnica. Se voc tirar o cdigo de criao automtica do formulrio e tentar executar o Show ou ShowModal voc vai receber um erro do tipo Access Violation. Tome cuidado e faa isto um formulrio por vez. Ateno! No faa isto para o seu formulrio principal. O formulrio principal precisa ser o primeiro formulrio a ser criado. Assim melhor mant-lo como auto-criado. Esta tcnica efetivamente distribui o tempo de carga e inicializao do aplicativo pela execuo do programa. Os formulrios agora so carregados sob-demanda. Os formulrios nunca utilizados nunca sero criados. Isto tambm melhora o uso de memria.

Escondendo o Programa de Ctrl+Alt+Del


unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private

110

{ Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} { Para ocultar um programa, deve-se registrar este programa como um servio do Windows. Normalmente um servio do Windows ativado quando com a inicializao do sistema (Windows) e permanece ativo at a finalizao deste. Este processo esconde o programa da lista "Ctrl+Alt+Del" } Const Servico_Simples = 1; Servico_Unregister = 1; Function RegisterServiceProcess(DwProcessID, dwType: DWord): DWord; StdCall; External KERNEL32.dll; procedure TForm1.FormCreate(Sender: TObject); begin RegisterServiceProcess(GetCurrentProcessID, Servico_Simples); end; procedure TForm1.FormDestroy(Sender: TObject); begin RegisterServiceProcess(GetCurrentProcessID, Servico_Unregister); end; end.

Alterando a pgina inicial do Internet Explorer via programao

function PaginaInicialIE(endereco : string) : boolean; Var Reg : TRegistry; begin Reg:= TRegistry.Create; try Reg.RootKey:= HKEY_CURRENT_USER; Reg.OpenKey(Software\Microsoft\ Internet Explorer\Main,false); try

111

try Reg.WriteString (Start Page,endereco); result := true; finally Reg.CloseKey; result := True; end; except result := false; end; finally Reg.Free; end; end; procedure TForm1.Button1Click(Sender: TObject); begin if PaginaInicialIE(http://www.theclub.com.br) then ShowMessage(Foi alterado com sucesso) else ShowMessage(No foi alterado); end;

Verifica se o BDE est instalado


// Usando o registrador do Windows procedure TForm1.Button1Click (Sender: TObject); var Reg: TRegistry; begin reg := TRegistry.create; try reg.RootKey := HKEY_CURRENT_USER; reg.OpenKey(\Software\Borland, False); if Reg.KeyExists(BdeAdmin) then ShowMessage(BDE j instalado) else ShowMessage(Sem BDE); finally Reg.CloseKey; Reg.Free; inherited; end; end;

112

Arredondar casas decimais de forma personalizada


Na seo de procedures digite: Function Arredondar (value: double;casas : integer): double; Na seo implementation digite a funo conforme descrita abaixo. Function Tform1.Arredondar(value: double;casas : integer): double; Var fracao, Total:real; decimal:string; begin try fracao:=Frac(value); //Retorna a parte fracionria de um nmero decimal:=(RightStr(floattostr(fracao), length(floattostr(fracao))-2)); //decimal recebe a parte decimal //enquanto o tamanho da variavel decimal for maior que o nmero de casas faa while length(decimal) > casas do begin //Verifica se o ltimo digito da varivel decimal maior que 5 if strtoint(RightStr(decimal,1))>5 then begin //Descarta o ltimo digito da varivel Decimal decimal:=leftstr(decimal,length(decimal)-1); //Soma o valor nmero da variavel decimal + 1 decimal:=floattostr(strtofloat(decimal) + 1); end else decimal:=leftstr(decimal,length(decimal)-1); //Descarta o ltimo digito da varivel Decimal end; result:=(int(value) + (strtofloat(decimal)/100)); //devolve o resultado para a funo except Raise Exception.Create(Erro no arredondamento); end; end; Como usar... arredondar(Campo ou vaivel do tipo Real (Float) , nmero de casas decimais desejado); Ex:Var valor,Resultado:real; Valor:=10.005.526 Resultado :=Arredondar(valor,2); Resultado=10.005,53

113

Obs: O codigo foi escrito em Delphi 6 porm isso no a impede de funcionar no Delphi 4 ou 5, pouco provavel que ocorra erro.

Verificando se um alias est instalado


var vList: TStringList; x: Integer; begin vList := TStringList.Create; Session.Open; Session.GetAliasNames(vList); if vList.Find(NomeDoAlias, x) then // x receber a posio do alias na lista // Alias encontrado else // Alias no encontrado end;

Como prevenir a movimentao do mouse para fora do form?


procedure TForm1.FormMouseDown (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Form1.Left <= 0 then Form1.Left := 0; if Form1.Top <= 0 then Form1.Top := 0; if Form1.Left >= Screen.Width - Form1.Width then Form1.Left := Screen.Width - Form1.Width; if Form1.Top >= Screen.Height - Form1.Height then Form1.Top := Screen.Height - Form1.Height; end;

Como criar hints customizados?


type TGraphicHintWindow = class(THintWindow) constructor Create(AOwner: TComponent); override; private FActivating: Boolean; public procedure ActivateHint(Rect: TRect; const AHint: string); override; protected procedure Paint; override;

114

published property Caption; end; {...} constructor TGraphicHintWindow.Create (AOwner: TComponent); begin inherited Create(AOwner); { Aqui voc pode customizar as propriedades da fonte } with Canvas.Font do begin Name := Arial; Style := Style + [fsBold]; Color := clBlack; end; end; procedure TGraphicHintWindow.Paint; var R: TRect; bmp: TBitmap; begin R := ClientRect; Inc(R.Left, 2); Inc(R.Top, 2); {*************************************** O cdigo abaixo um exemplo de como crier um objeto Hint customizado: } bmp := TBitmap.Create; bmp.LoadfromFile(D:\hint.bmp); with Canvas do begin Brush.Style := bsSolid; Brush.Color := clsilver; Pen.Color := clgray; Rectangle(0, 0, 18, R.Bottom + 1); Draw(2,(R.Bottom div 2) - (bmp.Height div 2), bmp); end; bmp.Free; /Cor do Hint customizada Color := clWhite; Canvas.Brush.Style := bsClear; Canvas.TextOut(20, (R.Bottom div 2) - (Canvas.Textheight(Caption) div 2), Caption); {**************************************} end; procedure TGraphicHintWindow.ActivateHint (Rect: TRect; const AHint: string); begin FActivating := True;

115

try Caption := AHint; //Ajuste a propriedade Height do Hint Inc(Rect.Bottom, 14); //Ajuste a propriedade Width do Hint Rect.Right := Rect.Right + 20; UpdateBoundsRect(Rect); if Rect.Top + Height > Screen.DesktopHeight then Rect.Top := Screen.DesktopHeight Height; if Rect.Left + Width > Screen.DesktopWidth then Rect.Left := Screen.DesktopWidth - Width; if Rect.Left < Screen.DesktopLeft then Rect.Left := Screen.DesktopLeft; if Rect.Bottom < Screen.DesktopTop then Rect.Bottom := Screen.DesktopTop; SetWindowPos(Handle, HWND_TOPMOST, Rect.Left, Rect.Top, Width, Height, SWP_SHOWWINDOW or SWP_NOACTIVATE); Invalidate; finally FActivating := False; end; end; procedure TForm1.FormCreate(Sender: TObject); begin HintWindowClass := TGraphicHintWindow; Application.ShowHint := False; Application.ShowHint := True; end;

Como capturar a tela?


uses Graphics; // Captura a tela inteira procedure ScreenShot(Bild: TBitMap); var c: TCanvas; r: TRect; begin c := TCanvas.Create; c.Handle := GetWindowDC(GetDesktopWindow); try r := Rect(0, 0, Screen.Width, Screen.Height); Bild.Width := Screen.Width; Bild.Height := Screen.Height; Bild.Canvas.CopyRect(r, c, r); finally

116

ReleaseDC(0, c.Handle); c.Free; end; end; procedure TForm1.Button1Click(Sender: TObject); begin Form1.Visible := False; Sleep(750); // um atraso ScreenShot(Image1.Picture.BitMap); Form1.Visible := True; end; // Somente a janela ativa procedure ScreenShotActiveWindow(Bild: TBitMap); var c: TCanvas; r, t: TRect; h: THandle; begin c := TCanvas.Create; c.Handle := GetWindowDC(GetDesktopWindow); h := GetForeGroundWindow; if h <> 0 then GetWindowRect(h, t); try r := Rect(0, 0, t.Right - t.Left, t.Bottom - t.Top); Bild.Width := t.Right - t.Left; Bild.Height := t.Bottom - t.Top; Bild.Canvas.CopyRect(r, c, t); finally ReleaseDC(0, c.Handle); c.Free; end; end; procedure TForm1.Button2Click(Sender: TObject); begin Form1.Visible := False; Sleep(750); //um atraso ScreenShotActiveWindow(Image1.Picture.BitMap); Form1.Visible := True; end; {*****************************************} // Outra funo de print screen function: // Captura a tela inteira procedure ScreenShot(x: Integer; y: Integer; Width: Integer; Height: Integer; bm: TBitMap);

117

var dc: HDC; lpPal: PLOGPALETTE; begin if ((Width = 0) or (Height = 0)) then Exit; bm.Width := Width; bm.Height := Height; dc := GetDc(0); if (dc = 0) then Exit; if (GetDeviceCaps(dc, RASTERCAPS) and RC_PALETTE = RC_PALETTE) then begin GetMem(lpPal, SizeOf(TLOGPALETTE) + (255 * SizeOf(TPALETTEENTRY))); FillChar(lpPal^, SizeOf(TLOGPALETTE) + (255 * SizeOf(TPALETTEENTRY)), #0); lpPal^.palVersion := $300; lpPal^.palNumEntries := GetSystemPaletteEntries(dc, 0, 256, lpPal^.palPalEntry); if (lpPal^.PalNumEntries <> 0) then bm.Palette := CreatePalette(lpPal^); FreeMem(lpPal, SizeOf(TLOGPALETTE) + (255 * SizeOf(TPALETTEENTRY))); end; BitBlt(bm.Canvas.Handle, 0, 0, Width, Height, Dc, x, y, SRCCOPY); ReleaseDc(0, dc); end; // Examplo: procedure TForm1.Button1Click(Sender: TObject); begin ScreenShot(0,0,Screen.Width, Screen.Height, Image1.Picture.Bitmap); end;

118

{****************************************} // Captura a janela procedure ScreenShot(hWindow: HWND; bm: TBitmap); var Left, Top, Width, Height: Word; R: TRect; dc: HDC; lpPal: PLOGPALETTE; begin if not IsWindow(hWindow) then Exit; GetWindowRect(hWindow, R); Left := R.Left; Top := R.Top; Width := R.Right - R.Left; Height := R.Bottom - R.Top; bm.Width := Width; bm.Height := Height; dc := GetDc(0); if (dc = 0) then begin Exit; end; if (GetDeviceCaps(dc, RASTERCAPS) and RC_PALETTE = RC_PALETTE) then begin GetMem(lpPal, SizeOf(TLOGPALETTE) + (255 * SizeOf(TPALETTEENTRY))); FillChar(lpPal^, SizeOf(TLOGPALETTE) + (255 * SizeOf(TPALETTEENTRY)), #0); lpPal^.palVersion := $300; lpPal^.palNumEntries := GetSystemPaletteEntries(dc, 0, 256, lpPal^.palPalEntry); if (lpPal^.PalNumEntries <> 0) then begin bm.Palette := CreatePalette(lpPal^); end; FreeMem(lpPal, SizeOf(TLOGPALETTE) + (255 * SizeOf(TPALETTEENTRY))); end; BitBlt(bm.Canvas.Handle, 0,

119

0, Width, Height, Dc, Left, Top, SRCCOPY); ReleaseDc(0, dc); end; // Exemplo procedure TForm1.Button1Click(Sender: TObject); begin ScreenShot(GetForeGroundWindow, Image1.Picture.Bitmap); end; {**********************************************} {As vezes voc quer capturar a tela, no entanto o Windows tem problemas com grande quantidade de dados e fica muito lento. Uma soluo bem simples fazer pequenas capturas e colar o resultado unindo tudo. No a velocidade da luz, mas mais rpido que capturar a tela inteira.} const cTileSize = 50; function TForm1.GetSCREENSHOT: TBitmap; var Locked: Boolean; X, Y, XS, YS: Integer; Canvas: TCanvas; R: TRect; begin Result := TBitmap.Create; Result.Width := Screen.Width; Result.Height := Screen.Height; Canvas := TCanvas.Create; Canvas.Handle := GetDC(0); Locked := Canvas.TryLock; try XS := Pred(Screen.Width div cTileSize); if Screen.Width mod cTileSize > 0 then Inc(XS); YS := Pred(Screen.Height div cTileSize); if Screen.Height mod cTileSize > 0 then Inc(YS); for X := 0 to XS do for Y := 0 to YS do begin R := Rect( X * cTileSize, Y * cTileSize, Succ(X) * cTileSize,

120

Succ(Y) * cTileSize); Result.Canvas.CopyRect(R, Canvas, R); end; finally if Locked then Canvas.Unlock; ReleaseDC(0, Canvas.Handle); Canvas.Free; end; end;

Como mostrar um TMenuItem alinhado direita?


procedure TForm1.FormCreate(Sender: TObject); const MenuIndex = 3; var MII: TMenuItemInfo; MainMenu: hMenu; Buffer: array[0..50] of Char; begin MainMenu := GetMenu(Handle); with MII do begin cbSize := SizeOf(MII); fMask := MIIM_TYPE; dwTypeData := Buffer; cch := SizeOf(Buffer); GetMenuItemInfo(MainMenu, MenuIndex, True, MII); fType := fType or MFT_RIGHTJUSTIFY; SetMenuItemInfo(MainMenu, MenuIndex, True, MII); DrawMenuBar(Handle); end; end;

Como mover o form clicando em qualquer lugar?


private procedure WMNCHitTest(var msg: TWMNCHitTest); message WM_NCHITTEST; end; var Form1: TForm1; implementation {$R *.DFM}

121

procedure TForm1.WMNCHitTest(var msg: TWMNCHitTest); begin inherited; if msg.Result = htClient then msg.Result := htCaption; end; {...} { ************************* } procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); const SC_DRAGMOVE = $F012; begin if Button = mbleft then begin ReleaseCapture; Form1.Perform(WM_SYSCOMMAND, SC_DRAGMOVE, 0); end; end;

Como mostrar um texto de vrias linhas em um TCombobox?


unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) ComboBox1: TComboBox; procedure FormCreate(Sender: TObject); procedure ComboBox1MeasureItem (Control: TWinControl; Index: Integer; var Height: Integer); procedure ComboBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject); begin Combobox1.Style := csOwnerDrawVariable; // preencha o combobox com alguns exemplos

122

with Combobox1.Items do begin Add(Short, kurzer String); Add(A long String. / Ein langer String.....); Add(Another String); Add(abcd defg hijk lmno); Add(..-.-.-.-.-.-.-.-.-); end; end; procedure TForm1.ComboBox1MeasureItem(Control: TWinControl; Index: Integer; var Height: Integer); // Calculata o tamanho necessrio para o texto com vrias linhas var i, PosSp: Integer; strVal: string; strTmp: string; begin if Index >= 0 then begin strVal := Combobox1.Items[Index]; // coloque a string em vrias linhas, // cada linha separada por #$D#$A strTmp := WrapText(strVal, 20); // Nmero de separadores de linha // + 1 = nmero de linhas i := 1; while Pos(#$D#$A, strTmp) > 0 do begin i := i + 1; strTmp := Copy(strTmp, Pos(#13#10, strTmp) + 2, Length(strTmp)); end; // calcule o tamanho do texto Height := i * Combobox1.ItemHeight; end; end; procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); // Escreva o texto em um combobox. Se o texto muito comprido, ento sera feito var strVal: string; strTmp: string; intPos: Integer; i: Integer; rc: TRect; begin strVal := WrapText(Combobox1.Items[Index], 20); i := 0;

123

Combobox1.Canvas.FillRect(Rect); // sada de cada linha while Pos(#$D#$A, strVal) > 0 do begin intPos := Pos(#$D#$A, strVal); // copie a linha corrente da string if intPos > 0 then strTmp := Copy(strVal, 1, intPos - 1) else strTmp := strVal; rc := Rect; rc.Top := Rect.Top + i * Combobox1.ItemHeight; ComboBox1.Canvas.TextRect(rc, Rect.Left, Rect.Top + i * Combobox1.ItemHeight, strTmp); // delete a linha da string strVal := Copy(strVal, intPos + 2, Length(strVal)); Inc(i); end; rc := Rect; rc.Top := Rect.Top + i * Combobox1.ItemHeight; //escreva a ltima linha ComboBox1.Canvas.TextRect(rc, Rect.Left, Rect.Top + i * Combobox1.ItemHeight, strVal); Combobox1.Canvas.Brush.Style := bsClear; // faa um retangulo em volta do texto Combobox1.Canvas.Rectangle(Rect); end; end.

Como criar tooltips com bales?


{....} uses Commctrl; {....} const TTS_BALLOON = $40; TTM_SETTITLE = (WM_USER + 32); var hTooltip: Cardinal; ti: TToolInfo; buffer : array[0..255] of char; {....} procedure CreateToolTips(hWnd: Cardinal); begin hToolTip := CreateWindowEx(0, Tooltips_Class32', nil, TTS_ALWAYSTIP or TTS_BALLOON, Integer(CW_USEDEFAULT),

124

Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT), hWnd, 0, hInstance, nil); if hToolTip <> 0 then begin SetWindowPos(hToolTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE); ti.cbSize := SizeOf(TToolInfo); ti.uFlags := TTF_SUBCLASS; ti.hInst := hInstance; end; end; procedure AddToolTip(hwnd: DWORD; lpti: PToolInfo; IconType: Integer; Text, Title: PChar); var Item: THandle; Rect: TRect; begin Item := hWnd; if (Item <> 0) and (GetClientRect(Item, Rect)) then begin lpti.hwnd := Item; lpti.Rect := Rect; lpti.lpszText := Text; SendMessage(hToolTip, TTM_ADDTOOL, 0, Integer(lpti)); FillChar(buffer, SizeOf(buffer), #0); lstrcpy(buffer, Title); if (IconType > 3) or (IconType < 0) then IconType := 0; SendMessage(hToolTip, TTM_SETTITLE, IconType, Integer(@buffer)); end; end; procedure TForm1.Button1Click(Sender: TObject); begin CreateToolTips(Form1.Handle); AddToolTip(Memo1.Handle, @ti, 1, Tooltip text, Title); end; {IconType pode ser: 0 Sem cone 1 - Informao 2 - Aviso 3 - Erro }

125

Como mostrar Menu Item Hints


Quando o mouse est sobre um componente (um TButton, por exemplo) se a propriedade ShowHint True e se houver algum texto na propriedade Hint, o hint/tooltip ser mostrado para o componente. Hints para itens de menu? Por projeto, mesmo se voc colocar algo na propriedade Hint de um Menu Item o popup hint no ser exibido. No entanto, os Itens do menu Iniciar do Windows mostram hints, e o menu dos Favoritos do Internet Explorer tambm. comum usar o evento OnHint nas variveis globais da aplicao, nas aplicaes Delphi, para mostrar os hints do menu como uma barra de status. O Windows no expe as mensagens necessrias que suportem o evento tradicional OnMouseEnter. No entanto, a implementao do WM_MENUSELECT no TCustomForm (ancestral do TForm) tem o item hint de menu no Application.Hint que pode ser usado no evento Application.OnHint. Se voc quer adicionar itens de menu com popup hints nos menus de sua aplicao Delphi voc precisa somente apontar a mensagem WM_MenuSelect corretamente. A classe TMenuItemHint hints popup para itens de menu! Como no podemos depender do mtodo Application.ActivateHint para mostrar a janela para os itens de menu (o apontamento de menus feito totalmente pelo Windows), para obter a janela de hint exibida voc precisa criar sua prpria verso da janela hint derivando uma nova classe a partir de THintWindow. Segue como criar a classe TMenuItemHint uma janela hint que realmente exibida nos itens de menu. Primeiro voc precisa apontar a mensagem WM_MENUSELECT do Windows: type TForm1 = class(TForm) ... private procedure WMMenuSelect(var Msg: TWMMenuSelect) ; message WM_MENUSELECT; end ... implementation ... procedure TForm1.WMMenuSelect (var Msg: TWMMenuSelect) ; var

126

menuItem : TMenuItem; hSubMenu : HMENU; begin inherited; // from TCustomForm //(so that Application.Hint is assigned) menuItem := nil; if (Msg.MenuFlag <> $FFFF) or (Msg.IDItem <> 0) then begin if Msg.MenuFlag and MF_POPUP = MF_POPUP then begin hSubMenu := GetSubMenu (Msg.Menu, Msg.IDItem) ; menuItem := Self.Menu.FindItem (hSubMenu, fkHandle) ; end else begin menuItem := Self.Menu.FindItem (Msg.IDItem, fkCommand) ; end; end; miHint.DoActivateHint(menuItem) ; end; (*WMMenuSelect*) A mensagem WM_MENUSELECT enviada janela proprietria do menu (Form 1) quando o usurio seleciona (no quando clica) um item de menu. Usando o mtodo FindItem da classe TMenu, voc consegue pegar o item de menu que est selecionado no momento. Os parmetros da funo FindItem relatam as propriedades que a mensagem recebeu. Uma vez que voc saiba qual o item de menu sobre qual est o mouse, chamaremos o mtodo DoActivateHint da classe TMenuItemHint. Observe que a varivel miHint definida como var miHint : TMenuItemHint e criada no evento OnCreate do Form. Agora vamos fazer a implementao da classe TMenuItemHint. Aqui est a parte da interface: TMenuItemHint = class(THintWindow) private activeMenuItem : TMenuItem; showTimer : TTimer; hideTimer : TTimer; procedure HideTime(Sender : TObject) ; procedure ShowTime(Sender : TObject) ; public constructor Create (AOwner : TComponent) ; override; procedure DoActivateHint

127

(menuItem : TMenuItem) ; destructor Destroy; override; end; Voc pode ver toda a implementao no projeto exemplo. Basicamente, a funo DoActivateHint chama o mtodo ActivateHint do THintWindow usando a propriedade Hint do TMenuItem (se estiver atribuda). O showTimer usado para se ter certeza que o HintPause (do Application) transcorre antes do hint ser mostrado. O hideTimer usa o Application.HintHidePause para esconder a janela do hint aps um intervalo especfico. Quando usar os hints nos itens do menu? Enquanto alguns podem dizer que no uma boa coisa mostrar hints nos itens de menu, h situaes que mostrar hints no menu muito melhor do que mostrar uma barra de status. Segue o cdigo fonte do Form, com a implementao da classe TMenuItemHint. unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Menus, AppEvnts, StdCtrls, ExtCtrls, ComCtrls; type TMenuItemHint = class(THintWindow) private activeMenuItem : TMenuItem; showTimer : TTimer; hideTimer : TTimer; procedure HideTime(Sender : TObject) ; procedure ShowTime(Sender : TObject) ; public constructor Create (AOwner : TComponent) ; override; procedure DoActivateHint (menuItem : TMenuItem) ; destructor Destroy; override; end; TForm1 = class(TForm) ... procedure FormCreate(Sender: TObject) ;

128

procedure ApplicationEvents1Hint (Sender: TObject) ; private miHint : TMenuItemHint; procedure WMMenuSelect (var Msg: TWMMenuSelect) ; message WM_MENUSELECT; end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate (Sender: TObject) ; begin miHint := TMenuItemHint.Create(self) ; end; (*FormCreate*) procedure TForm1.ApplicationEvents1Hint (Sender: TObject) ; begin StatusBar1.SimpleText := App.OnHint : + Application.Hint; end; (*Application.OnHint*) procedure TForm1.WMMenuSelect (var Msg: TWMMenuSelect) ; var menuItem : TMenuItem; hSubMenu : HMENU; begin inherited; // TCustomForm // (se certifica que o Application.Hint // atribudo) menuItem := nil; if (Msg.MenuFlag <> $FFFF) or (Msg.IDItem <> 0) then begin if Msg.MenuFlag and MF_POPUP = MF_POPUP then begin hSubMenu := GetSubMenu (Msg.Menu, Msg.IDItem) ; menuItem := Self.Menu.FindItem (hSubMenu, fkHandle) ; end else begin

129

menuItem := Self.Menu.FindItem (Msg.IDItem, fkCommand) ; end; end; miHint.DoActivateHint(menuItem) ; end; (*WMMenuSelect*)

{ TMenuItemHint } constructor TMenuItemHint.Create (AOwner: TComponent) ; begin inherited; showTimer := TTimer.Create(self) ; showTimer.Interval := Application. HintPause; hideTimer := TTimer.Create(self) ; hideTimer.Interval := Application. HintHidePause; end; (*Create*) destructor TMenuItemHint.Destroy; begin hideTimer.OnTimer := nil; showTimer.OnTimer := nil; self.ReleaseHandle; inherited; end; (*Destroy*) procedure TMenuItemHint.DoActivateHint (menuItem: TMenuItem) ; begin //fora a remoo da velha janela //do hint hideTime(self) ; if (menuItem = nil) or (menuItem.Hint = ) then begin activeMenuItem := nil; Exit; end; activeMenuItem := menuItem; showTimer.OnTimer := ShowTime; hideTimer.OnTimer := HideTime;

130

end; (*DoActivateHint*) procedure TMenuItemHint.ShowTime (Sender: TObject) ; var r : TRect; wdth : integer; hght : integer; begin if activeMenuItem <> nil then begin //position and resize wdth := Canvas.TextWidth (activeMenuItem.Hint) ; hght := Canvas.TextHeight (activeMenuItem.Hint) ; r.Left := Mouse.CursorPos.X + 16; r.Top := Mouse.CursorPos.Y + 16; r.Right := r.Left + wdth + 6; r.Bottom := r.Top + hght + 4; ActivateHint(r,activeMenuItem.Hint) ; end; showTimer.OnTimer := nil; end; (*ShowTime*) procedure TMenuItemHint.HideTime(Sender: TObject) ; begin //esconde (destroy) a janela hint self.ReleaseHandle; hideTimer.OnTimer := nil; end; (*HideTime*) end

Overwrite no TMemo e Tedit


Os controles do Windows TMemo e TEdit no tm a capacidade overwrite. No entanto, possvel simular este comportamento, ajustanto a propriedade SelLength do controle edit ou memo durante o processamento do evento KeyPress. Isso faz com que o caractere que est na posio corrente seja sobrescrito. O exemplo a seguir mostra como emular a capacidade de overwrite de um componente TMemo. O estado do modo de sobrescrever pode ser mudado pressionando a tecla Insert.

131

type TForm1 = class(TForm) Memo1: TMemo; procedure Memo1KeyDown (Sender: TObject; var Key: Word; Shift: TShiftState) ; procedure Memo1KeyPress (Sender: TObject; var Key: Char) ; private { Private declarations } InsertOn : bool; public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Memo1KeyDown (Sender: TObject; var Key: Word; Shift: TShiftState) ; begin if (Key = VK_INSERT) and (Shift = []) then InsertOn := not InsertOn; end; procedure TForm1.Memo1KeyPress (Sender: TObject; var Key: Char) ; begin if ((Memo1.SelLength = 0) and (not InsertOn)) then Memo1.SelLength := 1; end; Algumas vezes precisamos limpar todos os componentes Edit que esto no Form. Esta tarefa feita facilmente com o seguinte procedimento: procedure ClearEdits; var j : Integer; begin for j := 0 to ComponentCount-1 do if (Components[j] is TEdit) then (Components[j] as TEdit).Text := ; end;

132

Como chamar o Ver fonte (view source) em um WebBrowser


Aqui est como chamar o Ver fonte do IE (para examinar o HTML) com o componente TWebBrowser. Simplesmente arraste uma instncia do componente TWebBrowser em um formulrio e um boto (Button) e faa como segue: uses ActiveX; procedure WBViewSourceDialog (AWebBrowser: TWebbrowser) ; const CGID_WebBrowser: TGUID = {ED016940-BD5B-11cf-BA4E-00C04FD70816}; HTMLID_VIEWSOURCE = 2; var CmdTarget : IOleCommandTarget; vaIn, vaOut: OleVariant; PtrGUID: PGUID; begin New(PtrGUID) ; PtrGUID^ := CGID_WebBrowser; if AWebBrowser.Document <> nil then try AWebBrowser.Document. QueryInterface(IOleCommandTarget, CmdTarget) ; if CmdTarget <> nil then try CmdTarget.Exec(PtrGUID, HTMLID_VIEWSOURCE, 0, vaIn, vaOut) ; finally CmdTarget._Release; end; except end; Dispose(PtrGUID) ; end; procedure TForm1.FormCreate (Sender: TObject); begin WebBrowser1.Navigate (http://www.delphi.about.com) ; end;

133

procedure TForm1.Button1Click (Sender: TObject) ; begin WBViewSourceDialog(WebBrowser1) ; end;

MessageBox com timeout


Aqui est como chamar um Message Box com timeout, ele ir fechar a si mesmo aps um perodo de tempo. O truque chamar uma API no documentada localizada no user32.dll, a API a MessageBoxTimeOut. A funo retorna um valor inteiro para MB_TIMEDOUT (indicando que o perodo de tempo para o timeout foi alcanado e o Message Box foi automaticamente fechado), ou um valor representando o boto que o usurio clicou. Observe que o valor retornado sempre 1, quando o Message Box tem somente um boto de OK (MB_OKFlag). //declarao de interface const MB_TIMEDOUT = 32000; function MessageBoxTimeOut (hWnd: HWND; lpText: PChar; lpCaption: PChar; uType: UINT; wLanguageId: WORD; dwMilliseconds: DWORD): Integer; stdcall; external user32 name MessageBoxTimeoutA; //implementao (Apontamento do evento //OnClick do Button1 no Form1) procedure TForm1.Button1Click (Sender: TObject) ; var iRet: Integer; iFlags: Integer; begin iFlags := MB_OK or MB_SETFOREGROUND or MB_SYSTEMMODAL or MB_ICONINFORMATION; MessageBoxTimeout (Application.Handle, Test a timeout of 2 seconds., MessageBoxTimeout Teste, iFlags, 0, 2000) ; iFlags := MB_YESNO or MB_SETFOREGROUND or MB_SYSTEMMODAL or MB_ICONINFORMATION; iRet := MessageBoxTimeout (Application.Handle, Teste de timeout 134

de 5 segundos., MessageBoxTimeout Teste, iFlags, 0, 5000) ; case iRet of IDYES: ShowMessage(Yes) ; IDNO: ShowMessage(No) ; MB_TIMEDOUT: ShowMessage(TimedOut) ; end; end;

Como colocar uma barra de progresso dentro de um dialog box padro


Vamos dizer que voc tem um dialog box padro do Windows mostrando uma pergunta ao usurio com os botes de Yes e No. No seria timo se existisse uma barra de progresso contando o tempo at que o dialog box se feche automaticamente? Vamos l ento: Vamos criar um dialog usando CreateMessageDialog. Esta funo retornar um form object com o dialog. Neste objeto podemos adicionar a barra de progresso. Tambm podemos adicionar um objeto Timer para uma atualizao dinmica da posio da barra de progresso. Mostramos o dialog com ShowModal. Apontamos o evento OnTimer do componente TTimer para ver o nmero se passou a quantidade de segundos necessria, se sim, fechamos o dialog ajustando a propriedade ModalResult, no cdigo, para mrCancel. Se no, usamos StepIt para atualizar a barra de progresso. Coloque um boto no formulrio e tente este cdigo: procedure TForm1.Button1Click (Sender: TObject) ; var AMsgDialog : TForm; AProgressBar : TProgressBar; ATimer : TTimer; begin AMsgDialog := CreateMessageDialog(Quickly! Answer Yes or No!, mtWarning, [mbYes, mbNo]) ; AProgressBar := TProgressBar. Create(AMsgDialog) ; ATimer := TTimer.Create(AMsgDialog) ; with AMsgDialog do try Tag := 10; //seconds! Caption := You have 10 seconds; Height := 150;

135

with AProgressBar do begin Name := Progress; Parent := AMsgDialog; Max := AMsgDialog.Tag; //seconds Step := 1; Top := 100; Left := 8; Width := AMsgDialog.ClientWidth - 16; end; with ATimer do begin Interval := 1000; OnTimer:=DialogTimer; end; case ShowModal of ID_YES: ShowMessage(Answered Yes.) ; ID_NO: ShowMessage(Answered No.) ; ID_CANCEL: ShowMessage(Time up!) end;//case finally ATimer.OnTimer := nil; Free; end; end; //make sure you add this functions //header in the private part of the TForm1 //type declaration. procedure TForm1.DialogTimer(Sender:TObject); var aPB : TProgressBar; begin if NOT (Sender is TTimer) then Exit; if ((Sender as TTimer).Owner) is TForm then with ((Sender as TTimer).Owner) as TForm do begin aPB := TProgressBar (FindComponent(Progress)) ; if aPB.Position >= aPB.Max then ModalResult := mrCancel else aPB.StepIt; end; end;

136

Como imprimir uma pgina/documento com o TWebBrowser


Voc primeiro precisa carregar uma pgina no TWebBrowser, por exemplo (supondo que voc tem um componente chamado WebBroser1): WebBrowser1.Navigate(http://theclub.activeinterno.com.br); // impresso sem aparecer um dialog procedure WBPrintNoDialog(WB: TWebBrowser) ; var vIn, vOut: OleVariant; begin WB.ControlInterface.ExecWB (OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, vIn, vOut) ; end; //com chamada do dialog procedure WBPrintWithDialog(WB: TWebBrowser) ; var vIn, vOut: OleVariant; begin WB.ControlInterface.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, vIn, vOut) ; end; // Preview de impresso procedure WBPrintPreview(WB: TWebBrowser) ; var vIn, vOut: OleVariant; begin WB.ControlInterface.ExecWB(OLECMDID_PRINTPREVIEW, OLECMDEXECOPT_DONTPROMPTUSER, vIn, vOut); end; //Chama o dialog de setup de pgina procedure WBPrintPageSetup(WB: TWebBrowser) ; var vIn, vOut: OleVariant; begin WB.ControlInterface.ExecWB(OLECMDID_PAGESETUP, OLECMDEXECOPT_PROMPTUSER, vIn, vOut) ; end;

Como esconder o text cursor dentro de um Tmemo


Aqui est um cdigo exemplo de como esconder o text cursor no Memo1 dentro do Form1. Substitua todo o cdigo pelo que segue abaixo:

137

unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, ExtCtrls; const WM_MYMEMO_ENTER = WM_USER + 500; type TForm1 = class(TForm) Memo1: TMemo; procedure Memo1Enter(Sender: TObject) ; procedure Memo1Exit(Sender: TObject) ; procedure Memo1Change(Sender: TObject); private public procedure WMMYMEMOENTER (var Message: TMessage) ; message WM_MYMEMO_ENTER; end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.WMMYMEMOENTER (var Message: TMessage) ; begin CreateCaret(Memo1.Handle,0,0,0) ; end; procedure TForm1.Memo1Enter(Sender: TObject); begin PostMessage (Handle, WM_MYMEMO_ENTER, 0, 0); end; procedure TForm1.Memo1Exit(Sender: TObject); begin CreateCaret(Memo1.handle,1,1,1) ; end; procedure TForm1.MemoChange(Sender: TObject); begin

138

CreateCaret(Memo1.handle,0,0,0) ; end; end.

Como determinar a posio do cursor dentro de um TrichEdit


Veja o exemplo: { Usage: var sRC:string; src := GetPosition(RichEdit1) ; //src reults in a string //formated like: Row:Col } function GetPosition (ARichEdit: TRichEdit): string var iX,iY : Integer; begin iX := 0; iY := 0; iY := SendMessage(ARichEdit.Handle, EM_LINEFROMCHAR,ARichEdit.SelStart,0) ; iX := ARichEdit.SelStart SendMessage(ARichEdit.Handle, EM_LINEINDEX, iY, 0) ; Result := IntToStr(iY + 1) + : + IntToStr(iX + 1) ; end;

Como completer strings parciais digitadas dentro de um Combo Box


O exemplo abaixo mostra como completar strings parciais digitadas dentro de um combo box. O cdigo representa o apontamento do evento OnKeyPress do combo box, que faz a execuo padro das teclas antes de encontrar o item na lista correspondente e atualizar o texto. Observao: O evento OnKeyPress no faz nada quando o usurio pressiona Delete. Neste caso deve-se capturar a tecla utilizando-se o evento OnKeyDown. procedure TForm1.ComboBox1KeyPress(Sender: TObject; var Key: Char) ; var Found: boolean; j,SelSt: Integer;

139

TmpStr: string; begin { primeiro, processe a tecla para obter a string corrente } { Este cdigo requer que todos os itens estejam listados em uppercase} if Key in [a..z] then Dec(Key,32) ; {Somente Uppercase!} with (Sender as TComboBox) do begin SelSt := SelStart; if (Key = Chr(vk_Back)) and (SelLength <> 0) then TmpStr := Copy(Text,1,SelStart)+Copy (Text,SelLength+SelStart+1,255) else if Key = Chr(vk_Back) then {SelLength = 0} TmpStr := Copy(Text,1,SelStart1)+Copy(Text,SelStart+1,255) else {Key in [A..Z, etc]} TmpStr := Copy(Text,1,SelStart)+Key+Copy (Text,SelLength+SelStart+1,255) ; if TmpStr = then Exit; { atualize SelSt para a posio corrente de insero } if (Key = Chr(vk_Back)) and (SelSt > 0) then Dec(SelSt) else if Key <> Chr(vk_Back) then Inc(SelSt) ; Key := #0; { indica qual tecla foi apontada } if SelSt = 0 then begin Text:= ; Exit; end; {Agora que TmpStr a string sendo digitada no momento, veremos se conseguimos encontrar uma correspondncia } Found := False; for j := 1 to Items.Count do if Copy(Items[j-1],1,Length(TmpStr)) = TmpStr then begin

140

Text := Items[j-1]; { atualize para a correspondente que foi encontrada} ItemIndex := j-1; Found := True; Break; end; if Found then { selecione o final no digitado da string } begin SelStart := SelSt; SelLength := Length(Text)-SelSt; end else Beep; end; end;

Como arredondar os cantos dos controles


Aqui est como desenhar controles com os cantos arredondados. Para testar, arraste um TEdit, TPanel e TMemo em um formulrio. procedure DrawRounded(Control: TWinControl) ; var R: TRect; Rgn: HRGN; begin with Control do begin R := ClientRect; rgn := CreateRoundRectRgn(R.Left, R.Top, R.Right, R.Bottom, 20, 20); Perform(EM_GETRECT, 0, lParam(@r)) ; InflateRect(r, - 4, - 4) ; Perform(EM_SETRECTNP, 0, lParam(@r)) ; SetWindowRgn(Handle, rgn, True) ; Invalidate; end; end; procedure TForm1.FormCreate(Sender: TObject); begin // arredondando o Panel1 DrawRounded(Panel1) ; // arredondando o Memo1 Memo1.BorderStyle := bsNone; DrawRounded(Memo1) ; // arredondando o Edit1 Edit1.BorderStyle := bsNone;

141

DrawRounded(Edit1) ; end;

Usando as setas do teclado para se mover entre os controles


As teclas Up e Down so virtualmente inteis em controles Edit. Ento, porque no uslas para navegar entre os controles? Se voc ajustar a propriedade KeyPreview de um form para True voc pode usar o seguinte cdigo no seu evento OnKeyDown do formulrio para controlar a navegao: procedure TForm1.FormKeyDown( Sender : TObject; var Key: Word; Shift : TShiftState ); var Direction : Integer; begin Direction := -1; case Key of VK_DOWN, VK_RETURN : Direction := 0; {Next} VK_UP : Direction := 1; {Previous} end; if Direction <> -1 then begin Perform(WM_NEXTDLGCTL, Direction, 0) ; Key := 0; end; end;

Qual a palavra sob o cursor do mouse em um TRichEdit?


Aqui est o cdigo para voc saber qual a palavra que est sob o cursor do mouse. A varivel string WordInRE conter a palavra. Observao: Voc precisar de um TRichEdit (RichEdit1), um form (Form1), e o cdigo abaixo no evento OnMouseMove do RichEdit1.

142

uses RichEdit; var WordInRE : string; procedure TForm1.RichEdit1MouseMove (Sender: TObject; Shift: TShiftState; X, Y: Integer) ; var ci, lix, co, k, j: Integer; Pt: TPoint; s: string; begin with TRichEdit(Sender) do begin Pt := Point(X, Y) ; ci := Perform(Messages. EM_CHARFROMPOS, 0, Integer(@Pt)) ; if ci < 0 then Exit; lix := Perform (EM_EXLINEFROMCHAR, 0, ci); co := ci - Perform (EM_LINEINDEX, lix, 0) ; if -1 + Lines.Count < lix then Exit; s := Lines[lix]; Inc(co) ; k := co; while (k > 0) and (s[k] <> ) do k:=k-1; Inc(co) ; j := co; while (j <= Length(s)) and (s[j] <> ) do Inc(j) ; WordInRE := Copy(s, k, j - i) ; end; end;

143

Mostra o total de pginas


Voc pode fazer este tipo de trabalho, mas ele ter que ser manual. O primeiro passo pegar o total de pginas e jogar para uma varivel. Para pegar o total de pginas voc pode executar o cdigo abaixo antes de chamar o relatrio. QuickRep1.Prepare; TotalPaginas := QuickRep1.PageNumber; TotalPaginas mostrada anteriormente uma varivel do tipo inteiro. Para mostrar isto no QuickReport voc pode utilizar um componente QRSysData alterando a propriedade Data para PageNumber e colocar a rotina a seguinte no evento OnPrint. procedure TForm1.QRSysData1Print (sender: TObject; var Value: String); begin Value := Value + / + IntToStr(TotalPaginas) end;

InnoSetup Verificando a verso do software, se inferior, ento, no instalar


O InnoSetup permite a incluso de scripts em uma sua seo CODE e isso sem dvidas permite grande flexibilidade no desenvolvimento de instalaes personalizadas. Abaixo, segue um script para o InnoSettup onde demonstramos como efetuar este tipo de verificao. [Setup] AppName=VerificaVersao AppVerName=VerificaVersao DefaultDirName={pf}\VerificaVersao DisableStartupPrompt=true Uninstallable=false DisableDirPage=true OutputBaseFilename=VerificaVersao [Code] function GetVersion(): String; var sVersion: String; begin sVersion := ; GetVersionNumbersString( ExpandConstant

144

({win}\notepad.exe) , sVersion ); Result := sVersion; end; function InitializeSetup(): Boolean; begin if GetVersion() = 5.1.2600.0 then begin MsgBox( Verso instalada: + GetVersion() + chr(13) + Voc s poder instalar uma verso superior., mbInformation, MB_OK ); Result := false; end else Result := true; end;

InnoSetup Manipulao de arquivos texto


Utilizando a seo de codificao do InnoSetup possvel implementar a manuteno em arquivos texto de forma bem simples, acompanhe o script abaixo: [Setup] AppName=EditaTexto AppVerName=EditaTexto DefaultDirName={pf}\EditaTexto DisableStartupPrompt=true Uninstallable=false DisableDirPage=true OutputBaseFilename=EditaTexto [Code] function AddToText(strFilename, strNewLine: String): Boolean; var strTemp : String; iLineCounter : Integer; a_strTextfile : TArrayOfString; begin Result := False; { Carrega as linhas do texto em um Array } LoadStringsFromFile(strFilename, a_strTextfile); { Adiciona uma linha no Array } SetArrayLength(a_strTextfile, GetArrayLength(a_strTextfile)+1); { Escreve o texto } a_strTextfile[GetArrayLength (a_strTextfile)-1] := strNewLine;

145

{ Regrava o arquivo } SaveStringsToFile(strFilename, a_strTextfile, False); Result := True; end; function InitializeSetup(): Boolean; var Arquivo: String; begin Arquivo := ExpandConstant({pf}\ Firebird\Firebird_1_5\aliases.conf); if AddToText(Arquivo, THECLUB = D:\THECLUB\THECLUB.FDB) then begin MsgBox(Alterao efetuada com sucesso!, mbInformation, MB_OK ); Result := false; end else Result := true; end;

Finalizando processos do Windows via programao


Segue abaixo instruo para finalizar um processo do Windows, via Delphi. implementation Uses Tlhelp32; {$R *.dfm} function KillTask(ExeFileName: string): Integer; const PROCESS_TERMINATE=$0001; var ContinueLoop: BOOL; FSnapshotHandle: THandle; FProcessEntry32: TProcessEntry32; begin Result := 0; FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); FProcessEntry32.dwSize := Sizeof(FProcessEntry32); ContinueLoop := Process32First (FSnapshotHandle, FProcessEntry32); while integer(ContinueLoop) <> 0 do begin

146

if ((UpperCase(ExtractFileName (FProcessEntry32.szExeFile)) = UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) = UpperCase (ExeFileName))) then Result := Integer(TerminateProcess (OpenProcess(PROCESS_TERMINATE, BOOL(0),FProcessEntry32. th32ProcessID), 0)); ContinueLoop := Process32Next (FSnapshotHandle, FProcessEntry32); end; CloseHandle(FSnapshotHandle); end; procedure TForm1.Button1Click(Sender: TObject); begin KillTask( Outlook.exe ); end;

Gravando CDs
No endereo: http://sourceforge.net/projects/delphineroapi/ encontrar um pacote de APIs para Delphi que possibilitam efetuar a gravao de CDs.

Quick Report - Obtendo a lista de papeis disponveis


No caso do QReport, o mesmo possui uma tipagem prpria com nomes dos papeis que no coincidem com os tipos pr-definidos no Windows. Assim sendo, adicione estes valores fixos ao seu ComboBox, pois, estes so dos tipos possvel aceitos pelo QR: TQRPaperSize = (Default, Letter, LetterSmall, Tabloid, Ledger, Legal, Statement, Executive, A3, A4, A4Small, A5, B4, B5, Folio, Quarto, qr10X14, qr11X17, Note, Env9, Env10, Env11, Env12, Env14, CSheet, DSheet, ESheet, Custom) Para pegar o valor do ComboBox e alterar no QReport, utilize o seguinte: implementation uses QrPrNtr, TypInfo; {$R *.dfm} procedure SetPaper(const PaperName: string; QR: TQuickRep); var Paper : TQRPaperSize; 147

begin Paper := TQRPaperSize(GetEnumValue(TypeInfo (TQRPaperSize),PaperName)); QR.Page.PaperSize := Paper; end; procedure TForm1.Button1Click(Sender: TObject); begin SetPaper(LetterSmall, QuickRep1); // ou SetPaper(ComboBox.Items[ComboBox.ItemIndex], QuickRep1); end;

DBGrid - Como fazer quebra de linhas


Iremos demonstrar aqui como fazer quebra de linhas no texto apresentado em um DBGrid. Para isso, ser necessrio declararmos um tipo para poder acessar propriedades protegidas do mesmo. { tipo para acessar propriedades protegidas } type TGrid = class(TCustomDBGrid); { Flags de alinhamento } const AlignFlags : array [TAlignment] of Integer = ( DT_LEFT or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX, DT_RIGHT or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX, DT_CENTER or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX ); RTL: array [Boolean] of Integer = (0, DT_RTLREADING); var Form1: TForm1; implementation {$R *.dfm} { Evento OnDrawColumnCell do DBGrid. } procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); var R: TRect; begin with DBGrid1 do begin if DataCol = 1 then { Verifica se a 2 coluna} begin

148

CopyRect(R, Rect); Canvas.FillRect(Rect); { Ajusta limite para Quebrar o texto, neste caso, verifica a largura da coluna } R.Right := R.BottomRight.X; { desenha o texto na "rea" determinada em "R" } DrawText(Canvas.Handle, PChar(Column.Field.AsString), StrLen(PChar(Column.Field.AsString)), R, DT_EXPANDTABS or DT_WORDBREAK ); end; end; end; { Evento OnCreate do Form } procedure TForm1.FormCreate(Sender: TObject); begin { Ajusta altera padro para as linhas } TGrid(DBGrid1).DefaultRowHeight := 50; end;

Mensagens: Alterar a cor da fonte de um ShowMessage


Neste dica, utilizamos um evento do objeto Application para verificar que houve mudana de formulrio e se o formulrio que foi chamado for do tipo TmessageForm (o qual indica que uma caixa de mensagem), ir alterar a cor da fonte do texto da mesma. Vamos ao cdigo: type TForm1 = class(TForm) Button1: TButton; procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure Button1Click(Sender: TObject); private public procedure FormFoco(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormFoco(Sender: TObject); var Comp: TLabel; begin { Verifica se o form que est com o

149

foco o form de mensagem } if Screen.ActiveForm.ClassName = TMessageForm then begin { Pesquisa o componente label de mensagem } Comp := TLabel(Screen.ActiveForm. FindComponent(Message)); if Comp <> Nil then Comp.Font.Color :=clBlue; { Altera a sua cor } end; end; procedure TForm1.FormCreate(Sender: TObject); begin Screen.OnActiveFormChange := FormFoco; end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin Screen.OnActiveFormChange := Nil; end; procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage(THE CLUB - O maior clube de programadores do Brasil); end; end.

Arquivo: Verificar se est ReadOnly


var Attributes: Word; begin Attributes := FileGetAttr(d:\arquivo.txt); if (Attributes and faReadOnly) = faReadOnly then ShowMessage(ReadOnly); end;

DBGrid: Como alterar a altura das linhas


Existem propriedades protegidas no DBGrid que para podermos acess-las somos obrigados a derivar uma nova classe. Veja o cdigo abaixo: type TGrid = class(TCustomDBGrid); var Form1: TForm1;

150

implementation {$R *.dfm} procedure TForm1.SpeedButton1Click(Sender: TObject); begin { ajusta altura padro para as linhas } TGrid(DBGrid1).RowHeights[1] := 50; end;

Treeview Foco
Veja neste exemplo como mandar o foco um tem do treeview quando clicar no boto de expanso (+): // evento OnMouseDown do Treeview. procedure TForm1.TreeView1MouseDown (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var T: TTreeNode; begin // Pega o tem atravs das coordenadas do mouse. T := Treeview1.GetNodeAt(X,Y); if T <> nil then Treeview1.Selected := T; end;

Rave Report Indicar pgina inicial


O Rave Reports permite ter vrias pginas de relatrio (cada pgina com um layout) para um mesmo relatrio. Neste exemplo, iremos demonstrar como definir via programao qual pgina ser apresentada como inicial. uses RVClass, RVProj, RVCsStd; procedure TForm1.btnChamaRelClick (Sender: TObject); var Pagina: TRavePage; Report: TRaveReport; QualPagina: String; begin // Nome da pgina dentro do projeto Rave. QualPagina := Page2;

151

// Abre RvProject. RvProject1.Open; // Pega referncia do Report // dentro do projeto Rave. Report := RvProject1.ProjMan.ActiveReport; // Pega referncia da Page dentro do Report. Pagina := RvProject1.ProjMan.FindRaveComponent (Report1.+QualPagina,nil) as TRavePage; // Indica a pgina inicial. Report.FirstPage := Pagina; // Executa o relatrio. RvProject1.Execute; end;

Desktop do Windows auto-arranjar icones


Esta dica pode ser til aps a instalao de sua aplicao, onde geralmente disponibilizado um cone na rea de trabalho do Windows e em muitos casos sendo necessrio arranj-los aps a instalao. mplementation uses CommCtrl; {$R *.dfm} function GetDesktopListViewHandle: THandle; var S: String; begin Result := FindWindow(ProgMan, nil); Result := GetWindow(Result,GW_CHILD); Result := GetWindow(Result, GW_CHILD); SetLength(S, 40); GetClassName(Result, PChar(S), 39); if PChar(S) <> SysListView32 then Result := 0; end; procedure TForm1.Button1Click(Sender: TObject); begin SendMessage(GetDesktopListViewHandle, LVM_ARRANGE, 0, 0); end;

152

Clculo de Parcelas
Neste simples exemplo iremos demonstrar como fazer a diviso de um valor em parcelas, fazendo o tratamento da diferena, jogando para a primeira ou ltima parcela, na figura 1 poder verificar o layout sugerido para o formulrio deste exemplo.

Figura 1 Layout sugerido Acompanha agora o cdigo do boto Gerar: procedure TForm1.btnGerarClick(Sender: TObject); var Total, ValorParc, TotParc: Extended; NParc: Integer; Parcelas: Array of Extended; i: Integer; begin { Variveis auxiliares } Total := 0; ValorParc := 0; TotParc := 0; NParc := 0; ListParcelas.Clear; { tenta converter o valor do Edit } try Total := StrToFloat(edValor.Text); except ShowMessage(Valor Invlido!); Abort; end; { Verifca nmero de parcelas } if speParcelas.Value < 2 then

153

Exit else NParc := speParcelas.Value; { Pega somente a parte inteira da diviso } ValorParc := Trunc(Total / NParc); { Ajusta array que guardar o } {valor de cada parcela } SetLength(Parcelas, NParc); { Atribui valor de cada parcela e acumula total } for i := Low(Parcelas) to High(Parcelas) do begin Parcelas[i] := 0; Parcelas[i] := ValorParc; TotParc := TotParc + Parcelas[i]; end; { Verifica em qual parcela ser jogada a } { diferena } if rg_diferenca.ItemIndex = 0 then Parcelas[Low(Parcelas)] := Parcelas[Low(Parcelas)] + (Total - TotParc) else Parcelas[High(Parcelas)] := Parcelas[High(Parcelas)] + (Total - TotParc); { mostra parcelas no ListBox } for i := Low(Parcelas) to High(Parcelas) do ListParcelas.Items.Add(FormatFloat(###,##0.00, Parcelas[i])); end; O exemplo referente esta dica est disponvel para download em: http://theclub.activeinterno.com.br/revista/downloads/CalcParcelas.zip

Porta Serial Como verificar se uma porta est em uso


Existem APIs do Windows que possibilitam fazer acesso e manuteno portas seriais, veja abaixo: var portHandle: Integer; begin portHandle := 0; portHandle := CreateFile(Pchar(ComboCOM.Text), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if portHandle > 0 then

154

ShowMessage(Porta em uso!) else raise Exception.Create (No consegui abrir a porta!); end;

GIF Como converter uma imagem GIF para BMP


Neste exemplo, estamos utilizando o objeto TGifImage que instalado junto com a suite de componentes RxLib. Esta suite gratuta e possui vrios componentes bem legais e, caso haja interesse, poder baixar em nosso site, theclub.activeinterno.com.br. Abaixo, segue a rotina de converso: implementation uses RxGif; {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); var GIF: TGIFImage; BMP: TBitmap; begin GIF := TGIFImage.Create; BMP := TBitmap.Create; try GIF.LoadFromFile(c:\banner_theclub.gif); BMP.Assign(GIF); BMP.SaveToFile(c:\theclub.bmp); finally GIF.Free; BMP.Free; end; end;

Veja como criar atalhos no menu iniciar do Windows


Neste exemplo, iremos demonstrar uma forma bastante simples para criar: - Grupos de programas - Items de programas - Atalhos para programas Em nossa abordagem, no iremos utilizar a criao via interface DDE por alguns questes de parametrizao e sim, demonstraremos a partir da criao direta de folders na pasta Programs do Windows.

155

Primeiramente, vamos criar uma procedure para criao de atalhos: implementation uses ShlObj, ActiveX, ComObj; {$R *.dfm} procedure CriaShortCut(aNome, aFileName, aPathGroup: string; aLocation: integer); var IObject : IUnknown; ISLink : IShellLink; IPFile : IPersistFile; PIDL : PItemIDList; InFolder : array[0..MAX_PATH] of Char; TargetName : String; LinkName,s : WideString; begin TargetName := aFileName; IObject := CreateComObject(CLSID_ShellLink); ISLink := IObject as IShellLink; IPFile := IObject as IPersistFile; with ISLink do begin SetPath(pChar(TargetName)); SetWorkingDirectory(pChar(ExtractFilePath(TargetName))); end; SHGetSpecialFolderLocation(0, aLocation, PIDL); SHGetPathFromIDList(PIDL, InFolder); s := InFolder; LinkName := s + \ + aPathGroup + \ + aNome + .LNK; IPFile.Save(PWChar(LinkName), false); end; Esta procedure recebe como parmetro o Nome do atalho a ser apresentado, o caminho e nome do aplicativo a ser executado, e por ltimo o grupo ao qual ele ir pertencer no menu Iniciar do Windows. Agora vamos para a procedure responsvel em criar o Grupo e o tem de Programa: function CreateFolder(Foldername: string; aLocation: integer): boolean; var pIdl: PItemIDList; hPath: PChar; begin Result := False;

156

if SUCCEEDED(SHGetSpecialFolderLocation(0, aLocation, pidl)) then begin hPath := StrAlloc(max_path); SHGetPathFromIDList(pIdl, hPath); SetLastError(0); if ForceDirectories(PChar(hPath + \\ + Foldername)) then Result := true; StrDispose(hPath); end; end; Observe que esta procedure recebe como parmetro o nome do grupo (que na realidade ser o nome de um Folder e a localizao, ou seja, onde ele dever ser criado. Exemplo de utilizao: procedure TForm1.Button1Click(Sender: TObject); begin // cria Grupo principal. CreateFolder(The Club, CSIDL_PROGRAMS); // cria sub-grupo dentro do The Club CreateFolder(The Club\Grupo 1, CSIDL_PROGRAMS); // cria sub-grupo dentro do The Club CreateFolder(The Club\Grupo 2, CSIDL_PROGRAMS); // cria sub-grupo dentro do The Club CreateFolder(The Club\Grupo 3, CSIDL_PROGRAMS); // cria sub-grupo dentro do The Club\Grupo 1 CreateFolder(The Club\Grupo 1\Sub Grupo 1, CSIDL_PROGRAMS); // cria sub-grupo dentro do The Club\Grupo 2 CreateFolder(The Club\Grupo 2\Sub Grupo 1, CSIDL_PROGRAMS); // cria sub-grupo dentro do The Club\Grupo 3 CreateFolder(The Club\Grupo 3\Sub Grupo 4, CSIDL_PROGRAMS); // cria atalho para os programas CriaShortCut(Calculadora, c:\windows\system32\calc.exe , The Club\Grupo 1, CSIDL_PROGRAMS); CriaShortCut(Bloco de Notas, c:\windows\system32\notepad.exe, The Club\Grupo 2, CSIDL_PROGRAMS); CriaShortCut(WordPad, C:\Program Files\Windows NT\Accessories\wordpad.exe, The Club\Grupo 3, CSIDL_PROGRAMS); end; Dica: A constante CSIDL_PROGRAMS indica a pasta padro onde os tens do menu iniciar do Windows ficam armazenados. Trabalhando com esta constante, independente da verso e linguagem do Windows, a pasta ir ser criada no local correto. Observe que primeiramente criamos um grupo principal, chamado The Club. Seguindo, dentro de The Club criamos sub-grupos e dentro dos sub-grupos os atalhos que iro chamar os aplicativos em questo.

157

Este exemplo est disponvel para download em nosso site no endereo: http://theclub.activeinterno.com.br/revista/download/CriaGrupoAtalho.zip

Como mover um componente em Run-time


Para montar este exemplo vamos incluir um componente Button. Para testar este exemplo mantenha a tecla CTRL pressionada clique com o mouse sobre o componente Button e arraste-o para qualquer lugar do form.

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure Button1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure Button1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); private { Private declarations } public { Public declarations } MouseDownSpot : TPoint; Capturing : bool; end; var Form1: TForm1; implementation {$R *.dfm} // Evento OnMouseDown do boto procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 158

begin if ssCtrl in Shift then begin SetCapture(Button1.Handle); Capturing := true; MouseDownSpot.X := x; MouseDownSpot.Y := Y; end; end; // Evento OnMouseMove do boto procedure TForm1.Button1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if Capturing then begin Button1.Left:= Button1.Left(MouseDownSpot.x-x); Button1.Top:= Button1.Top (MouseDownSpot.y-y); end; end; // Evento OnMouseUp do boto procedure TForm1.Button1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Capturing then begin ReleaseCapture; Capturing := false; Button1.Left := Button1.Left (MouseDownSpot.x -x); Button1.Top := Button1.Top (MouseDownSpot.y - y); end; end;

Como apresentar o nmero da linha e coluna em um DBGrid?


O DBGrid possui estas informaes, porm elas no esto visveis para acesso direto. Contudo, podemos derivar uma classe a partir de TDBGrid e utiliz-las sem problemas...

implementation {$R *.DFM} type TMostraProp = class (TDBGrid);

159

{evento OnColEnter do DBGrid} procedure TForm1.DBGrid1ColEnter(Sender: TObject); begin Caption := Format(Coluna: %2d; Row: %2d, [TMostraProp(DbGrid1).Col, TMostraProp(DbGrid1).Row]); end; { evento OnDataChange do DataSource } procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField); begin DBGrid1ColEnter(Sender); end;

Como implementar um log de todos os erros gerados na aplicao?


Isso poder ser implementado utilizando um componente TApplicationEvents (aba Additional), interceptando seu evento OnException e gerando um arquivo texto com as mensagens de erros geradas durante a execuo do aplicativo. Para isso, adicione um componente TapplicationEvents no Form principal de sua aplicao e abra o evento OnExxception onde iremos programar o seguinte:

procedure TFormLog.LogException(Sender: TObject; E: Exception); var NomeDoLog: string; Arquivo: TextFile; begin { preparar o arquivo de log utiliza o nome da aplicao, trocando a extenso para .log. } NomeDoLog := ChangeFileExt(Application.Exename, .log); { pega ponteiro para o arquivo } AssignFile(Arquivo, NomeDoLog); { verifica se existe } if FileExists(NomeDoArquivo) then Append(Arquivo) { se existir, apenas adiciona linhas } else ReWrite(Arquivo); { cria um novo se no existir } try { grava Data e Hora + Mensagem de erro } WriteLn(Arquivo, DateTimeToStr(Now) + : + E.Message); { mostra mensagem original de erro } Application.ShowException(E); finally { fecha o arquivo } CloseFile (LogFile); end; end;
Para testar, bastar por exemplo em um boto, gerar uma exceo de diviso por zero:

160

procedure TForm1.Button1Click(Sender: TObject); var a, b, c: Integer; begin a := 10; b := 0; c := a div b; ShowMessage(IntToStr(c)); end;

Printers - Como retornar informaes das impressoras instaladas na mquina


Nesta dica, demonstraremos como retornar informaes teis das impressoras instaladas na mquina, como por exemplo, o caminho da rede, seu nome de compartilhamento, porta, etc. Insira um componente ListView e um boto, como mostra a figura 1.

Na lista de uses, declare:

uses Printers, WinSpool; { Procedure que ir adicionar as informaes ao ListView } procedure AdicionaImpressoras(LV: TListView; Servidor, NomeImpressora, Compartilhamento, Porta, NomeDriver, Comentario: String); var i: integer; begin with LV do begin Items.Add; i := Items.Count-1; Items[i].Caption := Servidor; Items[i].SubItems.Add(NomeImpressora); Items[i].SubItems.Add(Compartilhamento); Items[i].SubItems.Add(Porta); Items[i].SubItems.Add(NomeDriver); Items[i].SubItems.Add(Comentario);

161

end; end;
O retorno das informaes ser feito atravs da API EnumPrinters:

procedure GetPrinterList(List: TListView); var Buffer, PrinterInfo: PChar; Flags, Count, NumInfo: DWORD; i: Integer; Level: Byte; begin Flags := PRINTER_ENUM_CONNECTIONS or PRINTER_ENUM_LOCAL; Level := 2; Count := 0; EnumPrinters(Flags, nil, Level, nil, 0, Count, NumInfo); if Count > 0 then begin GetMem(Buffer, Count); try if not EnumPrinters(Flags, nil, Level, PByte(Buffer), Count, Count, NumInfo) then Exit; PrinterInfo := Buffer; for i := 0 to NumInfo - 1 do begin case Level of 2: begin AdicionaImpressoras(List, PPrinterInfo2(PrinterInfo)^.pServerName, PrinterInfo2(PrinterInfo)^.pPrinterName, PPrinterInfo2(PrinterInfo)^.pShareName, PPrinterInfo2(PrinterInfo)^.pPortName, PPrinterInfo2(PrinterInfo)^.pDriverName, PPrinterInfo2(PrinterInfo)^.pComment); Inc(PrinterInfo, SizeOf(TPrinterInfo2)); end; 4: begin AdicionaImpressoras(List, PPrinterInfo4(PrinterInfo)^.pServerName, PPrinterInfo4(PrinterInfo)^.pPrinterName, null, null, null, null); Inc(PrinterInfo, SizeOf(TPrinterInfo4)); end; 5: begin AdicionaImpressoras(List, null, PPrinterInfo5(PrinterInfo)^.pPrinterName, null, PPrinterInfo2(PrinterInfo)^.pPortName,

162

null, null); Inc(PrinterInfo,SizeOf(TPrinterInfo5)); end; end; end; finally FreeMem(Buffer, Count); end; end; end; { abaixo, fazemos a chamada da procedure no evento OnClick do boto } GetPrinterList(LView);
O projeto completo referente esta dica est disponvel para download em http://theclub.activeinterno.com.br/revista/download/ListaImpressoras.zip

IP Como retornar o hostname a partir de um endereo IP


Em muitas situaes, necessitamos saber o nome de uma mquina e temos apenas seu endereo IP. Na unit WinSock, poderemos encontrar diversas APIs para este tipo de abordagem, veja abaixo um simples exemplo: implementation uses WinSock; {$R *.dfm} function ResolveHostByIp(IP: string): String; type TAPInAddr = Array[0..100] of PInAddr; PAPInAddr = ^TAPInAddr; var WSAData: TWSAData; Address: String; InetAddr: u_long; HostEntPtr: PHostEnt; HostEnt: THostEnt; HostName: String; len, struct: Integer; i: Integer; begin Result := ; WSAStartUp( $101, WSAData );

163

try Address := Trim(IP); if Address = then raise Exception.Create ( IP address not entered ); // Convert textual IP address to binary format InetAddr := inet_addr( PChar(Address) ); if InetAddr = SOCKET_ERROR then raise Exception.Create ( Invalid address entered ); // Get hist entry by IP HostEntPtr := GetHostByAddr( @InetAddr, len, struct ); if HostEntPtr = NIL then raise Exception.Create( WinSock error: + IntToStr( WSAGetLastError() ) ); // Insert hostname into list HostName := String( HostEntPtr^.h_name ); Result := HostName; except on E: Exception do begin Beep(); ShowMessage( E.Message ); end; end; WSACleanUp(); end;
Para utilizar:

Edit.Text := ResolveHostByIp(200.210.71.16); // retorna o nome da mquina

Windows Como criar grupos e subgrupos de programas no menu iniciar


Uma das formas para fazer a criao de grupos e subgrupos de aplicativos no menu iniciar do Windows, obtendo o path de sistema onde o Windows guarda estas informaes e nele criar os grupos. Veja abaixo como proceder: implementation uses ShlObj, FileCtrl; {$R *.dfm}

164

function GetProgramFolder: string; var pidl: PItemIDList; Path: array[0..MAX_PATH] of char; begin SHGetSpecialFolderLocation(Application.Handle, CSIDL_PROGRAMS, pidl); SHGetPathFromIDList(pidl,path); Result := path; Result := Result + \; end; function CriaGrupo(Path: string): Boolean; begin Result := ForceDirectories(GetProgramFolder+Path); end; procedure TForm1.Button1Click(Sender: TObject); begin if CriaGrupo(TheClub\Grupo 1) then ShowMessage(Grupo TheClub\Grupo 1 criado com sucesso!); if CriaGrupo(TheClub\Grupo 2) then ShowMessage(Grupo TheClub\Grupo 2 criado com sucesso!); if CriaGrupo(TheClub\Grupo 3) then ShowMessage(Grupo TheClub\Grupo 3 criado com sucesso!); end;

Windows Como desabilitar uma combinao de teclas genericamente


Para desabilitar uma combinao de teclas vlida para todos os formulrios da aplicao, ser necessrio fazer um tratamento de mensagens do Windows. O exemplo abaixo demonstra como desabilitar a combinao CTRL+P:

type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); private procedure ProcessaMsg(var Msg: TMsg; var Handled: Boolean); { Private declarations } public { Public declarations } end; var Form1: TForm1;

165

implementation {$R *.DFM} { procedure de tratamento } procedure TForm1.ProcessaMsg(var Msg: TMsg; var Handled: Boolean); begin if Msg.message = WM_KEYDOWN then begin if (GetASyncKeyState(VK_CONTROL) <> 0) and (GetASyncKeyState(Ord(P)) <> 0) then // Ctrl+P begin ShowMessage(Ctrl+P est sendo desabilitado!); Msg.wParam := VK_CLEAR; end; end; end; procedure TForm1.FormCreate(Sender: TObject); begin { liga a procedure } Application.OnMessage := ProcessaMsg; end; end.

Veja como definir o papel de impresso personalizado no Windows XP/2000/NT


No Windows 9x, para definirmos um papel como personalizado basta acessar as propriedades da impressora que iremos encontrar este tipo de papel. Porm, no Windows XP isso um pouco diferente, pois no h um papel pr-definido como personalizado, porm temos a opo de criar um novo tipo de papel nas medidas que desejarmos. Para isso, abra o item Impressoras & Faxes de seu Windows e sem selecionar NENHUMA impressora acesse o menu Arquivo ( ou File) e neste selecione a opo Propriedades do Servidor (ou Server Properties) como mostra a imagem ao lado. Agora, bastar clicar em Create a new form e criar o seu papel personalizado e salvar logo em seguida e clicar em OK para finalizar!

166

Bom, agora bastar acessar as propriedades da impressora e definir este novo papel nas configuraes de sua impressora, como exemplo:

funo que me retorne a quantidade de arquivos existentes em um dado diretrio? Poder utilizar o objeto TSearchRec para obter o nmero de arquivos em um dado diretrio:

implementation {$R *.dfm} function GetTotFiles(Diretorio: String): Integer; var SRec: TSearchRec; 167

Res: Integer; begin Result := 0; Res := FindFirst(Diretorio+\*.*, faAnyFile, SRec); while Res = 0 do begin Res := FindNext(SRec); Inc(Result); end; end; procedure TForm1.Button1Click(Sender: TObject); begin Caption := IntToStr( GetTotFiles(d:\testes) ); end;

168

Você também pode gostar