无论其 z 顺序如何,都捕获窗口像素 [英] Capture window pixels regardless of its z-order

查看:19
本文介绍了无论其 z 顺序如何,都捕获窗口像素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实际上是在尝试读取被其他人隐藏的窗口上的特定像素.我想使用 GDI 库中的 GetPixel 函数,但它似乎只适用于全局设备上下文.我无法从特定窗口读取像素,我不明白为什么..我发现 这篇文章 使用 PrintWindow 函数将特定窗口内容复制到可以读取的临时设备上下文.但我无法重现它.

I'm actually trying to read a specific pixel on a window which is hidden by others. I want to use the GetPixel function from GDI library but it seems it only works with the global device context. I can't read pixel from a specific window and I don't understand why.. I found this article which uses the PrintWindow function to copy a specific window content to a temporary device context which can be read. But I can't reproduce it.

编辑

谢谢,我的问题都解决了:)
该脚本为您提供所选窗口上指针的 RGB 颜色,即使该窗口是隐藏的.请注意,此程序必须以管理员权限启动才能获取以管理员权限启动的进程的像素.

Thank you all my problem is solved :)
This script give you the RGB color of the pointer on the choosen window, even though the window is hidden. Remind that this program must be launch with admin privileges to get the pixels of processes launched with admin privileges.

#define STRICT
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
// 0x0501 for PrintWindow function
// You must be at least running Windows XP
// See http://msdn.microsoft.com/en-us/library/6sehtctf.aspx

#include <stdio.h>
#include <string.h>
#include <windows.h>

#define WINDOW_LIST_LIMIT 32
#define WINDOW_NAME_LIMIT 1024

void FatalError(char* error)
{
    printf("%s", error);
    exit(-1);
}

HWND window_list[WINDOW_LIST_LIMIT];
unsigned int window_list_index = 0;

BOOL EnumWindowsProc(HWND window_handle, LPARAM param)
{
    char window_title[WINDOW_NAME_LIMIT];

    if(!IsWindowVisible(window_handle)) return TRUE;

    RECT rectangle = {0};
    GetWindowRect(window_handle, &rectangle);
    if (IsRectEmpty(&rectangle)) return TRUE;

    GetWindowText(window_handle, window_title, sizeof(window_title));
    if(strlen(window_title) == 0) return TRUE;
    if(!strcmp(window_title, "Program Manager")) return TRUE;

    window_list[window_list_index] = window_handle;
    window_list_index++;

    printf("%u - %s\n", window_list_index, window_title);

    if(window_list_index == WINDOW_LIST_LIMIT) return FALSE;
    return TRUE;
}

int main(int argc, char** argv)
{
    unsigned int i, input;

    EnumWindows((WNDENUMPROC) EnumWindowsProc, (LPARAM) NULL);

    printf("\nChoose a window: ");
    scanf("%u", &input);
    printf("\n");
    if(input > window_list_index) FatalError("Bad choice..\n");

    HDC window_dc = GetWindowDC(window_list[input - 1]), global_dc = GetDC(0), temp_dc;
    if(!window_dc && !global_dc) FatalError("Fatal Error - Cannot get device context.\n");

    POINT cursor, previous_cursor;

    while(1)
    {
        temp_dc = CreateCompatibleDC(window_dc);
        if(!temp_dc) FatalError("Fatal Error - Cannot create compatible device context.\n");

        RECT window_rectangle;
        GetWindowRect(window_list[input - 1], &window_rectangle);

        HBITMAP bitmap = CreateCompatibleBitmap(window_dc,
            window_rectangle.right - window_rectangle.left,
            window_rectangle.bottom - window_rectangle.top);

        if (bitmap)
        {
            SelectObject(temp_dc, bitmap);
            PrintWindow(window_list[input - 1], temp_dc, 0);
            DeleteObject(bitmap);
        }

        GetCursorPos(&cursor);
        if(cursor.x != previous_cursor.x && cursor.y != previous_cursor.y)
        {
            COLORREF color = GetPixel(temp_dc, cursor.x - window_rectangle.left, cursor.y - window_rectangle.top);
            int red = GetRValue(color);
            int green = GetGValue(color);
            int blue = GetBValue(color);

            printf("\rRGB %02X%02X%02X", red, green, blue);

            cursor = previous_cursor;
        }

        DeleteDC(temp_dc);
        Sleep(50); // for lags
    }

    ReleaseDC(window_list[input - 1], window_dc);
    return 0;
}

我改变了一些东西,现在 User32 不是动态加载的.
它编译为

I've changed some things, now User32 isn't dynamically loaded.
It compiles with

gcc main.c -o main.exe -lGid32 -lUser32

祝您有美好的一天!

推荐答案

您正在将进程句柄传递给 GetDC.那是不对的.进程没有设备上下文,Windows 有.请记住,一个进程可以有多个窗口,甚至根本没有.

You are passing a process handle to GetDC. That's not right. Processes don't have device contexts, windows do. Remember a process can have many windows, or even none at all.

您需要获取相关窗口的窗口句柄 HWND,并将其传递给 GetDC.我希望使用 FindWindowEnumWindows 来查找目标顶级窗口.

You need to get hold of the window handle, the HWND, for the window in question, and pass that to GetDC. I'd look to using FindWindow or EnumWindows to find your target top-level window.

当然,您的代码可能还有其他问题,但这是我突然想到的问题.

Of course, there may be other problems with your code, but that's the one that jumps out at me.

这篇关于无论其 z 顺序如何,都捕获窗口像素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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