创建窗口的应用程序

通过前面的基础知识的学习,已经对ctypes库的基本功能学会了使用,为了加强这种知识训练,以及运用刚学习的知识的快乐,我们来创建一个稍稍复杂一点的应用程序。这个应用程序是所有后面应用程序的基础,只有学会这个程序的基本原理,才可以更进一步学习WIN32的API程序开发。更何况后面所有程序都会在这个程序上修改而成,这个就相当你的爬向高楼顶层的第一个台阶。在所有工程技术里,都会从一个小小的演示程序开始,逐渐地增加功能,慢慢地变成一个强大的应用程序。如果发现这些API函数不清楚,可以参考我写的另外一本书《Windows API一日一练》,在那本书里有完整的介绍和例子,不过这些例子使用C++来编写的。

下面就来开始浏览整个程序的功能吧,第一步是先把ctypes库导入,这样才可以使用它的功能,并且还导入ctypes.wintypes,它有对应WIN32的类型,这样使用起来更方便,比如消息结构MSG。这段代码如下:

#windows应用程序

from ctypes import *

from ctypes.wintypes import *

接着下来定义一个Windows的窗口回调函数的原型,因为Windows指定了每个窗口都需要有一个窗口消息函数来处理窗口所有发生的事件消息,这样你写的应用程序才有机会去响应窗口所发生的事件或操作。这行代码如下:

WNDPROCTYPE = WINFUNCTYPE(c_int, HWND, c_uint, WPARAM, LPARAM)

由于WIN32的定义常量全部是在C语言的头文件里定义,要想在Python中直接使用是不行的。目前只有两种方法,一个是使用一个转换程序,把所有SDK里提供的头文件进行转换为Python定义的形式的模块文件;另外一个就是自己使用到那些,就定义那些常量。本例子里,采用的是最后一种方法,使用到那些就定义就定义那些常量,这样做是为了这个例子保持简单,这些常量定义如下:

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

在这些常量主要是窗口的格式、样式、以及显示方式,还有一个消息定义和画笔。由于每个新创建的窗口都需要在Windows里注册唯一的名称,以便创建时从系统内存里找到相应的窗口类,所有其它窗口可以以这个窗口为基本模板,复制N个相同的出来。每个窗口还有一个主题名称,又叫做窗口名称,这两个定义常量如下:

#窗口类的名称

wclassName = u‘ShenzhenCai‘

wname = u‘Hello World‘

第一个常量窗口类名称,第二个常量是窗口显示的标题。

窗口的格式、样式通过定义一个结构的方式传递给WIN32的API函数,在这里定义窗口类的结构体如下:

#定义窗口类结构

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)]

这个窗口类的结构体与C语言里描述的结构体是一样的,通过这样定义,就可以给窗口说明窗口的类型了。具体每项的值,请参考《Windows API一日一练》。接着下来,查看窗口回调函数,这里定义了处理窗口收到消息。主要处理了当窗口关闭(WM_DESTROY)时就退出程序。调用API函数PostQuitMessage发送消息给主程序循环,需要结束应用程序了。其它的消息都是调用API函数DefWindowProcW来做默认的处理。

#窗口消息处理回调函数

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

接着下来是设置窗口类的属性,注册窗口的类型,以便后面可以创建这个窗口,这里主要是调用函数RegisterClassExW来实现。同时这里把前面的回调函数WndProc、程序实例句柄hInst、窗口类名称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))

窗口的回调函数已经定义,窗口类型又已经注册,接着下来就是创建窗口,并把窗口显示出来了,代码如下:

#主函数入口

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.‘)

在这个主函数里,融合前面介绍内容。如果对前面介绍都比较了解,那么在这里就很容易理解它,如果还是不懂,请再查看前面的内容,多练习一下。GetModuleHandleW函数是用来获取当前进程的实例句柄,WNDPROCTYPE是用来转换回调函数,initwinclass函数是用来初始化窗口类型并注册,CreateWindowExW函数是用来创建窗口,ShowWindow函数是用来显示窗口出来,UpdateWindow是用来刷新窗口的显示客户区,pointer函数是用来转换消息指针,GetMessageW函数是获取窗口的消息,TranslateMessage函数是用来转换消息,DispatchMessageW函数是把转换后的消息发送到消息队列。通过创建窗口、显示窗口及更新窗口这三步曲,就完成窗口的显示。后面通过消息循环处理,响应了窗口所有的事件处理。最后还差一个触发这个主函数main的方式,它的实现如下:

if __name__ == "__main__":

print( "Win32 Application in python" )

main()

这里使用了Python的一个特性,当本文件最先运行加载时,就会设置当前文件运行的名称为__main__属性,这样就会调用main函数运行了。当你运行这个例子时,最激动人心的时刻到来了,它运行的结果如下:

那个白色的窗口,就是我们创建的窗口。通过使用ctypes库,就可以使用WIN32的API函数,并且实现最大化地使用Python方式的代码来书写。当然,这里主要演示是WIN32 API的调用,其实ctypes还可以使用在测试领域的,比如你写了一个C++的动态连接库,这个动态连接库是用来对文件压缩的,你需要对它进行测试,就可以写一个Python的程序来调用这个动态连接库,比写起C++的测试代码要快得多,因为它不需要进行编译的步骤,也没有什么临时文件生成,并且可以随时修改,比较灵活的。要想提高软件的开发效率,在目前这种环境之下,需要掌握多种语言才可行,比如要运行性能高的就使用C++来编写,要开发速度快性能要求不高的就使用Python来编写,像很多测试用例,自动化的工具等。混合编程已经是目前的主流方向,正在学习编程的小伙伴们努力、加油吧。

