Repérer un programme inactif et le fermer...

cs_marignan1515 Messages postés 4 Date d'inscription dimanche 31 octobre 2004 Statut Membre Dernière intervention 29 mai 2006 - 27 mai 2006 à 18:57
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 - 29 mai 2006 à 23:20
Bonjour,
Voilà mon problème. Je veux créer une application qui chaîne plusieurs diaporamas faits par des enfants. Ces diaporamas sont en exe... avez-vous une idée quant au moyen de les fermer sans intervention extérieure quand la dernière image est affichée plus de 5 sec ? Par défaut les images restent affichées 5 s sauf la dernière qui reste affichée jusqu'à l'appui sur la touche 'esc'. L'API 'WaitForSingleObject()' est-elle une bonne piste (les diaporamas sont lancés par CreateProcess) ?
Merci de votre aide...

Marignan1515

8 réponses

Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
27 mai 2006 à 19:09
Salut,

ces diaporamas sont fait avec quel outil

parce que si c'est fait avec Delphi alors la solution devrait être très simple

@+
Cirec
0
cs_marignan1515 Messages postés 4 Date d'inscription dimanche 31 octobre 2004 Statut Membre Dernière intervention 29 mai 2006
27 mai 2006 à 19:27
En effet, ça aurait bien arrangé les choses... Mais ils sont faits à partir d'un freeware 'diaporama' disponible sur www.softchris.com.
Cordialement,

Marignan1515
0
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
28 mai 2006 à 19:18
>marignan1515: Non ce n'est pas possible de déterminer depuis combien de temps un processus est inactif (du moins pas de façon vraiment déterministe). On pourrait essayer de calculer le pourcentage de ressource processeur qu'il utilise mais ce n'est pas très fiable, et de plus un programme "inactif" en apparence peut quand même consommer de la ressource...

Mais j'ai peut-être une solution à ton problème. Si j'ai bien suivi, il te suffit de savoir si ce qui est affiché à l'écran n'a pas bougé depuis 5 secondes? Voilà une fonction qui te permettra de savoir depuis combien de temps ce qui n'est pas affiché à l'écran n'a pas changé:

function MonitorScreen(TimeOut:Cardinal):Boolean;
var
  DC:HDC;
  Bitmap:TBitmap;
  Buffer1,Buffer2:Pointer;
  TickStart,TickEnd:Cardinal;
  BuffSize:Integer;
  BI:TBitmapInfo;
begin
  DC:=GetDC(GetDesktopWindow);
  Bitmap:=TBitmap.Create;
  Bitmap.Width:=400;
  Bitmap.Height:=400;
  BuffSize:=Align32(24*Bitmap.Width)*Bitmap.Height;
  GetMem(Buffer1,BuffSize);
  ZeroMemory(Buffer1,BuffSize);
  GetMem(Buffer2,BuffSize);
  ZeroMemory(Buffer2,BuffSize);
  Sleep(500);
  try
    ZeroMemory(@BI,SizeOf(BI));
    with BI.bmiHeader do begin
      biSize:=SizeOf(TBitmapInfoHeader);
      biWidth:=Bitmap.Width;
      biHeight:=Bitmap.Height;
      biPlanes:=1;
      biBitCount:=24;
      biCompression:=BI_RGB;
      biSizeImage:=BuffSize;
    end;
    StretchBlt(Bitmap.Canvas.Handle,0,0,Bitmap.Width,Bitmap.Height,DC,0,0,Screen.Width,Screen.Height,SRCCOPY);
    if GetDIBits(Bitmap.Canvas.Handle,Bitmap.Handle,0,Bitmap.Height,Buffer1,BI,DIB_RGB_COLORS)=0 then
      RaiseLastOSError;
    TickStart:=GetTickCount;
    repeat
      Sleep(500);
      StretchBlt(Bitmap.Canvas.Handle,0,0,Bitmap.Width,Bitmap.Height,DC,0,0,Screen.Width,Screen.Height,SRCCOPY);
      if GetDIBits(Bitmap.Canvas.Handle,Bitmap.Handle,0,Bitmap.Height,Buffer2,BI,DIB_RGB_COLORS)=0 then
        RaiseLastOSError;
      TickEnd:=GetTickCount;
    until (TickEnd-TickStart>TimeOut) or not CompareMem(Buffer1,Buffer2,BuffSize);
    Result:=TickEnd-TickStart<=TimeOut;
  finally
    FreeMem(Buffer1);
    FreeMem(Buffer2);
    ReleaseDC(GetDesktopWindow,DC);
    Bitmap.Destroy;
  end;
