在Visual C++.NET中建立视窗应用程序

来源: 作者: 2006-11-24 出处:pcdog.com

.net  java  xml  硬盘  
       
大多数人都会告诉你在Visual C++.NET中无法创建一个Windows视窗应用程序。但严格说来,并非如此。在Visual C++中,我们无法利用图形设计器来拖动、撤消以及调整布置你的按钮,标识。
像我这样的老程序员都记得Visual C++的命名来于它的权能,但我们也记得另一种途径。通过这种途径,我们可以制作用户界面,创建按钮标识以及在程序中类似出现的操作界面,并利用数行程序代码来设定其界面的大小和位置。所有的视觉图形设计程序所做的是在图形景象背后生成程序代码,而此时此刻,这些程序仅仅只能生成C#或VB.NET代码。 

在.NET中,由设计程序所生成的原代码并没有被隐藏在什么地方,或只有当你创建时才生成程序代码。无论如何,只要打开数个文件夹便能轻松得到这些程序代码,而且这也意味着拷贝这些程序代码并非难事。下面,我将告诉大家如何利用C#程序来创建一个用户界面,然后只需稍做编译便可转换成一个100%的C++应用程序。在上述过程中,读者也会对C#语言和C++语言之间的差异有所认识。 

微软开发商网络(MSDN)有一个用户化方案的样本被称为ManagedCWinFormWiz。当你将MSDN的光盘或数字视频光盘中的一些文件夹拷贝到电脑硬盘的特定位置时,下次一旦你在C++环境中点击File->New Project便会得到一个额外的选择项:Managed C++ Windows Forms Project。到达这样一个向导无需什么步骤,也不费很多工作,但不要过于沉浸于如此简易的操作中。点击选项后便可看到一个带有菜单和几个控制键的视窗界面,在这个视窗中你可以看到那些需要手动添加程序代码的地方。但拷入硬盘的这些文件对于创建用户界面根本毫无作用,甚至当你的Windows应用程序运行时去掉背景中的丑陋的黑色的命令提示行这样简单的变换,那些文件都无法帮你完成。那么在本次专栏中提供的样本代码,如果好好利用,你将受益匪浅。 

当然也要记住这个事实:.NET具有交叉语言应用发展能力。这就意味着我们可以用C#语言来创作你的用户界面,并可以和用C++语言编写的商用软件共同运行。尽管如此,我仍然确信我能在一个工程中只使用其中的一种语言来完成这一切,因为我并不认为Visual C++会以何种方式而受到限制。 

现在开始

我将以建立一个C#应用程序来开始我的讲解。如果你想跟上我的讲解,请打开Visual Studio并选择File->New Project,然后在界面左边选择Visual C#并在界面的右边选择Windows Application,并给新工程命名为cs1,以便你所有的文件名和我的文件名相称。在视窗设计软件中,很快地拖住一个按钮和它旁边的一个标识即可(你也可以通过选择View->Toolbox来将按钮和卷标界面拖出)。所得到的用户界面如图一所示。 

在Visual C++.NET中建立视窗应用程序
图1


将按钮上字幕说明改为Greet Me并将卷标上的字幕说明改为空白,但仍然将它们的名称保留为创建时的名称。对于一个真正意义上的应用程序,应该继续顺利进行下去,制作一个功能综合而且界面漂亮的用户界面。下一步我们便双击这个按钮以产生一个事件处理器,我在这里仅添加了一行代码: 

label1.txt="hello!"
 
如果你愿意,可以创建并运行这行代码以让你自己确信这行代码能正常运行。点击按钮便可发现卷标的字幕说明变成了"Hello!",这正是你需要的。退出这个应用并选择File->Close Solution以便在Visual Studio中关闭该工程。 

创建C++应用程序

要创建一个能逐渐演变为展示你Windows视窗应用程序的空C++应用程序,首先选择File->New Project,并在界面左边选择Visual C++ projects,在界面右边选择Managed C++ Application。将该工程命名为cpp1以便让你的文件名和变量名与我的相匹配。用记事本从C#应用程序打开代码Form1.cs,选择并拷贝表格中的所有内容,粘贴到_tmain() function函数之前的cpp1.cpp中。 

C#和C++之间的区别

现在的工作是要把C#语言的程序转变为C++的程序。在做这个工作的时候,请记住一点,编译器是你的朋友,它会提醒你所忘记做的任何变换。这两种语言最重要的区别主要包括: 

1. C#在主名字空间与子名字空间之间、主名字空间与类之间、类与静态成员函数之间以及对象引用和实例函数之间用点号(.)隔开,而C++则使用范围分解运算符(::)来分隔前三类关系,使用符号(->)来分隔最后一类关系。 

2. C#中返回的是对象的参量,而C++返回的却是指针。C++无法生成指定对象的实例,而只能得到指向该对象的一个指针,因此必须将声明由Foo改为Foo*。 

