今天开始入坑windows程序开发。
来看第一个“hello world”程序:
通过Visual C++ 6.0的”文件”–>”新建”–>”工程”, 选择”Win32 Application”创建一个空的项目, 再在这个项目中新建一个”文件”, 文件类型为”C++ Source File”, 文件以.c为扩展名, 将下面的代码敲入或者复制粘贴到这个文件内容中, 经过编译运行就可以得到一个对话框了。
或者在vs2010/12/13/15/17中,新建一个Win32项目,然后在下一步记得选择“空项目”复选框,然后项目–>添加新项。新建文件cpp类型的文件,文件名可以随意取一个,最后点击“添加即可”。将下面的代码敲入或者复制粘贴到这个文件内容中, 经过编译运行就可以得到一个对话框了。
#include
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )
{
MessageBox( NULL, TEXT("Hello,world!"), TEXT("MessageBox"), 0 );
return 0;
}
这里windows程序的程序入口和win32控制台程序的入口类似, 为WinMain()函数,返回类型也是int类型。
winmain()参数
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // pointer to command line
int nCmdShow // show state of window
);
第一个参数hInstance是指向当前程序实例的一个实例句柄,好比该实例的一个标识符。
句柄:一个句柄是指使用的一个唯一的整数值,即一个4字节(64位程序中为8字节)长的数值,来标识应用程序中的不同对象和同类对象中的不同的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等。
句柄与指针的区别 :指针包含的是引用对象的内存地址,而句柄则是由系统所管理的引用标识,该标识可以被系统重新定位到一个内存地址上。这种间接访问对象的模式增强了系统对引用对象的控制。
无论它的本质是什么,句柄并不是一个真正意义上的指针。从声明上看,句柄是一个指针,尽管它没有指向用于存储某个对象的内存位置。事实上,句柄指向一个包含了对该对象进行的引用的位置。
typedef void *HANDLE //声明
应用程序能够通过句柄访问相应的对象的信息,但是句柄不是一个指针,程序不能利用句柄来直接阅读文件中的信息。如果句柄不在I/O文件中,它是毫无用处的。 句柄是Windows用来标志应用程序中建立的或是使用的唯一整数,window使用了大量的句柄来标识很多对象。
句柄底层机制 :windows 之所以要设立句柄,根本上源于内存管理机制的问题—虚拟地址,简而言之数据的地址需要变动,变动以后就需要有人来记录管理变动,(就好像户籍管理一样),因此系统用句柄来记载数据地址的变更。数据对象加载进入内存中之后即获得了地址,但是这个地址并不是固定的,数据对象会根据需要在内存与硬盘之间来回移动(例如不常用的数据会为常用数据让出其占用的内存空间进而被淘汰进硬盘中的虚拟内存之中以优化配置整体系统的资源进而提升效率性能),因此其物理地址总是变动的,那么作为管理者 则必须对 管理对象所发生的变化了如指掌才行,因此系统为进程分配固定的地址(句柄)来存储进程下的数据对象变化后的地址也就是当前的地址,其实设计机制很简单 :系统的某个部门移动了对象的地址后,同时上报给句柄所属部门管理者,管理者将改动写入句柄即可。该数据被重新起用时去其所属句柄内按内容存取即可。
第二个参数hPrevInstance同样是个实例句柄, 在win16程序设计中程式通过检查hPrevInstance 参数就能够确定自身的其他执行实体是否正在运行,然后达到某一些目的。但在32位的Windows程序设计中, WinMain函数的实例句柄概念已不再采用, 因此WinMain的第二个参数通常总是NULL。
第三个参数lpCmdLine是用来运行程序的命令行,它被传递给应用程序的参数字符串,利用它可以在启动时将档案载入记忆体。
第四个参数是一个int型参数,指出了程序最初显示的方式,可以满屏显示,最大化显示等等。
MessageBox函数定义如下:
int MessageBox(
HWND hWnd, // handle of owner window, 窗口的一个句柄
LPCTSTR lpText, // address of text in message box, 一个文本(字符串)的指针
LPCTSTR lpCaption, // address of title of message box, 标题字符串的指针
UINT uType // style of message box, 对话框的风格
);
其中,第一个参数是窗口的句柄,如果为NULL, 表示不属于任何窗口。
第二个参数为对话框的内容, 第三个参数为对话框的标题, 但是这两个参数都使用了一个TEXT()的函数。
第四个参数是对话框的风格, 一些以MB_开头的一些常量的组合, 可以使用OR(|)运算进行组合, 这些常量定义在WINUSER.H中, 例如常用的有:
1.按钮风格:
#define MB_OK 0x00000000L //仅有一个"确定"按钮
#define MB_OKCANCEL 0x00000001L //"确定" + "取消"
#define MB_ABORTRETRYIGNORE 0x00000002L //"终止" + "重试" + "忽略"
#define MB_YESNOCANCEL 0x00000003L //"是" + "否" + "取消"
#define MB_YESNO 0x00000004L //"是" + "否"
#define MB_RETRYCANCEL 0x00000005L //"重试" + "取消"
2.图标风格:
#define MB_ICONHAND 0x00000010L //一个红X的错误/停止图标
#define MB_ICONQUESTION 0x00000020L //一个问号的询问图标
#define MB_ICONEXCLAMATION 0x00000030L //一个黄色感叹号的警告图标
#define MB_ICONASTERISK 0x00000040L //一个带有i的信息提示图标