如前所述,控制台应用程序让你能够把应用程序的商务逻辑从DOS环境迁移到Windows环境。你也可以迁移某些(甚至是绝大多数)显示逻辑,但也需要一些MFC提供的功能。本质上讲,控制台应用程序就像添加了一些特性的DOS应用程序。编码之后,需要彻底地测试控制台应用程序,以确保从DOS迁移到Windows的各种特性依然能够正确地工作。 让我们探讨一个相当简单的控制台应用程序,看看在这个程序中你能做些什么。这个示例中,我们并不把程序的功能看得很重要,只是要了解应该如何完成示例。当然,第一步的工作是创建程序框架。按下述步骤进行操作: 1. 如果你还没有启动Visual C++,那么启动Visual C++。 2. 使用File|New命令显示如下图所示的New对话框。注意,我已经选择了Projects选项卡并加亮了要在本例中使用的工程类型。  3. 当选择了Win32 Console Application后,在Project Name域中键入程序名称。这个样本程序使用的名称为Console。你或许还需要修改一下Location域的内容,那么单击一下该域旁边的浏览按钮,系统会显示Choose Directory对话框,在这个对话框中选择应用程序的存放目录。 4. 单击OK按钮。你会看到Win32 Console Application - Step 1 of 1对话框,如下图所示。注意,在这个对话框中有几个应用程序类型供选择。这也是VisualC++ 6.0的一个新特性。以前版本的Visual C++简单地创建一个空的工程。现在到了选择要创建哪种类型工程的时候了(即使空工程也要进行选择)。  5. (必要时)选择An Empty Project,然后单击Finish。你会看到一个NewProject Information对话框,它告诉你都选择了哪些选项。 6. 单击OK按钮创建示例程序。 在该工程真正能够运行之前,还需要完成其它一些步骤。该工程需要MFC类。当你把对该类的支持加入到上面的应用程序向导的设置中时,再次使用该向导把DOS应用程序转换到Windows下时所需的重写代码的代码量就会显著减少。选择Project | Settings命令显示Project Settings对话框,选择该对话框的General选项卡,并在Settings For组合框中选择All Configurations,在MicrosoftFoundation Classes组合框中选择Use MFC in a Shared DLL选项。单击OK完成设置工作。 现在到了给示例程序添加代码的时候了。需要完成的第一件事是向工程中添加一个文件,让我们看看添加过程。 1. 使用File | New命令打开New对话框,选择File选项卡,其中显示了文件类型的完整列表,包括Resource Template以及像Icon File这样的各种图像文件。 2. 加亮C++ Source File选项。由于我们要在样本代码中添加一些类,因此要选择C++源文件选项。 3. 在File Name域中键入Console(Visual C++会自动添加上正确的文件扩展名)。 4. 单击OK。系统显示一个空的C++源文件。 现在我们有了一个要使用的空文件,该添加一些代码了。程序列表2.1显示了该示例的C++源程序。注意,其中它既直接包括了一些C代码,也包括了一些C++代码。我这样做的目的就是为了让读者看清楚在这种环境下系统是如何工作的。 程序列表2.1 #include <afxcoll.h> //Provides Access to MFC functions Class CDrawBox : public CObject { public : // Draws the box. void DoDraw(char * string) }; void CDrawBox :: DoDraw(char * cValue) { int iCount; //Loop counter int iSpace; //Amount of spaces to add for string. // Draw the top of the box fprintf(stdout,"\311"); for (iCount = 1; iCount <= 78 ; iCount ++) { fprintf(stdout,"\315"); } fprintf(stdout,"\273"); // Figure out the center of the string, then display it // with the box sides. iSpace = (80 - strlen(cValue)) / 2; fprintf(stdout,"\272"); for (iCount = 1; iCount <= iSpaces ; iCount ++) { fprintf(stdout," "); } fprintf(stdout, "%s", cValue); // Compensate for odd sized strings, then complete the side. if ((strlen(cValue) % 2) == 1) { iSpaces --; } for (iCount = 1; iCount <= iSpaces ; iCount ++) { fprintf(stdout, " "); } fprintf(stdout,"\272"); // Draw the bottom of the box fprintf(stdout, "\310"); for (iCount = 1; iCount <= 78 ; iCount ++) { fprintf(stdout, "\315"); } fprintf(stdout, "\274\n"); }
int main(int argc, char ** argv) { char * cName; // Name of person typed at command line. char * cLocale; // Program execution location. CTime oMyTime; // A time object. CString cDate; // String used to hold time and date. CDrawBox oMyDraw; // Special text display. // See if we have enough command line arguments. if ( argc != 2) { fprintf(stderr, "Type the program name followed by your name.\n"); return 1; }
// Get the command line arguments cLocale = argv[0]; cName = argv[1];
// Get the current time and put it in a string. oMyTime = CTime::GetCurrentTime(); cDate = oMyTime.Format( "%A, %B %d,%Y" ); //Display everything we've collected. fprintf(stdout, "Hello %s\n\n", cName); fprintf(stdout, "Program is executing from: \n%s\n\n", cLocale); fprintf(stdout, "The date is: %s\n", cDate);
// Use our class to draw a box around some text. oMyDraw.DoDraw("It's a box!"); return 0; }
如你所见,在这个示例中我展示了四个基本技巧。第一个技巧是对命令行参数适宜个数的检查,如果不满足所需个数的话,就在stderr设备上显示一条出错信息,然后返回出错代码并退出应用程序。你可以在DOS命令行中检测这个错误代码,但对Windows来说根本不起作用。一旦代码检测到有足够的命令行参数,它就把这些参数放入一对变量中,用于随后的显示。 到现在为止你看到的还都是DOS应用程序的代码。代码中使用的第二个技巧是得到当前时间,它使用了一个MFC调用来完成这项任务。那么,如何才能够在控制台应用程序中访问MFC函数呢?正如你所看到的,我在代码的一开始就包含AFXCOLL.H文件,这个文件包含了控制台应用程序中调用的有限个MFC函数的所有定义和类定义。 不要以为你可以任意使用MFC调用。例如,不能创建CDialog对象并实际使用该对象。如果这样做的话,即使你让代码通过了编译,也可能会产生下述两种情况:或者程序以运行时错误而终止运行,或者应用程序忽略与对话框有关的代码。 技巧 在确定哪些MFC类可以使用时的一条重要原则是看该类是否操作图像元素。如果某个类操作图像元素的话,你就不能在控制台应用程序中使用该类。另外,你还会发现某些系统调用不再有效,并且当系统调用涉及安全问题和磁盘访问时,你还必须小心仔细地进行实验。如果存在疑问的话,那么就只好使用AFXCOLL.H(或其它任何相关的头文件,比如AFX.H)中列出的调用,而不使用其它调用。在任何控制台应用程序中你都可以安全地使用AFXCOLL.H文件中列出的所有调用。 现在我们已经得到了一些要显示的数据,随后的代码把这些数据发送到stdout(标准输出)设备上,这就是我要向读者展示的第三个技巧。在绝大多数t(标准输出)设备上,这就是我要向读者展示的第三个技巧。在绝大多数情况下,stdout代表了显示,当然,如果需要的话,你也可以轻易地把输出发送到其它地方。这里的要点是使用了与以前使用格式化方式相同的格式化方式。这样,你也可以在代码中使用fprintf()函数调用的地方使用简单一些的fprint()函数调用。 在main()函数中还有一个调用没有讲到,我们把数据发送到一个名称为CDrawBox的类中,这是我要向读者展示的第四个技巧。这个类要完成的任务就是在一个文本框中让文本居中对齐(使用ASCII字符集的高位字符)。你或许在许多DOS应用程序中见到过这种做法。这里的想法是从MFC CObject类中导出一个新类,然后在控制台应用程序中使用该新类。同样地,在你自己创建的应用程序也可以使用类似的技巧。正如前面我曾经介绍过的那样,当你把DOS应用程序迁移到Windows环境时,你会有一种向应用程序中添加更多功能的强烈愿望。添加功能意义的大小依赖于应用程序迁移时所耗费的时间长短以及增强功能对整个应用程序的相对价值的大小。 这个控制台应用程序示例可以开始运行了。然而,与你写过的许多DOS应用程序相似,为了便于测试,我们需要一个批处理文件。程序列表2.2是本例使用的批处理文件的源代码,它完成的任务是调用程序、测试是否出错、如果出错时反馈一条出错信息。前面你已经看到了该应用程序的输出,这里就不再重复了。 程序列表2.2 @ ECHO OFF CONSOLE IF ERRORLEVEL==1 ECHO IT'S BAD CONSOLE JOHN IF ERRORLEVEL==1 ECHO IT'S BAD @ ECHO ON
|