如何找到活动窗口

时间:2010-07-28 02:22:57

标签: vba

我需要在特定过程中找到活动窗口。这样做的目的是获取活动窗口/文档的名称,即使其父应用程序具有多文档界面。

要获取活动进程,我正在使用GetGUIThreadInfo和user32.dll中的GetCurrentThreadId。这是相关的代码:

Private Type RECT
    Left As LongPtr
    Top As LongPtr
    Right As LongPtr
    Bottom As LongPtr
End Type

Private Type GUITHREADINFO

    cbSize As LongPtr
    flags As LongPtr
    hwndActive As LongPtr
    hwndFocus As LongPtr
    hwndCapture As LongPtr
    hwndMenuOwner As LongPtr
    hwndMoveSize As LongPtr
    hwndCaret As LongPtr
    rcCaret As RECT

End Type

Private Declare PtrSafe Function GetWindowThreadProcessId Lib "user32" ( _
    ByVal hWnd As LongPtr) As LongPtr

Private Declare PtrSafe Function GetGUIThreadInfo Lib "user32" _
    (ByVal dwthreadid As LongPtr, _
    lpguithreadinfo As GUITHREADINFO) As LongPtr

Sub MyFunction()

    Dim strWindowTitle As String
    strWindowTitle = Space(30)

    Dim GUIInfo As GUITHREADINFO
    GUIInfo.cbSize = LenB(GUIInfo)

    Call GetGUIThreadInfo(GetCurrentThreadId, GUIInfo)
    Call GetWindowText(GUIInfo.hwndActive, strWindowTitle, 30)

    Debug.Print strWindowTitle

End Sub

我尝试使用不同的方法更改类型以获取活动的线程ID。输出为空白。

打印GUIInfo.hwndActive给我0。

找到当前的线程ID,但我在GetGUIThreadInfo函数中做错了。

我已经尝试通过子窗口进行枚举,但是我很难分辨哪一个是活动的。如果有一个我错过的功能,那可能会有效。

我在64位计算机上运行Outlook 2010 x64,因此我使用了LongPtr。

1 个答案:

答案 0 :(得分:0)

我认为你正在用一些LongPtrs跳枪。例如,GetGUIThreadInfo的第一个参数是线程id的DWORD,即使在64位窗口上,DWORD仍然是32位。

    c:\Users\logan>type foop.c
    #include <windows.h>
    #include <stdio.h>

    int main()
    {
    int n = sizeof(DWORD);
    printf("%d\n", n);
    n = sizeof(DWORD_PTR);
    printf("%d\n", n);
    return 0;
    }


    c:\Users\logan>cl foop.c
    Microsoft (R) C/C++ Optimizing Compiler Version 14.00.50727.762 for x64
    Copyright (C) Microsoft Corporation.  All rights reserved.

    foop.c
    Microsoft (R) Incremental Linker Version 8.00.50727.762
    Copyright (C) Microsoft Corporation.  All rights reserved.

    /out:foop.exe
    foop.obj

    c:\Users\logan>foop.exe
    4
    8

同样,LONG实际上仍然是32位,所以你的RECT定义是错误的。

自从我完成VB以来已经很长时间了,但我不记得ByVal或ByRef是否是默认值。如果前者你需要在struct参数上指定ByRef来GetGUIThreadInfo。