Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Befehl immer wieder ausführen ohne CPU belastung (https://www.delphipraxis.net/152605-befehl-immer-wieder-ausfuehren-ohne-cpu-belastung.html)

BlueLiquidCell 29. Jun 2010 13:03


Befehl immer wieder ausführen ohne CPU belastung
 
Hallo
Ich schreibe immoment ein Programm das einen Befehl immer wieder ausführen soll. Es soll ein anderes Programm immer im Vordergrund halten. Klappt auch nur ist die CPU belastung relativ hoch weil ich es halt alle 50 Milisekunden wiederholen lasse. Gibt es da ne bessere variante?
Außerdem kann ich den (Sender=Butto2) nicht in die while Schleife direkt setzen, warum geht das nicht?

Code:

Delphi-Quellcode:
var
fHandle: HWND;
i:integer;
begin
 fHandle := FindWindow('notepad', nil);
if fHandle <> 0 then
begin
i:=0;
while i=0 do
begin
if Sender = Button2 then
i:=1;
delay(50);
SetForeGroundWindow(fHandle);
    end;
  end;
end;
Danke schonmal in voraus

DeddyH 29. Jun 2010 13:12

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Hallo und Willkommen in der DP :dp:,

würdest Du den Code bitte in Delphi-Tags einschließen? Dann ist er für andere besser zu lesen. Und was meinst Du mit in die Schleife setzen? Ist die Routine eine Methode oder eine reguläre Funktion/Prozedur?

shmia 29. Jun 2010 14:19

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Übrigens: wenn du das Notepad alle 50ms nach Vorne bringst werden Dich alle Benutzer hassen,
die gerade etwas anderes tun möchten (z.B. EMail lesen, im Internet surfen). :evil:

Der Benutzer will die Kontrolle haben, welches Fenster gerade oben ist; wenn das nicht nach seinem Willen läuft wird er stinkig.

DeddyH 29. Jun 2010 14:24

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Bist Du aber kleinlich :mrgreen:

Bummi 29. Jun 2010 14:27

AW: Befehl immer wieder ausführen ohne CPU belastung
 
folgender Code erzeugt bei mir keine Last, über Sinn und Unsinn kann man streiten.

Delphi-Quellcode:
procedure TForm5.Timer1Timer(Sender: TObject);
var

    fHandle: HWND;

    i:integer;

begin

    fHandle := FindWindow('notepad', nil);

    if fHandle <> 0 then
    begin
        i:=0;
        while i=0 do
        begin
            if Sender = Button2 then i:=1;
            Application.ProcessMessages;
            sleep(50);
            if GetForeGroundWindow <> fHandle then SetForeGroundWindow(fHandle);

        end;

    end;

end;

himitsu 29. Jun 2010 14:37

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Delphi-Quellcode:
if Sender = Button2 then
Der Sender kann sich niemals einfach so innerhalb des Funktionsaufrufs verändern.
Wenn der Timer weiterläuft, dann wird über Application.ProcessMessages
immer wieder eine neue "Instanz" von Timer1Timer gestartet, welche niemals enden wird (Endlosschleife)

Da aber immer mehr Prozeduren gesartet werden, wird dieses Unweigerlich irgendwann in einem Stacküberlauf enden müssen.

Wozu überhaupt diese Schleife?
Delphi-Quellcode:
procedure TForm5.Timer1Timer(Sender: TObject);
var
    fHandle: HWND;
begin
    fHandle := FindWindow('notepad', nil);
    if (fHandle <> 0) and (GetForeGroundWindow <> fHandle) then
        SetForeGroundWindow(fHandle);
end;
Timer1.Intervall auf 50 eingestellt und du hast das selbe Ergebnis, aber ohne das Stackproblem.

PS: Warum ein rießiger Integer i, wo dieser doch nur wie ein Boolean verwendet wird?

mleyen 29. Jun 2010 14:38

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Wozu i?
Hmm, wie schreibt man Endlosschleifen, "while true"? Unnötig, hier ist goto gefordert. :lol:
Delphi-Quellcode:
var fHandle: HWND;
label ComeFrom;
begin
  fHandle := FindWindow('notepad', nil);
  if fHandle <> 0 then
  begin
    if Sender<>btn1 then
      Exit;
    ComeFrom:
    Application.ProcessMessages;
    sleep(50);
    if GetForeGroundWindow <> fHandle then
      SetForeGroundWindow(fHandle);
    goto ComeFrom;
  end;
Obs performanter ohne Abfragebedingun ist? :gruebel:

Neutral General 29. Jun 2010 14:41

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Zitat:

Zitat von mleyen (Beitrag 1032331)
Wozu i?
Hmm, wie schreibt man Endlosschleifen, "while true"? Unnötig, hier ist goto gefordert. :lol:

Auf ihn mit Gebrüll! :evil:
:?

PS: Ich denke nicht, dass es performanter ist ;) Im Zweifelsfall wird der gleiche Assemblercode erzeugt wie bei der while-true Schleife.

