Showing posts with label GUI Hacks. Show all posts
Showing posts with label GUI Hacks. Show all posts

Tuesday, July 10, 2007

Lesson 6: The Extra Mile

Well, there are other options to dealing with dialogs....don't.

I use Winamp as my media player, not just because I can make it do strange and very useful little things but because I hate llamas. I have macros that will let me move forward and back in the media being played by 5 seconds, 30 seconds, and 3 minutes. I can also grab the current position of the playing media and save it to a text file sort of like "bookmarking". Now, of course you can do this via the buttons on the player and dialogs but it's clunky and not very responsive, so here's what I do.

I went nosing around the SDK for Winamp and got a hold of their 'WM_COMMAND Messages' definitions and menu ids. Now, instead of using a mouse command 'click here' on 'this window', I can forgo the whole graphical interface and it's associated problems. Here's how I'm moving 5 seconds forward or back using QM.

men 40144 win("" "Winamp v1.x") ;;Back 5 seconds
men 40060 win("" "Winamp v1.x") ;;FFwd 5 seconds

This responds MUCH faster via a trigger key than even using a mouse click manually but it's "faking" a menu choice. And, if I know I want to move 30 seconds forward (for skipping commercials on dl.tv-sorry, guys...but I do watch the interesting ones...and GoDaddy ain't one of 'em), I use this code:

int hwnd=win("" "Winamp v1.x")
if(!hwnd) ret
_i=SendMessage(hwnd WM_USER 0 105)
_i+30000;;time to skip in miliseconds (this is 30 seconds)
SendMessage(hwnd WM_USER _i 106)

If you look closely, you'll see that I'm using the 'SendMessage' capability to get the current position in milliseconds (105) and then sending a new value back to the player (106). I get remarkably fast response times when doing this; the video at worst barely even stutters. This is much better than even using my above macro repeated 6 times.

Once you start getting a feel for what the 'SendMessage' commands start returning, you can really start cooking up some useful things. For instance, when I get a hold of a really good tune, I have a tendency to listen to it for 5 or 6 hours just repeating over and over. So, I came up with a quick method to force Winamp to do this. Since there is no setting for "Repeat Song" you have to build it from 2 settings: "Repeat Playlist" and "Manual Advance".

int y z
int hwnd=win("" "Winamp v1.x")
if(!hwnd) ret
z=SendMessage(hwnd WM_USER 0 251);;get repeat playlist value
y=SendMessage(hwnd WM_USER 1 634);;get manual advance value
if y+z=2
,Speak("Continue" 0 "" 0 100)
,SendMessage(hwnd WM_USER 0 635)
,OnScreenDisplay("Continue" 1 1000 10 "Arial" 0 0x1d60cd 0 "psa")
else
,Speak("Song Looped" 0 "" 0 100)
,OnScreenDisplay("Song Looped" 1 1000 10 "Arial" 0 0x1d60cd 0 "psa")
,SendMessage(hwnd WM_USER 1 635);;set man advance
,SendMessage(hwnd WM_USER 1 253);;set repeat

Since I want this macro to 'toggle' this state of 'Song Looped' rather than merely just 'turn it on', I have it use an 'if' statement to determine what state it is in and then reverse that state. I also tell it to give me a little audio feedback so that I know that the macro executed and let me know what it did (that's the 'Speak' function).

Now you have two ways of dealing with the GUI (or rather 1 way of dealing with it and 1 way of avoiding it). So have at it and I'll see you next time cause the hook always brings you back.

Thursday, June 21, 2007

Lesson 6: Getting Stuck in the GUI Hacks

Getting Stuck in the GUI Hacks
GUI hacks are the processes that you have to create because you can't get at the option or method of doing something to/in a program. For example, a really ugly GUI Hack would be
  1. open Windows Explorer
  2. hit Alt-d and put in the directory you want to go to
  3. then hitting 'Tab' three times to get to the file list
  4. use the 'key' command to start spelling the name of the file you want so that it is selected
  5. type Ctl-c
  6. hit Alt-d to move to the address bar and put in the new directory
  7. hit 'Tab' three times to get to the file list
  8. hit Ctl-v

Of course no one would do this; that's what 'ren' or 'cop' is for but sometimes you just have to interact with program GUI dialogs. And God help me, I HATE GUI HACKS! There are just so many more things that can go wrong so many 'edge-cases' you have to account for...God help me but I hate them. Well, if you gotta you gotta so here's some ideas that might help.

Timing is everything in GUI hacking. If the dialog is slow to open, or if the field you need inside the dialog is slow to be drawn, or if...blah blah blah. The first thing I do to make sure my GUI hacks are going to work is put in 'wait's everywhere so that the macro 'paces' itself. Here's an example of that. Sometimes when I send emails via Outlook, I don't want a 'message receipt' nor do I want to keep a copy of the sent message, so I have a macro that changes the message property for me and then sends it. Here's what the dialog looks like.



As you can see, there are two check boxes I want to deselect; they can either be 'clicked' by the mouse (I find this less reliable for various reasons) or the values of the check boxes can be inverted by using keystrokes (Alt-r and Alt-n). First things first; I have to get the dialog to show up. I do that by using the "Accessible object actions" item in the "Windows, controls" button on the QM toolbar and drag the aiming reticle on top of the "Options..." button on the message I'm currently writing. This method works well enough but ask yourself what would happen if the toolbar that had that "Options..." button wasn't visible at the time; the macro would fail immediately (and so would my willowy grasp on sanity). I'd prefer a keyboard shortcut but I don't have one for it, so I make due. But now, I have to guess how long to wait for the dialog to show up before I start hitting my keystrokes....or do I?....Nope. Here's what I do.
0 WA "Message Options"
This is a version of the 'wait' command. The '0' tells QM to wait indefinitely for the window with the name "Message Options" to become 'active' ('WA'=wait till active). I pulled the window name directly from the QM Editor itself. When you have the editor open the status bar continually gives you information on both the cursor position and the window that it is currently hovering over. The window name is in the first row and comes just after the mouse position relative to the window. So now, when I start the macro, it 'clicks' the "Options..." button and waits for the dialog to become active; it then sends the keystrokes for the above check boxes and hits 'enter'. It then waits for the message itself to become active so that it can send the 'Send Message' command via an Alt-s keystroke.
spe 50
Acc option_a=acc("Options..." "DROPLIST" win(".*Message" "OpusApp" "" 0x200) "MsoCommandBar" "" 0x1001)
option_a.Mouse(1)
0 WA "Message Options"
'Ar
'An
'Y
0 WA "Message"
'As

Now you may ask about the second line from the bottom and say, "Gordon Bennett, not ALL your emails can be tittled 'Message'!"...ok, so maybe you wouldn't say that but someone did....probably.....might have....well, ok they could have said it give me that at least.... Well, this kind of gets into the 'win' function which I should cover another time in depth but let's suffice it to say that, it is case sensitive and can be anywhere within the window name. Here's what my window's tittle bar actually looks like with a standard message.
There it is; a macro with built rest stops (but smells better) for when you just 'have' to GUI hack.

So have at it and I'll see you next time cause the hook always brings you back.