解决GetPixel函数在Google Chrome中返回0无法正常工作的问题
解决GetPixel在Chrome窗口中返回0的问题
问题根源
Chrome默认启用硬件加速,窗口内容由GPU通过DirectComposition/DWM合成层渲染,而非传统GDI绘制方式。此时GetDC(window)获取的只是一个空的占位DC,无法读取到实际的像素数据,导致GetPixel始终返回0。
解决方案
临时测试方案:禁用Chrome硬件加速
- 打开Chrome,访问
chrome://settings/system - 关闭「使用硬件加速模式(如果可用)」选项
- 重启Chrome后运行程序,
GetPixel即可正常读取像素值
正式解决方案:用PrintWindow捕获窗口内容
PrintWindow可以绕过GDI限制,捕获硬件加速窗口的内容,步骤如下:
- 创建兼容DC和位图,匹配窗口客户区尺寸
- 调用
PrintWindow将窗口内容绘制到位图 - 从位图中提取像素数据
修改后的完整代码:
#include <windows.h> #include <iostream> #include <tchar.h> void handleGame(HWND& _window) { LPCWSTR windowClass = L"Chrome_WidgetWin_1"; LPCWSTR windowName = L"Stack Overflow - Where Developers Learn, Share, & Build Careers - Google Chrome"; _window = FindWindow(windowClass, windowName); while (_window == NULL) { std::cout << "failed" << std::endl; _window = FindWindow(windowClass, windowName); Sleep(1000); } } int main() { HWND window = NULL; while (true) { handleGame(window); if (GetAsyncKeyState(VK_NUMPAD1)) { RECT rect = {}; GetClientRect(window, &rect); int width = rect.right - rect.left; int height = rect.bottom - rect.top; // 创建兼容DC和位图 HDC hdcScreen = GetDC(NULL); HDC hdcMem = CreateCompatibleDC(hdcScreen); HBITMAP hBitmap = CreateCompatibleBitmap(hdcScreen, width, height); HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBitmap); // 捕获窗口客户区内容 PrintWindow(window, hdcMem, PW_CLIENTONLY); COLORREF characteristic_color = 5460819; bool found = false; POINT targetPos = {0,0}; // 读取位图中的像素 BITMAP bmp; GetObject(hBitmap, sizeof(BITMAP), &bmp); BITMAPINFOHEADER bi = {0}; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bmp.bmWidth; bi.biHeight = -bmp.bmHeight; // 负号表示从上到下的像素顺序 bi.biPlanes = 1; bi.biBitCount = 32; bi.biCompression = BI_RGB; DWORD* pixels = new DWORD[width * height]; GetDIBits(hdcMem, hBitmap, 0, height, pixels, (BITMAPINFO*)&bi, DIB_RGB_COLORS); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { COLORREF color = pixels[y * width + x]; if (color == characteristic_color) { std::cout << "FOUND!" << std::endl; targetPos.x = x; targetPos.y = y; found = true; goto cleanup; // 找到后直接跳转到资源释放 } } } cleanup: // 释放资源 delete[] pixels; SelectObject(hdcMem, hOldBitmap); DeleteObject(hBitmap); DeleteDC(hdcMem); ReleaseDC(NULL, hdcScreen); if (found) { // 转换客户区坐标为屏幕坐标 ClientToScreen(window, &targetPos); SetCursorPos(targetPos.x, targetPos.y); } else { std::cout << "not found..!" << std::endl; } break; } } std::cout << "end" << std::endl; return 0; }
代码关键点说明
PrintWindow(window, hdcMem, PW_CLIENTONLY):仅捕获窗口客户区内容,避免包含标题栏等非目标区域GetDIBits:将位图数据读取到内存数组中,方便遍历像素ClientToScreen:将客户区坐标转换为屏幕坐标,确保SetCursorPos定位正确- 所有GDI资源(DC、位图)使用后必须释放,避免内存泄漏
内容的提问来源于stack exchange,提问作者PsyKozZ09
相关产品推荐
相关产品推荐

