windows3.0环境下的C语言编程-用BorlandC++&TurboC++&开发Windows应用程序

内容分享10小时前发布
0 0 0

 1988年,美国Borland软件公司在深受软件工作者欢迎的Turbo C的基础上,推出新的面向对象的程序设计软件包—Borland C++2.0&Turbo C++1.X(以下简称BC++&TC++),如未特别指出,本节BC++均以Ver 2.0版为蓝本进行描述。BC++&TC++继承并发扬了Turbo C集成环境的优良特性,BC++和Turbo C++都与Turbo C相兼容,用Turbo C编写的程序要移植到BC++或TC++中去是很容易的。

 BC++&TC++实现了AT&TC++ 2.0版的全部功能,它不仅支持美国国家标准局的C语言标准ANSI C,同时也提供对Kernighan和Ritchie所定义的C的支持。当然,和Microsoft C一样,BC++&TC++也是开发Windows应用的强有力工具。在BC++&TC++环境中,老练的C程序员既可以仍然用C开发软件,也可以试着运行C++语言的特点,开发面向对象程序设计风格的尝试。这也是BC++&TC++的一个显著特点。

  本节仅针对BC++2.0进行叙述。

用BC++开发Windows应用程序的常规步骤

在BC++环境中开发Windows应用程序,其步骤与Microsoft C和SDK开发Windows应用程序大致上一样,只是每步中所用到的编译器、汇编程序、连接器等工具软件不同,但实现的功能是等效的。与Microsoft公司提供的SDK中的工具相匹配,Borland公司在BC++中提供了Whitewater资源工具箱WRT

BC++提供了四个编译器,其中BCC,BCCX为命令行编译器;BC,BCX是继承环境式的编译器,它们中的BCX和BCCX支持386保护模式。与Microsoft C不同,BC++编译的源文件多了一种.CPP文件,即C++源文件(.CPLUS PLUS)。

BC++的Whitewater资源工具箱WRT类似SDK,它提供了一些工具,用户可以利用这些工具来创建或修改位图、光标、图标等资源。WRT 是以二进制格式编辑和保存有关资源信息的文件,所以可以直接从WRT得到资源的.RES形式的文件。当然WRT也可以将资源保存到正文文件中,只要该正文文件满足与SDK用以编辑资源的资源描述文件(.RC)兼容的条件即可。

在开发Windows应用程序的过程中,当H,.C,.CPP等文件编制好以后,也可以用MAKE文件的方法一次性完成应用程序的编译和连接,这一点跟Microsoft C中是类似的(注意,在这两个系统中所用编译器、连接器以及参数是不同的,读者可参阅软件文档)。

利用BC++集成环境生成Windows应用程序

BC++&TC++程序员IDE(Intergrated Development Enviroment)是新一代的用户接口,它胜过以往的集成环境,提供对计算机全范围里程序和工具的访问,其中包括

支持鼠标器

支持多重覆盖窗口

支持多重文件编辑

支持内部汇编码

在DOS环境下,运行BC.EXE或BCX.EXE,即可进入BC++的程序员平台IDE。利用BC++的IDE生成可执行的Windows应用程序是非常方便的。

为了完成Windows的一个任务,所必须的C源文件(或C++源文件),头文件、资源文件、模块描述文件等都准备好以后,可以为这组文件建立一个工程文件(Project file),以PRJ作为文件扩展名。工程文件包括下述信息:

工程中的所有文件

文件可在磁盘的哪个路径找到

哪些文件依赖于其他被先编译的文件(自动依赖关系)

生成程序的每一模块用什么进行编译,以及使用哪些编译选择项

目标代码的存放目录

上次编译的代码长度、数据长度和行数

与Turbo C中的工程文件不同,BC++中的工程文件不是一个ASCII文件,所以不能用一般的文本编辑器来建立。在IDE集成环境中,可以选用它的工程文件管理功能来为任一组文件组织工程文件。用户只需按<Alt>+<P>组合键,选中功臣文件管理菜单、接着用Open Project菜单项为将要创建的工程文件指定一个以.RPJ结尾的文件名,再选用Add Item菜单项,用它的对话框指定工程中所包含的所有文件即可。至于工程文件中的其他信息,IDE中的工程管理程序将自动作相应处理。

