表单即将获得焦点时的事件? [英] Event when form is about to get focus?

查看:23
本文介绍了表单即将获得焦点时的事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想对屏幕键盘进行编程.

I want to program an on-screen keyboard.

要将密钥发送到另一个应用程序,我需要在我的应用程序即将获得焦点以及用户按下表单上的按钮发送密钥时存储当前的前景窗口(=具有焦点的窗口), 我将 SetForegroundWindow 设置为这个以前的窗口句柄.

To send keys to another application, I need to store the current foreground window (=the window with the focus) when my app is about to get the focus, and when the user presses a button on my form to send the key, I will SetForegroundWindow to this previous window handle.

这样文本将被发送到先前聚焦的窗口.

This way the text will be sent to the previously focussed window.

但是,我没有找到正确的事件.

However, I don't find the correct event for that.

Form_Activated 为时已晚.

Form_Activated is too late.

使用计时器不断检查当前前景窗口似乎有点粗鲁.

Using a timer to constantly check for the current foreground window seems a bit rude.

是否有官方"?在我的应用获得焦点之前发生的事件?

Is there an "official" event that occurs before my app gets the focus?

推荐答案

无耻:,我同意 Jimi 和 jmcilhinney 的评论,我也同意相信这不是实现屏幕键盘的正确方法,但这篇文章只是想帮助你:

Impoerant:, I agree with Jimi's and jmcilhinney's comments and I also believe it's not the right way of implementing an on-screen keyboard, but this post it just trying to help you on:

  • 查找停用窗口的句柄时此窗口已被激活.

当这个窗口被激活时,找到被停用窗口的句柄

您可以使用 SetWinEventHook 你可以收听 一些事件 来自其他进程并注册WinEventProc 回调方法接收事件时引发的事件.

Find handle of the deactivated window when this window has been activated

You can use SetWinEventHook you can to listen to some events from other processes and register a WinEventProc callback method to receive the event when the event raised.

这里我们对 EVENT_SYSTEM_FOREGROUND 感兴趣.每次我们收到这个事件,如果激活的窗口不是我们的窗体,我们跟踪已经激活的窗口,然后当我们的窗口被激活时,我们查看被跟踪的窗口的值,它现在是前一个丢失的窗口重点.

Here we are interested in EVENT_SYSTEM_FOREGROUND. Every time that we receive this event, if the activated window is not our form, we track the window which has been activated, then when our window is activated we look into the value of tracked window which is now the previous window which has lost its focus.

C#

这是我尝试过并且对我来说效果很好的代码:

Here is the code that I tried and worked well for me:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class MyForm : Form
{
    public const uint EVENT_SYSTEM_FOREGROUND = 0x0003;
    public const uint EVENT_OBJECT_DESTROY = 0x8001;
    public const uint WINEVENT_OUTOFCONTEXT = 0;

    public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, 
        IntPtr hwnd, int idObject, int idChild, 
        uint dwEventThread, uint dwmsEventTime);
    
    [DllImport("user32.dll")]
    public static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, 
        IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, 
        uint idProcess, uint idThread, uint dwFlags);
    
    [DllImport("user32.dll")]
    public static extern bool UnhookWinEvent(IntPtr hWinEventHook);

    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();

    IntPtr hook = IntPtr.Zero;
    protected override void OnLoad(EventArgs e)
    {
        previous = GetForegroundWindow();
        hook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, 
        EVENT_SYSTEM_FOREGROUND,
        IntPtr.Zero, new WinEventDelegate(WinEventProc),
        0, 0, WINEVENT_OUTOFCONTEXT);
        base.OnLoad(e);
    }
    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        UnhookWinEvent(hook);
        base.OnFormClosing(e);
    }
    IntPtr? previous = null;
    void WinEventProc(IntPtr hWinEventHook, uint eventType,
        IntPtr hwnd, int idObject, int idChild, uint dwEventThread,
        uint dwmsEventTime)
    {
        if (hwnd != this.Handle)
        {
            previous = hwnd;
        }
        else
        {
            if (previous.HasValue)
                this.Text = $"Previous window: {(int)previous:X}";
            else
                this.Text = $"No idea about previous window.";
        }
    }
}

VB.NET

Imports System.Runtime.InteropServices

Public Class MyForm
    Inherits Form

    Public Const EVENT_SYSTEM_FOREGROUND As UInteger = &H3
    Public Const EVENT_OBJECT_DESTROY As UInteger = &H8001
    Public Const WINEVENT_OUTOFCONTEXT As UInteger = 0
    Public Delegate Sub WinEventDelegate(ByVal hWinEventHook As IntPtr,
                                         ByVal eventType As UInteger,
                                         ByVal hwnd As IntPtr,
                                         ByVal idObject As Integer,
                                         ByVal idChild As Integer,
                                         ByVal dwEventThread As UInteger,
                                         ByVal dwmsEventTime As UInteger)
    <DllImport("user32.dll")>
    Public Shared Function SetWinEventHook(ByVal eventMin As UInteger,
                                           ByVal eventMax As UInteger,
                                           ByVal hmodWinEventProc As IntPtr,
                                           ByVal lpfnWinEventProc As WinEventDelegate,
                                           ByVal idProcess As UInteger,
                                           ByVal idThread As UInteger,
                                           ByVal dwFlags As UInteger) As IntPtr
    End Function
    <DllImport("user32.dll")>
    Public Shared Function UnhookWinEvent(ByVal hWinEventHook As IntPtr) As Boolean
    End Function
    <DllImport("user32.dll")>
    Private Shared Function GetForegroundWindow() As IntPtr
    End Function
    Private hook As IntPtr = IntPtr.Zero
    Protected Overrides Sub OnLoad(ByVal e As EventArgs)
        previous = GetForegroundWindow()
        hook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND,
                               EVENT_SYSTEM_FOREGROUND, IntPtr.Zero,
                               New WinEventDelegate(AddressOf WinEventProc),
                               0, 0, WINEVENT_OUTOFCONTEXT)
        MyBase.OnLoad(e)
    End Sub

    Protected Overrides Sub OnFormClosing(ByVal e As FormClosingEventArgs)
        UnhookWinEvent(hook)
        MyBase.OnFormClosing(e)
    End Sub

    Private previous As IntPtr? = Nothing

    Private Sub WinEventProc(ByVal hWinEventHook As IntPtr,
                             ByVal eventType As UInteger,
                             ByVal hwnd As IntPtr,
                             ByVal idObject As Integer,
                             ByVal idChild As Integer,
                             ByVal dwEventThread As UInteger,
                             ByVal dwmsEventTime As UInteger)
        If hwnd <> Me.Handle Then
            previous = hwnd
        Else

            If previous.HasValue Then
                Me.Text = $"Previous window: {CInt(previous):X}"
            Else
                Me.Text = $"No idea about previous window."
            End If
        End If
    End Sub
End Class

这篇关于表单即将获得焦点时的事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