不要觉得奇怪虽然我们拥有众多“所见即所得”编程方式来开发众多界面精美应
用这些可视化编程环境提供了大量类库和Control控件但是在开发者享受方便同时
他们手脚已经不知不觉受到了限制有很多深入到windows内部操作它们无法完成
为什么?所用类库不支持
事实上这些类库和Control控件都是架构在window api基础上面api即 application
programming erface -- 应用编程接口 缩写它不仅为应用所同时也是
windows部分windows自身运行也这些api要了解如何使用api就必须了
解些windows运行机制
简单地说windows是由事件驱动抢占式多任务操作系统事件驱动是相对于过程驱
动而言它改变了原来文件顺序执行方式;windows既然是多任务系统就必须能同时
处理多个事件系统为应用生成个消息队列消息在上面被张贴和发送应用只
要从其消息队列中取出消息然后执行就可以了
现在我将使用最最基本范例 hellowin 来介绍说明win32 api运行机制
首先个定要有进入点win32 app进入点名称是win它原型如下
apientry win(hinstance hinstance, hinstance hprevinstance,
lpstr lpcmdline, ncmdshow)
hinstance是所谓“例子句柄”它是个数值当在windows下运行时候它被用
来唯标示这个虽然用户可能同时运行多个同个即运行多个“例子”我
们可以看到每个例子都有区别hinstance值
hprevinstance简单地说就是没用…它是存在于16位windows中在编写
windows 9x/nt/2000 时候总应该是null
szcmdline是个指针指向个以0为终结字串里面包含传给该命令行参数
如果想要让处理命令行那么这个参数就有用了
icmdshow参数是个数值指示窗口将如何被显示这个数值由在windows下运行该
所决定通常是sw_shownormal
接下来是注册个窗口类窗口总是从窗口类基础上创建窗口类用以标示处理窗口消
息窗口过程注册窗口类时使用 registerex 它只需要个参数个指向
类型为 wndex 结构指针
具体注册是这样:
wndex wcex;
wcex.cbsize = (wndex); //结构大小
wcex.style = cs_hredraw | cs_vredraw; //类风格
wcex.lpfnwndproc = (wndproc)wndproc; //窗口类窗口过程
wcex.cbclsextra = 0; //在类结构中预留空间
wcex.cbwndextra = 0; //在windows内部保存窗口结构中预留空间
wcex.hinstance = hinstance; //例子句柄
wcex.hicon = loadicon(hinstance, (lpctstr)idi_example); //图标
wcex.hcursor = loadcursor(null, idc_arrow); //结构大小
wcex.hbrbackground = (hbrush)(color_window+1); //指定窗口背景颜色
wcex.lpszmenuname = (lpcstr)idc_example; //菜单
wcex.lpszname = szwindow; //类名和名相同
wcex.hiconsm = loadicon(wcex.hinstance, (lpctstr)idi_small); //也是图标
registerex(&wcex);
接下来定义个hwnd然后使用 createwindow 原型如下:
hwnd createwindow(
lpctstr lpname, // 窗口类名
lpctstr lpwindowname, // 窗口标题
dword dwstyle, // 窗口风格
x, // x
y, // y
nwidth, // 窗口宽
nheight, // 窗口高
hwnd hwndparent, // 父窗口句柄
hmenu hmenu, // 菜单句柄
hinstance hinstance, // 例子句柄
lpvoid lpparam // 创建参数
);
在 createwindow 返回的后windows内部已经创建了这窗口但是窗口并为显示
还需要两个个是 showwindow(hwnd, icmdshow):第个参数是刚刚创建窗口
句柄第 2个参数是传递给winncmdshow;另个是 updatewindow(hwnd) 导致
客户区域被绘制
接下来通过执行块被称为“消息循环”代码从消息队列中取出消息
while (getmessage(&msg, null, 0, 0))
{
(!translateaccelerator(msg.hwnd, hacceltable, &msg))
{
translatemessage(&msg);
dispatchmessage(&msg);
}
}
消息循环以 getmessage 开始它从消息队列中取出条消息只要从消息队列中取出消
息 message 域不为 wm_quitgetmessage 就返回个非零值否则将导致退出
消息循环然后中止返回 msg 结构 wparam 参数在循环中translatemessage
将 msg 结构内容进行修改而 dispatchmessage 找出准备窗口过程
上面进行仅仅是准备性工作:注册窗口类、创建窗口、显示窗口、进入消息循环取出消息
而实际动作都发生在窗口过程中
lresult callback wndproc(hwnd hwnd, //刚刚创建窗口句柄
u message, //得到消息
wparam wparam,
lparam lparam //消息进步详细参数
)
在中窗口过程通常是命名为 wndproc 其实窗口过程可以任意命名个
windows可以包含多个窗口过程个窗口过程总是和了 registerex 注册
窗口类相关联createwindow 根据窗口类来创建窗口但是个窗口类可以被用来创
建多个窗口
消息收到的后接下来应该根据消息区别来进行处理
switch(message)
{
…:
…
…
hellowin只需要处理两条消息即 wm_pa 和 wm_destroy
wm_pa 消息在windows中地位极其重要当窗口客户区部分或者全部变为
“无效”必须进行刷新时候将由这条消息通知
为什么客户区域会变得无效呢?在创建窗口时候整个客户区都是无效还没有画
任何东西第条 wm_pa 消息指示窗口过程在窗口上面画些东西;还有在用户改
变了窗口大小的后客户区域重新变得无效除此的外最小化窗口的后再还原、窗口
部分被覆盖都会引发这条消息
wm_destroy消息则是当用户按下“关闭”按钮时候被触发标准处理思路方法是
postquitmessage 将条 wm_quit 消息插入消息队列这将使得 getmessage
返回0从而退出消息循环结束整个
其实从上面可以看出windows这种运行机制并不是很难理解真正困难是不知
道什么去完成想要操作以及怎样那些从而灵活进行底层api
开发这是个循序渐进积累过程没有捷径可走请各位定要记住
最新评论