创建窗口的应用程序

时间: 2024-10-14 04:33:11

创建窗口的应用程序的相关文章

C++创建窗口程序初步

(1)在主函数里面使用类似下面的语句: MainWindow w; w.show(); 这样创建的窗口只有在程序结束运行的时候才会消失. (2)写一个函数,在函数里面用(1)的代码创建窗口,这样,在函数调用完毕出栈的时候窗口就会释放消失. void f() { MainWindow w; w.show(); } 这样,运行的感觉就是窗口刚出现就消失,即一闪而过. (3) 如果在函数里面创建了一个窗口,但是我不希望它在函数调用结束的时候被释放消失,那么考虑到我在java编程随感里面写到的,在函数中

MFC应用程序创建窗口的过程 good

MFC应用程序中处理消息的顺序 1.AfxWndProc()      该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc 2.AfxCallWndProc()  该函数负责保存消息(保存的内容主要是消息标识符和消息参数)供应用程序以后使用,然后调用WindowProc()函数 3.WindowProc()      该函数负责发送消息到OnWndMsg()函数,如果未被处理,则调用DefWindowProc()函数 4.OnWndMsg()        该函

学MFC之前必须会的金典创建窗口程序的过程代码

#include <windows.h> // 窗口过程函数 LRESULT CALLBACK MyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: PostQuitMessage (0); return 0; case WM_PAINT: PAINTSTRUCT ps; HDC hDC = BeginPaint (hwnd, &ps); Ell

控制台下创建窗口和WinMain入口创建窗口简单程序

控制台创建窗口(同时有控制台窗口和新创建的窗口)(项目类型:控制台应用程序) #include "windows.h" #include "TCHAR.h" LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); int _tmain(int argc, _TCHAR* argv[]) { HINSTANCE hInstance; hInstance = G

56 java编程思想——创建窗口和程序片 用户接口API

56.java编程思想--创建窗口和程序片 用户接口API Java 1.1 版同样增加了一些重要的新功能,包括焦点遍历,桌面色彩访问,打印"沙箱内"及早期的剪贴板支持. 焦点遍历十分的简单,因为它显然存在于AWT 库里的组件并且我们不必为使它工作而去做任何事.如果我们制造我们自己组件并且想使它们去处理焦点遍历,我们过载isFocusTraversable()以使它返回真值.如果我们想在一个鼠标单击上捕捉键盘焦点,我们可以捕捉鼠标按下事件并且调用requestFocus()需求焦点方法

52 java编程思想——创建窗口和程序片 程序片限制

52.java编程思想--创建窗口和程序片 程序片限制 出于安全缘故,程序片十分受到限制,并且有很多的事我们都不能做.您一般会问:程序片看起来能做什么,传闻它又能做什么:扩展浏览器中WEB 页的功能.自从作为一个网上冲浪者,我们从未真正想了解是否一个WEB 页来自友好的或者不友好的站点,我们想要一些可以安全地行动的代码.所以我们可能会注意到大量的限制: (1) 一个程序片不能接触到本地的磁盘.这意味着不能在本地磁盘上写和读,我们不想一个程序片通过WEB页面阅读和传送重要的信息.写是被禁止的,当然

【C语言探索之旅】 第三部分第二课:SDL开发游戏之创建窗口和画布

内容简介 1.第三部分第二课: SDL开发游戏之创建窗口和画布 2.第三部分第三课预告: SDL开发游戏之显示图像 第三部分第二课:SDL开发游戏之创建窗口和画布 在上一课中,我们对SDL这个开源库做了介绍,也带大家配置了SDL的开发环境.请大家按照上一课的步骤创建一个SDL工程,能够初步运行. 如果遇到问题,可以百度,Google相关平台SDL的配置.或者联系小编. 当然了,有些朋友可能会说开发C语言游戏还可以用GTK+这个库,但是个人认为GTK+没有SDL那么适合开发游戏,其创建图形界面的能

Python游戏引擎开发(二):创建窗口以及重绘界面

开发本地应用之前,我们得先有个窗口,用于显示界面.其次我们还得实现重绘机制,使游戏不停地刷新,达到动态化的目的.所以我们的引擎开发的第一个阶段就是创建窗口和重绘界面. 以下是之前的文章: Python游戏引擎开发(一):序 Qt的渲染机制 在上一章<序>中我们讲到本次开发用到了PyQt,也就是Qt的Python版.在开始实现引擎功能之前我们要先了解一下Qt,这里先了解渲染机制. 在Qt中,绘画用到的类叫做QPainter,顾名思义,就是个画家类吧.在这个类中,提供了非常多的方法用于操控这个&q

MFC Wizard创建的空应用程序中各个文件内容的解析

创建的MFC应用程序名为:wd,那么: 一.wd.h解析 // wd.h : main header file for the WD application // #if !defined(AFX_WD_H__89BE48D2_F377_4DF1_8C44_4D7372A61CE0__INCLUDED_) #define AFX_WD_H__89BE48D2_F377_4DF1_8C44_4D7372A61CE0__INCLUDED_ //////////////////////////////