2012-05-09 15 views
8

Ich versuche, eine Auto-Cliker für eine Windows-App zu machen. Es funktioniert gut, aber es ist unglaublich langsam! Ich verwende derzeit die Methode "getPixel", die ein Array jedes Mal neu lädt, wenn es aufgerufen wird.Get Pixel Farbe schnellste Weg?

Hier ist mein aktueller Code:

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

Also im Grunde, es scannen nur eine Reihe von Pixeln auf dem Bildschirm und startet ein Maus-Ereignis, wenn es eine rote Taste erkennt.

Ich weiß, dass es andere Möglichkeiten gibt, die Pixelfarbe zu erhalten, z. B. bitblt. Aber ich habe einige Nachforschungen angestellt, und ich verstehe nicht, wie ich das machen soll, um ein Farbfeld zu scannen. Ich brauche etwas, das den Bildschirm sehr schnell scannt, um den Knopf zu fangen.

Könnten Sie mir bitte helfen?

Danke.

+0

Wenn Ihr Code aufgerufen wird? im Leerlauf? wenn der Benutzer die Maus bewegt? Es gibt verschiedene Möglichkeiten, eine rote Schaltfläche zu erkennen, z. B. mit FindWindow(). –

+0

BTW, mein Code ist in einer Endlosschleife. Aber ich möchte einen Farb-Catcher verwenden, während ein Offset-Farb-Catcher verwendet wird. Also, wenn ich meinen Code starte, gehe ich einfach in die Schleife und suche nach dem roten Knopf. – Manitoba

+2

Wenn dieser Code in einer Endlosschleife ist, ist das Problem nicht "GetPixel". Es ist die Tatsache, dass Ihre App keine anderen CPU-Zeiten hat. – tenfour

Antwort

11

fand ich eine perfekte Art und Weise, die deutlich schneller als die GetPixel ist ein:

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

Ich hoffe, das jemand anderes helfen könnte.

+0

überprüft dies jedes Pixel? Ich verstehe deine x- und y-Aufgaben nicht. – user1397417

+0

"X" und "Y" sind der Ort des zu überprüfenden Pixels. Sie sind nutzlos, es sei denn, Sie möchten eine Aktion für dieses Pixel ausführen. Wenn die Farbe rot ist, wird die Maus auf dieses Pixel gesetzt und ein Linksklick ausgeführt. – Manitoba

+1

Gute Arbeit, aber da ist etwas, was ich nicht verstehe. Warum das Byte berücksichtigen, das der Alpha-Komponente des Pixels zugewiesen ist? Weil es ein Screenshot ist, ist der Wert von Alpha immer 255, oder? Also, wäre es nicht besser, den biBitCount Parameter auf 24 zu setzen? – Delgan

1

Die einfache Antwort ist, dass, wenn dies die Methode ist, auf der Sie bestehen, dann gibt es nicht viel zu optimieren. Wie andere in Kommentaren hervorgehoben haben, sollten Sie wahrscheinlich eine andere Methode verwenden, um den zu klickenden Bereich zu lokalisieren. Sehen Sie sich zum Beispiel FindWindow an.

Wenn Sie Ihre Methode nicht ändern möchten, dann schlafen Sie Ihren Thread nach jedem vollständigen Screen-Scan zumindest ein wenig.

+0

Hallo, kannst du mir mehr über Findfenster erzählen? Ich benutze es so: 'mhwnd = FindWindow (NULL," Application Window Name "); hdc = GetDC (mhwnd); 'Was kommt als nächstes? – Manitoba

+1

Die Schaltfläche, auf die Sie klicken möchten, hat wahrscheinlich ein eigenes Fensterhandle. Versuchen Sie es mit einem Fensterinspektorprogramm wie Spy ++, um das Fensterhandle des Objekts zu finden, auf das Sie klicken möchten, und Sie können dieses bestimmte Element wahrscheinlich mit cleverem Code finden. – korona

Verwandte Themen