web-dev-qa-db-fra.com

Gardez la fenêtre en haut et volez concentré sur Winforms

Je me rends compte que cela constituerait une toute mauvaise pratique dans des situations normales, mais il s'agit simplement d'une application de test qui doit être saisie à partir d'un scanner de code à barres (émulation d'un clavier). Le problème est que j'ai besoin de démarrer des scripts lors de la numérisation, j'ai donc besoin de la fenêtre pour reprendre la mise au point après que je clique sur le script pour l'exécuter. J'ai essayé d'utiliser Activate (), CadvertoFront (), Focus () ainsi que certains appels Win32 tels que SetForegroundwindow (), SetCapture () et SetactiveWindow () ... Cependant, le meilleur que je puisse obtenir l'un d'entre eux à faire est de Rendre la barre des tâches commence à clignoter pour me dire que c'est veut de se concentrer, mais quelque chose l'arrête. BTW, j'exécute cela sur XP SP2 et en utilisant .NET 2.0.

Est-ce possible?

Edit: Pour clarifier, je suis en train d'exécuter les scripts en double-cliquant sur eux dans Explorer. J'en ai donc besoin de voler sur l'explorateur et de l'application de test.

23
Adam Haile

J'ai eu du mal à un problème similaire pendant un certain temps. Après beaucoup d'expérimentation et de devinette, voici comment je résolvai-je:

// Get the window to the front.
this.TopMost = true;
this.TopMost = false;

// 'Steal' the focus.
this.Activate();
42
TallGuy

J'ai eu un problème similaire et j'ai trouvé ce qui suit pour faire le tour. Adapté à c # à partir de ici

        // force window to have focus
        uint foreThread = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);
        uint appThread = GetCurrentThreadId();
        const uint SW_SHOW = 5;
        if (foreThread != appThread)
        {
            AttachThreadInput(foreThread, appThread, true);
            BringWindowToTop(form.Handle);
            ShowWindow(form.Handle, SW_SHOW);
            AttachThreadInput(foreThread, appThread, false);
        }
        else
        {
            BringWindowToTop(form.Handle);
            ShowWindow(form.Handle, SW_SHOW);
        }
        form.Activate();

Modifier: Voici les définitions Pinvoke nécessaires pour C #:

[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

// When you don't want the ProcessId, use this overload and pass IntPtr.Zero for the second parameter
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);

[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();

/// <summary>The GetForegroundWindow function returns a handle to the foreground window.</summary>
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll")]
static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

[DllImport("user32.dll", SetLastError = true)]
static extern bool BringWindowToTop(IntPtr hWnd);

[DllImport("user32.dll", SetLastError = true)]
static extern bool BringWindowToTop(HandleRef hWnd);

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);
12
Ken

La façon dont j'ai abordé ce problème était de reproduire un autre fil dont le seul but était de s'assurer que la forme est la plus haute et axée à tout moment. Ce code rendra toutes les autres applications inutilisables pendant son exécution, ce qui est ce dont j'avais besoin pour mes applications spécifiques. Vous pouvez ajouter un sommeil dans KeepFocus ou avoir un autre événement le déclencher.

using System.Threading;          // be sure to include the System.Threading namespace

    //Delegates for safe multi-threading.
    delegate void DelegateGetFocus();
    private DelegateGetFocus m_getFocus;

    //Constructor.
    myForm()
    {
        m_getFocus = new DelegateGetFocus(this.getFocus);   // initialise getFocus
        InitializeComponent();
        spawnThread(keepFocus);                             // call spawnThread method
    }

    //Spawns a new Thread.
    private void spawnThread(ThreadStart ts)
    {
        try
        {
            Thread newThread = new Thread(ts);
            newThread.IsBackground = true;
            newThread.Start();
        }
        catch(Exception e)
        {
            MessageBox.Show(e.Message, "Exception!", MessageBoxButtons.OK, 
                MessageBoxIcon.Error);
        }
    }

    //Continuously call getFocus.
    private void keepFocus()
    {
        while(true)
        {
            getFocus();
        }
    }

    //Keeps Form on top and gives focus.
    private void getFocus()
    {
        //If we need to invoke this call from another thread.
        if (this.InvokeRequired)
        {
            try
            {
                this.Invoke(m_getFocus, new object[] { });
            }
            catch (System.ObjectDisposedException e)
            {
                // Window was destroyed. No problem but terminate application.
                Application.Exit();
            }
        }
        //Otherwise, we're safe.
        else
        {
            this.TopMost = true;
            this.Activate();
        }
    }       
}
7
mxgg250

Vous pourriez essayer de vous concentrer sur une entrée spécifique ou d'essayer la propriété de réglage .toptopment sur TRUE (puis de la désapprouver).

Mais je suppose que votre problème est que ces méthodes ne placent tout simplement pas de messages dans la file d'attente Windows Event, et votre programme doit attendre que tous les événements existants pour finir le traitement avant de ne pas gérer celui-ci et de focaliser l'application.

0
Joel Coehoorn