在CSDN上面发现一篇好的文章 特转载过来和朋友们分享
本文应一个初学Windows程序设计的朋友而作。

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

一、抽象渗漏法则
根据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语言的方式写出来:
 WINAPI HINSTANCE HINSTANCE    cmdShow    cmdShow 

        stdostringstream msg        msg     msg  MB_OK  MB_ICONSTOP
如此简单,WinMain这个函数只有这么短,分别调用三个自定义函数就OK了。

2、窗口消息回调函数

简单地说,回调(Callback)函数就是一个按规定原型实现的一个函数,当别人来调用。比如说,每个窗口都有一个窗口类(用RegisterClassEx登记的Class,或者系统缺省已实现的Class),每个窗口类有一个回调函数,当窗口收到WIndows消息的时候,就会去调用这个回调函数,而这个回调函数的代码是程序员自己写的,用来根据实际情况处理不同的窗口消息。
LRESULT CALLBACK HWND wnd UINT msg WPARAM wParam LPARAM lParam  msg  WM_DESTROY

 wnd msg wParam lParam

3、登记窗口类

在创建主窗口之前,一定要先用RegisterClassEx这个API函数登记一个类,类名必须是独一无二的,所以一般都用GUID字串来做类名。
    WNDCLASSEX  wce      wcecbSize           wce    wcestyle            CS_VREDRAW  CS_HREDRAW    wcelpfnWndProc      onMainWndMessage      wcehInstance            wcehIcon             IDI_WINLOGO    wcehCursor           IDC_ARROW    wcehbrBackground    HBRUSHCOLOR_BTNFACE    wcelpszClassName    CLASS_NAME     wcehIconSm          wcehIcon wce

4、创建主窗口

(略,直接看完整代码)

5、消息循环

消息循环很简单,仅当GetMessage这个API函数返回FALSE时,才退出循环。而GetMessage()仅当处理到消息队列中的WM_QUIT消息时才会返回FALSE。
    MSG msg msg    msgmsg

 msgwParam
四、完整的示例代码

    CLASS_NAME  

LRESULT CALLBACK HWND wnd UINT msg WPARAM wParam LPARAM lParam  msg  WM_DESTROY

 wnd msg wParam lParam

    WNDCLASSEX  wce      wcecbSize           wce    wcestyle            CS_VREDRAW  CS_HREDRAW    wcelpfnWndProc      onMainWndMessage      wcehInstance            wcehIcon             IDI_WINLOGO    wcehCursor           IDC_ARROW    wcehbrBackground    HBRUSHCOLOR_BTNFACE    wcelpszClassName    CLASS_NAME     wcehIconSm          wcehIcon wce

  cmdShow     HWND mainWnd   CLASS_NAME  WS_OVERLAPPEDWINDOW        CW_USEDEFAULT CW_USEDEFAULT CW_USEDEFAULT CW_USEDEFAULT

 mainWnd mainWnd cmdShowmainWnd

    MSG msg msg    msgmsg

 msgwParam

 WINAPI HINSTANCE HINSTANCE    cmdShow    cmdShow 

        stdostringstream msg        msg     msg  MB_OK  MB_ICONSTOP
转载来自:[url]http://blog.csdn.net/seawave/archive/2006/10/18/1338879.aspx[/url]
 

转载于:https://blog.51cto.com/suxiangjuner/148436

从WinMain开始相关推荐

  1. undefined reference to 'WinMain@16' 的四种情况

    undefined reference to 'WinMain@16' 意思为提示找不到 WinMain 函数,WinMain是windows程序的入口函数,有几种可能: int main() 写成了 ...

  2. 无法解析的外部符号 WinMain,该符号在函数 int __cdecl invoke_main(void) (?invoke_main@@YAHXZ) 中被引用

    无法解析的外部符号 WinMain,该符号在函数 "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) 中被引用 (2)项目- ...

  3. VS2022 C28251 WinMain批注不一致的解决方法

    警告 C28251 "WinMain"的批注不一致: 此实例包含 无批注. #include <windows.h>int WINAPI WinMain(_In_ HI ...

  4. QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数

    版权声明 请尊重原创作品.转载请保持文章完整性,并以超链接形式注明原始作者"tingsking18"和主站点地址,方便其他朋友提问和指正. QT源码解析(一) QT创建窗口程序.消 ...

  5. c语言Winmain 错误,C语言编译错误 undefined reference to `WinMain@16'

    1.把主函数 main() 写成了mian() 2.没写主函数main() 3.建的不是控制台应用程序 console application 4.[code] #include int main() ...

  6. 1.封装WinMain至动态链接库

    1.封装WinMain至动态链接库 DND的前言: DND是定位于Windows平台的2d游戏引擎,使用C++和DirectX 11实现,编译器使用vs2015.保留了一些3d功能,适合做一些pc上的 ...

  7. [转载]_tmain main wmain WinMain

    在visual c++ 2008 中,当选择编辑一个32位Win32控制台应用程序时. 初始状态下系统自带函数: int _tmain(int argc, _TCHAR* argv[]) {      ...

  8. strtok函数取WinMain的参数

    WinMain函数与main函数不同,main可以从argc得到函数个数,然后从argv[]数组里取参数. 而WinMain函数取参数是通过lpCmdLine,lpCmdLine里不能得到参数的个数. ...

  9. WinMain中的Console与main中的Window

    1.如何在WinMain中创建一个Console. 调用AllocConsole分配一个Console资源:调用GetStdHandle获得OS的标准设备(输入,输出或错误),此函数返回一个句柄,若要 ...

最新文章

  1. Maple Warrior 个人简历
  2. 顶级项目管理工具 Top 10
  3. java保持运行_保持Java程序无限运行的方法是有效的吗?
  4. ZZULIOJ 1125: 上三角矩阵的判断
  5. 小齐是如何提高自己的「编程能力」的?
  6. 【数据库系统设计】关系数据理论(函数依赖、码、范式、模式分解)
  7. Go 编码建议——功能篇
  8. JavaScript常见鼠标事件与用法分析
  9. L298N电机驱动模块详解
  10. network secruity studay day3
  11. 《社会动物——爱、性格和成就的潜在根源》读后感及摘录(3)
  12. 通过经纬度计算两点间的直线距离
  13. Excel公式向导,不会函数也可以单条件求平均值
  14. 淘宝标题可以改吗 淘宝标题优化技巧方法有哪些
  15. 推荐5款Windows桌面效率工具
  16. echarts柱状图 双柱状图基本用法
  17. Flask源码阅读-第四篇(flask\app.py)
  18. 数字电子技术实验作业(10)
  19. 计算机网络思科考试答案参考--网络应用通信考试
  20. CSS Text Style || CSS文本样式

热门文章

  1. 日本推出无人机伞,将推翻手持伞的历史
  2. 在华为路由器上配置IPv6 over IPv4隧道
  3. RStudio版本号管理 整合Git
  4. async [ə'zɪŋk] 函数
  5. 表面积最小(POJ3536)
  6. 【采集层】Kafka 与 Flume 如何选择
  7. Linux下做双向同步
  8. 包继承Maven的超级POM
  9. 北信源IPO,拟筹资开发企业级云安全管理平台
  10. php获取svn文件,然后ftp上传服务器代码