Autor Beitrag
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Fr 15.08.08 16:16 
Hallo,

mir ist was merkwürdiges aufgefallen. Hat man einen Timer, beispielsweise auf 50ms, prüft darin mittels GetKeyState ob die linke Maustaste gedrückt ist und ruft dann mit ShellExecute eine URL auf, dann geht die nicht nur einmal, sondern 20x auf. Das folgende Sleep oder ähnliche Delays werden vollkommen ignoriert. Ich halte bewusst die Maustaste eine kurze Zeit lang gedrückt. Beispiel:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
if GetKeyState(VK_LBUTTON) AND 128 = 128 then
begin
  MainForm.Memo1.Lines.Add('Test 1');
  ShellExecute(MainForm.Handle, 'open''http://www.heiliger-damm.de'nilnil, SW_SHOW);
  Sleep(1000);
  MainForm.Memo1.Lines.Add('Test 2');
end;


Logischerweiße müsste er ShellExecute ausführen, dann Sleep(1000); und erst danach die Prozedur erneut aufrufen. Das würde ja im Memo wie folgt aussehen (und das tut es auch, wenn ich ShellExecute weglasse (!)):

Zitat:
Test 1
Test 2
Test 1
Test 2
Test 1
Test 2


Was passiert aber in Wirklichkeit?

Zitat:
Test 1
Test 1
Test 1
Test 2
Test 2
Test 2


Die Prozedur wird drei Mal aufgerufen ohne den Rest zu beachten. Sleep zieht erst danach. Wie oben erwähnt, habe ich dieses Verhalten nicht, wenn ShellExecute weggelassen wird.

Kann sich einer erklären, in wie fern ShellExecute den Programmablauf beeinflusst? Wieso wird es plötzlich möglich, dass die Prozedur mehrmals gleichzeitig aufgerufen wird? Eine Notlösung ist die, dass ich am Anfang eine Boolean-Variable auf False setze und die Prozedur sofort verlasse, falls diese False ist. Dann wird das ganze auch nur einmal aufgerufen.

Bei Bedarf kann ich auch mal ein Testprojekt anhängen.

Grüße
GTA-Place

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
Xentar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2077
Erhaltene Danke: 2

Win XP
Delphi 5 Ent., Delphi 2007 Prof
BeitragVerfasst: Fr 15.08.08 17:29 
Vermutung:
ShellExecute kehrt erst zurück, wenn das Programm vollständig geöffnet / geladen wurde. In der Zwischenzeit werden aber bereits weitere Messages des Programms abgearbeitet, und somit auch neue Timer Ereignisse.

Deswegen verwend ich in solchen Situationen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
  TTimer(Sender).Enabled := false;
  try
    ...
  finally
    TTimer(Sender).Enabled := true;
  end;

_________________
PROGRAMMER: A device for converting coffee into software.
Tilman
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: Fr 15.08.08 17:45 
Es scheint zu funktionieren wenn man den Timer abstellt:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
  timer1.Enabled := false;
if GetKeyState(VK_LBUTTON) AND 128 = 128 then
begin
  Memo1.Lines.Add('Test 1');
  ShellExecute(Handle, 'open''http://www.heiliger-damm.de'nilnil, SW_SHOW);
  Sleep(3000);
  Memo1.Lines.Add('Test 2');
end;
  timer1.Enabled := true;


Es bleibt aber das Problem, dass wenn der Browser aufgeht der Timer immer weiterläuft (das Programm weiß ja nicht ob die Seite schon geöffnet ist. Wenn man im Browser linksklickt, dann geht ein weiterer Tab auf usw.). Es wäre daher vermutlich einfacher mit einer Komponente (z.B. einer leeren tPaintBox) und deren OnClick-Event zu realisieren.

// edit: irgendwie bin ich heute immer zu langsam ^^

_________________
Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
GTA-Place Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Fr 15.08.08 18:51 
Ne das ist eigentlich kein Problem. Du musst ja nur prüfen, ob dein Programm den Fokus hat, ansonsten werden keine Eingaben verarbeitet.

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
GTA-Place Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Sa 16.08.08 20:34 
Das hier hat den selben Effekt:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure TForm1.Timer1Timer(Sender: TObject);
var
  X: Integer;
begin
  if not (CheckBox1.Checked) then
    Exit;

  X := 10;
  Memo1.Lines.Add('ABC');

  while X = 10 do
    Application.ProcessMessages;

  Memo1.Lines.Add('DEF');
end;


Das Application.ProcessMessages; führt dazu, dass der Timer auch ausgeführt wird, obwohl die Prozedur noch gar nicht zu Ende ist. Da könnte man jetzt Spielereien aller Art durchführen ^_^

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)