由于 Typora 软件是多进程,并且使用工具 Pywinauto 查看其 control_type 是 Pane,不能像网上介绍的 notepad 的样例那样去使用,因此这里使用工具 PyAutoGUI,根据界面屏幕坐标去操作 Typora 软件。
由于这类控件没有 API 方法,因此只能通过 print_control_identifiers() 方法打印出控件的屏幕坐标信息,通过从控制台获取打印的信息,并进行处理得到控件的坐标信息,通过坐标值来操作此类控件,具体实现可以看下面的代码:
# 获取控制台打印的内容
class TextArea(object):
def __init__(self):
self.buffer = []
def write(self, *args, **kwargs):
self.buffer.append(args)
# 获取应用程序Typora指定标识符的屏幕坐标
def GetAppIdentifierPos(app, identifier):
# 获取控件信息
stdout = sys.stdout
sys.stdout = TextArea()
app["Typora"].print_control_identifiers()
text_area, sys.stdout = sys.stdout, stdout
# 搜索标识符的屏幕坐标
for tup in text_area.buffer:
i = tup[0].find(identifier)
if i > -1:
# 用于存控件的坐标
locate = []
starti = i + len(identifier)
startj = tup[0].find('(', starti, -1) + 1
endj = tup[0].find(')', starti, -1)
grid = tup[0][startj:endj].split(',')
for gridi in grid:
gridj = gridi.strip()
gridk = int(gridj[1:])
locate.append(gridk)
return [(locate[0]+locate[2])/2, (locate[1]+locate[3])/2]
return [0, 0]
如果手动输入屏幕坐标,则可以参照 https://blog.csdn.net/he_nan/article/details/106108344 。
本文在转换前,首先用工具 Pyautogui 自动获取各个控件的屏幕坐标,然后再转换所有的 Markdown 文件,Python 脚本实现如下:
# 退出Typora软件
def QuitTypora(quitAppCoor):
time.sleep(2)
pyautogui.hotkey('ctrl', 'w')
time.sleep(2)
pyautogui.click(quitAppCoor[0], quitAppCoor[1])
time.sleep(5)
# 将指定目录下的单个md文件转换为html文件
def ConvertMdToHtml(typoraApp, inFileCoor, fileMenuCoor, exportCoor, htmlCoor, outFileCoor, quitAppCoor, mdFile):
# 打开Typora应用程序
app = pywinauto.application.Application(backend="uia").start(typoraApp)
time.sleep(5)
# 打开md文件
pyautogui.hotkey('ctrl', 'o')
time.sleep(2)
pyautogui.click(inFileCoor[0], inFileCoor[1])
pyautogui.typewrite(mdFile)
pyautogui.press('enter', presses=1, interval=0.5)
time.sleep(1)
# 导出html
pyautogui.click(fileMenuCoor[0], fileMenuCoor[1])
time.sleep(1)
pyautogui.click(exportCoor[0], exportCoor[1])
time.sleep(1)
pyautogui.click(htmlCoor[0], htmlCoor[1])
time.sleep(2)
pyautogui.click(outFileCoor[0], outFileCoor[1])
pyautogui.hotkey('ctrl', 'a')
pyautogui.typewrite(mdFile[:-2] + FileFormat.HtmlFileSuffix())
pyautogui.press('enter', presses=1, interval=0.5)
time.sleep(1)
pyautogui.press('left', presses=1, interval=0.1)
pyautogui.press('enter', presses=1, interval=0.5)
# 关闭Typora
QuitTypora(quitAppCoor)
# 将指定目录下的所有md文件转换为html文件
def ConvertAllMdToHtml(typoraApp, mdFilesDir):
# 退出Typora时“放弃”修改按钮的屏幕坐标
app = pywinauto.application.Application(backend="uia").start(typoraApp)
time.sleep(5)
pyautogui.typewrite("Typora")
time.sleep(1)
pyautogui.hotkey('ctrl', 'w')
time.sleep(2)
quitAppCoor = GetAppIdentifierPos(app, u"Button - '丢弃'")
pyautogui.click(quitAppCoor[0], quitAppCoor[1])
time.sleep(5)
# 打开文件时输入框的屏幕坐标
app = pywinauto.application.Application(backend="uia").start(typoraApp)
time.sleep(5)
pyautogui.typewrite("Typora")
time.sleep(1)
pyautogui.hotkey('ctrl', 'o')
time.sleep(2)
inFileCoor = GetAppIdentifierPos(app, u"ComboBox - '文件名(N):'")
pyautogui.press('esc', presses=1, interval=0.5)
QuitTypora(quitAppCoor)
# 导出文件时导航菜单及输入框的屏幕坐标
app = pywinauto.application.Application(backend="uia").start(typoraApp)
time.sleep(5)
pyautogui.typewrite("Typora")
time.sleep(1)
fileMenuCoor = GetAppIdentifierPos(app, u"MenuItem - '文件(F)'")
pyautogui.click(fileMenuCoor[0], fileMenuCoor[1])
time.sleep(1)
exportCoor = GetAppIdentifierPos(app, u"MenuItem - '导出'")
pyautogui.click(exportCoor[0], exportCoor[1])
time.sleep(1)
htmlCoor = GetAppIdentifierPos(app, u"MenuItem - 'HTML'")
pyautogui.click(htmlCoor[0], htmlCoor[1])
time.sleep(2)
outFileCoor = GetAppIdentifierPos(app, u"ComboBox - '文件名:'")
pyautogui.press('esc', presses=1, interval=0.5)
QuitTypora(quitAppCoor)
# 筛选指定目录下的文件
for root, dirs, files in os.walk(mdFilesDir):
for name in files:
if FileFormat.IsMdFile(name):
mdFile = os.path.join(root, name)
ConvertMdToHtml(typoraApp, inFileCoor, fileMenuCoor, exportCoor, htmlCoor, outFileCoor, quitAppCoor, mdFile)
全部的完整脚本,见附件。
脚本放在与 Document
同级的目录下,直接执行 Markdown2Html.py
即可。