2012-05-09 16 views
8

Sto provando a creare un cliker automatico per un'applicazione Windows. Funziona bene, ma è incredibilmente lento! Attualmente sto usando il metodo "getPixel" che ricarica un array ogni volta che viene chiamato.Ottieni il colore più veloce dei pixel?

Ecco il mio codice corrente:

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

Quindi, fondamentalmente, solo eseguire la scansione di una gamma di pixel dello schermo e avvia un evento del mouse se rileva un pulsante rosso.

So che ci sono altri modi per ottenere il colore del pixel, come bitblt. Ma ho fatto alcune ricerche, e non capisco come dovrei fare, per scansionare un array di colori. Ho bisogno di qualcosa che scansiona lo schermo molto velocemente per prendere il pulsante.

Potrebbe aiutarmi per favore?

Grazie.

+0

Quando viene chiamato il codice? in idle time? quando l'utente muove il mouse? Esistono diversi modi per rilevare un pulsante rosso, ad esempio utilizzando FindWindow(). –

+0

Btw, il mio codice è in un ciclo infinito. Ma voglio usare un collettore di colori mentre uno sfalsato. Quindi, quando avvio il mio codice, basta andare nel ciclo e controllare il pulsante rosso. – Manitoba

+2

Se questo codice è in un ciclo infinito, il problema non è 'GetPixel'. È il fatto che la tua app non consente alle altre app di avere un tempo di CPU. – tenfour

risposta

11

ho trovato un modo perfetto che è chiaramente più veloce del 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); 
     } 
    } 
} 

Spero che questo potrebbe aiutare qualcun altro.

+0

sta controllando ogni pixel? Non capisco i tuoi incarichi xey. – user1397417

+0

'X' e' Y' sono la posizione del pixel in fase di revisione. Sono inutili, a meno che non vogliate fare un'azione su questo pixel. Se il suo colore è rosso, imposterà il mouse su questo pixel e farà un clic sinistro. – Manitoba

+1

Bel lavoro, ma c'è qualcosa che non capisco. Perché prendere in considerazione il byte assegnato al componente Alpha del pixel? Perché visto che è uno screenshot, il valore di alpha sarà sempre 255, giusto? Quindi, non sarebbe meglio rendere il parametro biBitCount del valore di 24? – Delgan

1

La semplice risposta è che se questo è il metodo che insisti a utilizzare, non c'è molto da ottimizzare. Come altri hanno sottolineato nei commenti, probabilmente dovresti utilizzare un metodo diverso per localizzare l'area in cui fare clic. Dai un'occhiata a FindWindow, per esempio.

Se non si desidera modificare il metodo, attendere almeno una volta il thread dopo ogni scansione completa dello schermo.

+0

Ciao, puoi dirmi di più su Findwindow? Lo sto usando in questo modo: 'mhwnd = FindWindow (NULL," Nome finestra dell'applicazione "); hdc = GetDC (mhwnd); 'Quali sono le prospettive? – Manitoba

+1

Probabilmente il pulsante che si desidera selezionare ha un handle di finestra. Prova a utilizzare un programma di ispezione di finestre come Spy ++ per trovare l'handle della finestra su cosa vuoi fare clic e probabilmente puoi individuare quell'elemento specifico con un codice intelligente. – korona

Problemi correlati