Windows编程学习笔记03-Windows程序结构

第一个程序

和控制台应用程序一样,Windows对应的“Hello,world”程序包括了同样的组成部分,即 include语句、程序入口、函数调用,以及return语句。

//控制台应用程序 HelloMsg.c 
#include <windows.h>

int main()
{
	MessageBox(NULL,TEXT("Hello,windows 98! "),TEXT("HelloMsg"),0);
	return 0;
}


//Windows桌面应用程序 HelloMsg.c 
//注意:此代码在控制台应用程序项目无法运行,入口函数不一样。
#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdshow)
{
	MessageBox(NULL,TEXT("Hello,windows 98! "),TEXT("HelloMsg"),0);
	return 0;
}

修改源文件后缀名为cpp也可以运行。

头文件

HelloMsg.c里打头的是在几乎所有用C语言编写的 Windows程序中都有的预处理器指令:

#include <windows.h>

windows.h是一个最重要的包含文件,它囊括了若干其他Windows头文件,其中的某些头文件又包含另外的一些头文件。下列几个是最重要也是最基本的头文件:

  • WinDef.H:基本数据类型定义。

  • Winnt.H:支持Unicode的类型定义。

  • WinBase.H :内核函数。

  • WinUser.H:用户界面函数。

  • WinGDI.H:图形设备接口函数。

    这些头文件定义了 Windows的所有数据类型、函数调用、数据结构以及常量标识符它们在Windows文档中占有至关重要的地位。你既可以外部依赖项打开这些头文件,直接翻阅它们的内容。

    头文件的详细说明在C++语言中。

程序入口

正像main是C程序的入口一样,Windows程序的入口是WinMain,它总是以下面的面目出现:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdshow)

程序入口在 WinBase.h 声明如下:

int
WINAPI
WinMain (
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nShowCmd
    );

返回值

WinMain 函数的返回值被定义为int。

WINAPI

minwindef.H中用以下语句来定义WINAPI标识符

#define WINAPI      __stdcall

这条语句规定了一种函数调用约定,表明如何生成在堆栈中放置函数调用参数的机器代码。绝大多数Windows函数调用都定义成WINAPI。

函数调用约定主要约束了两件事:
1.参数传递顺序
2.调用堆栈由谁(调用函数或被调用函数)清理
常见的函数调用约定:stdcall cdecl fastcall thiscall naked call

__stdcall表示
1.参数从右向左压入堆栈
2.函数被调用者修改堆栈
3.函数名(在编译器这个层次)自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸
在win32应用程序里,宏APIENTRY,WINAPI,都表示_stdcall,非常常见。

参数

改动了WinMain声明中的两个参数名,因为绝大部分Windows程序在变量命名上都采用所谓“匈牙利标记法”,变量名前都有个短前缀,用以表明该变量的数据类型。前缀i表示int,前缀sz表示“以零结尾的字符串”。

  1. hInstance:实例句柄
    WinMain的第一个参数一般叫做“实例句柄”。在 Windows程序中句柄无非就是一个数值,程序里用它来标识某些东西。比如在我们这个例子里,这个句柄就唯一标识了我们的这个程序。

  2. hPrevInstance:同一程序其它实例句柄
    实际上在某些Windows程序中,把句柄当作调用参数是必须的。比如在早期的 Windows版本中,当多路并发运行同一个程序时,就需要为那个程序创建多个实例。同一程序的所有的实例都共享代码以及只读存储(即菜单或对话框模板之类的资源)。一个程序可以通过查看 hPrevInstance参数从而知道是否有它的其他实例正在运行。它也就可以因此跳过某些零散杂务步骤,把一些数据从前一个实例搬到自己的数据区来。在32位 Windows中,这一概念已不再采用。因此 WinMain的第二个参数通常总是NULL(定义为0)。

  3. szCmdLine:

    用来运行程序的命令行(Command Line)。有些Windows程序在启动时用它来把文件装入内存。

    在上面示例HelloMsg.c中把LPSTR改成了PSTR。这两种数据类型在 Winnt.H中都声明为指向字符串的指针。前缀LP代表长指针(Long Pointer),它是16位 Windows的产物。

  4. iCmdshow:
    用来指明程序最初如何显示:或正常显示,或最大化到全屏,或最小化显示在任务栏上。

MessageBox函数

MessageBox(NULL,TEXT("Hello,windows 98! "),TEXT("HelloMsg"),0);

MessageBox函数是用来显示短信息的。尽管形式比较单一,MessageBox 所显示的小小窗口实际上也是一个对话框。

  • 第一个参数通常是一个窗口句柄。它的具体意思留到第3章再谈。

  • 第二个参数就是将要在信息框里出现的文本字符串。

  • 第三个参数是将要在标题栏上显示的文本字符串。在HELLOMSG.C中,这些文本串都被打包在 TEXT宏代码(Macro)里面。一般来说,并不需要把所有的字符串都打包到 TEXT宏代码里面,之所以这样做是因为这样在把程序转换成Unicode时会方便很多。我将在第2章中详细讨论这一点。

  • 第四个参数是以前缀MB_打头的一些常量的组合。WINUSER.H中定义了这些相关常量。从以下第一个常量集中,你可以任选一个来表示在对话框里希望用哪种按钮:

#define MB_OK 0x00000000L
#define MB_OKCANCEL 0x00000001L
#define MB_ABORTRETRYIGNORE 0x00000002L
#define MB_YESNOCANCEL 0x00000003L
#define MB_YESNO 0x00000004L
#define MB_RETRYCANCEL 0x00000005L

当你把 HELLOMSG 中的第四个参数选成0时,那就只显示OK按钮。你可以通过使用C里面的 OR(l)运算符把一个上述按钮常量跟下列常量组合起来,来描述哪个按钮为默认按钮:

#define MB_DEFBUTTON1 0x00000000L
#define MB_DEFBUTTON2 0x00000100L
#define MB_DEFBUTTON3 0x00000200L
#define MB_DEFBUTTON4 0x00000300L

在我们这个范例程序中,MessageBox函数返回的数值为1,更精确地说返回IDOK在 WINUSER.H中,IDOK定义为1。根据消息框中给出的其他按钮,MessageBox函数也可能返回ISYES、ISNO、IDCANCEL、IDABORT、IDRETRY 或 IDIGNORE。

编译链接运行

通常情况下在编译阶段,编译器从C源代码文件产生一个.OBJ(目标)文件。在链接阶段,链接器又把.OBJ文件和.LIB(库程序)文件放到一起产生.EXE (可执行)文件。你可以通过选择Project菜单下的Settings,并单击Link标签来查看这些库程序的文件列表。特别要注意的是KERNEL32.LIB、USER32.LIB 和 GDI32.LIB三个重要库程序,它们分别代表个主要的 Windows子系统。它们包含动态链接库的名字,以及与.EXE 相关的访问信息Windows利用这些信息来解析程序中对KERNEL32.DLL、USER32.DLL 和GDI32.DLL动态链接库内的函数的调用。
在Visual Studio里,你可以在不同的配置下编译和链接程序。默认情况下,这些配置通常称为Debug配置和Release配置。可执行文件就存放在以这些配置命名的子目录里。在 Debug配置下,.EXE文件中加入了一些有助于程序调试以及源代码跟踪的信息。

在这里插入图片描述

参考:《Windows 程序设计 第5版》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尘旭员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值