The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: Jimg on September 16, 2005, 03:26:41 PM

Title: click on menu item of another app
Post by: Jimg on September 16, 2005, 03:26:41 PM
I have a commercial application that I need to use many times every day.  It's a good app, but the user interface could use some help.  What I would like to do is write a program that would send a clicked message to one of the menu items and then one of the sub-menu items.  I've already figured out how to move the pop-ups around, I just can't seem to find the menu ids.  I'm sure I've seen this topic addressed before, but I'm having no luck finding the topic.  Reshacker was no help as it says the app was compressed.  How does one find the menu ids of a running app?  I thought about sending a mouse message but the I move the window around sometimes so the mouse coordinates wouldn't be the same, and it seems like just sending a WM_COMMAND with the id would be better.  No?
Title: Re: click on menu item of another app
Post by: AeroASM on September 16, 2005, 06:28:16 PM
There is a tool called Spy++ which lets you monitor, among other things, window messages. Start up Spy++ and monitor the window of your application, then click on a menu item and SPy++ will show the details of the message, which will contain the menu ID. In fact the details of the message will be the same ones that you need to send yourself.
Title: Re: click on menu item of another app
Post by: Jimg on September 16, 2005, 07:10:02 PM
Thank you, but I do not now nor do I ever intend to own C++
Title: Re: click on menu item of another app
Post by: AeroASM on September 16, 2005, 07:27:35 PM
But Spy++ is nothing to do with C++. How did you come to that conclusion?
Title: Re: click on menu item of another app
Post by: Jimg on September 16, 2005, 08:03:18 PM
Hmmmm-  I googled and everything came up that it was part of c++ or possibly visual studio?  I'll go look again.
Title: Re: click on menu item of another app
Post by: Jimg on September 16, 2005, 08:07:43 PM
Yup.  Definately part of visual studio.  I'll unpack my old vb6 disks to see if it's on there.

Later....

I'll be darned.  It was on there.  Thanks for the tip :P
Title: Re: click on menu item of another app
Post by: P1 on September 16, 2005, 08:29:33 PM
Quote from: Jimg on September 16, 2005, 08:07:43 PM
Yup.  Definately part of visual studio.  I'll unpack my old vb6 disks to see if it's on there.
Nope.

I got mine off a Learning Edition of VC++  v6.  Which was with a game programming book for free.  Never used the C stuff, but I used everyting else for MASM developement.   :toothy

Regards,  P1  :8)
Title: Re: click on menu item of another app
Post by: Jimg on September 16, 2005, 09:05:51 PM
Wow, that was sure entertaining and enlightening.

I look like the message to send is

WM_SYSCOMMAND uCmdType:SC_MOUSEMENU xPos:553 yPos:26

I would have never thought to do such a thing ::)

Does this sound reasonable to anyone??
Title: Re: click on menu item of another app
Post by: Jimg on September 17, 2005, 01:30:29 AM
Well, that kept me entertained for hours, but produced absolutely no results.  Surely this is something that is done all the time, one of those well known things that I just haven't had to do yet.  What's the secret????  Would it be better to try to send a keystroke?  How do you send an alt-p to an app??  It's not a normal wm_char type thing.
Title: Re: click on menu item of another app
Post by: Jimg on September 17, 2005, 07:16:35 PM
Ok, let's try this a different way.  Does anybody see why this code wouldn't click the menu items in the other app?

.data
CurrWnd   dd 0
TaskName  db 100 dup (0)
MedVed    db 'Default Portfolio - Medved QuoteTracker',0
hMedVed   dd 0
MedVedPid dd 0
ThisPid   dd 0
.code
Doit proc
    inv GetWindow,hWin,GW_HWNDFIRST
    mov CurrWnd,eax
