def BatchRename(): foxitWindow = automation.WindowControl(searchDepth=1, ClassName='classFoxitReader') foxitWindow.ShowWindow(automation.ShowWindow.ShowMaximized) foxitWindow.SetActive() automation.Logger.Log(foxitWindow.Name[:-len(' - Foxit Reader')] + '\n') time.sleep(1) automation.SendKeys('{Ctrl}0') time.sleep(0.5) editToolBar = automation.ToolBarControl(searchFromControl=foxitWindow, AutomationId='59583', Name='Caption Bar') if editToolBar.Exists(0, 0): editToolBar.Click(0.96, 0.5) time.sleep(0.5) automation.SendKeys('{Alt}y') time.sleep(0.5) editToolBar = automation.ToolBarControl(searchFromControl=foxitWindow, AutomationId='60683', Name='Caption Bar') if editToolBar.Exists(0, 0): editToolBar.Click(0.96, 0.5) time.sleep(0.5) automation.SendKeys('{Alt}y') time.sleep(0.5) paneWindow = automation.WindowControl(searchFromControl=foxitWindow, AutomationId='65280') bookmarkPane = automation.PaneControl(searchFromControl=paneWindow, searchDepth=1, foundIndex=1) l, t, r, b = bookmarkPane.BoundingRectangle #bookmarkButton = automation.ButtonControl(searchFromControl= bookmarkPane, Name = '书签') # can't find, but automation -a can find it, why if bookmarkPane.Name == '书签': if r - l < 40: bookmarkButton = automation.ControlFromPoint(l + 10, t + 40) if bookmarkButton.Name == '书签': bookmarkButton.Click(simulateMove=False) else: bookmarkButton = automation.ControlFromPoint(l + 10, t + 40) if bookmarkButton.Name == '书签': bookmarkButton.Click(simulateMove=False) tree = automation.TreeControl(searchFromControl=foxitWindow, ClassName='SysTreeView32') childItems = tree.GetChildren() bookMarks = [] depth = 1 for treeItem in childItems: if treeItem.ControlType == automation.ControlType.TreeItemControl: RenameTreeItem(tree, treeItem, bookMarks, depth) fout = open('rename_pdf_bookmark.txt', 'wt', encoding='utf-8') depth = 1 for bookMark in bookMarks: DumpBookMark(fout, bookMark, depth) fout.close() if Renamed: automation.Logger.Log('rename pdf: ' + foxitWindow.Name) automation.SendKeys('{Ctrl}s') time.sleep(0.5) while '*' in foxitWindow.Name: time.sleep(0.5)
def RenameTreeItem(tree, treeItem, bookMarks, depth, removeChapter=True): treeItem.ScrollIntoView() if depth > TreeDepth: return name = treeItem.Name if not name.strip(): return newName = RenameFunction(name, removeChapter) if newName.startswith('Appendix'): removeChapter = False bookMark = BookMark(name, newName) bookMarks.append(bookMark) if newName != name: global Renamed Renamed = True time.sleep(0.1) treeItem.RightClick(simulateMove=False) # FoxitReader书签右键菜单(BCGPToolBar,非Windows菜单)弹出后,枚举不到菜单,但从屏幕点上ControlFromPoint能获取到菜单, todo # 采用特殊处理获取重命名菜单 time.sleep(0.2) x, y = automation.Win32API.GetCursorPos() menuItem = automation.ControlFromPoint(x + 2, y + 2) if menuItem.ControlType == automation.ControlType.MenuItemControl: #鼠标右下方弹出菜单 while not (menuItem.Name == '重命名(R)' or menuItem.Name == 'Rename'): y += 20 menuItem = automation.ControlFromPoint(x + 2, y) if menuItem.ControlType != automation.ControlType.MenuItemControl: break else: #鼠标右上方弹出菜单 menuItem = automation.ControlFromPoint(x + 2, y - 2) while not (menuItem.Name == '重命名(R)' or menuItem.Name == 'Rename'): y -= 20 menuItem = automation.ControlFromPoint(x + 2, y) if menuItem.ControlType != automation.ControlType.MenuItemControl: break if menuItem.ControlType != automation.ControlType.MenuItemControl: automation.Logger.Log('this pdf not support editing') exit(0) menuItem.Click(simulateMove=False) edit = automation.EditControl(searchFromControl=tree, searchDepth=1) edit.SetValue(newName) automation.SendKeys('{Enter}') automation.Logger.Write('rename: ') automation.Logger.WriteLine(name, automation.ConsoleColor.Green) automation.Logger.Write(' to: ') automation.Logger.WriteLine(newName, automation.ConsoleColor.Green) if depth + 1 > TreeDepth: return treeItem.Expand() childItems = treeItem.GetChildren() if childItems: treeItem.Expand() for child in childItems: RenameTreeItem(tree, child, bookMark.children, depth + 1, removeChapter)
def uia_info(dir, namePrefix): if os.path.exists(dir) == False: os.mkdir(os.getcwd() + dir) #当前鼠标的x y绝对坐标 x, y = auto.GetCursorPos() #当前操作控件 control = currentControl = auto.ControlFromPoint(x, y) docInfo = xml.dom.minidom.Document() currentControlNode = docInfo.createElement('Control') currentControlNode.setAttribute('Name', currentControl.Name) currentControlNode.setAttribute('Type', currentControl.ControlTypeName) currentControlNode.setAttribute('ClassName', currentControl.ClassName) currentControlNode.setAttribute('AutomationId', currentControl.AutomationId) controlRect = currentControl.BoundingRectangle currentControlNode.setAttribute('RectLeft', str(controlRect.left)) currentControlNode.setAttribute('RectTop', str(controlRect.top)) currentControlNode.setAttribute('RectRight', str(controlRect.right)) currentControlNode.setAttribute('RectBottom', str(controlRect.bottom)) docInfo.appendChild(currentControlNode) fpInfo = open(dir + namePrefix + "-Info.xml", 'w') docInfo.writexml(fpInfo, encoding="utf-8") fpInfo.close() docXML = xml.dom.minidom.Document() root = docXML.createElement('Controlpath') docXML.appendChild(root) parents = [] #找父节点 while control: parents.insert(0, control) control = control.GetParentControl() i = 0 for c in parents: node = docXML.createElement('Control') node.setAttribute('Depth', str(i)) node.setAttribute('Name', c.Name) node.setAttribute('Type', c.ControlTypeName) node.setAttribute('Classname', c.ClassName) node.setAttribute('AutomationId', c.AutomationId) root.appendChild(node) i += 1 fpXML = open(dir + namePrefix + "-XML.xml", 'w') docXML.writexml(fpXML, encoding="utf-8") fpXML.close()
def doStep(taskName, instanceCount=0, run_mode=False): time.sleep(1) global app global dc # global run_mode # Load Action-Object Data ACTION_OBJECT_DB_FILE = './action_object_db/action_object_db.csv' with open(ACTION_OBJECT_DB_FILE, newline='') as csvfile: action_object_data = list(csv.reader(csvfile, delimiter=',')) # print(action_object_data) # while True: # command = getCommand('What is the name of your task?') command = taskName.lower() doc = nlp(command) token_text = [token.text for token in doc] # ['This', 'is', 'a', 'text'] print(token_text) token_pos = [token.pos_ for token in doc] # ['VERB', 'DET', 'NOUN', 'PUNCT'] print(token_pos) token_dep = [token.dep_ for token in doc] # ['ROOT', 'det', 'dobj', 'punct'] print(token_dep) # if commandReceived == "switch to voice": # prompt('Switching to voice mode') # manual_mode = False # if commandReceived == "switch to manual mode": # prompt('Switching to manual mode') # manual_mode = True if command == "switch to instruction mode": prompt('Entering instruction mode...') run_mode = False instructionMode() return '', '', 0 elif command == "help": prompt( "\n\nYou can say:\nswitch to instruction mode\nwhat is this\nhelp\nexit, shut up, shutdown, goodbye, stop it\nshow instruction list\n\n\nopen a/the/my***\nclick on/the/a\nclick on it\ngo to ***\n\n" ) return '', '', 0 # if commandReceived == "listen": # commandReceived = getCommand("What do you want me to do?") # doStep(commandReceived, 0, False) elif command == "show instruction list": instructionList = os.listdir(INSTRUCTIONS_FOLDER) print('\n\nInstruction List') print('======================') for instructionIndex, taskName in enumerate(instructionList): santizedTaskName = taskName.replace('_', ' ').replace('.csv', '') print(santizedTaskName) print('\n\n') return '', '', 0 # if commandReceived == "do this": # commandReceived = getCommand("What is the name of the task?") # prompt('Finding instructions from memory...') # runInstructions(commandReceived) elif command == "what is this": currentMouseX, currentMouseY = auto.GetCursorPos() control = auto.ControlFromPoint(currentMouseX, currentMouseY) for c, d in auto.WalkControl(control, True, 1000): print(c.ControlTypeName, c.ClassName, c.AutomationId, c.BoundingRectangle, c.Name, '0x{0:X}({0})'.format(c.NativeWindowHandle)) return '', '', 0 elif command == "exit" or command == "shut up" or command == "shutdown" or command == "goodbye" or command == "stop it": prompt('Thank you for using virtual employee. Goodbye.') sys.exit() if len(token_text) > 0: verbid = -1 dobjid = -1 first_word = token_text[0].lower().strip() # override behavior during TYPE command: # if first_word == 'type' for textid, text in enumerate(token_text): if (token_pos[textid] == 'VERB' and (token_dep[textid] == 'ROOT' or token_dep[textid] == 'amod')) or (token_pos[textid] == 'ADJ' and token_dep[textid] == 'amod'): verbid = textid if token_dep[textid] == 'dobj' or token_dep[textid] == 'pobj' or ( token_pos[textid] == 'NOUN' and token_dep[textid] == 'ROOT' ) or (token_pos[textid] == 'NOUN' and token_dep[textid] == 'advcl') or (token_pos[textid] == 'VERB' and token_dep[textid] == 'advcl') or ( token_pos[textid] == 'VERB' and token_dep[textid] == 'advmod') or ( token_pos[textid] == 'VERB' and token_dep[textid] == 'xcomp' ) or (token_pos[textid] == 'VERB' and token_dep[textid] == 'pcomp'): dobjid = textid if verbid == -1: prompt( 'There is no action in your instruction step. Please start with a verb.' ) else: if dobjid == -1: prompt( 'There is no object to act on. Please state a recipient of the action.' ) else: action_from_command = str(token_text[verbid].lower().strip()) object_from_command = str(token_text[dobjid].lower().strip()) # prompt('Instruction valid.') objectInstanceCount = 1 # Counts how many times it should match before selecting the right control # Look for built-in actions first for action, dobject, subprocess_command, requirement in action_object_data: # print('token_text[verbid]',token_text[verbid]) # print('action',action) # print('token_text[dobjid]', token_text[dobjid]) # print('dobject', dobject) # print('token_text[verbid] == action', token_text[verbid] == action) # print('token_text[dobjid] == dobject', token_text[dobjid] == dobject) action_from_db = str(action.lower().strip()) object_from_db = str(dobject.lower().strip()) if action_from_command == action_from_db and object_from_command == object_from_db: # prompt('Instruction found. [' + subprocess_command + ']') if action_from_command == 'open': # print(subprocess_command) subprocess.Popen(subprocess_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) time.sleep(2) control = auto.GetRootControl() # Get Target Window detectControls = ['WindowControl', 'PaneControl'] for c, d in auto.WalkControl(control, True, 1000): if c.ControlTypeName in detectControls: # print(c.ControlTypeName, c.ClassName, c.AutomationId, c.BoundingRectangle, c.Name, '0x{0:X}({0})'.format(c.NativeWindowHandle)) if object_from_db.lower() in c.Name.lower( ): dc.Clear() dc.SetPen(wx.Pen("blue")) dc.SetBrush( wx.Brush("blue", wx.TRANSPARENT)) ControlBoundingRect = c.BoundingRectangle # TODO: calculate dynamic width/height based on screensize using wx at header xScale = 1 #1.25 yScale = 1 #1.25 width = ( ControlBoundingRect.right * xScale ) - (ControlBoundingRect.left * xScale) height = ( ControlBoundingRect.bottom * yScale ) - (ControlBoundingRect.top * yScale) dc.DrawRectangle( (ControlBoundingRect.left * xScale), (ControlBoundingRect.top * yScale), width, height) break control = getActiveWindowControls() # Then process all other commands here if action_from_command == 'go': prompt(action_from_command + ' to ' + object_from_command) control = getActiveWindowControls() # Get controls of the target window # detectControls = ['TextControl', 'ButtonControl', 'EditControl'] possibleControlMatch = [] if object_from_command == 'dropdown': possibleControlMatch = ['▾'] detectControls = [ 'HyperlinkControl', 'EditControl', 'ButtonControl', 'ComboBoxControl', 'ListItemControl', 'ListControl', 'TextControl' ] for c, d in auto.WalkControl(control, True, 1000): # print(c.ControlTypeName, c.ClassName, c.AutomationId, c.BoundingRectangle, c.Name, '0x{0:X}({0})'.format(c.NativeWindowHandle)) if object_from_command in c.Name.lower().strip( ) or object_from_command in possibleControlMatch: if c.ControlTypeName in detectControls: # if object_from_db.lower() in c.Name.lower(): dc.Clear() dc.SetPen(wx.Pen("green")) dc.SetBrush(wx.Brush("green", wx.TRANSPARENT)) ControlBoundingRect = c.BoundingRectangle xScale = 1 #1.25 yScale = 1 #1.25 width = (ControlBoundingRect.right * xScale) - (ControlBoundingRect.left * xScale) height = (ControlBoundingRect.bottom * yScale) - (ControlBoundingRect.top * yScale) dc.DrawRectangle( (ControlBoundingRect.left * xScale), (ControlBoundingRect.top * yScale), width, height) controlCenterX = int(ControlBoundingRect.left + (width / 2)) controlCenterY = int(ControlBoundingRect.top + (height / 2)) auto.SetCursorPos(controlCenterX, controlCenterY) if run_mode == False: # confirmAction = getCommand('This one?') commandReceived = '' commandReceived = getCommand("This one?") while commandReceived == '': # print('waiting...') continue print('commandReceived', commandReceived) if commandReceived in yesConfirmations: break else: objectInstanceCount += 1 continue else: if int(objectInstanceCount) == int( instanceCount): break else: objectInstanceCount += 1 continue elif action_from_command == 'click': # prompt(action_from_command + ' on ' + object_from_command) if object_from_command == 'it': currentMouseX, currentMouseY = auto.GetCursorPos() auto.Click(currentMouseX, currentMouseY) else: control = getActiveWindowControls() # Get controls of the target window # detectControls = ['TextControl', 'ButtonControl', 'EditControl'] detectControls = [ 'HyperlinkControl', 'EditControl', 'ButtonControl', 'ComboBoxControl', 'ListItemControl', 'ListControl', 'TextControl' ] for c, d in auto.WalkControl(control, True, 1000): if object_from_command in c.Name.lower().strip(): # print(c.ControlTypeName, c.ClassName, c.AutomationId, c.BoundingRectangle, c.Name, '0x{0:X}({0})'.format(c.NativeWindowHandle)) # if c.ControlTypeName in detectControls: # if object_from_db.lower() in c.Name.lower(): dc.Clear() dc.SetPen(wx.Pen("green")) dc.SetBrush(wx.Brush("green", wx.TRANSPARENT)) ControlBoundingRect = c.BoundingRectangle xScale = 1 #1.25 yScale = 1 #1.25 width = (ControlBoundingRect.right * xScale) - (ControlBoundingRect.left * xScale) height = (ControlBoundingRect.bottom * yScale) - (ControlBoundingRect.top * yScale) dc.DrawRectangle( (ControlBoundingRect.left * xScale), (ControlBoundingRect.top * yScale), width, height) controlCenterX = int(ControlBoundingRect.left + (width / 2)) controlCenterY = int(ControlBoundingRect.top + (height / 2)) auto.SetCursorPos(controlCenterX, controlCenterY) if run_mode == False: commandReceived = getCommand('This one?') if commandReceived in yesConfirmations: auto.Click(controlCenterX, controlCenterY) break else: objectInstanceCount += 1 continue else: print('objectInstanceCount', objectInstanceCount) print('instanceCount', instanceCount) if int(objectInstanceCount) == int( instanceCount): print('It goes here 3') # auto.Click(controlCenterX, controlCenterY) currentMouseX, currentMouseY = auto.GetCursorPos( ) auto.Click(currentMouseX, currentMouseY) # time.sleep(2) break else: print('It goes here 2') objectInstanceCount += 1 continue return action_from_command, object_from_command, objectInstanceCount return '', '', 0
def RenameTreeItem(tree, treeItem, bookMarks, depth, removeChapter=True): treeItem.ScrollIntoView() if depth > TreeDepth: return name = treeItem.Name if not name.strip(): return newName, alert = RenameFunction(name, removeChapter) if newName.startswith('Appendix'): removeChapter = False bookMark = BookMark(name, newName) bookMarks.append(bookMark) if newName != name and depth not in TreeSkipDepthList: global Renamed Renamed = True time.sleep(0.1) find = False for i in range(3): treeItem.RightClick(simulateMove=False, waitTime=0.2) # FoxitReader书签右键菜单(BCGPToolBar,非Windows菜单)弹出后,枚举不到菜单,但从屏幕点上ControlFromPoint能获取到菜单, todo # 采用特殊处理获取重命名菜单 x, y = automation.Win32API.GetCursorPos() menuItem = automation.ControlFromPoint(x + 2, y + 2) if isinstance(menuItem, automation.MenuItemControl): #鼠标右下方弹出菜单 while 1: if menuItem.Name == '重命名(R)' or menuItem.Name == 'Rename': find = True break y += 20 menuItem = automation.ControlFromPoint(x + 2, y) if not isinstance(menuItem, automation.MenuItemControl): break else: #鼠标右上方弹出菜单 menuItem = automation.ControlFromPoint(x + 2, y - 2) while 1: if menuItem.Name == '重命名(R)' or menuItem.Name == 'Rename': find = True break y -= 20 menuItem = automation.ControlFromPoint(x + 2, y) if not isinstance(menuItem, automation.MenuItemControl): break if find: break else: automation.SendKeys('{Esc}') time.sleep(0.5) if not find: automation.Logger.Log('this pdf not support editing') exit(0) menuItem.Click(simulateMove=False, waitTime=0.2) edit = automation.EditControl(searchFromControl=tree, searchDepth=1) edit.SetValue(newName, waitTime=0.05) automation.SendKeys('{Enter}', waitTime=0.05) automation.Logger.Write('rename: ') automation.Logger.WriteLine(name, automation.ConsoleColor.Green) automation.Logger.Write(' @@to : ' if alert else ' to: ') automation.Logger.WriteLine( newName, automation.ConsoleColor.Yellow if alert else automation.ConsoleColor.Green) if depth + 1 > TreeDepth: return if automation.ExpandCollapseState.Collapsed == treeItem.CurrentExpandCollapseState( ): treeItem.Expand(0.1) childItems = treeItem.GetChildren() if childItems: for child in childItems: RenameTreeItem(tree, child, bookMark.children, depth + 1, removeChapter)