C/C++ Windows API——获取鼠标位置的窗口句柄_根据坐标获取右击窗口句柄 c++-程序员宅基地

技术标签: # Windows API  

// SpyDemo.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>

#define MAX_TEXT_LEN 255

BOOL CALLBACK EnumChildProcess(HWND hwnd, LPARAM lParam)
{
    if (hwnd == NULL) {
        return FALSE;
    }
    BOOL ret;
    RECT rect;
    ret = GetWindowRect(hwnd, &rect);
    if (!ret) {
        printf("GetWindowRect hwnd=%p -> fail(%ld)\n", hwnd, GetLastError());
    }
    else {
        //printf("GetWindowRect hwnd = %p -> rect=(left=%ld, top=%ld, right=%ld, bottom=%ld)\n", hwnd, rect.left, rect.top, rect.right, rect.bottom);
        ret = PtInRect(&rect, *(POINT *)lParam);
        if (ret) {
            printf("GetWindowRect hwnd = %p -> rect=(left=%ld, top=%ld, right=%ld, bottom=%ld)\n", hwnd, rect.left, rect.top, rect.right, rect.bottom);
            //printf("PtInRect\n");

            /*
            WINUSERAPI int WINAPI GetWindowText(
            _In_ HWND hWnd,
            _Out_writes_(nMaxCount) LPTSTR lpString,    //可能是标题名或者file:///打头的文件完整路径
            _In_ int nMaxCount
            );
            如果函数成功,返回值是拷贝的字符串的字符个数,不包括中断的空字符;如果窗口无标题栏或文本,或标题栏为空,或窗口或控制的句柄无效,则返回值为零。若想获得更多错误信息,请调用GetLastError函数。
            */
            TCHAR windowText[MAX_TEXT_LEN];
            int lenRet = GetWindowText(hwnd, windowText, MAX_TEXT_LEN);
            if (lenRet == 0 && GetLastError() != 0) {
                //GetLastError()〖0〗-操作成功完成
                printf("GetWindowText hwnd=%p -> fail(%ld)\n", hwnd, GetLastError());
            }
            else {
                _tprintf(_T("GetWindowText hwnd=%p -> windowText=%s, lenRet=%d\n"), hwnd, windowText, lenRet);
            }

            /*
            WINUSERAPI int WINAPI GetClassNameW(
                _In_ HWND hWnd,
                _Out_writes_to_(nMaxCount, return) LPWSTR lpClassName,
                _In_ int nMaxCount
            );

            如果函数成功,返回值为拷贝到指定缓冲区的字符个数:如果函数失败,返回值为0。若想获得更多错误信息,请调用GetLastError函数。
            */
            TCHAR className[MAX_TEXT_LEN];
            lenRet = GetClassName(hwnd, className, MAX_TEXT_LEN);
            if (lenRet == 0) {
                printf("GetClassName hwnd=%p -> fail(%ld)\n", hwnd, GetLastError());
            }
            else {
                _tprintf(_T("GetClassName hwnd=%p -> className=%s, lenRet=%d\n"), hwnd, className, lenRet);
            }

            /*
            找出某个窗口的创建者(线程或进程),返回创建者的标志符
            哪个线程创建了这个窗口,返回的就是这个线程的id号 (进程只有一个线程的话,那么线程标志符与进程标志符就是指同一个标志符)
            WINUSERAPI DWORD WINAPI GetWindowThreadProcessId(
                _In_ HWND hWnd,
                _Out_opt_ LPDWORD lpdwProcessId //进程号的存放地址(变量地址)
            );
            返回线程号
            */
            DWORD dwProcessId;
            DWORD dwThreadId = GetWindowThreadProcessId(hwnd, &dwProcessId);
            printf("GetWindowThreadProcessId hwnd=%p -> processId=%ld, threadId=%ld\n", hwnd, dwProcessId, dwThreadId);

            /*
            WINUSERAPI UINT WINAPI GetWindowModuleFileName(
                _In_ HWND hwnd,
                _Out_writes_to_(cchFileNameMax, return) LPTSTR pszFileName, //模块完整路径
                _In_ UINT cchFileNameMax
            );
            返回值是复制到缓冲区的字符总数。
            */
            TCHAR fileName[MAX_PATH];
            lenRet = GetWindowModuleFileName(hwnd, fileName, MAX_PATH);
            if (lenRet == 0) {
                //错误码〖126〗-找不到指定的模块。
                printf("GetWindowModuleFileName hwnd=%p -> fail(%ld)\n", hwnd, GetLastError());
            } else {
                _tprintf(_T("GetWindowModuleFileName hwnd=%p -> fileName=%s\n"), hwnd, fileName);
            }

            /*
            WINUSERAPI BOOL WINAPI GetWindowInfo(
                _In_ HWND hwnd,
                _Inout_ PWINDOWINFO pwi
            );

            typedef struct tagWINDOWINFO
            {
                DWORD cbSize;
                RECT rcWindow;
                RECT rcClient;
                DWORD dwStyle;
                DWORD dwExStyle;
                DWORD dwWindowStatus;
                UINT cxWindowBorders;
                UINT cyWindowBorders;
                ATOM atomWindowType;
                WORD wCreatorVersion;
            } WINDOWINFO, *PWINDOWINFO, *LPWINDOWINFO;
            */
            WINDOWINFO windowInfo;
            windowInfo.cbSize = sizeof(WINDOWINFO);
            ret = GetWindowInfo(hwnd, &windowInfo);
            if (!ret) {
                printf("GetWindowInfo hwnd=%p -> fail(%ld)\n", hwnd, GetLastError());
            }
            else {
                printf("GetWindowInfo hwnd=%p -> dwStyle=%ld, dwExStyle=%ld, dwWindowStatus=%ld, cxWindowBorders=%d, cyWindowBorders=%d, wCreatorVersion=%d\n", hwnd, windowInfo.dwStyle, windowInfo.dwExStyle, windowInfo.dwWindowStatus, windowInfo.cxWindowBorders, windowInfo.cyWindowBorders, windowInfo.wCreatorVersion);
            }
            printf("\n");
        }
    }

    return TRUE;
}

