0% found this document useful (0 votes)
116 views14 pages

As Funções Abaixo Forçam para Que A Janela Informada Fique em Primeiro Plano

The document discusses three alternatives for forcing a window to gain foreground focus in Windows. The first alternative uses API functions like AttachThreadInput, SetForegroundWindow, and GetForegroundWindow to switch the foreground window. The second alternative creates a tiny hidden form, simulates a mouse click on it to give it focus, and then sets the target window as foreground. The third alternative mentions an undocumented USER32 function called SwitchToThisWindow that is claimed to directly set the foreground window. The document notes that the first two alternatives worked in testing, but the third did not and is included for others to experiment with. It concludes by emphasizing testing is needed as Windows versions and behavior may differ.

Uploaded by

lokateste
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
116 views14 pages

As Funções Abaixo Forçam para Que A Janela Informada Fique em Primeiro Plano

The document discusses three alternatives for forcing a window to gain foreground focus in Windows. The first alternative uses API functions like AttachThreadInput, SetForegroundWindow, and GetForegroundWindow to switch the foreground window. The second alternative creates a tiny hidden form, simulates a mouse click on it to give it focus, and then sets the target window as foreground. The third alternative mentions an undocumented USER32 function called SwitchToThisWindow that is claimed to directly set the foreground window. The document notes that the first two alternatives worked in testing, but the third did not and is included for others to experiment with. It concludes by emphasizing testing is needed as Windows versions and behavior may differ.

Uploaded by

lokateste
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 14

Forçar foco em janela

As funções abaixo forçam 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 window 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 função abaixo consegue forçar o foco na janela especificada criando-se um


formulário com dimensão de um apenas 1 ponto e simulando um clique de
mouse neste formulário para que a aplicação receba o foco de entrada. Em
seguida a janela especificada é colocada em primeiro plano usando-se a
função SetForegroundWindow da API do Windows.
procedure ForceForegroundWindow(hwnd: THandle);
// (W) 2001 Daniel Rolf
// http://www.finecode.de
// [email protected]
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 função não documentada que propõe


forçar o foco em determinada janela. A declaração da função é:
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('notepad', nil), True);
end;
Atenção! 

Nos testes que fiz usando Windows XP Professional e Delphi 6, a primeira e


segunda alternativas funcionaram perfeitamente. A última não funcionou nos
testes, mas foi mantida aqui para que outras pessoas possam experimentá-la.

Autor: Desconhecido

Início

Anexar dois forms


É comum encontrarmos aplicativos que possuem dois ou mais
formulários que se mantém o tempo todo "colados" um ao outro.
É o caso, por exemplo, do conhecido Winamp. Como fazer isto
em aplicações Delphi? Vamos aos passos:

1. Crie um novo projeto com um form (Form1).


2. Adicione mais um form (Form2).
3. Declare os métodos abaixo na seção 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.

Observações

Neste exemplo, se o usuário mexer no Form2 o Form1 não se ajustará


automaticamente. Existem no mínimo duas alternativas para resolver este
caso: deixar o Form2 sem borda ou codificar os eventos do Form2 para ajustar
o Form1.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início

Impedir que o form seja fechado com Alt+F4


Este é um problema fácil 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 parâmetro por
referência normalmente chamado CanClose. Se alternarmos o valor
deste parâmetro para false o processo de fechar o formulário
será cancelado.

Uma vez que queremos impedir que o form seja fechado com
Alt+F4, temos que dar ao usuário outra forma de fechá-lo.
Neste exemplo vamos colocar um botão para esta tarefa.

Vamos aos passos:

1. Declare um campo (variável) na seção 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 botão no form e no seu evento Click coloque:

FPodeFechar := true;
Close;

Pronto! Execute e teste.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início

Impedir que o form seja arrastado para fora das margens da tela
- Na seção Private declare a procedure abaixo:

private
procedure WMMove(var Msg: TWMMove); message WM_MOVE;

- Abaixo da palavra implementation escreva a procedure


abaixo:

procedure TForm1.WMMove(var Msg: TWMMove);


begin
if Left < 0 then
Left := 0;
if Top < 0 then
Top := 0;
if Screen.Width - (Left + Width) < 0 then
Left := Screen.Width - Width;
if Screen.Height - (Top + Height) < 0 then
Top := Screen.Height - Height;
end;

Para testar:

- Execute o programa e tente arrastar o form para fora


das margens da tela e veja o que acontece.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início

Enviar comandos de rolagem vertical para um TMemo

Inclua na seção uses: Windows


Problema:

Gostaria que o meu programa rolasse automaticamente o


conteúdo de um TMemo, simulando o deslizamento da barra de
rolagem vertical. Isto é possível no Delphi?

Solução:

Sim. Utilizando mensagens do Windows isto é fácil. 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 - página para baixo.

Outros exemplos:

{ Página 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);

Observações

Além desta técnica existem API's do Windows que fazem um trabalho


equivalente.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início

Construir a barra de título do form com um Panel


Pegue o arquivo tbtitle.zip na seção Download de www.tecnobyte.com.br

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início

Criar form sem título que possa ser arrastado


Problema:

Fazer um relógio num form é fácil. Porém gostaria que esse


form não possuísse a barra de título, mas que o usuário
ainda pudesse arrastá-lo com o mouse. Isto é possível
no Delphi?

Solução:

Sim, é possível e é fácil. 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 seção private do Form1 e declare a procedure abaixo:

