2012-05-09 33 views
8

我正在嘗試爲Windows應用程序製作一個自動登陸器。它運作良好,但速度非常慢! 我目前正在使用「getPixel」方法,每次調用它時都會重新載入一個數組。獲取像素顏色最快的方式?

這裏是我當前的代碼:

hdc = GetDC(HWND_DESKTOP); 
bx = GetSystemMetrics(SM_CXSCREEN); 
by = GetSystemMetrics(SM_CYSCREEN); 
start_bx = (bx/2) - (MAX_WIDTH/2); 
start_by = (by/2) - (MAX_HEIGHT/2); 
end_bx = (bx/2) + (MAX_WIDTH/2); 
end_by = (by/2) + (MAX_HEIGHT/2); 

for(y=start_by; y<end_by; y+=10) 
{ 
    for(x=start_bx; x<end_bx; x+=10) 
    { 
     pixel = GetPixel(*hdc, x, y); 
     if(pixel==RGB(255, 0, 0)) 
     { 
      SetCursorPos(x,y); 
      mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 
      Sleep(50); 
      mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 
      Sleep(25); 
     } 
    } 
} 

因此,基本上,它只是掃描範圍像素的屏幕,如果它檢測到一個紅色按鈕啓動鼠標事件。

我知道還有其他方法可以獲得像素顏色,比如bitblt。但是我做了一些研究,並且我不明白我應該怎麼做,以便掃描一個顏色數組。我需要一些能夠非常快速地掃描屏幕的東西,以便捕捉按鈕。

你能幫我嗎?

謝謝。

+0

當你的代碼被調用?在空閒時間?當用戶移動鼠標?檢測紅色按鈕的方法有很多種,例如使用FindWindow()。 –

+0

順便說一句,我的代碼是在一個無限循環。但我想用一個顏色捕捉器,而一個偏移量。所以,當我開始我的代碼時,它會進入循環並檢查紅色按鈕。 – Manitoba

+2

如果此代碼處於無限循環中,則問題不是「GetPixel」。這是事實,你的應用程序不讓其他應用程序有任何CPU時間。 – tenfour

回答

11

我發現這顯然比與getPixel一個快一個完美的方式:我希望能幫助別人

HDC hdc, hdcTemp; 
RECT rect; 
BYTE* bitPointer; 
int x, y; 
int red, green, blue, alpha; 

while(true) 
{ 
    hdc = GetDC(HWND_DESKTOP); 
    GetWindowRect(hWND_Desktop, &rect); 
      int MAX_WIDTH = rect.right; 
     int MAX_HEIGHT = rect.bottom; 

    hdcTemp = CreateCompatibleDC(hdc); 
    BITMAPINFO bitmap; 
    bitmap.bmiHeader.biSize = sizeof(bitmap.bmiHeader); 
    bitmap.bmiHeader.biWidth = MAX_WIDTH; 
    bitmap.bmiHeader.biHeight = MAX_HEIGHT; 
    bitmap.bmiHeader.biPlanes = 1; 
    bitmap.bmiHeader.biBitCount = 32; 
    bitmap.bmiHeader.biCompression = BI_RGB; 
    bitmap.bmiHeader.biSizeImage = MAX_WIDTH * 4 * MAX_HEIGHT; 
    bitmap.bmiHeader.biClrUsed = 0; 
    bitmap.bmiHeader.biClrImportant = 0; 
    HBITMAP hBitmap2 = CreateDIBSection(hdcTemp, &bitmap, DIB_RGB_COLORS, (void**)(&bitPointer), NULL, NULL); 
    SelectObject(hdcTemp, hBitmap2); 
    BitBlt(hdcTemp, 0, 0, MAX_WIDTH, MAX_HEIGHT, hdc, 0, 0, SRCCOPY); 

    for (int i=0; i<(MAX_WIDTH * 4 * MAX_HEIGHT); i+=4) 
    { 
     red = (int)bitPointer[i]; 
     green = (int)bitPointer[i+1]; 
     blue = (int)bitPointer[i+2]; 
     alpha = (int)bitPointer[i+3]; 

     x = i/(4 * MAX_HEIGHT); 
     y = i/(4 * MAX_WIDTH); 

     if (red == 255 && green == 0 && blue == 0) 
     { 
      SetCursorPos(x,y); 
      mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 
      Sleep(50); 
      mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 
      Sleep(25); 
     } 
    } 
} 

+0

這是檢查每個像素?我不明白你的x和y作業。 – user1397417

+0

「X」和「Y」是正在審查的像素的位置。它們是無用的,除非你想對這個像素做一個動作。如果它的顏色是全紅,它會將鼠標設置爲該像素,並執行左鍵單擊。 – Manitoba

+1

不錯的工作,但有一些我不明白。爲什麼要考慮分配給像素的Alpha分量的字節?因爲它是一個截圖,alpha的值將始終爲255,對吧?那麼,使biBitCount參數值24更好嗎? – Delgan

1

簡單的答案是,如果這是你堅持使用的方法,那麼沒有太多優化。正如其他人在評論中指出的那樣,您應該使用不同的方法來定位要點擊的區域。例如,查看使用FindWindow。

如果你不想改變你的方法,那麼在每次完整的屏幕掃描後,至少要讓你的線程睡一會兒。

+0

你好,你能告訴我更多關於Findwindow的信息嗎?我正在使用它:'mhwnd = FindWindow(NULL,「Application Window Name」); hdc = GetDC(mhwnd);'接下來是什麼? – Manitoba

+1

您想單擊的按鈕可能具有自己的窗口句柄。嘗試使用諸如Spy ++之類的窗口檢查程序來查找要單擊的窗口句柄,並且可以使用一些巧妙的代碼來定位該特定項目。 – korona