News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Sending mouse clicks to another window.

Started by Nilrem, May 04, 2005, 04:15:23 PM

Previous topic - Next topic

Nilrem

Ok for my next coding endeavour this is what I have in mind:

Find the correct window and get a handle to it.
Send mouse clicks to it.

However there are a few snags already to this, the window is an internet explorer window, more a game page.
The mouse clicks to send therefore won't be the easy dlgitem because they're images. Perhaps pixel precision would be needed, but finding a specific pixel colour would be time consuming, very time consuming right?

Overall I am hoping to create a program that clicks just one button over and over again for me on an internet page. It isn't mass spam or anything it's a game called Keno over at www.pogo.com

Nilrem

Just to make it clear that I don't want it written for me, if there are already methods and apis used for such a program please point me in their direction. 8-)

Tedd

"SetCursorPos", followed by "mouse_event" :U

(correct parameters left as an exercise :lol)
No snowflake in an avalanche feels responsible.

Nilrem


Nilrem

I don't need mouse_event (so far hehe).
My problem is this how to set the window to send to. I think I know by using it's name, but what happens if the window happens to be an internet explorer one? Would I have to specify Internet Explorer - Window name
or could I just do Window name?
i'm asking now without testing because I won't have chance to for a few hours. Thanks a lot, highly appreciated. 8-)

Nilrem

Was browsing through looking for code snippets and ideas and found an excellent article, however I'm not sure how to do this:


DWORD dwPoint = GetMessagePos(); // Get the screen co-ords at the time
// GetMessage was last called

p.x = LOWORD(dwPoint); // Convert it to a points struct
p.y = HIWORD(dwPoint);


Would the LOWORD be the first 2 bytes and the HIWORD the last 2 bytes? I don't really understand it you see, I know x and y are of the POINT struct and they hold the co-ords etc, just cannot grasp this part?

I don't want the whole of this below code converting I'll try and adapt the bits I need myself first, but incase it helps you guys well here it is:


/******************************************************************************************/
/*   */
/*            Simple example to show how to get window handles from mouse clicks          */
/* by   */
/* recoup_this@yahoo.com   */
/*   */
/******************************************************************************************/
#include <windows.h>

BOOL g_bCaptureSet = FALSE; // Flag to indicate if window has called SetCapture()

BOOL CALLBACK MainDlgProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
switch(uiMsg)
{
case WM_LBUTTONDOWN:
{
if(g_bCaptureSet == TRUE) //Checks if the window has captured the mouse
{
POINT p;
HWND hWndGet;
char szTitle[256];
DWORD dwPoint = GetMessagePos(); // Get the screen co-ords at the time
// GetMessage was last called

p.x = LOWORD(dwPoint); // Convert it to a points struct
p.y = HIWORD(dwPoint);

memset(szTitle, 0, 256); // Empty szTitle, just incase !!
hWndGet = WindowFromPoint(p); // This gets the HWND of the window
// at point p

if(hWndGet == NULL) // Also it returns null if no window is
// there, so format an error message and
// Display it, then release capture of
// the mouse, and set g_bCaptureSet to
// reflect this
{
wsprintf(szTitle, "No window at selected point (%d, %d)", p.x, p.y);
MessageBox(hWnd, szTitle, "Error", MB_OK);
ReleaseCapture();
g_bCaptureSet = FALSE;
return TRUE;
}
// Otherwise get the found window's
// text, and display it, then
// release capture, and update
// g_bCaptureSet
GetWindowText(hWndGet, szTitle, 256);
MessageBox(hWnd, szTitle, "Window selected", MB_OK);
ReleaseCapture();
g_bCaptureSet = FALSE;
}
return TRUE;
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDCANCEL:
{
EndDialog(hWnd, 0);
return TRUE;
}
case IDOK:
{
if(g_bCaptureSet == TRUE) // Ignore the click if window already
// has capture
{
return TRUE;
}
SetCapture(hWnd); // Set the mouse capture to the window
g_bCaptureSet = TRUE; // and update g_bCaptureSet
return TRUE;
}
}
return FALSE;
}
}
return FALSE;
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int iCmdShow)
{
DialogBox(hInst, "MAINDIALOG", NULL, MainDlgProc);
return 0;
}


Once again, thankyou.

Nilrem

I've tried using different methods but to no avail.
The setcapture is working because I first tested it and used messagebox to report it.

However it is the SetForegroundWindow that is not working.