private
procedure WMNCHitTest(var Msg: TMessage);
message WM_NCHitTest;
public
{ Public declarations }
end;

- Vá na seção 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.

Observações

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

Início

Criar caixas de diálogo em tempo de execução

Inclua na seção uses: Forms, StdCtrls, Buttons


A função abaixo demonstra a criação de uma caixa de diálogo
que pode ser usada para permitir ao usuário digitar o seu
nome:

{ Esta função retorna true se for pressionado OK e false


em caso contrário. Se for OK, o texto digitado pelo usuário
será copiado para a variável Nome }

function ObterNome(var Nome: string): boolean;


var
Form: TForm; { Variável para o Form }
Edt: TEdit; { Variável para o Edit }
begin
Result := false; { Por padrão retorna false }
{ Cria o form }
Form := TForm.Create(Application);
try
{ Altera algumas propriedades do Form }
Form.BorderStyle := bsDialog;
Form.Caption := 'Atenção';
Form.Position := poScreenCenter;
Form.Width := 200;
Form.Height := 150;
{ Coloca um Label }
with TLabel.Create(Form) do begin
Parent := Form;
Caption := 'Digite seu nome:';
Left := 10;
Top := 10;
end;
{ Coloca o Edit }
Edt := TEdit.Create(Form);
with Edt do begin
Parent := Form;
Left := 10;
Top := 25;
{ Ajusta o comprimento do Edit de acordo com a largura
do form }
Width := Form.ClientWidth - 20;
end;
{ Coloca o botão OK }
with TBitBtn.Create(Form) do begin
Parent := Form;
{ Posiciona de acordo com a largura do form }
Left := Form.ClientWidth - (Width * 2) - 20;
Top := 80;
Kind := bkOK; { Botão Ok }
end;
{ Coloca o botão Cancel }
with TBitBtn.Create(Form) do begin
Parent := Form;
Left := Form.ClientWidth - Width - 10;
Top := 80;
Kind := bkCancel; { Botão Cancel }
end;
{ Exibe o form e aguarda a ação do usuário. Se for OK... }
if Form.ShowModal = mrOK then begin
Nome := Edt.Text;
Result := true;
end;
finally
Form.Free;
end;
end;

Para chamar esta função siga o exemplo abaixo:

procedure TForm1.Button1Click(Sender: TObject);


var
S: string;
begin
if ObterNome(S) then
Edit1.Text := S;
end;

Observações

Os componentes Label, Edit (var Edt) e BitBtn's (botões) não são destruídos
explicitamente (Componente.Free). Isto não é necessário, pois ao criá-los
informei como proprietário o Form (ex: TLabel.Create(Form)). Neste caso,
estes componentes são destruídos automaticamente ao destruir o Form
(Form.Free).

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início

Determinar se uma janela (form) está maximizada

Inclua na seção uses: Windows


if IsZoomed(Form1.Handle) then
{ Form1 está maximizado }
else
{ Form2 NÃO está maximizado }

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br
Início

Determinar se o aplicativo está minimizado

Inclua na seção uses: Windows


if IsIconic(Application.Handle) then
{ Minimizado }
else
{ Não minimizado }

Observações

Pode-se verificar qualquer janela (form). Só um lembrete: quando clicamos no


botão de minimizar do form principal, na verdade ele é oculto e o Application
é que é minizado.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início

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 código abaixo: }

Top := 0;
Left := 0;
Width := Screen.Width;
Height := Screen.Height;

Observações

Nos testes que fiz, mesmo com a barra de tarefas marcada como "Sempre
Visível", funcionou perfeitamente. Fiz os testes usando o Win95. Talvez em
novas versões, possa apresentar problemas.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início
Posicionar Form's em relação ao Desktop do Windows
{ Quando usamos a propridade Position de um Form para
centralizá-lo estamos sujeitos a um inconveniente:
dependendo da posição/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 seção 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 SystemParametersInfo(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 evento OnClick deste
conforme abaixo:
}

procedure TForm1.Button1Click(Sender: TObject);


begin
FormPos(Form1, StrToInt(Edit1.Text), StrToInt(Edit2.Text));
end;

Observações

Para testar, execute este exemplo e experimente digitar números de 1 a 3 em


ambos os Edit's e clique no Button para ver o resultado. O Edit1 indica a
posição horizontal (esquerda, centro e direita) e o Edit2 indica a posição
vertical (topo, centro e em baixo).

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br
Início

Salvar/restaurar o tamanho e posição 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 Section: 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 formulário que deseja salvar/restaurar:
- Inclua na seção uses: uFormFunc
- No evento OnShow digite:
tbLoadFormStatus(Self, Self.Name);
- No evento OnClose digite:
tbSaveFormStatus(Self, Self.Name);
}

Observações

O arquivo INI terá o nome do executável e extensão INI e será salvo no


diretório do Windows. A palavra Self indica o Form relacionado com a unit
em questão. 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 idêntico no evento OnShow e
OnClose de um mesmo Form, porém para cada Form deverá ser usado um
nome diferente.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início

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 botões 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 conteúdo 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.

Observações

O Form2 do exemplo é o Form de LogOn. Este deverá ser preparado para que
se possa escolher o usuário, digitar a senha, etc.

Autor: Daniel P. Guimarães
Home-page: www.tecnobyte.com.br

Início

Fazer a barra de título ficar intermitente (piscante)

Inclua na seção 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;

You might also like