3. C#可以通过菜单在工程中添加引用,而C++则需要使用#号来声明。(每个类的在线帮助都会告诉你该类是在什么样的汇编语言程序中,例如System.dll,因此你可以添加恰当地#号说明语句)。 

4. C#在每个声明中都可以重复使用存取指定符(private,public,etc),而C++则是为某一特定的存取指示符开辟一部分内存。 

5. C#在声明一个成员变量时可以对其进行初始化,而C++则不行。 

6. C#中对于表示空参变量的关键字是null,而C++始终把空指针表示为NULL。 

7. C#中,在一个基本类中忽略一个函数,你需要使用表示忽略的关键字来指示你是有意的忽略一个函数;而这样的指示对C++来说则是不必要的。 

8. 虽然C#没有一个预处理器,但C#却有一些以#开头的关键字,这些关键字更多的是直接对于集成电路设备的指令而并非对于编译器的指令。这些关键字在C++中通常都不被支持,因此必须删掉。例如,在概要语句中最普通的两个带#的关键字是#region和#endregion。 

9. C#可以很轻松的用圆括弧来声明非工作状态下的数组;C++却不允许把这样的数组看作是函数的参量。你或者创建一个符合要求的临时数组,或者寻找另外一个被称为多重计时的函数,这个函数无需符合要求的数组。 

10. C#中把基本类直接称为base,而C++却是使用基本类的确切名称以及范围分解运算符::。 

11. 在基本类库中的一些类实际上就是数值类型,这就意味着在C++中这样的类无法用新的代码语句来创建,也不能通过指针来查阅。指向(Point)和尺寸(Size)这两个类就是很好的例子。 

12. 在C++中合格的函数指针语句需要一个&符号,而在C#中却没有这个要求。C#中对成员函数指针的语法指定要比C++更简单一点。 

编辑成C++

了解并掌握了C#和C++之间的差异,我们接下来的工作就是一步步将你刚才粘贴到C++源文件中的那部分C#语言代码进行编译,使其成为正确的C++语言代码。 

1. 在类定义的结束处找到结束性圆括弧(不要与主名字空间部分结束处的圆括弧相混淆)并在括弧后面加一个分号。 

2. 将Form1类的成员声明表区:System.Windows.Forms.Form 改成Form1类的成员声明表区_gc: public System::windows::Forms::Form。 

3. 将以开始使用System的代码区变换成以开始使用主名字空间System的代码区。 

4. 将所有名称分隔符.改为::,例如将System.Data改为System::Data。 

5. 在使用主名字空间陈述代码区之前添加以下几行代码: 

#using <System.dll>
        #using <System.Drawing.dll>
        #using <System.Windows.Forms.dll>
        #using <System.Data.dll>
 
6. 找到那些类似System.Windows.Forms.Button这样完全符合要求的名称,将其中所有的.号改成::号,或最好去掉整个名称再将其定义成一个单词Button即可(对于程序容器来说,去掉全名可以避免编译器报错)。 

7. 将在C++中被看作固定对象的对引用的声明改为指针。例如,将Button button1变成Button* button1。 

8. 从各自单独的声明中去掉字private或public,并在提出声明之前的一行属于各自自身的代码中将其替换成private:或pulic:。 

9. 在声明成分的代码行中去掉=null,并针对构造器添加一行代码以把该成分设置为NULL。 

10. 将this.编辑并置换成this->或完全去掉,因为在这个例子中不存在任何名字上的冲突。 

11. 去掉代码中任何的表示忽略的关键字。 

12. 去掉所有象#region和#endregion这样的预处理指令。 

13. 将点击按钮1的程序button_1Click()的标记符改为获取指针: 

void button1_Click(Object* sender, System::EventArgs* e)
 
14. 把下列单独一行: 

Controls.AddRange(new System.Windows.Forms.Control[] );
 
改为以下两行: 

Controls->Add(label1); 
      Controls->Add(button1);
 
15. 在处理方法上,将base.Dispose( disposing ); 改为 Form::Dispose( disposing ); 

16. 找到那些创建新指向(Point)对象的代码行,并去掉新的关键字,这样我们可以把代码行改成如下所示的形式: 

label1->Location = Point(184, 96);
 
17. 对于有关尺寸(Size)类的代码行也做同样的变换,但仍然使用全名称谓System::Drawing::Size,这样可以避免与表格中的尺寸属性相冲突。 

18. 对InitializeComponent()这样能将button1_Click()添加到处理程序的清单列表中的函数中间部分做改动,以使得能够点击按钮1,那么代码行 

this.button1.Click += new System.EventHandler(this.button1_Click);
 
将改为 

button1->Click += new System::EventHandler(this, &Form1::button1_Click);

