You are on page 1of 14

Dicas de Delphi - Formulrios

y y y y y y y y y y y y y y y

Forar foco em janela Anexar dois forms Impedir que o form seja fechado com Alt+F4 Impedir que o form seja arrastado para fora das margens da tela Enviar comandos de rolagem vertical para um TMemo Construir a barra de ttulo do form com um Panel Criar form sem ttulo que possa ser arrastado Criar caixas de dilogo em tempo de execuo Determinar se uma janela (form) est maximizada Determinar se o aplicativo est minimizado Maximizar um form de forma que cubra toda a tela, inclusive a barra de tarefas Posicionar Form's em relao ao Desktop do Windows Salvar/restaurar o tamanho e posio de Form's Mostrar um Form de LogOn antes do Form principal Fazer a barra de ttulo ficar intermitente (piscante)

Forar foco em janela


As funes abaixo foram para que a janela informada fique em primeiro plano. Primeira alternativa
function ForceForegroundWindow(hwnd: THandle): Boolean; const SPI_GETFOREGROUNDLOCKTIMEOUT = $2000; SPI_SETFOREGROUNDLOCKTIMEOUT = $2001; var ForegroundThreadID: DWORD; ThisThreadID: DWORD; timeout: DWORD; begin if IsIconic(hwnd) then ShowWindow(hwnd, SW_RESTORE); if GetForegroundWindow = hwnd then Result := True else begin // Windows 98/2000 doesn't want to foreground a windo w when some other // window has keyboard focus if ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion > 4)) or ((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and ((Win32MajorVersion > 4) or ((Win32MajorVersion = 4) and (Win32MinorVersion > 0)))) then begin // Code from Karl E. Peterson, www.mvps.org/vb/sample.htm // Converted to Delphi by Ray Lischner // Published in The Delphi Magazine 55, page 16

Result := False; ForegroundThreadID := GetWindowThreadProcessID(GetForegroundWindow, nil); ThisThreadID := GetWindowThreadPRocessId(hwnd, nil); if AttachThreadInput(ThisThreadID, ForegroundThreadID, True) then begin BringWindowToTop(hwnd); // IE 5.5 related hack SetForegroundWindow(hwnd); AttachThreadInput(ThisThreadID, ForegroundThreadID, False); Result := (GetForegroundWindow = hwnd); end; if not Result then begin // Code by Daniel P. Stasinski SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @timeout, 0); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(0), SPIF_SENDCHANGE); BringWindowToTop(hwnd); // IE 5.5 related hack SetForegroundWindow(hWnd); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(timeout), SPIF_SENDCHANGE); end; end else begin BringWindowToTop(hwnd); // IE 5.5 related hack SetForegroundWindow(hwnd); end; Result := (GetForegroundWindow = hwnd); end; end; { ForceForegroundWindow }

Segunda alternativa A funo abaixo consegue forar o foco na janela especificada criando-se um formulrio com dimenso de um apenas 1 ponto e simulando um clique de mouse neste formulrio para que a aplicao receba o foco de entrada. Em seguida a janela especificada colocada em primeiro plano usando-se a funo SetForegroundWindow da API do Windows.
procedure ForceForegroundWindow(hwnd: THandle); // (W) 2001 Daniel Rolf // http://www.finecode.de // rolf@finecode.de var hlp: TForm; begin hlp := TForm.Create(nil); try hlp.BorderStyle := bsNone; hlp.SetBounds(0, 0, 1, 1); hlp.FormStyle := fsStayOnTop; hlp.Show; mouse_event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); mouse_event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP, 0, 0 , 0, 0);

SetForegroundWindow(hwnd); finally hlp.Free; end; end;

Terceira alternativa A biblioteca USER32.DLL possui uma funo no documentada que prope forar o foco em determinada janela. A declarao da funo :
procedure SwitchToThisWindow(h1: hWnd; x: bool); stdcall; external user32 Name 'SwitchToThisWindow'; {x = false: Size unchanged, x = true: normal size} { Exemplo } procedure TForm1.Button2Click(Sender: TObject); begin SwitchToThisWindow(FindWindow('note pad', nil), True); end;

Ateno! Nos testes que fiz usando Windows XP Professional e Delphi 6, a primeira e segunda alternativas funcionaram perfeitamente. A ltima no funcionou nos testes, mas foi mantida aqui para que outras pessoas possam experiment-la. Autor: Desconhecido Incio

Anexar dois forms