DoitLoop:
    cmp eax,0
    je DoitDone
    inv GetParent,eax
    inv GetWindowTextLength,CurrWnd
    .if eax>0
        inv GetWindowText,CurrWnd,addr TaskName,99
        PrintString TaskName
        mov ecx,offset TaskName
        mov edx,offset MedVed
    @@:
        mov al,[edx]
        cmp al,0
        je @f       ; good
        cmp al,[ecx]
        jne ng
        inc ecx
        inc edx
        jmp @b
    @@:

        mov eax,CurrWnd
        mov hMedVed,eax
        PrintHex hMedVed

        inv GetWindowThreadProcessId,hMedVed,ADDR MedVedPid
        inv GetCurrentThreadId
        mov ThisPid, eax
        inv AttachThreadInput, ThisPid, MedVedPid, TRUE
        inv SetForegroundWindow,hMedVed
        inv Sleep,500
        inv SendMessage,hMedVed, WM_SYSKEYDOWN, 50h,20190001h  ; 'alt-p'
        inv Sleep,500
        inv SendMessage,hMedVed, WM_SYSKEYUP,   50h,0e0190001h
        inv Sleep,500
        inv SendMessage,hMedVed, WM_SYSKEYDOWN, 45h,20120001h   ; 'alt-e'
        inv Sleep,500
        inv SendMessage,hMedVed, WM_SYSKEYUP,   45h,0E0120001h
        inv Sleep,500
               
        inv AttachThreadInput,ThisPid,MedVedPid,FALSE
        ret ; done
    .endif
    ng:
    inv GetWindow,CurrWnd,GW_HWNDNEXT
    mov CurrWnd,eax
    jmp DoitLoop
       
DoitDone:
    ret
Doit EndP


I know I have the right handle because the app get the focus.
Title: Re: click on menu item of another app
Post by: farrier on September 18, 2005, 01:11:08 AM
Jimg,

I have done a similar thing, but instead of using "inv SendMessage"

I used:
push eax
invoke keybd_event, eax, NULL, NULL, NULL                   ;Press key
invoke Sleep, 200
pop eax                                                      ;Get the same key from stack
invoke keybd_event, eax, NULL, KEYEVENTF_KEYUP, NULL        ;Release key


hth,

farrier
Title: Re: click on menu item of another app
Post by: Jimg on September 18, 2005, 02:44:13 AM
Excellent!  That actually worked!  I've got a little cleanup to do, for some reason the alt key gets stuck down ::)

Thank you very much farrier.
Title: Re: click on menu item of another app
Post by: farrier on September 18, 2005, 05:54:12 AM
Jimg,

You are welcomed!

Also look here:

http://board.win32asmcommunity.net/index.php?topic=21503.0

Haven't tried this, but it sounds like the way to go, if you are starting up the other program!

hth,

farrier
Title: Re: click on menu item of another app
Post by: Jimg on September 18, 2005, 04:59:37 PM
Everything is working except restoring the app if it is minimized  (OpenIcon).  I also found that I didn't need any sleeps or the attachthread stuff.  Anyone know why OpenIcon is not restoring the window?  The return shows no error.

Here's the code so far, including the part that moves the window that pops up from the menu clicks-

.686p
.model  flat, stdcall
option  casemap :none   ; case sensitive
.nolist
include windows.inc

inv equ Invoke

uselib  MACRO   libname
    include     libname.inc
    includelib  libname.lib
ENDM
uselib user32
uselib kernel32
;uselib masm32
;uselib debug

.listall

.data?
Phase     dd ?
CurrWnd   dd ?
TaskName  db 100 dup (?)

.data
MedVed    db 'Default Portfolio - Medved QuoteTracker',0
PortFolio db 'Portfolios and Alerts',0

.code

Program:

    mov Phase,1

DoitStart:
    inv FindWindow,0,0      ; get starting window
    mov CurrWnd,eax