idefix2 29. Jun 2010 15:02

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Gescheiter wäre es, die stayontop Eigenschaft des entsprechenden Objekts zu setzen, wenn es nur um die Sichtbarkeit geht. Dem Anwender alle 50ms den Focus wegzunehmen, kann doch nicht die Absicht sein?

Um sich beliebige Fenster im Vordergrund sichtbar zu halten, gibt es übrigens die Freeware Deskpins.

BlueLiquidCell 29. Jun 2010 15:23

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Hey
Also um das mal klarzustellen. Es geht nicht um Notepad das war nur um es zu testen^^

Es geht um nen Flugsimulator. Das Problem dort ist, wenn man ihn im Fenstermodus laufen lässt (was für meine Anwendung nicht anders geht) dann geht der Sound sofort weg wenn man wo anders hinklickt, deshalb wollte ich halt etwas haben was ihn im Vordergrund hält oder bzw dann sofort wieder zurück bringt wenn man wo anders hingeklickt hat.
Mit Deskpins geht leider nicht, das Fenster bleibt zwar im Vordergrund aber leider nicht aktiv :-( -> Sound geht aus
Und ich wollt das halt mit einem Button aktivieren und mit nem anderen abbrechen.
Habs jetzt so gemacht:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
Timer1.Enabled:=True;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Timer1.Enabled:=False;
end;
Gibts da ne einfachere möglichkeit? Problem ist bei 50ms oder 100ms muss man schon öfter drücken bis der befehl durchkommt :-P

Vlt geht das mit dem Sound ja auch anders????

Danke für die Antworten ;-)

lbccaleb 5. Jul 2010 10:29

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Also es geht um Flightsimulator X, hast du zu selbigen mal die 2 Service Packs ausprobiert? Das währe auf jedenfall ne bessere Lösung als das irgend ein selbstgeschriebenes Programm erledigen zu lassen ;)

BlueLiquidCell 5. Jul 2010 10:35

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Hey
Ja klar hab ich gemacht, bringt leider nix. Auch in Foren zum FSX gibt es nirgens eine Lösung deswegen wollte ich halt selber probieren.
Christoph

PS: Sorry wegen dem andern Thread, kenn mich hier noch net so aus ;-)

Hier nochmal das Problem:

Es geht um nen Flugsimulator. Das Problem dort ist, wenn man ihn im Fenstermodus laufen lässt (was für meine Anwendung nicht anders geht) dann geht der Sound sofort weg wenn man wo anders hinklickt, deshalb wollte ich halt etwas haben was ihn im Vordergrund hält oder bzw dann sofort wieder zurück bringt wenn man wo anders hingeklickt hat.
Mit Deskpins geht leider nicht, das Fenster bleibt zwar im Vordergrund aber leider nicht aktiv -> Sound geht aus
Und ich wollt das halt mit einem Button aktivieren und mit nem anderen abbrechen.
Habs jetzt so gemacht:

Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
var
    fHandle, fHandle2: HWND;
begin
    fHandle := FindWindow('fs98main', nil);
    if (fHandle <> 0) then
    begin
       BringWindowToTop(fHandle);
       SetForeGroundWindow(fHandle);
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Timer1.Enabled:=True;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Timer1.Enabled:=False;
end;
Problem 1:
Wenn der Timer auf 50ms oder 100ms gestellt ist muss man schon öfter die Abbrechen Taste drücken bis der befehl durchkommt.

Problem 2:
Wenn Ich das Programm unter Delphi teste funktioniert es immer.
Wenn ich es allerdings alleine (nur die .exe) starte, bringt es den Flugsimulator auch in den Vordergrund wenn ich aber danach ein Windows fenster anklicke funktioniert es anscheinend nicht mehr. Der Flugsimulator blinkt zwar unter in der Taskleiste kommt aber nicht in den Vordergrund.

Vlt geht das mit dem Sound ja auch anders???? Man Kann im Flugsimulator die Sound-Device ID einstellen. Kann man vlt ein Neues Device erstellen was den Sound immer weitergibt an das richtige Device?

Danke schonmal für die Antworten

Christoph

Mschmidt 5. Jul 2010 16:32

AW: Befehl immer wieder ausführen ohne CPU belastung
 
versuchs mal mit dem reagieren auf die Windows-Botschaft WM_NCACTIVATE().
:-mschmidt

Aphton 5. Jul 2010 17:58

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Zitat:

Zitat von himitsu (Beitrag 1032330)
PS: Warum ein rießiger Integer i, wo dieser doch nur wie ein Boolean verwendet wird?

Ein Boolean ist auch nicht gerade "winzig" ... ist immerhin 1/4 x so groß wie ein Integer :P