comum encontrarmos aplicativos que possuem dois ou mais formulrios que se mantm o tempo todo "colados" um ao outro. o caso, por exemplo, do conhecido Winamp. Como fazer isto em aplicaes Delphi? Vamos aos passos: 1. Crie um novo projeto com um form (Form1). 2. Adicione mais um form (Form2). 3. Declare os mtodos abaixo na seo private do Form1: private procedure AjustarForm2; procedure WMMove(var Msg: TMessage); message WM_MOVE; 4. Abaixo da palavra implementation escreva: procedure TForm1.AjustarForm2; begin if Form2 <> nil then begin Form2.Width := Width; Form2.Left := Left; Form2.Top := Top + Height; end;

end; procedure TForm1.WMMove(var Msg: TMessage); begin AjustarForm2; end; 5. Escreva o evento OnShow do Form1 como abaixo: procedure TForm1.FormShow(Sender: TObject); begin Form2.Show; end; 6. Escreve o evento OnHide do Form1 como abaixo: procedure TForm1.FormHide(Sender: TObject); begin Form2.Hide; end; 7. Escreve o evento OnReSize do Form1 como abaixo: procedure TForm1.FormResize(Sender: TObject); begin AjustarForm2; end; Pronto! Execute e experimente arrastar ou redimensionar o Form1 para ver o efeito.

Observaes Neste exemplo, se o usurio mexer no Form2 o Form1 no se ajustar automaticamente. Existem no mnimo duas alternativas para resolver este caso: deixar o Form2 sem borda ou codificar os eventos do Form2 para ajustar o Form1. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio

Impedir que o form seja fechado com Alt+F4


Este um problema fcil de resolver. Vejamos porque. Toda vez que um form recebe um comando para ser fechado, tal como Form1.Close ou mesmo uma mensagem WM_CLOSE, o evento OnCloseQuery disparado. Este evento passa um parmetro por referncia normalmente chamado CanClose. Se alternarmos o valor deste parmetro para false o processo de fechar o formulrio ser cancelado. Uma vez que queremos impedir que o form seja fechado com Alt+F4, temos que dar ao usurio outra forma de fech -lo. Neste exemplo vamos colocar um boto para esta tarefa.

Vamos aos passos: 1. Declare um campo (varivel) na seo private do Form: private FPodeFechar: boolean; 2. No evento OnCreate do form coloque: FPodeFechar := false; 3. No evento OnCloseQuery do form coloque: CanClose := FPodeFechar; 4. Coloque um boto no form e no seu evento Click coloque: FPodeFechar := true; Close; Pronto! Execute e teste.

Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio

Impedir que o form seja arrastado para fora das margens da tela
- Na seo Private declare a procedure abaixo: private procedure WMMove(var Msg: TWMMove); message WM_MOVE; - Abaixo da palavra implementation escreva a procedure abaixo: procedure TForm1.WMMove(var Msg: TWMMove); begin if Left < 0 then Left := 0; if Top < 0 then Top := 0; if Screen.Width - (Left + Width) < 0 then Left := Screen.Width - Width; if Screen.Height - (Top + Height) < 0 then Top := Screen.Height - Height; end; Para testar: - Execute o programa e tente arrastar o form para fora das margens da tela e veja o que acontece.

Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio

Enviar comandos de rolagem vertical para um TMemo


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: 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, W M_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. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio

Construir a barra de ttulo do form com um Panel


Pegue o arquivo tbtitle.zip na seo Download de www.tecnobyte.com.br

Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio

Criar form sem ttulo que possa ser arrastado


Problema: Fazer um relgio num form fcil. Porm gostaria que esse form no possusse a barra de ttulo, mas que o usurio ainda pudesse arrast -lo com o mouse. Isto possvel no Delphi? Soluo: Sim, possvel e fcil. Siga os passos abaixo: - Crie um novo projeto; - Mude as seguintes propriedades do Form1: BorderStyle = bsNone, FormStyle = fsStayOnTop, - Coloque um Label; - Coloque um Timer; - Altere o evento OnTimer do Timer1 conforme abaixo: procedure TForm1.Timer1Timer(Sender: TObject); begin Label1.Caption := TimeToStr(Time); end; - Altere o evento OnCreate do Form1 conforme abaixo: procedure TForm1.FormCreate(Sender: TObject); begin Width := 80; Height := 40; Label1.Left := 10; Label1.Top := 10; end; - V na seo private do Form1 e declare a procedure abaixo: private procedure WMNCHitTest(var Msg: TMessage); message WM_NCHitTest; public { Public declarations } end; - V na seo implementation e escreva a procedure abaixo: implementation {$R *.DFM} procedure TForm1.WMNCHitTest(var Msg: TMessage); begin

if GetAsyncKeyState(VK_LBUTTON) < 0 then Msg.Result := HTCAPTION else Msg.Result := HTCLIENT; end; - Execute e experimente arrastar form com o mouse.

Observaes Para fechar este aplicativo pressione Alt+F4. Uma alternativa mais elegante colocar um menu local (PopupMenu) com um comando para fechar. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio

