none
Lancer l'économiseur d'écran RRS feed

  • Question

  • Bonjour tout le monde,

    J'essaie de déclencher l'économiseur d'écran (et ne riez pas, c'est sous Windows XP). Le code ci-dessous fonctionne très bien si je l'exécute en mode console, ou si je mets un point d'arrêt au début. Sinon, dans un bouton Winform en fonctionnement normal, on perd le contrôle à partir du premier beep, et il n 'y a pas d'économiseur d'écran, il faut demander à Visual Studio d'arrêter le débogage (ou terminer le programme à la cosaque). Je croyais bien faire avec Application.DoEvents() pour redonner le contrôle au système le temps d'exécuter une instruction, apparemment ça ne sert à rien.

    J'ai tenté de mettre ce code dans un timer, et d'activer le timer par le bouton, ça n'a pas l'air terrible non plus. Un délai de 100 devrait bien être suffisant ?

    En fait toutes les recettes qu'on utilisait en VBA en pareille circonstance.

    Alors quoi je fais-je ? Un appel au code écrit en mode console ? ça fait un peu "ballot". Je sens venir qu'il va falloir que je me mette au multi-thread ? Comme mes premières idées ont été vaines j'aimerais bien que quelqu'un me confirme que celle-ci est bonne avant de trouver potentiellement d'autres moyens de planter la machine.

                timer1.Enabled = false;
                int delai = 10;
                Application.DoEvents();
                int SPI_SETSCREENSAVETIMEOUT = 0x000F;
                Beep(200, 10);
                Application.DoEvents();
                SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, delai, 0, 0);
                Application.DoEvents();
                Beep(200, 20);
                Application.DoEvents();
                System.Threading.Thread.Sleep(15000);
                Application.DoEvents();
                Beep(400, 20);
                Application.DoEvents();
                SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, 360, 0, 0);
                Application.DoEvents();



    • Déplacé Teodora SharkovaModerator mardi 27 octobre 2015 12:41 déplacé de Applications pour Windows Store
    • Modifié Gloops mercredi 28 octobre 2015 07:10
    vendredi 23 octobre 2015 16:01

