WINDOWS编程入门一个初级问题的分析

#include <windows.h>    //包括了所有基本的WINDOWS API函数,写WIN32应用程序必须包含


LRESULT CALLBACK WndProc(HWND hMainWnd,UINT message,WPARAM wParam,LPARAM lParam)

//LRESULT 是函数的类型,CALLBACK声明了函数参数的调用顺序。详情请看这里。
{

switch(message)   //建立消息循环。关于消息请看这里。
{
case WM_DESTROY:     //如果是WM_DESTROY消息,进入这个处理过程
{
PostQuitMessage(0);        //退出
return 0;
}
default:
break;
}
//以下这个函数是调用默认的消息处理函数
return DefWindowProc(hMainWnd,message,wParam,lParam);
}

//这里要注意了,这里是程序的入口点,相当于DOS里的 main()函数,只不过参数都了些。
int CALLBACK WinMain(HINSTANCE hInstance,    //这个参数是实例句柄
HINSTANCE hPrevInstance,                     //上一个实例句柄
LPSTR lpszCmdParam,                                                         //命令行字符串
int nCmdShow)                       
{
MSG message;                                 //定义消息数据结构
WNDCLASS myWC;                  //定义窗口风格
HAND hMainWnd;                //窗体句柄
char szAppTitle[]="API建立的程序";   //应用程序标题字符串
char szAppName[]="WinAPIDemo";      //应用程序名
if(! hPrevInstance)          
{            //以下的定义是关于窗口参数的
myWC.style = CS_HREDRAW | CS_VREDRAW;
myWC.lpfnWndProc=WndProc;
myWC.cbClsExtra= 0;
myWC.cbWndExtra =0;
myWC.hInstance=hInstance;
myWC.hIcon=LoadIcon(NULL,IDI_INFORMATION);
myWC.hCursor=LoadCursor(NULL,IDC_HELP);
myWC.hbrBackground=GetStockObject(WHITE_BRUSH);
myWC.lpszClassName=szAppName;
myWC.lpszMenuName = NULL;
RegisterClass(&myWC);             //注册窗体
}
hMainWnd=CreateWindow(szAppName,         //创建窗体
szAppTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hMainWnd,SW_SHOWMAXIMIZED);    //显示窗体

UpdateWindow(hMainWnd);                  //更新窗体
while(GetMessage(&message,NULL,0,0))         //建立消息循环
{
TranslateMessage(&message);
DispatchMessage(&message);

}
return (TRUE);
}

  这里面最让人不明白的就是数据类型了。当你学完标准的C后,你看这个程序,就跟看天书一样,很多的东西你明白语法,但是就是看不懂。所以,首先我来说一下WINDOWS编程里的数据类型。

  以下数据取自于VC6 Include目录下的“windef.h”文件。

#define CALLBACK PASCAL
#define WINAPI CDECL
#define WINAPIV CDECL
#define APIENTRY WINAPI
#define APIPRIVATE CDECL

#define PASCAL __pascal

#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
#define APIPRIVATE __stdcall
#define PASCAL __stdcall

typedef unsigned long DWORD;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef float FLOAT;

typedef int INT;
typedef unsigned int UINT;

typedef UINT WPARAM;
typedef LONG LPARAM;
typedef LONG LRESULT;

  你可以看到,这里面有很多的定义的本质是一样的,为的只是便于阅读而已。其实,WIN32环境下只有一种数据类型,就是32BIT整形,其他的都是来自于这里。而且,绝大部分数据类型直接就是32BIT的。这样,你所要做的事情,就是熟悉这些名字,详情见《WIN32数据类型入门》。

  int CALLBACK WinMain()  。这个函数是WIN32程序的入口,就象DOS下的main(),不同的是main函数的参数是可选的,WinMain函数的参数是必须的。相同的是,main和WinMain都不是给程序员调用的,而是有系统调用的。在C里面,main是没有返回值的,我们看到WinMain是有返回值的,它是用  int CALLBACK 来修饰的。CALLBACK 说明了WinMain函数参数调用的顺序。int是说明了函数的返回值。关于CALLBACK的意义,请参考《WIN32函数压栈顺序》。根据“windef.h”文件的定义,WinMain函数的修饰符的写法也不是唯一的。你可以有很多中写法。例如:INT PASCAL WinMain(),int __stdcall WinMain()。这些写法其实本质是一样的,只是为了不同的风格。

    下面,的语句很多书里都有介绍,我就不详细说了,如果你还不熟悉,请看《WIN32数据类型入门》。

    当你把程序全部书写完毕后,你会保存为一个C文件,在这里我保存为了miniwin.c。当你双击这个文件就会用VC6打开。这时候你首先要看看,你的程序有没有语法错误了,VC++可以帮你自动完成这个工作。选择Build-->>Compile winiwin.c。根据,我的经验,很多第一次手工输入这个程序的人,都会出现各种各样的错误,这个问题比较简单,一般都是拼写错误。对照上面的程序就可以了。当你点下菜单按纽后,出现一个消息框,提示你没有建立相关的工程,你直接选yes,VC会自动帮你建立的(看看你保存miniwin.c的目录下,是不是多了很多文件呀)。如果,你的程序拼写没问题的话,你将看到:miniwin.obj - 0 error(s), 0 warning(s)。这就是说明了,编译已经通过了。然后就是LINK了。你在Build菜单先选择“建立EXE”的选项。本来是可以建立的,但是VC却提示:Linking...
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/miniwin.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

miniwin.exe - 2 error(s), 0 warning(s)
  这个问题几乎存在于所有的VC入门教材里,程序有问题吗?显然不是的,上面的这个程序是正确的。问题出在这里了。请你选择Project-->>Setting,选择Link选项卡,最底下有个Project Options删除里面的/subsystem:console,按OK保存。然后再建立EXE试试。看到这个提示了吗?miniwin.exe - 0 error(s), 0 warning(s)。如果有,恭喜你,成功了。这时候在DEBUG目录下会有一个EXE文件,双击它,一个简单的窗体就出现在你面前了。

  至此,你已经可以建立WIN32程序了,这个程序是一个框架,里面是最基本的东西 . 

 

你可能感兴趣的:(编程,windows,null,callback,pascal,winapi)