2012-05-09 26 views
8

Estoy tratando de hacer un cliker automático para una aplicación de Windows. Funciona bien, ¡pero es increíblemente lento! Actualmente estoy usando el método "getPixel" que recarga una matriz cada vez que se llama.Obtén color de píxel más rápido?

Aquí está mi código actual:

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); 
     } 
    } 
} 

Así que, básicamente, sólo se analizan una serie de píxel en la pantalla y se inicia un evento de ratón si detecta un botón rojo.

Sé que hay otras formas de obtener el color de píxel, como bitblt. Pero hice algunas investigaciones, y no entiendo cómo se supone que debo hacer, para escanear un conjunto de colores. Necesito algo que escanee la pantalla muy rápido para atrapar el botón.

¿Podría ayudarme?

Gracias.

+0

¿Cuándo se llama a su código? en tiempo de inactividad? cuando el usuario mueve el mouse? Hay diferentes maneras de detectar un botón rojo, usando FindWindow() por ejemplo. –

+0

Por cierto, mi código está en un bucle infinito. Pero quiero usar un receptor de color mientras que uno de compensación. Entonces, cuando comienzo mi código, simplemente ingresa al ciclo y busca el botón rojo. – Manitoba

+2

Si este código está en un bucle infinito, entonces el problema no es 'GetPixel'. Es el hecho de que su aplicación no permite que otras aplicaciones tengan tiempo de CPU. – tenfour

Respuesta

11

he encontrado una manera perfecta que es claramente más rápido que el GetPixel uno:

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); 
     } 
    } 
} 

espero que esto podría ayudar a alguien más.

+0

¿Esto comprueba cada píxel? No entiendo tus asignaciones xe y. – user1397417

+0

'X' y' Y' son la ubicación del píxel que se está revisando. Son inútiles, a menos que quieras hacer una acción en este píxel. Si su color es rojo completo, establecerá el mouse en este píxel y hará un clic izquierdo. – Manitoba

+1

Buen trabajo, pero hay algo que no entiendo. ¿Por qué tener en cuenta el byte asignado al componente Alpha del píxel? Como es una captura de pantalla, el valor de alpha siempre será 255, ¿verdad? Entonces, ¿no sería mejor hacer que el parámetro biBitCount valga 24? – Delgan

1

La respuesta simple es que si este es el método que insiste en usar, entonces no hay mucho que optimizar. Como otros han señalado en los comentarios, probablemente debería usar un método diferente para ubicar el área a hacer clic. Eche un vistazo al uso de FindWindow, por ejemplo.

Si no desea cambiar su método, al menos deje dormir su hilo por un bit después de cada exploración de pantalla completa.

+0

Hola, ¿Me puedes decir más sobre Findwindow? Lo estoy usando así: 'mhwnd = FindWindow (NULL," Nombre de la ventana de la aplicación "); hdc = GetDC (mhwnd); '¿Qué sigue? – Manitoba

+1

El botón en el que desea hacer clic probablemente tenga un identificador de ventana propio. Intente utilizar un programa de inspector de ventanas como Spy ++ para encontrar el manejador de la ventana del objeto en el que desea hacer clic, y probablemente pueda ubicar ese elemento específico con algún código inteligente. – korona