使用 EnumWindows 找到满足你要求的窗口

原文:使用 EnumWindows 找到满足你要求的窗口

在 Windows 应用开发中,如果需要操作其他的窗口,那么可以使用 EnumWindows 这个 API 来枚举这些窗口。

本文介绍使用 EnumWindows 来枚举并找到自己关心的窗口(如 QQ/TIM 窗口)。


本文内容

    • `EnumWindows`
    • 遍历所有的顶层窗口
    • 遍历具有指定类名或者标题的窗口

EnumWindows

你可以在微软官网了解到 EnumWindows

要在 C# 代码中使用 EnumWindows,你需要编写平台调用 P/Invoke 代码。使用我在另一篇博客中的方法可以自动生成这样的平台调用代码:

我这里直接贴出来:

[DllImport("user32.dll")]
public static extern int EnumWindows(WndEnumProc lpEnumFunc, int lParam);


  • 1
  • 2

遍历所有的顶层窗口

官方文档对此 API 的描述是:

Enumerates all top-level windows on the screen by passing the handle to each window, in turn, to an application-defined callback function.

遍历屏幕上所有的顶层窗口,然后给回调函数传入每个遍历窗口的句柄。

不过,并不是所有遍历的窗口都是顶层窗口,有一些非顶级系统窗口也会遍历到,详见:EnumWindows 中的备注节

所以,如果需要遍历得到所有窗口的集合,那么可以使用如下代码:

public static IReadOnlyList<int> EnumWindows()
{
    var windowList = new List<int>();
    EnumWindows(OnWindowEnum, 0);
    return windowList;

    bool OnWindowEnum(int hwnd, int lparam)
    {
        // 可自行加入一些过滤条件。
        windowList.Add(hwnd);
        return true;
    }
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

遍历具有指定类名或者标题的窗口

我们需要添加一些可以用于过滤窗口的 Win32 API。以下是我们即将用到的两个:

// 获取窗口的类名。
[DllImport("user32.dll")]
private static extern int GetClassName(int hWnd, StringBuilder lpString, int nMaxCount);

// 获取窗口的标题。
[DllImport("user32")]
public static extern int GetWindowText(int hwnd, StringBuilder lptrString, int nMaxCount);


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

于是根据类名找到窗口的方法:

public static IReadOnlyList<int> FindWindowByClassName(string className)
{
    var windowList = new List<int>();
    EnumWindows(OnWindowEnum, 0);
    return windowList;

    bool OnWindowEnum(int hwnd, int lparam)
    {
        var lpString = new StringBuilder(512);
        GetClassName(hwnd, lpString, lpString.Capacity);
        if (lpString.ToString().Equals(className, StringComparison.InvariantCultureIgnoreCase))
        {
            windowList.Add(hwnd);
        }

        return true;
    }
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

使用此方法,我们可以传入 "txguifoundation" 找到 QQ/TIM 的窗口:

var qqHwnd = FindWindowByClassName("txguifoundation");


  • 1

要获取窗口的标题,或者把标题作为过滤条件,则使用 GetWindowText

在 QQ/TIM 中,窗口的标题是聊天对方的名字或者群聊名称。

var lptrString = new StringBuilder(512);
GetWindowText(hwnd, lptrString, lptrString.Capacity);


  • 1
  • 2


参考资料



我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。


walter lv

博客专家

发布了382 篇原创文章 · 获赞 232 · 访问量 47万+

私信
关注

原文地址:https://www.cnblogs.com/lonelyxmas/p/12051976.html

时间: 2024-11-04 07:16:00

使用 EnumWindows 找到满足你要求的窗口的相关文章

区别 FindWindow,FindWindowEx,EnumWindows,EnumChildWindows

1. FindWindow() HWND FindWindow(LPCSTR lpClassName, LPCSTR lpWindowName); 功能:查找与指定窗口类名和窗口名称相匹配的顶级窗口,这个函数不搜索子窗口. 参数:如果lpClassName为null,将会寻找任何与lpWindowName参数匹配的窗口,如果lpWindowName为NULL,则匹配所有窗口名. 返回值:成功返回窗口句柄.否则返回NULL. 2.FindWindowEx() HWND WINAPI FindWin

Unity 修改windows窗口的标题

修改windows窗口的标题名称,就是修改下图的东西: 第一种: using UnityEngine; using System; using System.Runtime.InteropServices; public class SetWindowText : MonoBehaviour { #region WIN32API delegate bool EnumWindowsCallBack(IntPtr hwnd, IntPtr lParam); [DllImport("user32&qu

学习vi和vim编辑器(16):vim的多窗口功能(1)

vim默认是在一个窗口中编辑所有文件,在文件间移动或者移动到文件的不同部分时只显示一个缓冲区.但vim也提供了多窗口编辑功能,可以简化复合的编辑任务.这篇文章将学习如何在一个运行的vim进程里使用多窗口,包括多窗口编辑工作的初始化与启动,在窗口间移动光标,在显示区中移动窗口等. 启动多窗口编辑: 可以在打开vim时启动多窗口编辑,也可以在编辑会话中分割窗口. 从命令行(shell)启动多窗口: 默认情况下,vim为一个会话只打开一个窗口,即使打开时已经指定多个文件.如果想从命令行中打开多个窗口,

201403-2窗口

//100分 #include<iostream>using namespace std; typedef struct Point{ int x1,x2,y1,y2; int order; int no;};typedef struct XY{ int x,y;};int main(){ int n,m,i,j,count = 0,ok = 0; cin>>n>>m; XY xy[m]; Point point[n]; for(i=0;i<n;i++){ cin

[算法系列之二十二]包含T全部元素的最小子窗口

题目描述 给定一个包含一系列字符的集合T和字符串S,请在字符串S中找到一个最小的窗口,这个窗口中必须包含T中的所有字符. 例如, S = "ADOBECODEBANC" T = "ABC" 最小窗口是"BANC" 分析 这是一个有趣的问题,这个有趣的问题有多种方法来解决,最好的方法是非常简单,美丽的. 在这篇文章中,我首先说明了一个方法,是我第一次遇见这个问题时想到的.我的第一个方法有点复杂,同时也不是最好的解决方案(时间复杂度为O(NlgM))

MFC注册窗口类以及FindWindow按窗口类名查询(避免用#32770获取窗口句柄)

呵呵,最近在研究SendMessage函数,其中需要用到m_hWnd,之后延伸着又尝试获得窗口的句柄,于是遇到了FindWindow函数,原型如下: HWND FindWindow ( LPCSTR lpClassName,    //输入窗口的类名,其实需要是注册过的类名才行,否则是要报错或者查找失败的. LPCSTR lpWindowName, //输入窗口的名称,就是窗口上面蓝色的那行玩意儿写的字. ); 对于这个函数,如果按照窗口的名称查找,相信大家都非常简单,因为名称在rc文件里,是已

string类问题之滑动窗口类型

Longest Substring Without Repeating Characters Given a string, find the length of the longest substring without repeating characters. Examples: Given "abcabcbb", the answer is "abc", which the length is 3. Given "bbbbb", the

MFC应用程序创建窗口的过程 good

MFC应用程序中处理消息的顺序 1.AfxWndProc()      该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc 2.AfxCallWndProc()  该函数负责保存消息(保存的内容主要是消息标识符和消息参数)供应用程序以后使用,然后调用WindowProc()函数 3.WindowProc()      该函数负责发送消息到OnWndMsg()函数,如果未被处理,则调用DefWindowProc()函数 4.OnWndMsg()        该函

窗口变化相关消息 OnSize、OnSizing和OnGetMinMaxInfo

最近用到窗口变化的一些东西,遇到几个相关的消息函数,简要分析,作为备忘. 3个消息分别是:WM_SIZE.WM_SIZING.WM_GETMINMAXINFO:分别对应相应的处理函数:OnSize.OnSizing.OnGetMinMaxInfo. 当窗口大小发生变化时,响应的顺序依次是:WM_GETMINMAXINFO-->WM_SIZING-->WM_SIZE. OnGetMinMaxInfo 这个函数在窗口初始化的时候会被调用一次,当窗口大小发生改变的时候也会被调用.利用这个函数,可以比