Réponses

  • Bonjour, Gloops,


    Veuillez consulter le thread en bas (le commentaire d'utilisateur IronRazer):
    Get and Set Screen Saver Timeout
    Je vous remercie par avance de votre retour.

    Cordialement,
    Teodora


    Votez! Appel à la contribution TechNet Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.


    mardi 27 octobre 2015 12:44
    Modérateur

Toutes les réponses

  • Bonjour, Gloops,


    Veuillez consulter le thread en bas (le commentaire d'utilisateur IronRazer):
    Get and Set Screen Saver Timeout
    Je vous remercie par avance de votre retour.

    Cordialement,
    Teodora


    Votez! Appel à la contribution TechNet Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.


    mardi 27 octobre 2015 12:44
    Modérateur
  • Bonjour,

    Oui effectivement il faut que je regarde ça, merci.

    Pour l'essentiel il a appelé le même code que moi, il faut que je vérifie les types de variables, parfois il y a un booléen qui devient un entier en changeant de version de Windows. ça serait assez inattendu que les types ne soient pas les mêmes entre Winform et console, mais il est possible qu'un environnement soit plus souple que l'autre.

    Sinon j'ai vu un Process.Start, mais j'ai regardé trop vite pour réaliser si c'était un aparte dans le fil au sujet d'autre chose, ou si d'entrée de jeu on est parti du principe que ce n'était pas la peine de chercher à appeler l'API directement depuis Winform.

    Je vais regarder ça ce soir (et il y a une histoire sous MVC qui attend aussi ...)

    mercredi 28 octobre 2015 07:04
  • Bonjour,

    J'ai créé un programme en VB.Net pour y créer la classe d'IronRazer, et ça fonctionne très bien (avec quelques secondes de délai).

    Pour ce qui est de mon programme C# j'ai dû oublier quelque chose quelque part : depuis le Form_Load je peux faire autant de Beep que je veux (ce qui tendrait à valider la signature de la fonction beep), en revanche depuis un Button_Click ou un Timer_Tick, le premier Beep est exécuté, et ensuite je perds le contrôle.

    Le module du formulaire commence comme ça :

    using System.Runtime.InteropServices;
    
    namespace ScreenSavePar
    {
        public partial class Form1 : Form
        {
            [DllImport("user32.dll", EntryPoint = "SystemParametersInfoA")]
            private static extern int SystemParametersInfo(int uAction, int uParam, int lpvParam, int fuWinIni);
            [DllImport("kernel32.dll")]
            private static extern int Beep(int dwFreq, int dwDuration);

    et j'ai bien entendu fait quelques essais en déclarant ces deux fonctions de type booléen plutôt qu'entier.

    J'ai déjà écrit dans le passé des programmes qui déclenchent des beep en cliquant sur un bouton donc il ne semble pas que ça soit le système.

    Je dois penser à désactiver l'antivirus sinon il met trop de temps à déverrouiller le code objet, mais une fois qu'il est désactivé ...

    Donc je peux soit appeler un programme console soit utiliser la classe d'IronRazer (en la compilant en DLL pour l'utiliser en C#), toutefois comprendre ce que j'ai fait de travers pourrait aussi présenter un intérêt.

    N.B. Pour les signatures d'API j'utilise l'API-Viewer

    • Modifié Gloops jeudi 29 octobre 2015 07:33
    jeudi 29 octobre 2015 06:58
  • De toute manière, ça n'a jamais été présenté comme une idée bien fameuse de déclarer les API directement dans le module utilisateur, d'ailleurs en VB6 c'était carrément interdit.

    J'ai repris l'idée d'une classe séparée pour l'accès aux API, et j'en ai tenté une en C#.

    Mauvaise surprise : autant l'appel en VB fonctionne sans problème, autant en C# quand j'essaie de lire le temps de déclenchement de l'économiseur d'écran, j'obtiens une erreur 3E6, accès invalide à la zone mémoire.

    Si j'avais oublié de déclarer Public la classe et la fonction le compilateur m'aurait rappelé à l'ordre, donc, il y a quelque chose d'un peu plus futé.

    A ce stade-là je ne me méfie pas trop de l'antivirus puisque j'ai dû le désactiver pour accéder au code objet.

    Peut-être quelque chose que j'ai su et que j'ai oublié ?

    Ah, une chose que j'ai faite différemment en C#, c'est d'utiliser des fonctions statiques plutôt que d'instancier le module. Est-ce une "conceté" ? Je me suis méfié que ça soit à cause de ça que j'aie une erreur d'accès, mais je suis revenu en arrière pour mettre des fonctions non statiques et instancier le module, et j'ai la même erreur.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace ScreenSavePar
    {
        public class APIS
        {
            [DllImport("user32.dll", EntryPoint = "SystemParametersInfoA")]
            static extern int SystemParametersInfo(
                 int uAction,
                 int uParam,
                 int lpvParam,
                 int fuWinIni);
            [DllImport("kernel32.dll")]
            private static extern bool Beep(int dwFreq, int dwDuration);
    
            [DllImport("kernel32.dll")]
            static extern int GetLastError();
            
            static int SPIF_UPDATEINIFILE = 0x0001;
            static int SPIF_SENDWININICHANGE = 0x0002;
            static int SPI_SETSCREENSAVETIMEOUT = 0x000F;
            static int SPI_GETSCREENSAVETIMEOUT = 0x000E;
    
            public static int SetScreensaveDelay(int delai)
            {
                return (SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, delai, 0, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE));
            }
    
            public static int GetScreensaveDelay()
            {
                int lSeconds=100;
                if(SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, 0, lSeconds, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE)==0)
                {
                    int ierr = GetLastError();
                    System.Windows.Forms.MessageBox.Show("Erreur " + ierr.ToString("X"));
                    return -1;
                }
                else
                {
                    return lSeconds;
                }
            }
    
            public static void Beepe(int freq, int dur)
            {
                Beep(freq, dur);
            }
        
        }
    }


    • Modifié Gloops jeudi 29 octobre 2015 10:53
    jeudi 29 octobre 2015 10:49
  • Alors après, j'aurais bien une autre question. Il y aurait bien matière à ouvrir un nouveau fil, pas forcément dans le même forum d'ailleurs, mais elle s'insère tellement bien sous le même titre que je vais à tout hasard la poser ici pour commencer.

    J'ai donc un bouton pour lancer l'économiseur d'écran (et si je peux aussi comprendre pourquoi le faire en C# a échoué ça sera plus "propre"), mais le but serait d'être capable de le faire apparaître sur l'écran d'accueil, quand celui-ci oublie d'afficher la liste des utilisateurs. En effet l'économiseur d'écran a ... un certain nombre de chances, sur un certain nombre, de corriger le problème, et la probabilité de refaire apparaître la liste d'utilisateurs s'accroît à chaque fois qu'on relance l'économiseur d'écran. D'ailleurs, il est rare que ça ne marche pas du premier coup.

    Il y a un an ou deux j'ai essayé d'ajouter une précédente version de ce programme à la liste des programmes d'accessibilité, qu'on affiche par le gestionnaire avec le raccourci Windows U, mais ça n'avait pas l'air évident du tout d'ajouter quelque chose là-dedans. Comme le délai d'économiseur s'était bloqué sur une valeur bien trop faible j'avais été obligé de carrément supprimer l'économiseur d'écran quelque temps, d'où le délai avant que le sujet revienne sur le tapis.

    Alors à défaut, j'ai cru trouver une solution en lançant mon programme à la place du clavier à l'écran, en le renommant C:\Windows\osk.exe, après avoir renommé celui-ci bien entendu. Et j'ai créé un deuxième bouton sur le formulaire pour lancer le vrai clavier à l'écran, à l'aide du nom que je lui ai donné.

    Mais voilà, tout ça fonctionne très bien dans la session, mais moi c'est en dehors de la session que j'en ai besoin, sur l'écran d'accueil, et là mon formulaire n'apparaît pas. J'ai mis l'attribut "Always on top" au formulaire, apparemment, il lui en faut encore un autre.

    Où est-ce que je chercherais bien ça ?



    • Modifié Gloops jeudi 29 octobre 2015 17:17
    jeudi 29 octobre 2015 17:11