DoitLoop:
    cmp eax,0
    je DoitDone
    inv GetWindowTextLength,CurrWnd
    .if eax>0
        inv GetWindowText,CurrWnd,addr TaskName,99
        ;PrintString TaskName
        mov ecx,offset TaskName
        .if Phase==1
            mov edx,offset MedVed
        .else
            mov edx,offset PortFolio
        .endif
    @@:
        mov al,[edx]    ; compare window found against what we want
        cmp al,0
        je @f           ; found all we wanted
        cmp al,[ecx]
        jne NextWindow  ; not this one, go look for next window name
        inc ecx
        inc edx
        jmp @b
    @@:
        .if Phase==1
            inv IsIconic,CurrWnd            ; if minimized
            .IF eax!=0
                inv OpenIcon,CurrWnd        ; restore
            .ENDIF
            inv SetForegroundWindow,CurrWnd
            inv keybd_event, VK_MENU, 0, 0, 0   ;Send Alt key 'down'
            inv Sleep, 40
            inv keybd_event, VK_P, 0, 0, 0 ;Send P key 'down'
            inv Sleep, 40           
            inv keybd_event, VK_P, 0, KEYEVENTF_KEYUP, 0 ;Send P key 'up'
            inv Sleep, 40
            inv keybd_event, VK_MENU, 0, KEYEVENTF_KEYUP, 0 ;Send Alt key 'up'
            inv Sleep, 40
            inv keybd_event, VK_E, 0, 0, 0 ;Send E key 'down'
            inv Sleep, 40
            inv keybd_event, VK_E, 0, KEYEVENTF_KEYUP, 0 ;Send E key 'up'
               
            inc Phase
            jmp DoitStart
        .else   ; Phase 2, move the window
            inv MoveWindow, CurrWnd, 425, 0, 600, 436, TRUE
            jmp DoitDone
        .endif
    .endif

NextWindow:
    inv GetWindow,CurrWnd,GW_HWNDNEXT
    mov CurrWnd,eax
    jmp DoitLoop
       
DoitDone:
    inv ExitProcess, 0

end Program


This is written as a console app, but I had to link it as a window to keep the console from flashing.

Edit:

I had to add the sleeps back in.  In some cases it was just too fast for the app to process.  I would have though these messages would have just stacked up to be processed whenever the app was ready, but it clearly has a problem at times.
Title: Re: click on menu item of another app
Post by: farrier on September 18, 2005, 11:23:39 PM
Jimg,

Have you tried:

ShowWindow

with:

SW_RESTORE

Then:

SetForegroundWindow

hth,

farrier
Title: Re: click on menu item of another app
Post by: Jimg on September 18, 2005, 11:38:26 PM
Yes, I did, but that didn't work either.
Title: Re: click on menu item of another app
Post by: farrier on September 19, 2005, 12:55:34 AM
Jimg,

That seems to indicate that you don't have the correct hWnd !!!

Spy++ may be your best bet to find and compare the real hWnd with what you are using at the time.

hth,

farrier
Title: Re: click on menu item of another app
Post by: Jimg on September 19, 2005, 03:32:26 AM
The handle I'm finding is the same handle as Spy++,  and everything else was working, so it should have been the correct handle anyway.

Looking a little more closely, I made some assumptions I shouldn't have.  I knew that the app was iconic, I just minimized it myself.  The IsIconic api, however, returned false.  So I wasn't really executing the openicon api.  When I forced the OpenIcon call, it restored the app to normal.  The wierd thing, however, is that afterward, I could not minimize the app again, the minimize button was just ignored.  The same thing happened using showwindow.  Obviously, I'm not doing this right.  If I can't trust IsIconic, what do I use??
Title: Re: click on menu item of another app
Post by: Jimg on September 19, 2005, 02:52:50 PM
After some testing, I've determined that this app is just wierd.  I tried the process on another app, and the isiconic and openicon worked properly.  For some reason, when this app is minimized, it doesn't test as minimized, and a GetWindowRect shows the same coordinates, minimized or not, where a normal app shows minimize coordinates way off the screen as expected.  Does anyone know what this effect is and how to handle it?
Title: Re: click on menu item of another app
Post by: P1 on September 19, 2005, 05:03:17 PM
Is it 16bit Windows 3.1 app???

Regards,  P1  :8)
Title: Re: click on menu item of another app
Post by: Jimg on September 19, 2005, 07:18:23 PM
No, not at all.   http://www.quotetracker.com/
Title: Re: click on menu item of another app
Post by: jojo on September 26, 2005, 03:10:37 PM
Quote from: farrier on September 18, 2005, 11:23:39 PM
SetForegroundWindow

There are some problems with SetForegroundWindow, check http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/setforegroundwindow.asp

A safe way to activate a window is
inv ShowWindow, Handle, SW_HIDE ;optional, may be faster
inv ShowWindow, Handle, SW_MINIMIZE
inv ShowWindow, Handle, SW_RESTORE
Title: Re: click on menu item of another app
Post by: Mark Jones on February 03, 2006, 12:51:03 AM
Also if you didn't notice this already, each "press" of the ALT key must occur twice in code - one call for down, and one call for up. That's why it "sticks."