Further suggestion for JSR-666.
Previous JSR-666 recommendations:
JSR-666: Rich text identifiers
As is so often the case, Microsoft is leading the way here.
Remember back in the bad old days of DOS and Windows 3.x? 8.3 filenames? Yuck! With Win9x came long file names, and better still, embedded spaces.
Lets have this in Java. And why stop there? Let's go for full rich text! my button could be different from my button, and my button different again. (After all, mybutton and myButton are already different, so it's not so great a leap. my exception might be more serious than my exception.
I'm sure that there are some parsing issues to sort out, but they are (waves hand) pretty trivial, I'd imagine...
(P.S. Check out the URL...)
Fizzy Cola Bottles, Flying Saucers? Sherbet Lemons?
Check out The Old Sweet Shop, for all your online crap sweet needs.
Remember the way that sherbert lemons used to lacerate the inside of your mouth? Bliss.
Some things you can do with a control once you have it.
See Driving win32 GUIs with Python, part 1 and Driving win32 GUIs with Python, part 2.
There are, of course, loads of things you can do with a control. Anything that you can do with a mouse or a keyboard can be automated. I'll just give a few simple examples, from which you should be able to extrapolate most things that you might need to do.
A great many of these actions are class specific - you can select one or many of a combo box's items, for example, but a button doesn't have items to select.
OK A nice simple one first. Let's click a button:
def click(hwnd):
win32gui.SendMessage(hwnd, win32con.WM_LBUTTONDOWN, 0, 0)
win32gui.SendMessage(hwnd, win32con.WM_LBUTTONUP, 0, 0)
We can use this function like so:
optDialog = findTopWindow(wantedText="Options")
def findAButtonCalledOK(hwnd, windowText, windowClass): # Define a function to find our button
return windowClass == "Button" and windowText == "OK"
okButton = findControl(optDialog, findAButtonCalledOK)
click(okButton)
You could do this more tersely with a lambda, by the way:
optDialog = findTopWindow(wantedText="Options")
okButton = findControl(optDialog, lambda hwnd, windowText, windowClass : windowClass == "Button" and windowText == "OK")
click(okButton)
I prefer the first form, but that's purely subjective.
And now, for my next trick, let's get the text from an Edit control. "But wait", you'll say, "can't you use the win32gui.GetWindowText() function"? No, actually, you can't. The thing is, this works for some classes of window - you can use win32gui.GetWindowText() to get the text of a button or a label, for example. But other classes don't have the kind of text that win32gui.GetWindowText() sets. An edit control is one of these - it has lines of text rather than just text. Here's a function which will get it for you:
def getEditText(hwnd):
result = []
bufferlength = struct.pack('i', 255)
linecount = win32gui.SendMessage(hwnd, win32con.EM_GETLINECOUNT, 0, 0)
for line in range(linecount):
linetext = bufferlength + "".ljust(253)
linelength = win32gui.SendMessage(hwnd, win32con.EM_GETLINE, line, linetext)
result.append(linetext[:linelength])
return result
The only complicated bit here is the struct stuff. When sending the win32con.EM_GETLINE, you need to pass a string, into which the line of text will be inserted. The first byte of this string must contain the total length of the string. struct to the rescue! It would be nice to wrap this up into a class, implementing a file-like interface, at some point. Or perhaps it should be a generator? Anyway, as it stands, you can use it like so:
genTop = findTopWindow(wantedText="Generating the Runtime")
def editFinder(hwnd, windowText, windowClass): return windowClass == "Edit"
genEdit = findControl(genTop, editFinder)
print getEditText(genEdit)
Now, combo-boxes. (These are the ones with a little down-arrow button to the right hand side, allowing you to select one (or perhaps more) from several options.) Here is the code to get a list of the values from a combo box:
def getComboboxItems(hwnd):
result = []
bufferlength = struct.pack('i', 255)
itemCount = win32gui.SendMessage(hwnd, win32con.CB_GETCOUNT, 0, 0)
for itemIndex in range(itemCount):
linetext = bufferlength + "".ljust(253)
linelength = win32gui.SendMessage(hwnd, win32con.CB_GETLBTEXT, itemIndex, linetext)
result.append(linetext[:linelength])
return result
Looks a bit like getEditText, doesn't it? I thought so - refactored version below:
def getMultipleWindowValues(hwnd, getCountMessage, getValueMessage):
result = []
bufferlength = struct.pack('i', 255)
count = win32gui.SendMessage(hwnd, getCountMessage, 0, 0)
for itemIndex in range(count):
value = bufferlength + "".ljust(253)
valueLength = win32gui.SendMessage(hwnd, getValueMessage, itemIndex, value)
result.append(value[:valueLength])
return result
def getComboboxItems(hwnd): return getMultipleWindowValues(hwnd, getCountMessage=win32con.CB_GETCOUNT, getValueMessage=win32con.CB_GETLBTEXT)
def getEditText(hwnd): return getMultipleWindowValues(hwnd, getCountMessage=win32con.EM_GETLINECOUNT, getValueMessage=win32con.EM_GETLINE)
Last thing today - selection a combo-box item.
def selectComboboxItem(hwnd, item):
win32gui.SendMessage(hwnd, win32con.CB_SETCURSEL, item, 0)
click(hwnd)
keystroke(hwnd, win32con.VK_RETURN)
def keystroke(hwnd, key):
win32gui.SendMessage(hwnd, win32con.WM_KEYDOWN, key, 0)
win32gui.SendMessage(hwnd, win32con.WM_KEYUP, key, 0)
I had hoped that the first of these messages would be enough. Unfortunately, it was not to be - while the selected item did change in the GUI, the application that I was automating didn't respond to the change without the click, and the drop-down list didn't disappear without the keystroke. If anyone can suggest a more elegant way of doing this, I'd be pleased to hear of it.
Here I put it all together
# Find the ACE window library selection combo
def findAceLibrarySelectionFunction(hwnd, windowText, windowClass): return windowClass == "ComboBox" and ("EVO1" in getComboboxItems(hwnd))
libCombo = findControl(findTopWindow(wantedText="ACE"), findAceLibrarySelectionFunction)
# Get a list of the combo items
items = getComboboxItems(libCombo)
print "Items: " + str(items)
import random
# Pick one at random, and select it
selectItemIndex = random.randrange(len(items))
print "Selecting: " + items[selectItemIndex]
selectComboboxItem(libCombo, selectItemIndex)
Well, that's just about it from me on this, really, though if anything else occurs to me, you'll be sure to know. ;-)
Update: See Driving win32 GUIs with Python, part 1, Driving win32 GUIs with Python, part 2, Driving win32 GUIs with Python, part 3 and Driving win32 GUIs with Python, part 4.
Generalizing polymorphism with multimethods
Dive under the skin of OOP, see how it's done, and see how it can be done a little differently...
Via postneo.
Hey, it's from the Whitehouse - it must be genuine!
It's well worth having a look round this site - it's hysterical. I particularly like Operation Infinite Purity: Winning the War on Masturbation, (a Democrat-created crisis), and Godly Tips on How to Punish and Beat Your Christian Child.
NB, I also like the fact that iSpell doesn't recognise 'Whitehouse', and suggested 'Whorehouse' as a correction.
Cath wants to keep them with her in Reading.
This is perfectly fair - after all, I get them most weekends. Cath needs some weekends to do stuff with them too. She has them during the week, of course, but during that time they are always rushing about, getting ready for school, or bed, or whatever. At the weekend, there is time to do stuff, and I'm lucky enough to get the lions share of that. Can't complain, can I?
But I still hate it. I never know what to do with myself at the weekend when I'm on my own.
I guess that I'll just have to get very drunk.
I'm not allowed a girlfriend, but it seems that the girls are allowed boyfriends.
Freja (six) said that she did have a boyfriend, but that she "dumped him", (her exact words), because he kept "chasing" her. This doesn't refer to being too attentive, or making too many phone calls. No, he just chased her around the playground.
She says that she doesn't want a boyfriend any more - boys are "Yuck". That's my girl.
Ella (4 1/2) claims to have three boyfriends. It would be wrong of me to make any allusion to her mother at this point, so I won't.