捕获窗口像素而不考虑其 z 顺序

标签 c windows winapi

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

编辑

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

#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 不是动态加载的。
它编译为

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

祝你有美好的一天!

最佳答案

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

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

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

关于捕获窗口像素而不考虑其 z 顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8707023/

相关文章:

c - 对 VeriFone 库的内存可用调用

c - 为什么我的旋转字符串函数中的模运算不正确?

c - 将文本文件中的一行读取到c中的字符数组中

windows - 升级到 Django 1.4 后,Eclipse 中的 Django 应用程序无法运行

c++ - 在哪个头文件中声明了函数 `_tcscpy_s`?

c - 如何从 Win32 中的 func ptr 获取模块句柄?

在C中将字符串MAC地址转换为char[6]

windows - GAE 转到 Windows - "Cannot run program", "is not a valid Win32 application"

wpf - 新项目的 Delphi vs C# & WPF?

c++ - 如何在 C++ Win32 中捕获鼠标在标题栏上的移动?