DlgProc PROTO :HWND,:UINT,:WPARAM,:LPARAM

.const

IDD_DIALOG1 equ 101
IDC_BTN_GET_POS equ 1001

;#########################################################################

.data?

hInstance dd ?
handle dd ?
beenclicked dd ?
hwndname HWND ?

;#########################################################################

.data

click_crd       POINT       <?>

;#########################################################################

start code
;###
.if eax==WM_INITDIALOG

.elseif eax==WM_COMMAND
mov eax,wParam
.if (eax==1001) ; GETPOS Button.
mov beenclicked, 1
invoke SetCapture,hWin
.endif
.elseif (eax==WM_LBUTTONDOWN)
cmp beenclicked,1
jnz @f
invoke GetActiveWindow
mov hwndname, eax
.if (eax==0)
invoke MessageBox,NULL,NULL,NULL,MB_OK
.endif
invoke ReleaseCapture
mov beenclicked, 0
@@:
.elseif (eax==WM_RBUTTONDOWN)
invoke SetForegroundWindow, hwndname

Nilrem

The button commands are working, but the foreground window is not been set and SetCapture is working fine. I just remembered 0 and NULL are different, changed .if (eax==0) to .if (eax==NULL) but no messagebox pops up when left clicking to get the handle.

pbrennick

Nilrem,
0 and NULL are different?  That is certainly news to me!  I have always used them interchangeably?!?

Paul

Nilrem

I though that! But my friend just convinced me! Bloody idiot making me look even more stupid then normal. Bah. Either way the program is not working as expected. 8-S

pbrennick

Nilrem,
You are certainly not stupid!!  And your problem is very interesting.  I am playing with it, not sure I can help but I am certain there are others who are furiously typing right now!  We all just love a good problem.

Paul

Tedd

Random guess..

Should you be using GetActiveWindow? Or do you mean to use GetForegroundWindow?
GetActiveWindow gives you the active window of YOUR thread, GetForegroundWindow gives the window with the current focus.

This would explain the SetForgroundWindow not working, because 'hwndname' wouldn't have the correct value.
No snowflake in an avalanche feels responsible.

AeroASM

Quote from: Nilrem on May 04, 2005, 08:54:05 PM
Would the LOWORD be the first 2 bytes and the HIWORD the last 2 bytes?

Like this:

A DWORD has four bytes, ordered like this in a register:

[BYTE 3|BYTE 2|BYTE 1|BYTE 0]

Of these, [BYTE 3|BYTE 2] is the HIWORD and [BYTE 1|BYTE 0] is the LOWORD.

However, in memory, the DWORD is stored like this:

BYTE 0,BYTE 1,BYTE 2,BYTE 3

This is called little endian. You needn't worry about swapping the orders when moving between reg and mem because the CPU does it for you.

Nilrem

If I read documentation properly then I would have known that, I thought it meant the selected (active to me means selected) window. I guess active would be if my program created a window right?

Here is the new code that works, interestingly enough I had to add 'invoke Sleep, 1' otherwise it didn't work, so .001 (right?) of a second pause is needed otherwise it doesn't get the handle. Thanks for all the hard help. Now to write some history essay (even though I want to code some more 8-().


DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
.if eax==WM_INITDIALOG

.elseif eax==WM_COMMAND
mov eax,wParam
.if (eax==1001) ; GETPOS Button.
mov beenclicked, 1
invoke SetCapture,hWin
.endif
.elseif (eax==WM_LBUTTONDOWN)
cmp beenclicked,1
jnz @f
invoke Sleep, 1
invoke GetForegroundWindow
mov hwndname, eax
.if (eax==NULL)
invoke MessageBox,NULL,NULL,NULL,MB_OK
.endif
invoke ReleaseCapture
mov beenclicked, 0
@@:
.elseif (eax==WM_RBUTTONDOWN)
invoke SetForegroundWindow, hwndname
.elseif eax==WM_CLOSE
invoke EndDialog,hWin,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret

DlgProc endp


So AeroAsm I would do mov byte ptr + 1 etc for LOWORD right?

Nilrem

Now that I have it working can someone point me in the right direction for sending a maximise message? I'm asking this because if the window is minimised obviously setting it as the foreground window doesn't maximise (or restore) it.

Edit

invoke SendMessage,hwndname, WM_SYSCOMMAND, SC_MAXIMIZE, 0

That is what I was looking for. MSDN really is useful. 8-)