程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> 使用C++的托管擴展針對Windows窗體編程

使用C++的托管擴展針對Windows窗體編程

編輯:vc教程

摘要:本文討論了如何使用 Visual C++ .NET 的托管擴展針對 Windows 窗體編程,並提供了使用直接訪問 Windows 窗體類的手動編程技術的示例,以及使用 Windows 窗體設計器的示例。此外,本文還對 Windows 窗體和 Microsoft 基礎類 (MFC) 應用程序進行了比較。

簡介

長期以來,程序員們都使用 C 和 C++ 來開發 Windows GUI 應用程序。對於我們當中很多人來說,這一段歷史可以追溯到 Windows 2.0 時期,那時,我們使用基於 C 的 16 位 Windows API,即便只是顯示一個窗口,也需要編寫數十行代碼。幸運的是,隨著時間的推移,抽象的級別越來越高,越來越好。在 1992 年,Microsoft 發行了 Programmer's Workbench,其中包括 Microsoft 基礎類庫 1.0 版。Microsoft 基礎類庫 1.0 版包含大約 60 個類,用於包裝窗口化編程和繪制部分的 16 位 Windows API。到 2002 年為止,Microsoft 基礎類庫 7.0 版已經發展為超過 200 個類,並且,其用途已經擴展為能夠提供 Microsoft Win32 API 的完整 C++ 對象模型替代物。

雖然 MFC 非常強大,但它也有很多缺點,比如它只是 Win32 API 外的一層薄薄的面板,並且對於很多程序員來說,它太過復雜,很難有效地使用。通常,要開發 Windows 應用程序,仍需要直接訪問 Win32 API,特別是在對 Windows 應用程序所需的基本功能的要求不斷提升的情況下。因此,要開發任何功能真正強大的 Windows GUI 應用程序,需要耗費大量時間精力。為了應對應用程序開發難度不斷提高的狀況,Microsoft 於 2002 年初發行了一個針對 Windows 平台的新編程環境。該環境稱為 .NET 框架,它為開發人員提供了一個托管 應用程序運行庫,以及稱為 .NET 框架類庫的大量庫。.NET 框架可以管理內存和安全性,從而能夠產生更為可靠的應用程序。.NET 框架類庫提供了一個大型、資源豐富和統一的類庫,任何 .NET 語言(包括 Micrisoft 為 .NET 程序員提供的 C++ 的托管擴展和 C++ 的托管版),都可以以相同的方式同等地訪問該類庫。作為 .NET 框架的一部分,Windows 窗體是一組用於構建客戶端 Windows GUI 應用程序的類。

本文中,我們將深入了解如何使用 C++ 的托管擴展編寫 Windows 窗體代碼,先介紹如何從頭開始編寫,然後講解如何使用 Microsoft Visual Studio .NET 2003 來完成這一任務。與此同時,我們將著重介紹 Windows 窗體的一些常用功能,如自動布局和數據綁定。最後,我們將把注意力集中到 Windows 窗體與 MFC 的比較以及在進一步使用托管擴展時,如何混合使用這兩套工具。

什麼是 Windows 窗體?

Windows 窗體是一個窗口化工具包,而不像 MFC 一樣是完整的應用程序框架。事實上,相對於 Windows 窗體所提供的用於構建基於文檔的獨立應用程序的功能來說,MFC 提供的功能更多。例如,如果要生成一個文本編輯器,在 MFC 中,只需運行一個向導,選擇適當的選項並編寫若干行代碼即可完成。僅僅是通過運行該向導得到的應用程序就包含了一個狀態欄、一個工具欄(浮動),並實現了所有的 File、Edit 和 Help 菜單項,其中包括最近使用的文件列表和打印以及上下文相關的幫助,所有這些內容都包含在一個完全徽標兼容的單文檔界面 (SDI)、多 SDI 或多文檔界面 (MDI) 應用程序中。作為基於文檔的應用程序框架,沒有能夠與 MFC 相匹敵的競爭者。