19. 将Form1::Main()中唯一的代码行移入_tmain()中,稍做编译变为:Application::Run(new cs1::Form1()); (如果你将原来主名字空间的名字cs1做了改变,那么对该行代码进行调整即可)。 

20. 因为Form1::Main()没有什么更深一步的工作要做,所以可以完全去掉它。 

21. 为了展示你的应用程序,还要将对_tmain()的声明改为int_stdcall WinMain(),这样你在运行你的Windows视窗应用程序时在你程序的视窗背景中不会出现一个黑色的警告框。 

以上就是我们所需要完成的工作,试着创建一个并运行看看。如果你的编译器报错,那可能是在修改语言时漏掉了某处,出现的提示信息会告诉什么地方需要修改。我为大家提供的程序代码大致如下: 

// This is the main project file for VC++ application project 
// generated using an Application Wizard.
#include "stdafx.h"
#using <mscorlib.dll>
#include <tchar.h>
#using <System.dll>
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>
#using <System.Data.dll>
using namespace System;
using namespace System::Drawing;
using namespace System::Collections;
using namespace System::ComponentModel;
using namespace System::Windows::Forms;
using namespace System::Data;
namespace cs1
{
   /// <summary>
   /// Summary description for Form1.
   /// </summary>
public __gc class Form1 : public System::Windows::Forms::Form
   {
   private:
      Button* button1;
      Label* label1;
      /// <summary>
      /// Required designer variable.
      /// </summary>
      System::ComponentModel::Container* components;
   public:
      Form1()
      {
         //
         // Required for Windows Form Designer support
         //
         components = NULL;
         InitializeComponent();

         //
         // TODO: Add any constructor code after 
         // InitializeComponent call
         //
      }

      /// <summary>
      /// Clean up any resources being used.
      /// </summary>
   protected:
      void Dispose( bool disposing )
      {
         if( disposing )
         {
            if (components != NULL) 
            {
               components->Dispose();
            }
         }
         Form::Dispose( disposing );
      }

      /// <summary>
      /// Required method for Designer support - do not modify
      /// the contents of this method with the code editor.
      /// </summary>
   private:
      void InitializeComponent()
      {
         button1 = new Button();
         label1 = new Label();
         SuspendLayout();
         // 
         // button1
         // 
         button1->Location = Point(48, 96);
         button1->Name = "button1";
         button1->TabIndex = 0;
         button1->Text = "Greet Me";
         button1->Click += new System::EventHandler(this,
                                    &Form1::button1_Click);
         // 
         // label1
         // 
         label1->Location = Point(184, 96);
         label1->Name = "label1";
         label1->TabIndex = 1;
         // 
         // Form1
         // 
         AutoScaleBaseSize =  System::Drawing::Size(5, 13);
         ClientSize =  System::Drawing::Size(292, 273);
         Controls->Add(label1);
         Controls->Add(button1);
         Name = "Form1";
         Text = "Form1";
         ResumeLayout(false);

      }

   private:
      void button1_Click(Object* sender, System::EventArgs* e)
      {
         label1->Text = "Hello from C++!";
      }
   };
}

// This is the entry point for this application
int __stdcall WinMain()
{
   Application::Run(new cs1::Form1());
    return 0;
}
 
你以后还想对你的用户界面做什么样的变换吗?是在用户界面上再添加一个按钮和处理器,还是想移动用户界面上已存在的某个控制键?那么,你有两个选择:对你已有的C++程序代码进行修改编译,或者你回到最初的C#应用程序中来编译改建你的用户界面,然后再对产生的新代码做一些细致的拷贝以及再编译工作使其C#代码转变成C++代码。 

你会发现界面中每个控制键的位置、名称以及控制键上的文字内容都是在InitializeCompenent()这个函数中定义设置的,所以改变编译这个函数中的的程序代码即可随意的重新布置你的用户界面,或拷贝这些程序代码就可以添加更多的控制键和处理器。 

小结

好了,这就是我这次讲解的全部内容。我希望能向你展示比你最初认识C++时更强的应用能力,而且也示范说明了C#和C++之间的一些语法上的差异。 

关于作者 

Kate Gregory是Gregory咨询公司(www.gregcons.com)的创建者之一。2002年1月,被指派为MSDN的多伦多地区的主管。她在C++方面的经验可以追溯到Visual C++存在以前。她是一个在大学和微软中知名的演说家,涉及的内容包括NET, Visual Studio, XML, UML, C++, Java, 和Internet。Kate和她公司的同事们擅长于结合软件和网站的开发以创建活力十足的网站。她们创建针对WEB页面和其他程序的畅销软件。Kate还是很多有关Que的书的作者,包括Special Edition Using Visual C++ .NET。 
更多内容请看PCdog.com--.NET应用研究  C/C++进阶技术文档  C/C++应用实例专题
上一篇:在VC++下关于工具条的设计
下一篇:在Visual C++中使用fopen()函数来读写文件