himitsu 5. Jul 2010 18:47

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Standardmäßig bietet er aber "logisch" gesehn genau die 2 nötigen Zustände.

BlueLiquidCell 5. Jul 2010 20:37

AW: Befehl immer wieder ausführen ohne CPU belastung
 
MSchmidt - WM_NCACTIVATE()

Hab das mit dem WM_NCACTIVATE() mal ausprobiert. Wie das bei meiner eigenen Form funktioniert ist klar aber wie kann ich das denn allgemein überwachen, welches Programm grade diesen Befehl bekommt.

Christoph

rollstuhlfahrer 5. Jul 2010 23:10

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Ich würde mal sagen, da du ja das Fensterhandle von deinem Prozess hast, kannst du auch an das die Nachricht schicken (Send-/PostMessage). Als Parameter solltest du für wParam ein TRUE und für lParam ein -1 nehmen. Laut MSDN sagt das dann dem Fenster, es soll sich eine aktive Titelleiste zulegen, auch wenn diese dann nicht gezeichnet wird.

Bernhard

BlueLiquidCell 6. Jul 2010 13:34

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Ja das könnte ich machen, aber das Problem war ja primär zu wissen wann es auf nicht aktiv gesetzt wird um dann was dagegen zu tun. Momentan mach ich das halt alle 100ms oder so, und das is ja nicht so das wahre.
Oder hab ich dich jetzt falsch verstanden?
Christoph

BlueLiquidCell 7. Jul 2010 10:51

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Also hab das WM_NCACTIVATE ausprobiert. Mit Notepad funktionierts. Bin momentan nicht an meinem anderen Rechner, deswegen kann ich das mitm sound grad nicht ausprobieren.
Das mit dem lParam hab ich allerdings noch nicht so ganz verstanden. Hab Einstellung 1, 0, -1 ausprobiert und nicht wirklich einen unterschied gemerkt.
Zur Aktivierung die Aktion ausgeführt wird hab ich mir überlegt, dass man ja nach jedem Mausklick ein bisschen wartet und es dann ausführt. Gibt es eine Möglichkeit den Mousklick auf dem gesamten Desktop zu überwachen? Oder geht das nur innerhalb der Form?
Christoph

rollstuhlfahrer 7. Jul 2010 12:19

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Du kannst alle Mausklicks durch einen Hook überwachen. Wenn dann einer dabei ist, der außerhalb deines Fensters ist, kannst du ihn entweder blocken oder einen in das Fenster nachsetzen.

Bernhard

Luckie 7. Jul 2010 12:27

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Sag mal, macht ihr euch auch mal Gedanken über die eure Themenüberschriften?
Zitat:

Befehl immer wieder ausführen ohne CPU belastung
Wenn das ginge, warum ist denn dann eine CPU überhaupt im Rechner drin? :wink:

Ich weiß nicht, ob das schon gesagt wurde, aber lass die CPU doch arbeiten, dazu hast du sie doch gekauft. Und so lange sie Rechenzeit abgibt, wenn andere Prozesse sie benötigen, ist doch alles in Ordnung. Eventuell sollte man sich ein anderes Konzept überlegen. Du rennst ja auch nicht alle fünf Minuten an die Tür und guckst, ob jemand davor steht, dazu hast du ja eine Klingel. die dich benachrichtigt, wenn jemand davor steht. Also anstatt immer das Fenster in den Vordergrund zu holen, über Sinn und Unsinn lasse ich mich jetzt nicht aus, könnte man überlegen, ob man eine Möglichkeit findet sie nur in den Vordergrund zu holen, wenn es nötig ist.

rollstuhlfahrer 7. Jul 2010 12:33

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Auch dafür gibt es einen Hook, der dann ausgibt, wann ein Fenster den Fokus bekommt/entzogen bekommt oder erschaffen wird. siehe msdn

Bernhard

BlueLiquidCell 7. Jul 2010 12:49

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Also das mit der WM_NACTIVATE funktioniert zwar aber der Sound bleibt trotzdem aus. :-(

Mit den Hooks muss ich mir mal genauer anschaun, davon hab ich keine Ahnung aber danke für den Tip ;-)

@ Luckie
Ich brauch die CPU Leistung für nen Spiel. Deswegen ist die Überschrift so! Versteh jetzt nicht was daran so schlimm ist?