但是,程序員們現在傾向於構建更多基於 HTML 的應用程序,或者能夠與業務對象或數據庫服務器通信的應用程序,而不是基於文檔的應用程序。.NET 框架和 Windows 窗體正是為這一目的而量身定做的。

這並不是說 Windows 窗體不能用來構建優秀的基於文檔的應用程序。實際上,由於 Windows 窗體只是 .NET 框架所提供的超過 2000 個類中的一小部分,您所需要的內容很有可能 Windows 窗體並沒有提供,而是位於該框架中的其他部分中。例如,Windows 窗體本身並不提供任何對象序列化支持,但是 .NET 框架類庫的其余部分提供了多種序列化對象圖的方法。

這是 MFC 和 Windows 窗體之間的主要區別。MFC 旨在替代基礎 Win32 API,但這並不能阻止 Win32 API 增長。事實上,就像 MFC 隨時間的不斷增長一樣,基礎 OS 的功能最少增加了十倍。但是,Windows 窗體只是 Win32 的窗口化部分的替代物。.NET 框架類的其余部分負責替代其余的 Win32。當然,框架永遠不可能替代整個 Win32 API,不過,由於在可預期的未來,大多數要添加到 Windows 中的新功能都要被添加到框架中,替代整個 Win32 API 將是一個未來的目標。

因此,雖然 Windows 窗體不能具有 MFC 的全部功能,但它的確提供了一組很強的功能,可以極大地便利客戶端應用程序開發人員,這其中包括一些 MFC 完全不具備的功能。下面,我們將介紹如何從頭開始構建應用程序,然後講解 Visual Studio .NET 2003 為 Windows 窗體 C++ 程序員提供的工作效率改進功能。

從頭開始創建 Windows 窗體

典型的 Windows 窗體應用程序有至少一個窗體。窗體就是一個窗口,也就是從 Windows 1.0 開始我們所看到的 Microsoft 用戶界面單元。通常,Windows 窗體應用程序中的一個窗體是主窗體,意思是它是應用程序的生存周期內可能顯示的所有其他窗體的父級或所有者。該窗體是顯示主菜單以及工具欄、任務欄等的位置。主窗體結束時,應用程序也退出。

應用程序的主窗體可以是一個簡單的消息框、一個對話框、一個 SDI 窗口、一個 MDI 窗口,或者更為復雜的控件,如 Visual Studio .NET 這樣的應用程序中具有多個子窗口、工具窗口和浮動工具欄的窗體。

如果您的應用程序極為簡單,可以使用充斥在任何窗口化系統中的簡樸的消息框來實現它:

#using <mscorlib.dll>
#using <System.dll>
#using <System.Windows.Forms.dll>
void __stdcall WinMain(HINSTANCE hInstance,
       HINSTANCE hPrevInstance,
     long lpCmdLine,
     int nCmdShow)
{
 System::Windows::Forms::MessageBox::Show("Hello, Windows Forms");
}

作為 C++ 程序員,您必定非常熟悉 WinMain 入口點,在托管應用程序中,仍需要該入口點。在我們的第一個 Windows 窗體應用程序中,唯一一行實際的代碼調用了 Windows::System::Forms::MessageBox 類的靜態 Show 方法,這其實只是調用包含在 Window::Systems::Forms 命名空間 內的 MessageBox 類的靜態方法的長寫形式。.NET 框架類庫中廣泛使用了命名空間來將類、結構、枚舉等類型分隔為不同的邏輯組。由於有數以千計的 Microsoft 雇員要從事添加 .NET 框架類庫的工作,而且有數以百計的第三方組織要擴展該類庫,同時有數以百萬計的程序員正在嘗試學習它,因此這種分隔是非常必要的。沒有命名空間,就需要采用各種復雜的約定來唯一地命名各種對象(像現有的 Win32 API 一樣)。