工程文件建立以后,就可以开始准备进行编译连接了。先选用IDE的Options|Application菜单项打开Set Application Options对话框,选中Windows App项,这意味着BC++将生成Windows应用程序的可执行文件。此外,BC++ 还能根据用户指定,分别生成标准的DOS可执行文件、DOS覆盖文件、windows动态链接库文件DLL三种类型的文件。再选用IDE的Complie|Build all菜单命令(按<F9>键即可),可以得到当前装入的工程文件编译连接后所生成的可执行文件。

3.用BC++为Windows应用程序编制C源文件和C++源文件

无论是使用Microsoft C还是BC++为Windows应用程序编制C源文件,都少不了要用到Microsoft公司提供的Windows.h文件,也就是说,MSC和BC++两者都提供对Windows库函数的全面支持。用MSC和BC++编制Windows的C程序计数,实际上是遵循在编写Windows应用程序要领的基础上的常规C编程技术,和Windows风格及Windows库函数应用计数的综合。

C++很适合于windows编程,如同面向对象的程序设计一样, Windows也试图通过提供包括数据和处理数据的方法来模拟人的思想。一个窗口就是一个对象,因为它封装了数据和对数据进行处理的函数,显示的窗口可以从许多基本结构上继承。Windows下的编程不仅仅会面向对象的编程的概念,也会和C++的特殊功能相得益彰。比如说,当用户在windows下定义一个窗口时,用户先初始化包含窗口信息的结构,该结构中包含一个指向函数的指针。在C语言中,可以用一个包含指针的数据结构来实现。在C++中,用户则只需简单地定义一个类,就可完成同样的工作。在Windows下设计一个类,就像为该结构套上一个“封面”,所有结构之间的相互使用都是通过类完成的。

下面通过讨论Windows应用程序WHELLO(用BC++编写的C++程序WHELLO.CPP),使读者对Windows的C++源程序有一个具体的印象

a.伪指令和初始化

下列代码段注释了文件的内容,列出了使用的头文件,并提供了函数原型:

//Borland C++ -(C)Copyright 1991 by Borland International

//Windows HELLO WORLD – C++ Version

#include <Windows.h>

#include <stdlib.h>

#include <string.h>

 

long FAR PASCAL _Exprort WndProc(HWND hWnd,WORD iMessage,WORD wParam,LONG lParam);

 

class Main

{

public:

static HANDLE hInstance;

static HANDLE hPrevInstance;

static int nCmdShow;

static int MessgaeLoop(void);

}

 

HANDLE Main::hInstance = 0;

HANDLE Main::hPrevInstance = 0;

int Main::nCmdShow = 0;

int Main::MessgaeLoop(void)

