At the Beginning...
由於近期愛好摸魚,並且對Gui開發萌生一絲興趣。在嘗試WPF被虐,使用Qt卻不太喜歡整套龐大的框架后……
I choose E language!
重拾了小學用的工具……
據我所知,易語言的Gui除了native E之外,主要是Ex_Ui和ExDui兩家,而Ex_Ui由於高度封裝,相對效率低一些,而逼格可能不如ExDui。
並且ExDui似乎有多語言支持,通用性更好。
於是選擇了EXDUI,開始學習……
Install
安裝的話,去官方論壇下載即可,提供了2個模塊,大概是封裝了dll函數。
核心應該是Lib_ExDui_Helper。
推薦加入官方群,有一些資源以后或許會用到。
Coding
使用_啟動子程序
的方式進行啟動,使用黑月3.6.6進行編譯,運行易語言核心庫。
在群內下載了窗口創建Demo,開始看源碼學習……(官方包中也有帶Demo)。
發現必須使用主題包,而官方文檔顯示ThemeMaker仍在開發中,對主題包如何制作實在是疑惑。后在群文件中發現了主題打包器。
這里直接使用Demo中自帶的default主題。
LoadTheme
主題包可以作為獨立外置文件,也可以作為res資源文件內嵌在程序中。這里使用外置的寫法,將主題包default.ext
放在同目錄下,寫代碼:
Bin(即字節集) Theme = ReadFile("default.ext");
由於不了解主題變量調用機制,聲明為全局變量。
InitEngine
初始化ExDui引擎,查官方文檔查到:
bool __stdcall
Ex_Init (
HINSTANCE hInstance,
DWORD dwGlobalFlags,
HCURSOR hDefaultCursor,
LPCTSTR lpszDefaultClassName,
LPVOID lpDefaultTheme,
DWORD dwDefaultThemeLen,
LPVOID lpDefaultI18N,
DWORD dwDefaultI18NLen
);
hInstance
Type: HINSTANCE
動態庫(DLL)的實例句柄 可為NULL
dwGlobalFlags
Type: DWORD
全局初始化標識 參見 EXGF
hDefaultCursor
Type: HCURSOR
默認鼠標指針句柄 可為NULL
lpszDefaultClassName
Type: LPCTSTR
默認窗口類名 可為NULL
lpDefaultTheme
Type: LPVOID
默認主題包指針
dwDefaultThemeLen
Type: DWORD
默認主題包緩沖區長度
lpDefaultI18N
Type: LPVOID
默認語言包指針
dwDefaultI18NLen
Type: DWORD
默認語言包指針緩沖區長度
Return Value / 返回值
Type: BOOL
初始化引擎
令我比較迷茫的是第一個參數,動態庫的實例句柄,發現Demo中使用了GetModuleHandleW
的API,查了查MSDN,得知是以名稱獲取模塊句柄的API。
Demo中如此使用:
GetModuleHandleW(0);
參數為0(其實應該是代表NULL)時返回調用者模塊的句柄。
易語言Dll聲明如下:
第二個參數是初始化標識,查到官方文檔:
Click
注意的是,如果有多個標識符,使用或運算
來合並。
第三個第四個參數無特殊需要直接為0即可,默認主題包指針則傳入theme
變量的地址。
對易語言中取得地址的操作有些疑問,發現YHan.Helper已經封裝了相關函數,使用了機器碼……
主題包長度則直接取字節集長度即可。
不使用語言包,后兩個參數也寫NULL。
Init返回True的話,就是初始化成功了。
Make My Window
Set Properties
隨后想想設置窗口的屬性。
標題等設置似乎都要提供指針,因此YHanHelper的確是至關重要啊……
發現Demo中使用了A2W函數,Google查后發現是轉寬字符的函數,大概是為了支持中文。
A2W, Ansi to w_char?僅個人猜測。
這個函數我也不熟悉。
聲明字節集型的變量,作為Title和ClassName:
Bin Title = A2W("Hello,ExDui!"),ClassName = A2W("Demo");
Register ClassName
隨后需要注冊窗口類名,這個原因同樣令我疑惑,上網查到了一位網友的回答:
關於窗口類
每一個窗口對應一個窗口過程,而該窗口過程是被所有使用這個窗口類的窗口所共享的。每一個進程在要創建窗口之前,必須要先注冊改窗口所屬的窗口類。注冊窗口類就是將窗口過程,窗口風格以及其他窗口屬性用一個類名相關連起來。當進程在CreateWindow, CreateWindowEx中使用窗口類名時,所創建的窗口屬性就和窗口類中的各屬性相聯系了。
大概可以理解為注冊窗口類模板,而顯示的窗口是實例。感性理解一下,具體我也並不明白,或有理解錯誤。
使用此API:Click
如果圖標、鼠標等不打算特殊設置大概都可以寫NULL?
Create Window
注冊好窗口類名之后,可以用該類名來創建一個窗口實例。
應該調用的是Windows API,封裝在ExDui的lib中了,返回Windows窗口句柄。
ExDui的文檔:Click
用整數型保存下來。
隨后使用ExDui引擎托管窗口,使用API:
int Ex_DuiBindWindowEx(int hWnd,int hTheme,int dwStyle,int lParam,int lpfnMsgProc);
//Ex_DuiBindWindow(int hWnd,int hTheme,int dwStyle);
這個API在官方的文檔中查不到,應該是文檔還不完善,看起來dwStyle的參數跟上面的windows API重復了,Demo中是直接使用這個函數設置的dwStyle,猜測應該是ExDui會自行實現dwStyle。
lParam用途為止,寫NULL。
lpfnMsgProc是綁定消息循環的函數地址用的,先聲明一個空子程序,到整數轉成整數型綁上去。
常量是一樣的。
返回引擎句柄,也用整數型保存。
用這個句柄可以訪問引擎,比如Ex_DuiGetLong
之類的看起來像是訪問成員變量的API等。
我們給窗口設置一個背景顏色:
Ex_DUISetLong (m_hExDui, #EWL_CRBKG, RGB2ARGB (rgb (42, 41, 49), 250))
MsgProc
消息循環類似於這樣:
while(true)
MsgProc();
也就是說,會一直占用線程直到窗口被關閉。
消息循環應該也是Windows API中的,ExDui要求的函數如下:
其實返回值的用處我還沒查清楚,以后再測測吧。
Final
寫完之后,按下F5,一個窗口就出現了!
程序體積方面,用了黑月匯編模式編譯僅14kb,而ExDui的dll 700kb,體積還是比較小巧的。