用java创建窗口程序,创建窗口的应用程序
創(chuàng)建窗口的應(yīng)用程序
通過前面的基礎(chǔ)知識(shí)的學(xué)習(xí),已經(jīng)對(duì)ctypes庫(kù)的基本功能學(xué)會(huì)了使用,為了加強(qiáng)這種知識(shí)訓(xùn)練,以及運(yùn)用剛學(xué)習(xí)的知識(shí)的快樂,我們來創(chuàng)建一個(gè)稍稍復(fù)雜一點(diǎn)的應(yīng)用程序。這個(gè)應(yīng)用程序是所有后面應(yīng)用程序的基礎(chǔ),只有學(xué)會(huì)這個(gè)程序的基本原理,才可以更進(jìn)一步學(xué)習(xí)WIN32的API程序開發(fā)。更何況后面所有程序都會(huì)在這個(gè)程序上修改而成,這個(gè)就相當(dāng)你的爬向高樓頂層的第一個(gè)臺(tái)階。在所有工程技術(shù)里,都會(huì)從一個(gè)小小的演示程序開始,逐漸地增加功能,慢慢地變成一個(gè)強(qiáng)大的應(yīng)用程序。如果發(fā)現(xiàn)這些API函數(shù)不清楚,可以參考我寫的另外一本書《Windows API一日一練》,在那本書里有完整的介紹和例子,不過這些例子使用C++來編寫的。
下面就來開始瀏覽整個(gè)程序的功能吧,第一步是先把ctypes庫(kù)導(dǎo)入,這樣才可以使用它的功能,并且還導(dǎo)入ctypes.wintypes,它有對(duì)應(yīng)WIN32的類型,這樣使用起來更方便,比如消息結(jié)構(gòu)MSG。這段代碼如下:
#windows應(yīng)用程序
from ctypes import *
from ctypes.wintypes import *
接著下來定義一個(gè)Windows的窗口回調(diào)函數(shù)的原型,因?yàn)閃indows指定了每個(gè)窗口都需要有一個(gè)窗口消息函數(shù)來處理窗口所有發(fā)生的事件消息,這樣你寫的應(yīng)用程序才有機(jī)會(huì)去響應(yīng)窗口所發(fā)生的事件或操作。這行代碼如下:
WNDPROCTYPE = WINFUNCTYPE(c_int, HWND, c_uint, WPARAM, LPARAM)
由于WIN32的定義常量全部是在C語言的頭文件里定義,要想在Python中直接使用是不行的。目前只有兩種方法,一個(gè)是使用一個(gè)轉(zhuǎn)換程序,把所有SDK里提供的頭文件進(jìn)行轉(zhuǎn)換為Python定義的形式的模塊文件;另外一個(gè)就是自己使用到那些,就定義那些常量。本例子里,采用的是最后一種方法,使用到那些就定義就定義那些常量,這樣做是為了這個(gè)例子保持簡(jiǎn)單,這些常量定義如下:
WS_EX_APPWINDOW = 0x40000
WS_OVERLAPPEDWINDOW = 0xcf0000
WS_CAPTION = 0xc00000
SW_SHOWNORMAL = 1
SW_SHOW = 5
CS_HREDRAW = 2
CS_VREDRAW = 1
CW_USEDEFAULT = 0x80000000
WM_DESTROY = 2
WHITE_BRUSH = 0
在這些常量主要是窗口的格式、樣式、以及顯示方式,還有一個(gè)消息定義和畫筆。由于每個(gè)新創(chuàng)建的窗口都需要在Windows里注冊(cè)唯一的名稱,以便創(chuàng)建時(shí)從系統(tǒng)內(nèi)存里找到相應(yīng)的窗口類,所有其它窗口可以以這個(gè)窗口為基本模板,復(fù)制N個(gè)相同的出來。每個(gè)窗口還有一個(gè)主題名稱,又叫做窗口名稱,這兩個(gè)定義常量如下:
#窗口類的名稱
wclassName = u'ShenzhenCai'
wname = u'Hello World'
第一個(gè)常量窗口類名稱,第二個(gè)常量是窗口顯示的標(biāo)題。
窗口的格式、樣式通過定義一個(gè)結(jié)構(gòu)的方式傳遞給WIN32的API函數(shù),在這里定義窗口類的結(jié)構(gòu)體如下:
#定義窗口類結(jié)構(gòu)
class WNDCLASSEX(Structure):
_fields_ = [("cbSize", c_uint),
("style", c_uint),
("lpfnWndProc", WNDPROCTYPE),
("cbClsExtra", c_int),
("cbWndExtra", c_int),
("hInstance", HANDLE),
("hIcon", HANDLE),
("hCursor", HANDLE),
("hBrush", HANDLE),
("lpszMenuName", LPCWSTR),
("lpszClassName", LPCWSTR),
("hIconSm", HANDLE)]
這個(gè)窗口類的結(jié)構(gòu)體與C語言里描述的結(jié)構(gòu)體是一樣的,通過這樣定義,就可以給窗口說明窗口的類型了。具體每項(xiàng)的值,請(qǐng)參考《Windows API一日一練》。接著下來,查看窗口回調(diào)函數(shù),這里定義了處理窗口收到消息。主要處理了當(dāng)窗口關(guān)閉(WM_DESTROY)時(shí)就退出程序。調(diào)用API函數(shù)PostQuitMessage發(fā)送消息給主程序循環(huán),需要結(jié)束應(yīng)用程序了。其它的消息都是調(diào)用API函數(shù)DefWindowProcW來做默認(rèn)的處理。
#窗口消息處理回調(diào)函數(shù)
def PyWndProc(hWnd, Msg, wParam, lParam):
if Msg == WM_DESTROY:
windll.user32.PostQuitMessage(0)
else:
return windll.user32.DefWindowProcW(hWnd, Msg, wParam, lParam)
return 0
接著下來是設(shè)置窗口類的屬性,注冊(cè)窗口的類型,以便后面可以創(chuàng)建這個(gè)窗口,這里主要是調(diào)用函數(shù)RegisterClassExW來實(shí)現(xiàn)。同時(shí)這里把前面的回調(diào)函數(shù)WndProc、程序?qū)嵗浔鷋Inst、窗口類名稱wclassName組合一起了。
#初始化主窗口
def initwinclass(hInst, WndProc):
wndClass = WNDCLASSEX()
wndClass.cbSize = sizeof(WNDCLASSEX)
wndClass.style = CS_HREDRAW | CS_VREDRAW
wndClass.lpfnWndProc = WndProc
wndClass.cbClsExtra = 0
wndClass.cbWndExtra = 0
wndClass.hInstance = hInst
wndClass.hIcon = 0
wndClass.hCursor = 0
wndClass.hBrush = windll.gdi32.GetStockObject(WHITE_BRUSH)
wndClass.lpszMenuName = 0
wndClass.lpszClassName = wclassName
wndClass.hIconSm = 0
return windll.user32.RegisterClassExW(byref(wndClass))
窗口的回調(diào)函數(shù)已經(jīng)定義,窗口類型又已經(jīng)注冊(cè),接著下來就是創(chuàng)建窗口,并把窗口顯示出來了,代碼如下:
#主函數(shù)入口
def main():
hInst = windll.kernel32.GetModuleHandleW(None)
WndProc = WNDPROCTYPE(PyWndProc)
if initwinclass(hInst, WndProc) <= 0:
return False
hWnd = windll.user32.CreateWindowExW(
0, wclassName, wname,
WS_OVERLAPPEDWINDOW | WS_CAPTION,
CW_USEDEFAULT, CW_USEDEFAULT,
800, 600, 0, 0, hInst, 0)
if not hWnd:
print('Failed to create window')
exit(0)
windll.user32.ShowWindow(hWnd, SW_SHOW)
windll.user32.UpdateWindow(hWnd)
msg = MSG()
lpmsg = pointer(msg)
print('Entering message loop')
while windll.user32.GetMessageW(lpmsg, 0, 0, 0) != 0:
windll.user32.TranslateMessage(lpmsg)
windll.user32.DispatchMessageW(lpmsg)
print('done.')
在這個(gè)主函數(shù)里,融合前面介紹內(nèi)容。如果對(duì)前面介紹都比較了解,那么在這里就很容易理解它,如果還是不懂,請(qǐng)?jiān)俨榭辞懊娴膬?nèi)容,多練習(xí)一下。GetModuleHandleW函數(shù)是用來獲取當(dāng)前進(jìn)程的實(shí)例句柄,WNDPROCTYPE是用來轉(zhuǎn)換回調(diào)函數(shù),initwinclass函數(shù)是用來初始化窗口類型并注冊(cè),CreateWindowExW函數(shù)是用來創(chuàng)建窗口,ShowWindow函數(shù)是用來顯示窗口出來,UpdateWindow是用來刷新窗口的顯示客戶區(qū),pointer函數(shù)是用來轉(zhuǎn)換消息指針,GetMessageW函數(shù)是獲取窗口的消息,TranslateMessage函數(shù)是用來轉(zhuǎn)換消息,DispatchMessageW函數(shù)是把轉(zhuǎn)換后的消息發(fā)送到消息隊(duì)列。通過創(chuàng)建窗口、顯示窗口及更新窗口這三步曲,就完成窗口的顯示。后面通過消息循環(huán)處理,響應(yīng)了窗口所有的事件處理。最后還差一個(gè)觸發(fā)這個(gè)主函數(shù)main的方式,它的實(shí)現(xiàn)如下:
if __name__ == "__main__":
print( "Win32 Application in python" )
main()
這里使用了Python的一個(gè)特性,當(dāng)本文件最先運(yùn)行加載時(shí),就會(huì)設(shè)置當(dāng)前文件運(yùn)行的名稱為__main__屬性,這樣就會(huì)調(diào)用main函數(shù)運(yùn)行了。當(dāng)你運(yùn)行這個(gè)例子時(shí),最激動(dòng)人心的時(shí)刻到來了,它運(yùn)行的結(jié)果如下:
編程已經(jīng)是目前的主流方向,正在學(xué)習(xí)編程的小伙伴們努力、加油吧。
http://www.dengb.com/Javabc/866195.htmlwww.dengb.comtruehttp://www.dengb.com/Javabc/866195.htmlTechArticle創(chuàng)建窗口的應(yīng)用程序 通過前面的基礎(chǔ)知識(shí)的學(xué)習(xí),已經(jīng)對(duì)ctypes庫(kù)的基本功能學(xué)會(huì)了使用,為了加強(qiáng)這種知識(shí)訓(xùn)練,以及運(yùn)用剛學(xué)習(xí)的知識(shí)的...
總結(jié)
以上是生活随笔為你收集整理的用java创建窗口程序,创建窗口的应用程序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java连接access_关于k8s下使
- 下一篇: keep行走和计步_App Store