Criar caixas de dilogo em tempo de execuo


Inclua na seo uses: Forms, StdCtrls, Buttons
A funo abaixo demonstra a criao de uma caixa de dilogo que pode ser usada para permitir ao usurio digitar o seu nome: { Esta funo retorna true se for pressionado OK e false em caso contrrio. Se for OK, o texto digitado pelo usurio ser copiado para a varivel Nome } function ObterNo me(var Nome: string): boolean; var Form: TForm; { Varivel para o Form } Edt: TEdit; { Varivel para o Edit } begin Result := false; { Por padro retorna false } { Cria o form } Form := TForm.Create(Application); try { Altera algumas propri edades do Form } Form.BorderStyle := bsDialog; Form.Caption := 'Ateno'; Form.Position := poScreenCenter; Form.Width := 200; Form.Height := 150; { Coloca um Label } with TLabel.Create(Form) do begin Parent := Form; Caption := 'Digite seu nome:'; Left := 10; Top := 10; end; { Coloca o Edit } Edt := TEdit.Create(Form); with Edt do begin Parent := Form; Left := 10;

Top := 25; { Ajusta o comprimento do Edit de aco rdo com a largura do form } Width := Form.ClientWidth - 20; end; { Coloca o boto OK } with TBitBtn.Create(Form) do begin Parent := Form; { Posiciona de acordo com a largura do form } Left := Form.ClientWidth - (Width * 2) - 20; Top := 80; Kind := bkOK; { Boto Ok } end; { Coloca o boto Cancel } with TBitBtn.Create(Form) do begin Parent := Form; Left := Form.ClientWidth - Width - 10; Top := 80; Kind := bkCancel; { Boto Cancel } end; { Exibe o form e aguarda a ao do usurio. Se for OK... } if Form.ShowModal = mrOK then begin Nome := Edt.Text; Result := true; end; finally Form.Free; end; end; Para chama r esta funo siga o exemplo abaixo: procedure TForm1.Button1Click(Sender: TObject); var S: string; begin if ObterNome(S) then Edit1.Text := S; end;

Observaes Os componentes Label, Edit (var Edt) e BitBtn's (botes) no so destrudos explicitamente (Componente.Free). Isto no necessrio, pois ao cri-los informei como proprietrio o Form (ex: TLabel.Create(Form)). Neste caso, estes componentes so destrudos automaticamente ao destruir o Form (Form.Free). Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio

Determinar se uma janela (form) est maximizada


Inclua na seo uses: Windows

if IsZoomed(Form1.Handle) then { Form1 est maximizado } else { Form2 NO est maximizado }

Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio

Determinar se o aplicativo est minimizado


Inclua na seo uses: Windows
if IsIconic(Application.Handle) then { Minimizado } else { No minimizado }

Observaes Pode-se verificar qualquer janela (form). S um lembrete: quando clicamos no boto de minimizar do form principal, na verdade ele oculto e o Application que minizado. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio

Maximizar um form de forma que cubra toda a tela, inclusive a barra de tarefas
{ um "maximizar" com jeitinho brasileiro... mas funciona. No evento OnShow do form coloque o cdigo abaixo: } Top := 0; Left := 0; Width := Screen.Width; Height := Screen.Height;

Observaes Nos testes que fiz, mesmo com a barra de tarefas marcada como "Sempre Visvel", funcionou perfeitamente. Fiz os testes usando o Win95. Talvez em novas verses, possa apresentar problemas. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br

Incio

Posicionar Form's em relao ao Desktop do Windows