PS: Warum können die das denn nicht einfach ordentlich Programmieren :-(

BlueLiquidCell 8. Jul 2010 21:26

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Hooks?!
Also das mit den Hooks versteh ich net so wirklich. Hat jemand Ahnung davon? Könntet ihr nen kleines Beispiel zum Fenster und Maus hook hier rein schreiben?
Vielen Dank!
Christoph

NicoleWagner 9. Jul 2010 11:21

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Das ist ein ganz alter Sound-Code. Weiss nicht, was Du etwas davon gebrauchen kannst.
Warnungen wirst Du sehen. Funktionieren sollte er aber schon.

Beachte bitte, dass "Beep" in mehreren Units vorhanden ist.
Es gibt einen von system, utils, windows oder so.


Delphi-Quellcode:
unit Sound_ausgabe;
Interface
uses windows, sysutils;
Procedure Tonausgabe;
procedure Sound(aFreq, aDelay: Integer) ;
procedure NoSound;

//******************************************************************************
implementation
Procedure Tonausgabe;
begin
 { 
aufrufen mit:
  Tonausgabe; // Ausgabe auf dem Systemlautsprecher, also ohne Boxen



 Sound(500, 100) ; //erst Ton, dann Dauer
   Sound(590, 90) ;
   Sound(710, 160) ; // klingt falsch
   Sound(440, 100) ; //erst Ton, dann Dauer
   Sound(880, 90) ;
   Sound(260, 160) ;  // klingt wie ein nervendes Spiel
   
   Sound(260, 90);
   Sound(440, 100);
   Sound(880, 100); }

   Sound(440,200);
   NoSound;
end;
{
G: 440
a, eine Oktave tiefer (leere A-Saite) hat genau die halbe Schwingungszahl, nämlich 220 Hz
(Oktaven bilden also immer exakte Vielfache oder glatte Quotienten einer Grundzahl.
Die Oktaven zum Ton a (= 440 Hz) liegen nach unten bei 220, 110, 65, 32,5
und 16,25 Hz, nach oben bei 880, 1760 Hz usw.)

Frequenz: 136,10 Hertz (Ton: CIS)
Frequenz: 147,85  Hertz (Ton: D)
Frequenz: 172,06 Hertz (Ton: F) 22.12
Frequenz: 194,18 Hertz (Ton: G)
Frequenz: 210,42 Hertz (Ton: GIS) 16.24
Frequenz: 221,23 Hertz (Ton: A)
Frequenz: 194,18 Hertz (Ton: Ais) ???
Frequenz: 241,56 Hertz (Ton: H)
 
}


procedure SetPort(address, Value: Word) ;
var
   bValue: Byte;
begin
   bValue := trunc(Value and 255) ;
   asm
     mov dx, address
     mov al, bValue
     out dx, al
   end;
end;
//******************************************************************************
function GetPort(address: Word): Word;
var
   bValue: Byte;
begin
   asm
     mov dx, address
     in al, dx
     mov bValue, al
   end;
   GetPort := bValue;
end;
//******************************************************************************
procedure Sound(aFreq, aDelay: Integer) ;
////////////////////////////////////////////////////////////////////////////////
   procedure DoSound(Freq: Word) ;
   var
     B: Byte;
   begin
     if Freq > 18 then
     begin
       Freq := Word(1193181 div Longint(Freq)) ;
       B := Byte(GetPort($61)) ;

       if (B and 3) = 0 then
       begin
         SetPort($61, Word(B or 3)) ;
         SetPort($43, $B6) ;
       end;

       SetPort($42, Freq) ;
       SetPort($42, Freq shr 8) ;
     end;
   end;
////////////////////////////////////////////////////////////////////////////////
   procedure Delay(MSecs: Integer);// habe vor GetTick Count 2x Abs() eingefügt
   var
     FirstTickCount: Integer; //vorher: LongInt; sollte ident sein
   begin
     FirstTickCount := Abs(GetTickCount);
     repeat
       Sleep(1) ;
       //or use Application.ProcessMessages instead of Sleep
     until ((Abs(GetTickCount) - FirstTickCount) >= Longint(MSecs)) ;
   end;
//GetTickCount aus Kernel:
// Retrieves the number of milliseconds that have elapsed since the system was started
////////////////////////////////////////////////////////////////////////////////
begin
   if Win32Platform = VER_PLATFORM_WIN32_NT then
   begin
     Windows.Beep(aFreq, aDelay) ;
   end
   else
   begin
     DoSound(aFreq) ;
     Delay(aDelay) ;
   end;
end;
//******************************************************************************
procedure NoSound;
var
   Value: Word;
begin
   if not (Win32Platform = VER_PLATFORM_WIN32_NT) then
   begin
     Value := GetPort($61) and $FC;
     SetPort($61, Value) ;
   end;
end;
//******************************************************************************
end.

OldGrumpy 9. Jul 2010 11:41

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Bitte einmal Pizza für Jonas Wagner und eine große Portion Eis und einen Ventilator für Nicole Wagner :mrgreen:

BlueLiquidCell 10. Jul 2010 22:41

AW: Befehl immer wieder ausführen ohne CPU belastung
 
Hallo Nicole
Danke für den Code. Wirklich verstehen tue ichs aber net. Vlt bin ich aber auch zu doof ;-)
Christoph


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:54 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz