Fórum Posicionamento da Calculadora #357047
13/04/2008
0
Eu desenvolvi uma pequena aplicação onde a tela possui 2 divisões: na 1ª, o usuário escolhe qual o tipo de cálculo ele quer fazer (por. ex. IMC - índice de massa corpórea). na 2ª, aparecem os campos referentes ao tipo de cálculo escolhido. O problema é que há uma opção para que o usuário utilize a calculadora do windows para efetuar um outro cálculo. Eu gostaria que a calculadora fosse executada e centralizada dentro do panel, que fica na 2ª divisão. Eu até encontrei alguma coisa (tópico ´Execultar programa externo´), mas só funciona se a calculadora já estiver aberta.
Aí eu tentei fazer isso:
procedure TForm6.Button1Click(Sender: TObject);
var
Handle: THandle;
begin
Handle := FindWindow(nil, ´Calculadora´);
if Handle > 0 then
Windows.SetParent(Handle, Panel1.Handle)
else
begin
WinExec(´calc.exe´, SW_SHOWDEFAULT);
Windows.SetParent(Handle, Panel1.Handle);
end;
end;
O problema é que a calculadora é executada fora do panel, se eu clicar novamente no botão, aí a calculadora é executada dentro do panel.
Existe alguma forma de executar direto no panel, e de preferência centralizada?
[]s
Roger1976
Curtir tópico
+ 0Posts
14/04/2008
Rodc
procedure TForm6.Button1Click(Sender: TObject); var Handle: THandle; begin Handle := FindWindow(nil, ´Calculadora´); if Handle > 0 then Windows.SetParent(Handle, Panel1.Handle) else begin WinExec(´calc.exe´, SW_SHOWDEFAULT); Handle := FindWindow(nil, ´Calculadora´); if Handle > 0 then Windows.SetParent(Handle, Panel1.Handle); end; end;
Gostei + 0
14/04/2008
Martins
procedure TForm6.Button1Click(Sender: TObject); var Handle: THandle; begin Handle := FindWindow(nil, ´Calculadora´); if Handle > 0 then Windows.SetParent(Handle, Panel1.Handle) else begin WinExec(´calc.exe´, SW_SHOWDEFAULT); Handle := FindWindow(nil, ´Calculadora´); if Handle > 0 then Windows.SetParent(Handle, Panel1.Handle); end; end;
Esse código aqui deve realmente funcionar, pq verifica se já existe um Handle para a calculadora para poder colocá-la dentro do Panel, caso contrário executa a calculadora e verifica novamente.
Vale testá-lo.
Boa sorte.
Gostei + 0
14/04/2008
Roger1976
Muito obrigado pela força de vcs, e se tiverem algumas sugestão, agradeço.
[]s
Gostei + 0
15/04/2008
Rodc
procedure TForm6.Button1Click(Sender: TObject); var Handle: THandle; rect: TRect; begin Handle := FindWindow(nil, ´Calculadora´); if Handle > 0 then Windows.SetParent(Handle, Panel1.Handle) else begin WinExec(´calc.exe´, SW_SHOWDEFAULT); Handle := FindWindow(nil, ´Calculadora´); if Handle > 0 then Windows.SetParent(Handle, Panel1.Handle); end; if Handle > 0 then begin Windows.GetWindowRect(Handle, rect); // Pega a posição da calculadora Windows.MoveWindow(Handle, 0, 0, rect.right-rect.left, rect.bottom-rect.top, true); // Move a posição da calculadora end; end;
Uma coisa que percebi é que a calculadora fica em memória depois, por isto, sugiro antes de fechar o programa fazer a calculadora sair do panel ou guardar o Handle da calculadora para fechá-la usando a função
PostMessage(Handle, WM_CLOSE, 0, 0);
Gostei + 0
15/04/2008
Roger1976
Muito obrigado!
[]s
Gostei + 0
15/04/2008
Marco Salles
[b:c66db98d8d]´mas acho´[/b:c66db98d8d] que voce pode melhorar ainda mais o seu codigo ..
aproveitando um pouco do que foi falado aqui e utilizando refectoring
no codigo , alem do que [b:c66db98d8d]´eu acho´[/b:c66db98d8d] que o codigo postado tem erro de logica pois o WinExec(´calc.exe´, SW_SHOWDEFAULT); sempre será executado , por isso que voce observou deste do inicio :
citação de rogger
[b:c66db98d8d]
então sugiro que se tente o codigo abaixo :
//guardar o Handle da calculadora para fechá-la
private
{ Private declarations }
hCalc:THandle;procedure TForm1.Button1Click(Sender: TObject); var Hjanela,hmemo: THandle; rect: TRect; begin hJanela := FindWindow( ´TForm1´, nil ); hMemo := FindWindowEx( hJanela, 0, ´TPanel´, nil ); hCalc := FindWindowEx( hmemo, 0,´scicalc´,nil ); if hcalc <= 0 Then begin WinExec(´calc.exe´, SW_SHOWDEFAULT); hcalc := FindWindow(nil, ´Calculadora´); Windows.SetParent(hcalc, Panel1.Handle); Windows.GetWindowRect(hCalc, rect); // Pega a posição da calculadora Windows.MoveWindow(hCalc, 0, 0, rect.right-rect.left, rect.bottom-rect.top, true); // Move a posição da calculadora end else Windows.SetParent(hcalc, Panel1.Handle); end;
[b:c66db98d8d]citação de rodc...[/b:c66db98d8d]
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin if hCalc > 0 Then PostMessage(Hcalc, WM_CLOSE, 0, 0); end;
espero ter sido util
Gostei + 0
15/04/2008
Roger1976
1ª- não acho interessante para o usuário q veja a calculadora se movimentando para dentro do panel, sei q é muito rápido, mas fica estranho;
2ª- não estou conseguindo fazer com que a calculadora seja executada apenas uma vez, ou seja, tem que haver uma condição que verifique se a calculadora está sendo executada, se estiver, não poderá carregá-la novamente.
Muito obrigado a você e ao rodc pelas dicas, e espero por uma resposta para saber se o que foi questionado é possível de se fazer ou não (principalmente a 1ª questão).
[]´s
Gostei + 0
15/04/2008
Dopi
Criar uma dependencia de um programa externo não é uma boa... E se a calculadora não estiver instalada ? E se estiver sendo exibida no modo científico ?
Na Jedi existe uma calculadora... No ACBr temos o [b:c058d37a81]ACBrCalculadora [/b:c058d37a81]que contempla apenas as operações básicas, mas permite vc posiciona-la onde quiser... além de uma bobina (memo) com as operações efetuadas
Vc pode usar uma função que chame o programa externo e aguarde pelo seu termino... seria parecido com um ShowModal...
{-----------------------------------------------------------------------------
- Executa programa Externo descrito em "Command", adcionando os Parametros
"Params" na linha de comando
- Se "Wait" for true para a execução da aplicação para esperar a conclusao do
programa externo executado por "Command"
- WindowState apenas é utilizado na plataforma Windows
---------------------------------------------------------------------------- }
procedure RunCommand(Command: String; Params: String; Wait : Boolean;
WindowState : Word);
var
{$ifdef MSWINDOWS}
SUInfo: TStartupInfo;
ProcInfo: TProcessInformation;
Executed : Boolean ;
PCharStr : PChar ;
{$endif}
ConnectCommand : PChar;
begin
{$ifdef LINUX}
Command := Trim(Command + ´ ´ + Params) ;
if not Wait then
Command := Command + ´ &´ ; { & = Rodar em BackGround }
{$IFNDEF FPC}
ConnectCommand := PChar(Command);
Libc.system(ConnectCommand);
{$ELSE}
Shell(Command)
{$ENDIF}
{$endif}
{$ifdef MSWINDOWS}
Command := Trim(Command) ;
PCharStr := PChar(Trim(Params)) ;
if Length(PCharStr) = 0 then
PCharStr := nil ;
if not Wait then
ShellExecute(0,´open´,PChar(Command),PCharStr, nil, WindowState )
// winexec(ConnectCommand, WindowState)
else
begin
ConnectCommand := PChar(Trim(Command + ´ ´ + Params));
PCharStr := PChar(ExtractFilePath(Command)) ;
if Length(PCharStr) = 0 then
PCharStr := nil ;
FillChar(SUInfo, SizeOf(SUInfo), #0);
with SUInfo do
begin
cb := SizeOf(SUInfo);
dwFlags := STARTF_USESHOWWINDOW;
wShowWindow := WindowState;
end;
Executed := CreateProcess(nil, ConnectCommand, nil, nil, false,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
PCharStr, SUInfo, ProcInfo);
try
{ Aguarda até ser finalizado }
if Executed then
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
finally
{ Libera os Handles }
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
end;
end;
{$endif}
end;
Gostei + 0
15/04/2008
Marco Salles
Voce esta [b:b8bacd91bc]fazendo confusão[/b:b8bacd91bc] .... o codigo que lhe enviei é exatamente para que a calculadora não seja chamada mais de uma Vez ..
Por acso voce colocou o método e executou :?: :?: :?: :?:
... Perceba que o
WinExec(´calc.exe´, SW_SHOWDEFAULT);
[b:b8bacd91bc]é executado somente uma vez[/b:b8bacd91bc]
Agora quanto a sua primeira obervação ,
Ai já é outra história
Primeiro vamos resolver a Segunda pendência , pq ela é bem mais antiga
A primeira pendencia é novissima , voce esta levantando agora .
Gostei + 0
16/04/2008
Roger1976
Dopi, infelizmente não poderei utilizar o componente que você citou no projeto, por uma questão de regra. No entanto, para estudo, vou testá-lo em casa sim, pois poderá ser útil em um projeto futuro onde eu tenha uma liberdade maior de utilizar o componente que eu quiser.
Gostei + 0
16/04/2008
Marco Salles
Voce tem certeza que o codigo que lhe passei abre mais de uma calculadora ????? Aqui comigo posso de garantir que so so Abre uma .
Observe que hcalc é uma variavel declarada na secção Private e não é uma variavel Local .. Se voce estiver declarando no esboço da procedure
ai sim , não irá resolver
De Qualque modo vou repetir o codigo :
private
{ Private declarations }
hCalc:THandle;
procedure TForm1.Button1Click(Sender: TObject);
var
Hjanela,hmemo: THandle;
rect: TRect;
begin
hJanela := FindWindow( ´TForm1´, nil );
hMemo := FindWindowEx( hJanela, 0, ´TPanel´, nil );
hCalc := FindWindowEx( hmemo, 0,´scicalc´,nil );
if hcalc <= 0 Then
begin
WinExec(´calc.exe´, SW_SHOWDEFAULT);
ShowWindow(FindWindow(nil,´calc.exe´),SW_HIDE);
hcalc := FindWindow(nil, ´Calculadora´);
Windows.SetParent(hcalc, Panel1.Handle);
Windows.GetWindowRect(hCalc, rect); // Pega a posição da calculadora
Windows.MoveWindow(hCalc, 0, 0, rect.right-rect.left, rect.bottom-rect.top, true); // Move a posição da calculadora
end
else
Windows.SetParent(hcalc, Panel1.Handle);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if hCalc > 0 Then
PostMessage(Hcalc, WM_CLOSE, 0, 0);
end;Gostei + 0
16/04/2008
Rodc
Gostei + 0
16/04/2008
Roger1976
[b:b897d35501]ShowWindow(FindWindow(nil,´calc.exe´),SW_HIDE);[/b:b897d35501]
Sobre a 1ª questão que eu levantei, de ficar visível para o usuário o movimento, mesmo que rápido, da calculadora para o panel, de repente estou querendo algo que não seja possível, mas fica aí uma questão interessante, pois se tiver como, aí ficará perfeito.
rodc, bem observado, vc sabe como é, às vezes algum processo no sistema não funciona por causa de um mísero detalhe.
Obrigado a vcs pela ajuda, foi um grande aprendizado.
[]s
Gostei + 0
16/04/2008
Marco Salles
[b:40efd567f8]vai entender [/b:40efd567f8]:?: :?: :?: ... Acho que o primeiro codigo funciona .. Na verdade esta linha apareceu no segundo post , porque estava tentando que a calculadora ficasse invisível e aparecer finalmente no panel . Mas não ocorreu conforme eu esperava ... Não seu pq o codigo do promeiro post não deu certo para voce :?: :?: :?: :?:
Bem enfim sobre a primeira questão :
tem que perder um pouquinho de tempo na net .
a minha simples duvida é , não sei o porque mas a instrução
[b:40efd567f8]WinExec(´calc.exe´, SW_Hide); [/b:40efd567f8]
Abre a calculadora , mas ela não fica invisivel ????? To sem entender
Algume sabe o Porque ?????
Gostei + 0
17/04/2008
Roger1976
Valeu pela força!
[]s
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)