命名空間中的類型的定義位於 .NET 程序集 中。程序集是打包為 DLL 或 EXE 的托管類型的容器。#using 指令用於將程序集中的類型應用到您的應用程序中。例如,mscorlib 和 System 程序集提供了基本的 .NET 框架類型,如 int 和 string。System.Windows.Forms 程序集包含了 Windows 窗體類型。

使用 #using 將程序集應用到應用程序中後,就可以以前面講到的長寫形式引用類型,或者,可以使用標准的 C++ using namespace 語句來省略鍵入代碼的工作:

#using <mscorlib.dll>
#using <System.Windows.Forms.dll>
using namespace System::Windows::Forms;
void __stdcall WinMain(HINSTANCE hInstance,
       HINSTANCE hPrevInstance,
     long lpCmdLine,
     int nCmdShow)
{
 MessageBox::Show("Hello, Windows Forms");
}

因此,雖然這個簡單的示例很有效地演示了最基本的 .NET 框架和 C++ 的托管擴展的概念,但它並不能很好地演示典型的 Windows 窗體程序。對於真實的應用程序,將需要一個 Form 類(或從 Form 派生的類)的實例,如下所示:

void __stdcall WinMain(HINSTANCE hInstance,
       HINSTANCE hPrevInstance,
     long lpCmdLine,
     int nCmdShow)
{
 Form* form = new Form();
 ...
}

form 變量引用了托管類型的一個實例。托管對象是由 .NET 框架的公共語言運行庫 (CLR) 處理的,它們的生存周期由垃圾回收器控制的,該回收器在一定的時間取消分配內存。因此,C++ 程序員無需顯式地刪除托管類型,但是同樣不能指望在任何特定時刻(如關閉范圍時)破壞對象。

創建窗體後,就需要顯示它。如果您曾經看過 Windows 窗體的文檔,可能已經注意到了 Form 方法 Show,這意味著:

void __stdcall WinMain(HINSTANCE hInstance,
       HINSTANCE hPrevInstance,
     long lpCmdLine,
     int nCmdShow)
{
 Form* form = new Form();
 form->Show(); // This is not what you want to do.
}

雖然上面的代碼可以顯示窗體,但是必須眼疾手快才可以看到該窗體,這是因為 Show 以無模式的方式顯示窗體。這意味著在 Show 將新的窗體顯示到屏幕上之後,會立即將控制權返回給 Main 函數,該函數在返回時將退出進程,同時關閉剛剛顯示不久的窗體。要以有模式的方式顯示窗體,文檔建議使用 ShowDialog 函數:

void __stdcall WinMain(HINSTANCE hInstance,
       HINSTANCE hPrevInstance,
     long lpCmdLine,
     int nCmdShow)
{
 Form* form = new Form();
 form->ShowDialog(); // This is not quite what you want to do.
}

雖然這些代碼事實上可以顯示一個空窗體,並且在用戶關閉它之後才會將控制權返回給 Main 函數,但通常您並不會編寫這樣的代碼。相反,您將把一個窗體指定為主窗體,使得應用程序的其他部分可以把它當作主窗體來進行訪問。為此,可以將主窗體作為一個參數傳遞給 Windows 窗體的 Application 對象的 Run 方法:

#using <mscorlib.dll>
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System::Windows::Forms;
void __stdcall WinMain(HINSTANCE hInstance,
       HINSTANCE hPrevInstance,
     long lpCmdLine,
     int nCmdShow)
{
 Application::Run(new Form);
}

Application 類的靜態 Run 方法將顯示主窗體並開始發送 Windows 消息,直到主窗體關閉為止。主窗體關閉後,Run 將返回,讓我們的 Main 函數退出,以便結束進程。要實際查看這一過程,可以使用下面的命令行編譯這個小小的 Windows 窗體應用程序:

C:MSDNMYFIRS~1>cl /clr MyFirstApp.cpp

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved