PCB论坛网

 找回密码
 注册
查看: 1317|回复: 2

从WinMain开始

[复制链接]
发表于 2011-2-18 17:43:56 | 显示全部楼层 |阅读模式
目录


抽象渗漏法则(摘自Joel)
针对Windows GUI编程的封装
只用API函数创建GUI程序
WinMain函数
登记自己的窗口类
创建主窗口
消息循环
完整的示例代码

--------------------------------------------------------------------------------

一、抽象渗漏法则
根据Joel的抽象渗漏法则,所有重大的抽象机制在某种程度上都是有漏洞的。Joel举过一个例子:

C 字符串类型应该能让你假装字符串是个基本类型,它们尝试“字串很难处理”这个事实抽象掉,让它使用上象整型一样容易,几乎所有C 字串类型都会重载加号运算符,才能把字串连接写成s "bar"。不过你知道吗?不管怎么努力,世上还是没有C 字串类型能让你写成 "foo" "bar",因为C 里的字串常数一定是char *,绝对不会变成字串。这个抽象机制呈现一个程序语言本身不给补的漏洞。

当我想训练某人成为C 程序员时,最好能完全不教char *和指针运算,直接去学STL字符串。问题是总有一天他们会写出 "foo" "bar" 这样的代码,然后看到怪事出现,于是我就得停下来教他们有关char *的事情。他们也可能会试着调用某个需要OUT LPTSTR参数的Windows API,于是又得把char *、指针、Unicode、wchar_t以及tchar.h搞懂,才会知道如何调用。而这些全都是漏洞。

二、针对Windows GUI编程的封装
而针对Windows的GUI编程,有很多封装,如VCL、MFC、WTL等,凡此种种,都把WinMain、CreateWindow和 RegisterClassEx这些API与程序员隔离开来,对一个一开始就只接触这些类库的初学者来说,根本不知道原来一个Windows程序的入口点 其实是WinMain(事实上,一个Win32 EXE的入口点也并不是WinMain,而是编程语言的Runtime库,不过,这里把它抽象掉似乎更有益于理解)。
用API来搭建一个GUI程序是比较枯燥的,这种对于Windows GUI程序的枯燥搭建进行的抽象封装,它的所谓“某种程度上的漏洞”,也许就是使程序员根本不知道每个窗口都有一个窗口类(不是指OO语言里的Class),而每一个窗口类都有一个回调函数(Callback)来对不同的窗口消息进行不同的响应。


做为现在才接触Windows GUI编程的初学者,几乎都不了解一个Windows GUI程序是从WinMain开始的(前面说过,从WinMain开始也只是一个抽象而已,真实的情况并不是这样),那么如何仅仅使用Windows的API函数来创建一个GUI程序呢?

三、只用API搭建Windows GUI程序
1、WinMain()函数
首先,必须要声明一个WinMain()函数(为了简明起见,这里先不讨论_tWinMain这个宏,也不考虑Unicode的问题),它的原型在Windows.h中定义:

int WINAPI WinMain(    HINSTANCE hInstance,       //程序当前实例的句柄,以后随时可以用GetModuleHandle(0)来获得    HINSTANCE hPrevInstance,   //这个参数在Win32环境下总是0,已经废弃不用了    char * lpCmdLine,          //指向以\0结尾的命令行,不包括EXE本身的文件名,                               //以后随时可以用GetCommandLine()来获取完整的命令行    int nCmdShow               //指明应该以什么方式显示主窗口);声明,并且实现这个函数,让Linker程序可以找到它,让编程语言的运行时刻库在完成一些必要的初始化工作后,能够正确地调用它。所以,认为它就是程序的入口点,也是一种简单的“抽象法则”。

在这个入口点函数中,需要按顺序做下面几件事(如果是基于事先设计并存放在资源里的对话框的程序,稍有不同,以后再说):


用RegisterClassEx函数登记一个独一无二的Class
用CreateWindowEx函数创建一个主窗口
进入一个”消息循环“,直到收到WM_QUIT消息
从WinMain函数返回

基本上所有的流程都如出一辙,所以完全可以设计出一个“Template模式”出来重用,让以后的程序直接从某个抽象基类继承,实现基类所需的虚方法就可以了,不过为了不偏离重心,还是用C语言的方式写出来:

int WINAPI WinMain(HINSTANCE, HINSTANCE, char *, int cmdShow) {    if (registerMyClass() && createMyWindow(cmdShow)) {        return messageLoop();    } else {        std:stringstream msg;        msg << "创建主窗口失败,错误代码:" << GetLastError();        MessageBoxA(0, msg.str().c_str(), 0, MB_OK | MB_ICONSTOP);        return 0;    }}如此简单,WinMain这个函数只有这么短,分别调用三个自定义函数就OK了。

..................
更多详情参考:http://www.hzlitai.com.cn/article/ARM9-article/example/1520.html
回复

使用道具 举报

发表于 2011-3-1 17:06:38 | 显示全部楼层
值得支持一下!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-4-13 10:34:47 | 显示全部楼层
技术研发人员首选产品--------立宇泰6410开发板!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|小黑屋|手机版|PCB设计论坛|EDA论坛|PCB论坛网 ( 沪ICP备05006956号-1 )

GMT+8, 2024-5-17 07:09 , Processed in 0.139552 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表