【问题标题】:GetDIBits: Where's that pixel? (x, y coordinates)GetDIBits:那个像素在哪里? (x, y 坐标)
【发布时间】:2013-02-20 16:19:58
【问题描述】:

所以,我正在使用以下应用程序测试以下功能 FindPixel。 HWNDCOLORREF 是我用 Spy++ 和 Color Cop 确定的用于调试的常量;程序的最终版本会自动找到这些。

我已经确认该算法中确定是否颜色存在的部分有效(即:如果颜色存在于窗口中的任何位置,则 if 语句最终为真,如果它不是 if 语句永远不会正确),但是,我无法弄清楚如何隔离 which 像素发生这种情况。 SetCursorPos(rect.left+i, rect.top+i2); 行不会将鼠标移动到正确位置附近的任何位置。

我正在调试的窗口是完全白色的,只有一个像素为 16776960。该函数可以判断它在那里,但 (i, i2) 的值不是 (x, y) 坐标它发生在哪里。

这里有什么我遗漏的吗?

#include <Windows.h>
void FindPixel(HWND hWnd, COLORREF target)
{
        HDC hDC = GetDC(hWnd);
        HDC memDC = CreateCompatibleDC (hDC);
        BYTE *ScreenData = NULL;
        HBITMAP hBitmap;
        BITMAPINFOHEADER bmHeader = {0};
        RECT rect;
        int width, height;
        int i, i2;
        GetWindowRect(hWnd, &rect);
        width = rect.right-rect.left;
        height = rect.bottom-rect.top;
        ScreenData = (BYTE*)malloc(4*width*height);
        hBitmap = CreateCompatibleBitmap(hDC, width, height);
        bmHeader.biSize = sizeof(BITMAPINFOHEADER);
        bmHeader.biPlanes = 1;
        bmHeader.biBitCount = 24;
        bmHeader.biWidth = width;
        bmHeader.biHeight = -height;
        bmHeader.biCompression = BI_RGB;
        SelectObject(memDC, hBitmap);
        BitBlt(memDC, 0, 0, width, height, hDC, 0, 0, SRCCOPY);

        GetDIBits(hDC, hBitmap, 0, height, ScreenData, (BITMAPINFO*)&bmHeader, DIB_RGB_COLORS);
        //      i=0;
        for(i = 0; i < width; i++)
        {
                for(i2 = 0; i2 < height; i2++)
                {
                        if(RGB((ScreenData[3*((i2*width)+i)+2]),(ScreenData[3*((i2*width)+i)+1]), ScreenData[3*((i2*width)+i)])==target)
                        {
                                SetCursorPos(rect.left+i, rect.top+i2);
                                DeleteObject(hBitmap);
                                DeleteDC(memDC);
                                free(ScreenData);
                                ReleaseDC(hWnd, hDC);
                                return;
                        }
                }
        }
        DeleteObject(hBitmap);
        DeleteDC(memDC);
        free(ScreenData);
        ReleaseDC(hWnd, hDC);
}

int APIENTRY WinMain(HINSTANCE hi, HINSTANCE hpi, LPSTR lpcl, int nsc)
{
        const COLORREF px = 16776960;
        const HWND hWnd = (HWND)0x000C04BC;
        Sleep(1000);
        FindPixel(hWnd, px);
        return 0;
}

【问题讨论】:

  • 窗口是否有标准边框?当您调用 GetWindowRect 时,您正在使用非客户端坐标,但 GetDC 将返回客户端区域的 DC,这意味着当您调用时,您的 x/y 坐标将偏离顶部/左侧非客户端帧大小SetCursorPos.
  • 您还必须考虑步幅。每行像素的末尾可以有填充。步幅由((width * bits_per_pixel) + 7) / 8 计算
  • 参见stackoverflow.com/a/3688558/56778,以及对该问题的其他回复。
  • 是的,一旦我考虑到跨步,函数就会正确找到它:) 谢谢@JimMischel

标签: windows winapi bitmap gdi


【解决方案1】:

问题确实是我没有考虑到步幅。这是工作循环:

stride = ((((width * 24) + 31) & ~31) >> 3);

totalpx = stride*height;
for(i = 0; i < totalpx; i++)
{
    //int x = i % width;
    //int y = ((i-x)/width);
    if(RGB(
        (ScreenData[(3*i)+2]),
        (ScreenData[(3*i)+1]),
        (ScreenData[(3*i)+0]))==target)
    {       
        int x = i % stride;
        int y = ((i-x)/width);
        SetCursorPos(rect.left+x,rect.top+y);
        DeleteObject(hBitmap);
        DeleteDC(memDC);
        free(ScreenData);
        ReleaseDC(hWnd, hDC);
        return;
    }

}

【讨论】:

    猜你喜欢
    • 2011-04-10
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-23
    • 2020-07-02
    • 1970-01-01
    • 2020-06-28
    相关资源
    最近更新 更多