int main()
{
    BOOL ret;
    while (true) {
        /*
        typedef struct tagPOINT
        {
            LONG  x;
            LONG  y;
        } POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;
        */
        POINT point;
        ret = GetCursorPos(&point);
        if (!ret) {
            printf("GetCursorPos -> fail(%ld)\n", GetLastError());
        }
        else {
            printf("GetCursorPos -> (%ld, %ld)\n", point.x, point.y);

            //获取桌面句柄
            HWND desktopHwnd = GetDesktopWindow();

            /*
            BOOL EnumChildWindows(
                HWND hWndParent,         // handle to parent window // 父窗口句柄
                WNDENUMPROC lpEnumFunc,  // callback function // 回调函数的地址
                LPARAM lParam            // application-defined value // 你自已定义的参数
            );
            直到调用到最个一个子窗口被枚举或回调函数返回一个false,否则将一直自动枚举下去。
            */
            ret = EnumChildWindows(desktopHwnd, EnumChildProcess, (LPARAM)&point);
        }

        /*
        WINBASEAPI VOID WINAPI Sleep(
            _In_ DWORD dwMilliseconds
        );
        Sleep会将线程挂起,把CPU让给其它线程,单位是毫秒
        */
        Sleep(20000);
    }

    system("pause");
    return 0;
}

这里写图片描述

在评论里有人说道,可以用“WindowFromPoint”来实现这个功能,于是就有了下列代码。

// SpyDemo.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>

