#!/bin/env python
# -*- coding: utf-8 -*-
import ctypes
class PostWinMsg( object ) :
def __init__ ( self , hwnd, wait= 0 , fg= False ) :
self .hwnd = hwnd
self .wait = wait
if fg: self .foreground ( )
@ classmethod
def target( cls, wname, cname= None , chwnd= None , phwnd= None ) :
return ctypes.windll .user32 .FindWindowExW (
phwnd if phwnd else 0 , chwnd if chwnd else 0 ,
ctypes.c_wchar_p ( cname) if cname else 0 ,
ctypes.c_wchar_p ( wname) if wname else 0 )
def getclassname( self , l) :
buf = ctypes.c_wchar_p ( u' ' * ( l + 1 ) )
ctypes.windll .user32 .GetClassNameW ( self .hwnd , buf, l + 1 )
return buf.value
def foreground( self ) :
ctypes.windll .user32 .SetForegroundWindow ( self .hwnd )
def topmost( self , flg= True ) :
ctypes.windll .user32 .SetWindowPos ( self .hwnd ,
-1 if flg else -2 , # HWND_TOPMOST or HWND_NOTOPMOST
0 , 0 , 0 , 0 , 3 ) # SWP_NOSIZE | SWP_NOMOVE
def sleep( self , ms) :
ctypes.windll .kernel32 .Sleep ( ms)
def isalnum( self , c) :
return ( 0x30 <= c <= 0x39 ) or ( 0x41 <= c <= 0x5A ) or ( 0x61 <= c <= 0x7A )
def wm( self , msg, wp, lp) :
if self .wait : self .sleep ( self .wait )
ctypes.windll .user32 .PostMessageW ( self .hwnd , msg, wp, lp)
def syskeyd( self , vk) :
self .wm ( 260 , vk, 1 << 29 ) # WM_SYSKEYDOWN lparam = Alt down
def syskeyu( self , vk) :
self .wm ( 261 , vk, 6 << 29 ) # WM_SYSKEYUP lparam = Alt up
def syskeydu( self , vk) :
self .wm ( 260 , vk, 1 << 29 ) # WM_SYSKEYDOWN lparam + Alt
if self .isalnum ( vk) : self .wm ( 262 , vk, 7 << 29 ) # WM_SYSCHAR lparam + Alt
self .wm ( 261 , vk, 7 << 29 ) # WM_SYSKEYUP lparam + Alt
def altkeys( self , s) :
self .syskeyd ( 18 ) # Alt down
for c in s: self .syskeydu ( ord ( c) )
self .syskeyu ( 18 ) # Alt up
def keydu( self , vk) :
self .wm ( 256 , vk, 0 ) # WM_KEYDOWN
if self .isalnum ( vk) : self .wm ( 258 , vk, 0 ) # WM_CHAR
self .wm ( 257 , vk, 0 ) # WM_KEYUP
def keys( self , s) :
for c in s: self .keydu ( ord ( c) )
def mouseclk( self , b, x, y, dbl= False ) :
lp = x + y * 2 ** 16
wp = 1 if b == 0 else 2 if b == 1 else 16
o = 3 * b
self .wm ( 513 + o, wp, lp) # WM_LBUTTONDOWN
self .wm ( 514 + o, wp, lp) # WM_LBUTTONUP
if dbl: self .wm ( 515 + o, wp, lp) # WM_LBUTTONDBLCLK
if __name__ == '__main__' :
target = PostWinMsg.target ( u'無題 - メモ帳' )
pwm = PostWinMsg( target, wait= 1000 , fg= True )
pwm.keys ( 'xyz abc' )
pwm.altkeys ( 'FS' )
IyEvYmluL2VudiBweXRob24KIyAtKi0gY29kaW5nOiB1dGYtOCAtKi0KCmltcG9ydCBjdHlwZXMKCmNsYXNzIFBvc3RXaW5Nc2cob2JqZWN0KToKICBkZWYgX19pbml0X18oc2VsZiwgaHduZCwgd2FpdD0wLCBmZz1GYWxzZSk6CiAgICBzZWxmLmh3bmQgPSBod25kCiAgICBzZWxmLndhaXQgPSB3YWl0CiAgICBpZiBmZzogc2VsZi5mb3JlZ3JvdW5kKCkKCiAgQGNsYXNzbWV0aG9kCiAgZGVmIHRhcmdldChjbHMsIHduYW1lLCBjbmFtZT1Ob25lLCBjaHduZD1Ob25lLCBwaHduZD1Ob25lKToKICAgIHJldHVybiBjdHlwZXMud2luZGxsLnVzZXIzMi5GaW5kV2luZG93RXhXKAogICAgICBwaHduZCBpZiBwaHduZCBlbHNlIDAsIGNod25kIGlmIGNod25kIGVsc2UgMCwKICAgICAgY3R5cGVzLmNfd2NoYXJfcChjbmFtZSkgaWYgY25hbWUgZWxzZSAwLAogICAgICBjdHlwZXMuY193Y2hhcl9wKHduYW1lKSBpZiB3bmFtZSBlbHNlIDApCgogIGRlZiBnZXRjbGFzc25hbWUoc2VsZiwgbCk6CiAgICBidWYgPSBjdHlwZXMuY193Y2hhcl9wKHUnICcgKiAobCArIDEpKQogICAgY3R5cGVzLndpbmRsbC51c2VyMzIuR2V0Q2xhc3NOYW1lVyhzZWxmLmh3bmQsIGJ1ZiwgbCArIDEpCiAgICByZXR1cm4gYnVmLnZhbHVlCgogIGRlZiBmb3JlZ3JvdW5kKHNlbGYpOgogICAgY3R5cGVzLndpbmRsbC51c2VyMzIuU2V0Rm9yZWdyb3VuZFdpbmRvdyhzZWxmLmh3bmQpCgogIGRlZiB0b3Btb3N0KHNlbGYsIGZsZz1UcnVlKToKICAgIGN0eXBlcy53aW5kbGwudXNlcjMyLlNldFdpbmRvd1BvcyhzZWxmLmh3bmQsCiAgICAgIC0xIGlmIGZsZyBlbHNlIC0yLCAjIEhXTkRfVE9QTU9TVCBvciBIV05EX05PVE9QTU9TVAogICAgICAwLCAwLCAwLCAwLCAzKSAjIFNXUF9OT1NJWkUgfCBTV1BfTk9NT1ZFCgogIGRlZiBzbGVlcChzZWxmLCBtcyk6CiAgICBjdHlwZXMud2luZGxsLmtlcm5lbDMyLlNsZWVwKG1zKQoKICBkZWYgaXNhbG51bShzZWxmLCBjKToKICAgIHJldHVybiAoMHgzMCA8PSBjIDw9IDB4MzkpIG9yICgweDQxIDw9IGMgPD0gMHg1QSkgb3IgKDB4NjEgPD0gYyA8PSAweDdBKQoKICBkZWYgd20oc2VsZiwgbXNnLCB3cCwgbHApOgogICAgaWYgc2VsZi53YWl0OiBzZWxmLnNsZWVwKHNlbGYud2FpdCkKICAgIGN0eXBlcy53aW5kbGwudXNlcjMyLlBvc3RNZXNzYWdlVyhzZWxmLmh3bmQsIG1zZywgd3AsIGxwKQoKICBkZWYgc3lza2V5ZChzZWxmLCB2ayk6CiAgICBzZWxmLndtKDI2MCwgdmssIDEgPDwgMjkpICMgV01fU1lTS0VZRE9XTiBscGFyYW0gPSBBbHQgZG93bgoKICBkZWYgc3lza2V5dShzZWxmLCB2ayk6CiAgICBzZWxmLndtKDI2MSwgdmssIDYgPDwgMjkpICMgV01fU1lTS0VZVVAgbHBhcmFtID0gQWx0IHVwCgogIGRlZiBzeXNrZXlkdShzZWxmLCB2ayk6CiAgICBzZWxmLndtKDI2MCwgdmssIDEgPDwgMjkpICMgV01fU1lTS0VZRE9XTiBscGFyYW0gKyBBbHQKICAgIGlmIHNlbGYuaXNhbG51bSh2ayk6IHNlbGYud20oMjYyLCB2aywgNyA8PCAyOSkgIyBXTV9TWVNDSEFSIGxwYXJhbSArIEFsdAogICAgc2VsZi53bSgyNjEsIHZrLCA3IDw8IDI5KSAjIFdNX1NZU0tFWVVQIGxwYXJhbSArIEFsdAoKICBkZWYgYWx0a2V5cyhzZWxmLCBzKToKICAgIHNlbGYuc3lza2V5ZCgxOCkgIyBBbHQgZG93bgogICAgZm9yIGMgaW4gczogc2VsZi5zeXNrZXlkdShvcmQoYykpCiAgICBzZWxmLnN5c2tleXUoMTgpICMgQWx0IHVwCgogIGRlZiBrZXlkdShzZWxmLCB2ayk6CiAgICBzZWxmLndtKDI1NiwgdmssIDApICMgV01fS0VZRE9XTgogICAgaWYgc2VsZi5pc2FsbnVtKHZrKTogc2VsZi53bSgyNTgsIHZrLCAwKSAjIFdNX0NIQVIKICAgIHNlbGYud20oMjU3LCB2aywgMCkgIyBXTV9LRVlVUAoKICBkZWYga2V5cyhzZWxmLCBzKToKICAgIGZvciBjIGluIHM6IHNlbGYua2V5ZHUob3JkKGMpKQoKICBkZWYgbW91c2VjbGsoc2VsZiwgYiwgeCwgeSwgZGJsPUZhbHNlKToKICAgIGxwID0geCArIHkgKiAyICoqIDE2CiAgICB3cCA9IDEgaWYgYiA9PSAwIGVsc2UgMiBpZiBiID09IDEgZWxzZSAxNgogICAgbyA9IDMgKiBiCiAgICBzZWxmLndtKDUxMyArIG8sIHdwLCBscCkgIyBXTV9MQlVUVE9ORE9XTgogICAgc2VsZi53bSg1MTQgKyBvLCB3cCwgbHApICMgV01fTEJVVFRPTlVQCiAgICBpZiBkYmw6IHNlbGYud20oNTE1ICsgbywgd3AsIGxwKSAjIFdNX0xCVVRUT05EQkxDTEsKCmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6CiAgdGFyZ2V0ID0gUG9zdFdpbk1zZy50YXJnZXQodSfnhKHpoYwgLSDjg6Hjg6LluLMnKQogIHB3bSA9IFBvc3RXaW5Nc2codGFyZ2V0LCB3YWl0PTEwMDAsIGZnPVRydWUpCiAgcHdtLmtleXMoJ3h5eiBhYmMnKQogIHB3bS5hbHRrZXlzKCdGUycp