{

MSG msg;

while(GetMessage(&msg,NULL,0,0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

 

return msg.wParam;

}

 

 Main类围绕着winMain的参数来服务。Main包含了对应于WinMain参数的静态数据成员。之所以将它们定义成静态成员,是因为只需这些值的一个副本,也正因为它们时静态的,使用这些值时,就不必再定义一个类Main的对象。使用时,只要将它们申明为public成员,就可以对其值进行存取。如果在程序中还用到了WinMain的参数lpiCmdLine,用户也可以用相似的形式来定义和使用一个LPSTR的静态数据成员。

 由于每一个Windows应用程序的消息循环都类似,因此可以将消息循环函数放在静态函数成员Main::MessageLoop中,这样可以使WinMain函数变得简单,不会隐藏任何细节。

 定义Windows类:

class Window

{

protected:

 HWND hWnd;

public:

 //Provide(read) access to the window's handle in case it is needed

 //elsewhere.

 HWND GetHandle(void){return hWnd;}

 BOOL Show(int nCmdShow){return ShowWindow(hWnd,nCmdShow);};

 void Update(void){Updatewindow(hWnd);}

 //Pure virtual function makes Window an abstract class.

 virtual long WndProc(WORD iMessage,WORD wParam,LONG lParam) = 0;

};

 Window类的定义反映了C++中“继承”这个概念的优点。每个窗口都有一个处理过程,并在每个窗口上完成一套相同的动作(例如Show或update),这样,就可以将相同的动作和数据放入一个从Mainwindows中派生出的windows类中。一般来书哦,如果想添加通用于任何窗口的成员到窗口,则可以从窗口中派生出所有的窗口类。

b.定义派生类

class MainWindow::pulic window

{

private:

 static char szClassName[14];

 //Helper function used by Paint function;it is used as a

 //callback function by lineDDA.

 static void FAR PASCAL LineFunc(int X,int Y,LPSTR lpData);

public:

 //Register the class only After WinMain assigns appropriate

 //values to static members of Main and only if no previous

 //instances of the program exist(a previous instance would

 //have alread performed the registration).

 static void Register(void)

 {

  WNDCLASS wndclass;

  //Structure used to register Windows class.

 

  wndclass.style = CS_HREDRAW|CS_VREDRAW;

  wndclass.lpfnWndProc = ::WndProc;

  wndclass.cbClsExtra = 0;

 

  //Reserve extra bytes for each instance of the window;

  //we will use these bytes to store a pointer to the C++

  //(Mainwindow)object correspounding to the window.

  //the size of a 'this' pointer depends on the memory model.

 

  wndclass.cbWndExtra = sizeof(MainWindows*);

  wndclass.hInstance = Main::hInstance;

  wndclass.hIcon = loadIcon(Main::hInstance,”whello”);

  wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);

  wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);

  wndclass.lpszMenuName = NULL;

  wndclass.lpszClassName = szClassName;

  

  if(!RegisterClass(&wndclass))

  {

   exit(FALSE);

  }

 }

}

 Windows需要得到用户程序所使用的不同窗口类的信息。用户可以通过填充WND-CALSS结构(定义在Windows.h中)或调用RegisterClass来传送这些信息。对于每一窗口类,用户只须做一次。也就是说,同一程序的先前实例必须用windows来注册类,这可通过包括一个静态成员函数来实现。在本程序中该函数即为Register函数,该成员函数填充用来表示Windows类的C++类的WNDCLASS对象,如果有必要,可以在WinMain中调用该函数,用来注册Windows类。

 窗口过程负责许多不同的动作,但现在关心的是为每个windows消息调用一个正确的成员函数。遗憾的是,这不可能直接实现,因为函数WndProc将传送一个句柄来标识一个窗口,而一个与窗口对应的C++对象的指针是调用一个对象成员函数所必需的。有一种较好的处理方式可以满足要求,即使用窗口类的附加字节。在Windows注册窗口类时,可以将定义的窗口类的属性填充到WNDCLASS中,cbWndExtra域则为每个窗口实例分配的额外字节数。如果用户把窗口类比作C++ 的类,那么可把窗口的附加字节比作C++类中的成员函数。就像把在WNDCLASS的cbClsExtra域中定义的类附加字节比做一个类中的静态成员数据一样。在MainWindow构造函数中,用最后一个参数来调用CreateWindows函数。

//Do not create unless prevoidsly registered

MainWindow(void)

{

 //pass'this'pointer in lpParam of CreateWindow().

 hWnd = CreateWindow(szClassName,

  szClassName,

  WS_OVERLAPPEDWINDOW,

  CW_USEDEFAULT,

  0,

  CW_USEDEFAULT,

  0,

  NULL,

  NULL,

  Main::hInstance

  (LPSTR)this);

 

 if(!hWnd)

 {

  exit(FALSE);

 }

 

 Show(Main::nCmdShow);

 Update();

 

}

 

long WndProc(WORD iMessage,WORD wParam,LONG lParam);

//print a message in the client rectangle.

void Paint(void);

//Sturct used by Paint to pass information to callback funciton

//used by lineDDA

 

struct LINEFUNCDATA

{

 HDC hDC;

 char FAR* LineMessage;

 int MessageLength;

 

 LINEFUNCDATA(char* Message)

 {

  hDC = 0;

  MessageLength = strlen(Message);

  LineMessage = new far char[MessageLength +1];

  lstrcpy(LineMessage,Message);

 }

 ~LINEFUNCDATA(void){delete lineMessage;};

}

 

char MainWindow::szClassName[]= “Hello,World!”;

 

void MainWindow::Paint(void)

{

 PAINTSTRUCT ps;

 RECT rect;

 FARPROC

© 版权声明

相关文章

暂无评论

none
暂无评论...