int main()
{
    BOOL ret;
    UINT count;
    /*
    typedef struct tagPOINT
    {
        LONG  x;
        LONG  y;
    } POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;
    */
    POINT point;
    TCHAR pszFileName[MAX_PATH];
    TCHAR lpClassName[MAX_PATH];
    TCHAR windowText[MAX_PATH];
    while(true) {
        ret = GetCursorPos(&point);
        if (!ret) {
            printf("GetCursorPos -> fail(%ld)\n", GetLastError());
        } else {
            printf("GetCursorPos -> (%ld, %ld)\n", point.x, point.y);
            HWND hwnd = WindowFromPoint(point);
            if (hwnd == NULL || hwnd == INVALID_HANDLE_VALUE) {
                printf("WindowFromPoint point=(%ld, %ld) -> hwnd=%p -> fail(%ld)\n", point.x, point.y, hwnd, GetLastError());
            }
            else {
                printf("WindowFromPoint -> hwnd=%p\n", hwnd);

                /*
                检索与指定的窗口句柄关联的模块的完整路径和文件名称
                WINUSERAPI UINT WINAPI GetWindowModuleFileNameW(
                    _In_ HWND hwnd,
                    _Out_writes_to_(cchFileNameMax, return) LPWSTR pszFileName,
                    _In_ UINT cchFileNameMax
                );
                返回值是复制到缓冲区的字符总数。
                */
                count = GetWindowModuleFileName(hwnd, pszFileName, MAX_PATH);
                _tprintf(_T("GetWindowModuleFileName hwnd=%p -> count=%d, fileName=%s\n"), hwnd, count, pszFileName);

                /*
                WINUSERAPI int WINAPI GetClassName(
                    _In_ HWND hWnd,
                    _Out_writes_to_(nMaxCount, return) LPTSTR lpClassName,
                    _In_ int nMaxCount
                );
                */
                count = GetClassName(hwnd, lpClassName, MAX_PATH);
                _tprintf(_T("GetClassName hwnd=%p -> count=%d, lpClassName=%s\n"), hwnd, count, lpClassName);


                count = GetWindowText(hwnd, windowText, MAX_PATH);
                _tprintf(_T("GetWindowText hwnd=%p -> count=%d, lpClassName=%s\n"), hwnd, count, windowText);
            }

            //Screen(屏幕坐标)到Client(客户区坐标)的转换。
            ret = ScreenToClient(hwnd, &point);
            if (!ret) {
                printf("ScreenToClient hwnd=%p -> fail(%ld)\n", hwnd, GetLastError());
            }
            else {
                printf("ScreenToClient hwnd=%p -> point=(%ld, %ld)\n", hwnd, point.x, point.y);

                //返回父窗口中包含了指定点的第一个子窗口的句柄
                HWND childHwnd = ChildWindowFromPoint(hwnd, point);
                printf("ChildWindowFromPoint hwnd=%p, point=(%ld, %ld) -> childHwnd=%p\n", hwnd, point.x, point.y, childHwnd);

                count = GetClassName(hwnd, lpClassName, MAX_PATH);
                _tprintf(_T("GetClassName hwnd=%p -> count=%d, lpClassName=%s\n"), hwnd, count, lpClassName);

                count = GetWindowText(hwnd, windowText, MAX_PATH);
                _tprintf(_T("GetWindowText hwnd=%p -> count=%d, lpClassName=%s\n"), hwnd, count, windowText);
            }
        }
        Sleep(5000);
    }
    return 0;
}

这里写图片描述


但是有一个问题:
  为什么 GetWindowModuleFileName 虽然句柄每次都不一样,但是获取到的模块文件路径每次都是一样的当前的路径。
  希望有大神能帮我解答一下,感激不尽。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/chy555chy/article/details/52900785

智能推荐

python中文显示不出来_解决Python词云库wordcloud不显示中文的问题-程序员宅基地

文章浏览阅读2.6k次。解决Python词云库wordcloud不显示中文的问题2018-11-25背景:wordcloud是基于Python开发的词云生成库,功能强大使用简单。github地址:https://github.com/amueller/word_cloudwordcloud默认是不支持显示中文的,中文会被显示成方框。安装:安装命令:pip install wordcloud解决:经过测试发现不支持显示中文..._词云python代码无法输出文字

台式计算机cpu允许温度,玩游戏cpu温度多少正常(台式电脑夏季CPU一般温度多少)...-程序员宅基地

文章浏览阅读1.1w次。随着炎热夏季的到来,当玩游戏正爽的时候,电脑突然死机了,自动关机了,是不是有想给主机一脚的冲动呢?这个很大的原因是因为CPU温度过高导致的。很多新手玩家可能都有一个疑虑,cpu温度多少以下正常?有些说是60,有些说是70,到底多高CPU温度不会死机呢?首先我们先看看如何查看CPU的温度。下载鲁大师并安装,运行鲁大师软件,即可进入软件界面,并点击温度管理,即可看到电脑各个硬件的温度。鲁大师一般情况下..._台式机玩游戏温度多少正常

小白自学Python日记 Day2-打印打印打印!_puthon打印任务收获-程序员宅基地

文章浏览阅读243次。Day2-打印打印打印!我终于更新了!(哭腔)一、 最简单的打印最最简单的打印语句: print(“打印内容”)注意:python是全英的,符号记得是半角下面是我写的例子:然后进入power shell ,注意:你需要使用cd来进入你保存的例子的文件夹,保存时名字应该取为xxx.py我终于知道为什么文件夹取名都建议取英文了,因为进入的时候是真的很麻烦!如果你没有进入正确的文件夹..._puthon打印任务收获

Docker安装:Errors during downloading metadata for repository ‘appstream‘:_"cenerrors during download metadata for repository-程序员宅基地

