Python 和 MFC 中的一个皮肤化对话框
帮助您轻松地使用 Python、XML 和 UI 窗口 DLL 制作带皮肤的对话框程序。
引言
通过遵循 MVC,您可以创建漂亮的带皮肤的 UI,并非常轻松地用 Python 编写程序的逻辑部分。
背景
当我第一次想到这个程序时,我使用了 python 中的 tkinter。但是,使用 tkinter 很难创建一个漂亮的窗口。使用 tkinter 更像是使用 Java 中的 Swing。当时,我对 Python 不是很熟悉。所以我决定做一个 MFC 带皮肤的 UI,它可以与 python 通信。这几乎是 7 年前的事了。在制作了一个小型应用程序后,我将代码留在我的硬盘上。最近,我一直在使用 dropbox,我意识到 dropbox 是用 python 制作的。dropbox 让我想起了这段代码。所以我把它发布在 CodeProject 上。我不确定它是否可以帮助像我一样思考的其他人,但我希望如此。
使用代码
该程序由三个部分组成:用于皮肤的 XML 脚本、用于实际执行程序的 Python 脚本,以及用于创建带皮肤的对话框并将用户操作传递给 Python 脚本的 MFC DLL。
- 用于皮肤的 XML 脚本
- Python 脚本
- MFC 模块的 API 描述
CWebpage
: web control referenced: https://codeproject.org.cn/KB/COM/cwebpage.aspx?msg=2804355- Expat: XML parser library: http://expat.sourceforge.net/
<?xml version="1.0"?>
<brandnewui>
<info>
information about this skin...
</info>
<resource>
<bitmap id="bmp" file="HelloWorld.bmp"/>
resources...
<icon id="icon" file="HelloWorld.ico"/>
</resource>
<window id="hello" type="cwnd">
<position x="150" y="150" width="292" height="171"/>
<bgcolor color="0x00000"/>
<icon id="icon"/>
<region/>
<alwaystop/>
<magnetic/>
<opacity value="80"/>
<move x="0" y="0" width="292" height="25"/>
actuall control's position and properties...
<emcontrol id="bg" type="pic">
<position x="0" y="0" width="292" height="171"/>
<background id="bmp"/>
<region/>
</emcontrol>
<emcontrol id="hello" type="static">
<position x="40" y="60" width="144" height="37"/>
<background id="bmp_bg"/>
<bgcolor value="ECE9D8"/>
<textcolor value="000000"/>
<font type="system" size="30" align="right" bold="true"/>
<text value="Hello World"/>
</emcontrol>
</window>
</brandnewui>
XML 皮肤是直观的,不需要描述。您应该记住的是窗口标签和窗口 ID。因为 Python 脚本将使用 ID 属性作为窗口的标识符向窗口发送消息。
## import modules
import win32api, win32con, win32gui
import win32ui
import win32con
import string
from ctypes import *
from BrandNewUI import *
## Skin Window Message Procedure
def SkinWndProc(str):
operator = string.split(str.value,"/")
## pressed off
if operator[0] == "btn_close":
HelloWorld.SendSkinMessage("wndmgr","cls","hello")
HelloWorld.FinalSkin()
EndPumpMessage()
pass
HelloWorld = CBrandNewUI(".\\BrandNewUI.dll",".\\HelloWorld\\HelloWorld.xml")
HelloWorld.LoadModule()
HelloWorld.InitSkin()
HelloWorld.SetAppHwnd()
HelloWorld.GetSkinMessage()
HelloWorld.SendSkinMessage("wndmgr","opn","hello")
HelloWorld.SetSkinProc(SkinWndProc)
StartPumpMessage()
LoadModule
用于加载 MFC DLL。InitSkin
用于读取 XML 皮肤文件并解析该文件。SetAppHwnd
用于 Python 窗口和 MFC 窗口之间的通信。它们应该互相知道才能发送消息。SendSkinMessage
用于向 MFC DLL 模块发送消息。在本例中,wndmgr
是“窗口管理器”的缩写。它是一个命令,用于打开 ("opn
") 一个窗口 ("hello
"),该窗口应与 XML 中窗口管理器中的窗口相同。与 opn
相反的是 cls
("close
")。
该模块与 python 创建的窗口通信。它通过窗口 SendMessage
以及 CString
指针发送消息。Python 脚本将接收字符串消息并解析该字符串。API 中的函数包括
_Initialize _Finalize _SendSkinMessage _SetAppHWND _GetSkinMessage _GetLastRespond _GetLastError _GetSkinInfo _UnzipSkinFile
这些函数是 Python 脚本的 API。Python 脚本可以使用 win32api
、win32con
、win32gui
调用这些 API。请参阅 BrandNewUI.py(这是一个陈词滥调的名字 :-() 文件,该文件显示了如何加载窗口 DLL 并调用它。我还使用了这些外部代码
兴趣点
使用 py2exe 制作一个包
您可以使用 py2exe 创建一个 exe 文件。首先,您必须准备如下脚本
# setup.py
from distutils.core import setup
import py2exe
setup(windows=["Calculator.py"])
创建脚本后,在控制台中运行“python setup.py py2exe”。然后将 DLL 和您的皮肤文件夹复制到您在运行“py2exe”时创建的“dist”文件夹中。这些是作为独立程序运行所必需的:libexpat.dll、mfc71.dll、msvcp71.dll、msvcr71.dll。最后,您可以在 dist 文件夹中启动一个独立的 exe 文件。这是 py2exe 站点链接:http://www.py2exe.org/index.cgi/Tutorial。
将 c 字符串消息发送到 python
ctypes 模块可以帮助我轻松地将 CSstring 指针类型转换为 Python 字符串。
//MFC msg string is like this
m_strAppMessage.Format("%s/%s/%s/%d", lpszID , lpszAction , lpszValue , nUnitID );
//MFC
::SendMessage(python windows hwnd, wparam as a pointer of string message,
lparam as a pointer of id string.);
//PYTHON
python_string = c_char_p(string)
//PYTHON
msg = string.split(python_string,"/")
更多详细信息:https://docs.pythonlang.cn/library/ctypes.html。
历史
- 1.0:首次上传。