end;

Si tu appelles la fonction ainsi (le paramètre TimeOut s'exprime en millisecondes):
MonitorScreen(10000)

2 possibilités:

1/si le contenu de l'écran n'a pas changé au bout de 10 secondes, la fonction s'arrète et renvoie False

2/si le contenu de l'écran change avant que 10 secondes ne se soient écoulées, cette fonction s'arrète à la première modification détectée et renvoie True.

Ainsi, en appelant Monitor(6000) par exemple, tu sauras si ton programme est resté inactif plus de 6000 millisecondes (donc 6 secondes>5 secondes). A noter que pour être compilée, la fonction nécessite les unités Graphics et Windows dans la clause uses de ton unité (elles sont déjà mises par défaut par Delphi pour les fiches).

La fonction est précis à une demi-seconde près environ (à cause du Sleep(500)) si tu veux que ce soit un peu plus précis tu peux diminuer 500 et mettre une valeur en millisecondes plus petite, mais cette fonction consommera plus de ressources processeur.

Voilà, j'espère avoir résolu ton problème     
0
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
28 mai 2006 à 19:20
Oups j'ai oublié, il faut rajoutter cette fonction-là juste avant la précédante:
function Align32(x:Integer):Integer;
begin
  if x mod 32=0 then
    Result:=x div 8
  else
    Result:=1+x div 8;
end;
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_marignan1515 Messages postés 4 Date d'inscription dimanche 31 octobre 2004 Statut Membre Dernière intervention 29 mai 2006
28 mai 2006 à 21:48
Un grand merci,
Je ne suis pas sûr de tout comprendre quant aux diverses instructions. J'ajouterai ces fonctions à mon application et te (vous) tiendrai au courant dès que possible. Cordialement,

Marignan1515
0
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
29 mai 2006 à 02:10
Je crois que le style habituel du forum est le tutoiement, donc je propose qu'on s'y tienne.

Le code ci-dessus permet de récupérer l'image de l'écran et de la copier sur un TBitmap (l'objet standard de Delphi pour contenir des images). C'est la procédure
StretchBlt

qui permet de le faire. La procédure

GetDIBits

permet de récupérer dans un Buffer les données de cette image (en fait un tableau de RGB, rouge vert et bleu). Toutes les 500 millisecondes, ce Buffer stocké dans Buffer2 est comparé avec l'image de départ stockée au préalable dans Buffer1. Tant que les 2 zones de données sont égales, l'image n'a pas changé donc on continue la boucle repeat...until.

Si les 2 buffers ne contiennent pas les même données (donc que l'image a changé), ou si le temps écoulé a dépassé TimeOut ms alors on quitte la boucle. Le résultat est True si on a quitté la boucle avant la fin du temps imparti (TickEnd-TickStart<TImeOut), False sinon.

GetTickCount est une fonction qui permet de récupérer le nombre de millisecondes écoulées depuis le lancement de WIndows. Elle sert à initialiser TickStart avant la boucle, et à récupérer le temps écoulé à chaque fois dans TickEnd. Le reste du code n'est que de l'allocation/libération de mémoire et de constantes, et la récupération d'un objet windows pour obtenir l'image affichée sur l'écran de la machine: DC:=GetDC(GetDesktopWindow).

Voilà, j'espère que c'est (un peu) plus clair!

A bientôt
0
cs_marignan1515 Messages postés 4 Date d'inscription dimanche 31 octobre 2004 Statut Membre Dernière intervention 29 mai 2006
29 mai 2006 à 08:01
Voilà une affaire qui roule, tes deux fonctions m'ont rendu un sacré service !  Merci aussi pour les explications. Les diaporamas s'enchaînent sans problème.

Marignan1515
0
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
29 mai 2006 à 23:20
Marignan1515 : Pensez à cliquer sur Réponse acceptée lorsque la réponse vous convient...


Et bravo à Forman pour ce magnifique code.
0
Rejoignez-nous