Capturing the mouse cursor
#1
Posted 11 December 2005 - 01:15 PM
#2
Posted 11 December 2005 - 01:27 PM
Edited by MHz, 11 December 2005 - 01:28 PM.
#3
Posted 11 December 2005 - 01:45 PM
#4
Posted 11 December 2005 - 02:16 PM
I wanna get the colors of the mouse cursor. For instance in many games the ID of the mouse cursor is usually 0 (unknown) and changes of the mouse cursor in the game do not change the ID. So I need to read out the mouse cursor's color. One workaround I had was to use something like HyperSnap DX to grab a picture of the mouse cursor, then check the bytes of that file to detect differences and thus know which it is. If HyperSnap DX can capture the mouse cursor (and it is only the cursor it captures) out of games, then AutoIt can do it too (soon) I hope.Are you refering to needing something like the existing MouseGetPos() ?
Something like MousePixelSearch() would seem an appropriate name (to do a pixelsearch on the mouse x-hair).
Note: I have actually no idea how easy/hard it is to implement. Common sense would say that if this was easy, they would have added it to v3 by now. So maybe it is hard?
Edited by Noobie9876, 11 December 2005 - 02:50 PM.
#5
Posted 14 December 2005 - 03:01 AM
Opt("MouseCoordMode", 1) Func _getMousePointPixelColor() Local $pos = MouseGetPos ( ) Return PixelGetColor ( $pos[0] , $pos[1] ) EndFunc
Returns a decimal value of the pixel color of the mouse tip.
#6
Posted 14 December 2005 - 01:18 PM
Edited by w0uter, 14 December 2005 - 01:19 PM.
#7
Posted 14 December 2005 - 02:58 PM
it gets the value from UNDER the mouse (atleast thats what im told)
Tried this also with AutoIt, but couldnt find a proven way of doing it.
Wrote a little c++ routine which grabs the BitMap of the actual cursor and does a unique checksum on it. As it uses GetBitMapBits its extremely fast as well. Works only for colored cursors (games) at the moment.
Is that the kind of function you are looking for ?
Edited by Kangaroo, 14 December 2005 - 03:04 PM.
#8
Posted 14 December 2005 - 04:10 PM
I Windows it would, but what about in a full-screen game where, as far as AutoIt knows, the cursor is rendered as part of the image on the screen?it gets the value from UNDER the mouse (atleast thats what im told)
Edited by c0deWorm, 14 December 2005 - 04:11 PM.
#9
Posted 14 December 2005 - 05:30 PM
I Windows it would, but what about in a full-screen game where, as far as AutoIt knows, the cursor is rendered as part of the image on the screen?
Good question, but the cursor bitmap is still separate, so you wont get the Cursor pixel that way.
Just tested it with an Online RPG to be 100% sure.
@Noobie no , its not hard to implement, the checksum thingy is actually 12 lines of code only.
But it probably wasnt implemented a long time ago, as AutoIt is not intended mainly for the Gamers scene I guess.
Edited by Kangaroo, 14 December 2005 - 05:40 PM.
#10
Posted 15 December 2005 - 12:21 AM
I spend some time to try and do the same. I managed to get it to work, but I got stuck after I got a handler for the cursor. I was about to try to turn the handler into a pointer and getting the data from there, but then I realised I actually could detect a cursor change with the handler, so I was happy anyway. That was untill I realised that the game has 3 cursors. hehe. After that I went to look into some online code repositories & MSDN. I found some code, but they all stopped after getting the handleGood question, but the cursor bitmap is still separate, so you wont get the Cursor pixel that way.
Just tested it with an Online RPG to be 100% sure.
@Noobie no , its not hard to implement, the checksum thingy is actually 12 lines of code only.
But it probably wasnt implemented a long time ago, as AutoIt is not intended mainly for the Gamers scene I guess.
Would love to see your code. This is the code I got now (which works for the game, but I wanna get the data from the handle).
#include <stdio.h> #include <windows.h> #include <string.h> HCURSOR GetCurrentCursorHandle() { DWORD cursorWindowIDDword, currentFocusedWindowIDDword; HCURSOR cursorHandle = NULL; HWND currentWindowHandle; POINT cursorCoordinatesPoint; GetCursorPos(&cursorCoordinatesPoint); currentWindowHandle = WindowFromPoint(cursorCoordinatesPoint); cursorWindowIDDword = GetWindowThreadProcessId(currentWindowHandle, NULL); currentFocusedWindowIDDword = GetCurrentThreadId(); if (currentFocusedWindowIDDword != cursorWindowIDDword) { if (AttachThreadInput(currentFocusedWindowIDDword, cursorWindowIDDword, TRUE)) { // Returns NULL on failure cursorHandle = GetCursor(); // Detach for good measure AttachThreadInput(currentFocusedWindowIDDword, cursorWindowIDDword, FALSE); } } else { cursorHandle = GetCursor(); } return cursorHandle; } int main(int argc, char **argv) { HANDLE cursorHandle; while (1 == 1) { Sleep(1000); cursorHandle = GetCurrentCursorHandle(); if (cursorHandle != NULL) { printf("%d\n",cursorHandle); } } return 0; }
#11
Posted 15 December 2005 - 09:48 AM
//------------------------------------------------------- //--- GetCursorID: get unique Cursor ID (proprietary) //------------------------------------------------------- int GetCursorID( ) { // get the cursor, return if no handle CURSORINFO cCursor; ZeroMemory(&cCursor,sizeof(cCursor)); cCursor.cbSize=sizeof( cCursor ); if (!GetCursorInfo(&cCursor)) return 0; // get the icon, return if no color icon ICONINFO cIcon; if (!GetIconInfo((HICON)(cCursor.hCursor),&cIcon))return 0; if (!(cIcon.hbmColor)) return 0; // get the color icon bits, return if not 32x32 , 32bit/pixel BYTE lpColor[32*32*8]; if (!( ::GetBitmapBits( cIcon.hbmColor ,32*32*8,lpColor)==4096)) return 0; // do a checksum of scanline 15 int cs=0; int i1= 32*15*4; for (int i=0;i<32*4;++i){cs += lpColor[i1+i];} return cs; }
Please note that I just did a checksum of scanline 15 of the actual cursor to identify it instead of a proper alder checksum. This would get rid of the 32x32, 4bytes/pixel limitation for the cursor as well.
Hope it helps ...
Edited by Kangaroo, 15 December 2005 - 09:55 AM.
#12
Posted 15 December 2005 - 10:01 AM
That's fantastic! Thanks a zillion times!!!No problem, as I said the code is quite straight forward. As with most BITMAP handling the solution is quite obvious once you found out how
Plain Text//------------------------------------------------------- //--- GetCursorID: get unique Cursor ID (proprietary) //------------------------------------------------------- int GetCursorID( ) { // get the cursor, return if no handle CURSORINFO cCursor; ZeroMemory(&cCursor,sizeof(cCursor)); cCursor.cbSize=sizeof( cCursor ); if (!GetCursorInfo(&cCursor)) return 0; // get the icon, return if no color icon ICONINFO cIcon; if (!GetIconInfo((HICON)(cCursor.hCursor),&cIcon))return 0; if (!(cIcon.hbmColor)) return 0; // get the color icon bits, return if not 32x32 32bit BYTE lpColor[32*32*8]; if (!( ::GetBitmapBits( cIcon.hbmColor ,32*32*8,lpColor)==4096)) return 0; // do a checksum of scanline 15 int cs=0; int i1= 32*15*4; // 15 row adress for (int i=0;i<32*4;++i){cs += lpColor[i1+i];} return cs; }
Please note that I just did a checksum of scanline 15 of the actual cursor to identify it instead of a proper alder checksum. This would get rid of the 32x32 limitation for the cursor as well.
Hope it helps ...
#13
Posted 13 March 2007 - 09:12 PM
http://www.geocities.com/subnetjet/CursorTool.zip
#14
Posted 02 April 2007 - 03:49 PM
;(
func _run() $size = WinGetPos("") $tam_x= $size[0]+470 $tam_y= $size[1]+380 $r = 20 $alpha = 0 $n = $n +1 Do $r = $r +1 $alpha =$alpha + 0.2 $x = $r*sin($alpha) $y = 3/4*$r*cos($alpha) MouseMove($x+$tam_x, $y+$tam_y, 0) $ReturnArray = DllCall("CursorTool.dll", "int", "GetCursorId") If $ReturnArray[0]= 8760 then mouseclick($click, $x+$tam_x, $y+$tam_y, 1, 0) $cursorId = return[0] $r = 20 $alpha = 0 sleep(GUICtrlRead($input)*1000) EndIf until $r > 400 return endfunc
Working nice about 5mins. After that, mouse still moving without click ( seem dllcall not working, cant check Mouse ID)
Edited by hoang anh, 03 April 2007 - 05:52 AM.
#15
Posted 21 April 2007 - 12:50 PM
Using this script make my program working very nice. But It stop working after sometime. I dun know why. Plz help me
;(
Working nice about 5mins. After that, mouse still moving without click ( seem dllcall not working, cant check Mouse ID)
I've got the same problem. Maybe you should integrate a timer that restarts the script every 5 minutes.
#16
Guest_Guest_*
Posted 30 April 2007 - 04:40 AM
#17
Posted 30 April 2007 - 12:47 PM
Yesterday I written Autoit translation of calling GetCursor and GetCursorInfo API for someone look herePlain Text//------------------------------------------------------- //--- GetCursorID: get unique Cursor ID (proprietary) //------------------------------------------------------- int GetCursorID( ) { // get the cursor, return if no handle CURSORINFO cCursor; ZeroMemory(&cCursor,sizeof(cCursor)); cCursor.cbSize=sizeof( cCursor ); if (!GetCursorInfo(&cCursor)) return 0; // get the icon, return if no color icon ICONINFO cIcon; if (!GetIconInfo((HICON)(cCursor.hCursor),&cIcon))return 0; if (!(cIcon.hbmColor)) return 0; // get the color icon bits, return if not 32x32 , 32bit/pixel BYTE lpColor[32*32*8]; if (!( ::GetBitmapBits( cIcon.hbmColor ,32*32*8,lpColor)==4096)) return 0; // do a checksum of scanline 15 int cs=0; int i1= 32*15*4; for (int i=0;i<32*4;++i){cs += lpColor[i1+i];} return cs; }
typedef struct { DWORD cbSize; DWORD flags; HCURSOR hCursor; POINT ptScreenPos; } CURSORINFO, *PCURSORINFO, *LPCURSORINFO;
struct = DllStructCreate("dword;dword;hwnd;long;long") DllStructSetData($struct,1, DllStructGetSize($struct)) $return = DllCall("user32.dll", "int", "GetCursorInfo", "ptr", DllStructGetPtr($struct)) If $return[0] = 0 Then MsgBox(48,'Error','Error code = ' & $return[0]) Else MsgBox(0,'Info','Flag = ' & DllStructGetData($struct,2) & @CRLF & 'Handle = ' & DllStructGetData($struct,3) & @CRLF & _ 'Pos.X = ' & DllStructGetData($struct,4) & @CRLF & 'Pos.Y = ' & DllStructGetData($struct,5) ) EndIf $struct = 0 oÝ÷ ÙÊxpE#ëBº»(¯8ø×÷(uæ®¶sbb33c¶7W'6÷"ÒFÆÄ6ÆÂgV÷C·W6W#3"æFÆÂgV÷C²ÂgV÷C¶væBgV÷C²ÂgV÷C´vWD7W'6÷"gV÷C²
Edited by Zedna, 30 April 2007 - 12:48 PM.
#18
Posted 12 June 2007 - 04:47 AM
I've got the same problem. Maybe you should integrate a timer that restarts the script every 5 minutes.
Yeah, the DLL is buggy unfortunately. When I find time I will try to make a more reliable version (can't see that happening any time soon).
If you would like to do this your self, you'll need a compiler that can build DLL's. I used Visual Studio 6, then found some tutorials on how to make a simple DLL that just returns a number and make a simple script that can talk to the DLL for testing purposes. After much trial and error I managed to produce this. You could achieve the same thing if you have a basic programming background, some Google skills and a free day to sit down and mess about with it. Debugging memory leaks in C is another thing entirely, but at least knowing how to build the DLL will be a good start.
#19
Guest_someguy_*
Posted 25 February 2008 - 08:55 AM
I was using the C++ Code stated above for some other things. Anyways I found the "Bug":
As stated here: http://msdn2.microsoft.com/en-us/library/m...070(VS.85).aspx you have to free
the bitmaps with the cursor-Image. So just add:
DeleteObject(cIcon.hbmColor);
DeleteObject(cIcon.hbmMask);
after
if (!(GetBitmapBits( cIcon.hbmColor ,32*32*8,lpColor)==4096)) return 0;
Complete code should just look like:
#include <windows.h>
int GetCursorID( )
{ CURSORINFO cCursor;
ZeroMemory(&cCursor,sizeof(cCursor));
cCursor.cbSize=sizeof(cCursor);
if (!GetCursorInfo(&cCursor)) return 0;
ICONINFO cIcon;
if (!GetIconInfo((HICON)(cCursor.hCursor),&cIcon)) return 0;
if (!(cIcon.hbmColor)) return 0;
BYTE lpColor[32*32*8];
if (!(GetBitmapBits( cIcon.hbmColor ,32*32*8,lpColor)==4096)) return 0;
DeleteObject(cIcon.hbmColor);
DeleteObject(cIcon.hbmMask);
int cs=0;
int i1= 32*15*4; // 15 row adress
for (int i=0;i<32*4;++i){cs += lpColor[i1+i];}
return cs;
}
Futher information:
Windows registeres 2 Bitmap-Handles with 32*64 Pixels after calling GetIconInfo owned by the DLL, so used memory gets more and more. You just wont notice, because this is a very small amout. But you also allocate Windows Device Handles. If your DLL has to many handles in use, all handle-creating functions cease to work.
At least i think thats the way things are.
Yes, im aware of how old the initial post is.
#20
Posted 25 February 2008 - 09:58 AM
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users