{ Quando usamos a propridade Position de um Form para centraliz -lo estamos sujeitos a um inconveniente: dependendo da posio/tamanho da barra de tarefas do Windows, o nosso Form poder ficar parcialmente coberto por ela. Uma forma eficaz de resolver este problema posicionar o form considerando apenas a rea livre do Desktop. Vejamos este exemplo : - Crie um novo projeto; - Na seo implementation digite a procedure abaixo: } procedure FormPos(Form: TForm; const Horz, Vert: byte); { Horz: 1=esquerda, 2=centro, 3=direita Vert: 1=topo, 2=centro, 3=em baixo } var R: TRect; begin if not Sys temParametersInfo(SPI_GETWORKAREA, 0, @R, 0) then R := Rect(0, 0, Screen.Width, Screen.Height); with Form do case Horz of 1: Form.Left := 0; 2: Form.Left := (R.Right - R.Left - Width) div 2; 3: Form.Left := R.Right - Width; end; with Form do case Vert of 1: Form.Top := 0; 2: Form.Top := (R.Bottom - R.Top - Height) div 2; 3: Form.Top := R.Bottom - Height; end; end; { - Coloque dois TEdit's: Edit1 e Edit2; - Coloque um TButton e altere o eve nto OnClick deste conforme abaixo: } procedure TForm1.Button1Click(Sender: TObject); begin FormPos(Form1, StrToInt(Edit1.Text), StrToInt(Edit2.Text)); end;

Observaes Para testar, execute este exemplo e experimente digitar nmeros de 1 a 3 em ambos os Edit's e clique no Button para ver o resultado. O Edit1 indica a posio horizontal (esquerda, centro e direita) e o Edit2 indica a posio vertical (topo, centro e em baixo). Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br

Incio

Salvar/restaurar o tamanho e posio de Form's


{ Crie uma nova Unit conforme abaixo: } unit uFormFunc; interface uses Forms, IniFiles, SysUtils, Messages, Windows; procedure tbLoadFormStatus(Form: TForm; const Section: string); procedure tbSaveFormStatus(Form: TForm; const Section: string); implementation procedure tbSaveFormStatus(Form: TForm; const Sec tion: string); var Ini: TIniFile; Maximized: boolean; begin Ini := TIniFile.Create(ChangeFileExt( ExtractFileName(ParamStr(0)),'.INI')); try Maximized := Form.WindowState = wsMaximized; Ini.WriteBool(Section, 'Maximized', Maximized); if not Maximized then begin Ini.WriteInteger(Section, 'Left', Form.Left); Ini.WriteInteger(Section, 'Top', Form.Top); Ini.WriteInteger(Section, 'Width', Form.Width); Ini.WriteInteger(Section, 'Height', Form.Height); end; finally Ini.Free; end; end; procedure tbLoadFormStatus(Form: TForm; const Section: string); var Ini: TIniFile; Maximized: boolean; begin Maximized := false; { Evita msg do compilador } Ini := TIniFile.Create(ChangeFileExt( ExtractFileName (ParamStr(0)),'.INI')); try Maximized := Ini.ReadBool(Section, 'Maximized', Maximized); Form.Left := Ini.ReadInteger(Section, 'Left', Form.Left); Form.Top := Ini.ReadInteger(Section, 'Top', Form.Top); Form.Width := Ini.ReadInteger(Section, 'Width', Form.Width); Form.Height := Ini.ReadInteger(Section, 'Height', Form.Height); if Maximized then Form.Perform(WM_SIZE, SIZE_MAXIMIZED, 0); { A propriedade WindowState apresenta Bug. Por isto usei a mensagem WM_SIZE } finally Ini.Free; end; end;

end. { Em cada formulrio que deseja salvar/restaurar: - Inclua na seo uses: uFormFunc - No evento OnShow digite: tbLoadFormStatus(Self, Self.Name); - No evento OnClose digite: tbSaveFormStatus(Self, Self.Name); }

Observaes O arquivo INI ter o nome do executvel e extenso INI e ser salvo no diretrio do Windows. A palavra Self indica o Form relacionado com a unit em questo. Poderia ser, por exemplo, Form1, Form2, etc. Onde aparece Self.Name poder ser colocado um nome a sua escolha. Este nome ser usado como SectionName no arquivo INI e deve ser idntico no evento OnShow e OnClose de um mesmo Form, porm para cada Form dever ser usado um nome diferente. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio

Mostrar um Form de LogOn antes do Form principal


{ * Crie um novo Projeto. Este certamente ter o Form1. * Adicione um novo Form (Form2). * Coloque no Form2 dois botes TBitBtn. * Mude a propriedade Kind do BitBtn1 para bkOK. * Mude a propriedade Kind do BitBtn2 para bkCancel. * V no menu "Project/Options" na aba "Forms" e passe o Form2 de "Auto -create Forms" para "Available Forms". * Abra o arquivo Project.dpr (menu Project/View Source). * Altere o contedo deste arquivo conforme abaixo: } program Project1; uses Forms, Controls, Unit1 in 'Unit1.pas' {Form1}, Unit2 in 'Unit2.pas' {Form2}; {$R *.RES} var F: TForm2; begin F := TForm2.Create(Application); try

if F.ShowModal = mrOK then begin Application.Initialize; Application.CreateForm (TForm1, Form1); Application.Run; end; finally F.Free; end; end.

Observaes O Form2 do exemplo o Form de LogOn. Este dever ser preparado para que se possa escolher o usurio, digitar a senha, etc. Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio

Fazer a barra de ttulo ficar intermitente (piscante)


Inclua na seo uses: Windows
{ Coloque um TTimer no Form desejado. Define a propriedade Interval do Timer para 1000 (1 segundo). Modifique o evento OnTimer do Timer conforme abaixo: } procedure TForm1.Timer1Timer(Sender: TObject); begin FlashWindow(Handle, true); FlashWindow(Application.Handle, true); end;

Autor: Daniel P. Guimares Home-page: www.tecnobyte.com.br Incio