文章浏览阅读1k次。centos8问题参考CentOS 8 EOL如何切换源? - 云服务器 ECS - 阿里云_"cenerrors during download metadata for repository \"appstream"

尚硅谷_谷粒学苑-微服务+全栈在线教育实战项目之旅_基于微服务的在线教育平台尚硅谷-程序员宅基地

文章浏览阅读2.7k次,点赞3次,收藏11次。SpringBoot+Maven+MabatisPlusmaven在新建springboot项目引入RELEASE版本出错maven在新建springboot项目引入RELEASE版本出错maven详解maven就是通过pom.xml中的配置,就能够从仓库获取到想要的jar包。仓库分为:本地仓库、第三方仓库(私服)、中央仓库springframework.boot:spring-boot-starter-parent:2.2.1.RELEASE’ not found若出现jar包下载不了只有两_基于微服务的在线教育平台尚硅谷

随便推点

网络学习第六天(路由器、VLAN)_路由和vlan-程序员宅基地

文章浏览阅读316次。路由的概念路由器它称之为网关设备。路由器就是用于连接不同网络的设备路由器是位于OSI模型的第三层。路由器通过路由决定数据的转发。网关的背景:当时每家计算机厂商,用于交换数据的通信程序(协议)和数据描述格式各不相同。因此,就把用于相互转换这些协议和格式的计算机称为网关。路由器与三层交换器的对比路由协议对比路由器的作用:1.路由寻址2.实现不同网络之间相连的功能3.通过路由决定数据的转发,转发策略称为 路由选择。VLAN相关技术什么是VLAN?中文名称叫:虚拟局域网。虚_路由和vlan

设置div背景颜色透明度,内部元素不透明_div设置透明度,里面的内容不透明-程序员宅基地

文章浏览阅读2.8w次,点赞6次,收藏22次。设置div背景颜色透明度,内部元素不透明:.demo{  background-color:rgba(255,255,255,0.15) } 错误方式:.demo{ background-color:#5CACEE;opacity:0.75;} 这样会导致div里面的元素内容和背景颜色一起变透明只针对谷歌浏览器的测试_div设置透明度,里面的内容不透明

Discuz!代码大全-程序员宅基地

文章浏览阅读563次。1.[ u]文字:在文字的位置可以任意加入您需要的字符,显示为下划线效果。2.[ align=center]文字:在文字的位置可以任意加入您需要的字符,center位置center表示居中,left表示居左,right表示居右。5.[ color=red]文字:输入您的颜色代码,在标签的中间插入文字可以实现文字颜色改变。6.[ SIZE=数字]文字:输入您的字体大小,在标签的中间插入文..._discuzcode 大全

iOS NSTimer定时器-程序员宅基地

文章浏览阅读2.6k次。iOS中定时器有三种,分别是NSTimer、CADisplayLink、dispatch_source,下面就分别对这三种计时器进行说明。一、NSTimerNSTimer这种定时器用的比较多,但是特别需要注意释放问题,如果处理不好很容易引起循环引用问题,造成内存泄漏。1.1 NSTimer的创建NSTimer有两种创建方法。方法一:这种方法虽然创建了NSTimer,但是定时器却没有起作用。这种方式创建的NSTimer,需要加入到NSRunLoop中,有NSRunLoop的驱动才会让定时器跑起来。_ios nstimer

Linux常用命令_ls-lmore-程序员宅基地

文章浏览阅读4.8k次,点赞17次,收藏51次。Linux的命令有几百个,对程序员来说,常用的并不多,考虑各位是初学者,先学习本章节前15个命令就可以了,其它的命令以后用到的时候再学习。1、开机 物理机服务器,按下电源开关,就像windows开机一样。 在VMware中点击“开启此虚拟机”。2、登录 启动完成后,输入用户名和密码,一般情况下,不要用root用户..._ls-lmore

MySQL基础命令_mysql -u user-程序员宅基地

文章浏览阅读4.1k次。1.登录MYSQL系统命令打开DOS命令框shengfen,以管理员的身份运行命令1:mysql -u usernae -p password命令2:mysql -u username -p password -h 需要连接的mysql主机名(localhost本地主机名)或是mysql的ip地址(默认为:127.0.0.1)-P 端口号(默认:3306端口)使用其中任意一个就OK,输入命令后DOS命令框得到mysql>就说明已经进入了mysql系统2. 查看mysql当中的._mysql -u user

推荐文章

热门文章

相关标签