--- .NET Framework 元件互通**
**在本逐步解說中,您將會用 MFC 建立預訂機票的應用程式,
然後再將其升級為以 .NET Framework 為目標,並使用 Managed Extensions
for C++。
MFC 應用程式會處理預訂的工作。使用者介面為 MFC 應用程式,
其引擎是由包含公司差旅規定的 Helper 函式的 DLL (原生 C++) 和處理---
---預訂機位的 COM 物件 (原生 C++) 所構成 **
*注意 若要建立本逐步解說中所描述的應用程式,您必須能夠存取已經---
---安裝 Pubs 或 Northwind 資料庫的資料庫伺服器 *
**
*在本逐步解說中,您將會 :
*
*應用程式完成後的架構 :
***
*建立 MFC 應用程式
在本章節中,您將建立具有三個專案 (MFC、ATL COM 和 MFC DLL)---
--- 的原生 C++ MFC 應用程式,稱之為 ReservationDemo,
然後您可以在後面各章節中再對其進行修改 *
**若要建立 MFC 專案**
*
- 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。
出現 [新增專案] 對話方塊。 - 在 [專案類型] 窗格中按一下 [Visual C++ 專案],然後再按一下 [MFC]。
- 在 [範本] 窗格中按一下 [MFC 應用程式]。在 [名稱] 欄位中輸入 ReservationDemo,
- 然後按一下 [確定]。 出現 MFC 應用程式精靈。
- 按一下 [應用程式類型],然後選取 [對話方塊架構]。按一下 [完成]。
- 在 [類別檢視] 中用滑鼠右鍵按一下專案節點。在快速鍵功能表上
- 按一下 [加入],然後再按一下 [加入類別]。 出現 [加入類別] 對話方塊。
- 在 [類別] 窗格中展開 [Visual C++ 專案] 資料夾,然後再按一下 [泛用] 資料夾。
- 按一下 [開啟]。 出現泛用 C++ 類別精靈。
- 輸入 CEmployee 做為泛用 C++ 類別名稱。這是沒有基底類別的公用類別。
- 重複執行步驟 4 和 5,以建立泛用 C++ 類別 CReservation
*
- 在 [方案總管] 中用滑鼠右鍵按一下方案節點。在快速鍵功能表上按一下 [加入],
- 然後再按一下 [新增專案]。 出現 [加入新的專案] 對話方塊。
- 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下 [ATL]。
- 在 [樣板] 窗格中,按一下 [ATL 專案]。在 [名稱] 欄位中輸入 BookingObject,
- 然後選取 [加入至方案]。按一下 [確定]。 ATL 專案精靈就會出現。
- 按一下 [完成] 以接受預設值。
- 在 [類別檢視] 中用滑鼠右鍵按一下專案節點。在快速鍵功能表中按一下 [加入],
- 然後再按一下 [加入類別]。 出現 [加入類別] 對話方塊。
- 在 [類別] 窗格中展開 [Visual C++ 專案] 資料夾,然後再按一下 [ATL] 資料夾。
- 選取 [ATL 簡單物件] 並按一下 [開啟]。 出現 ATL 簡單物件精靈。
- 在 [簡短名稱] 欄位輸入 Booking,再按一下 [確定]。
- 在 [方案總管] 中連按兩下 Booking.h,將粗體字所示的程式碼加入
IBooking
{
[id(1), helpstring("method Reserve")] HRESULT Reserve(void);
[id(2), helpstring("method NewBooking")] HRESULT NewBooking([in]
BSTR fromCity, [in] BSTR toCity, [in] BYTE day, [in] BYTE month);
[id(3), helpstring("method CheckAvailability")] HRESULT
CheckAvailability([out,retval] BYTE* result);
};
8).在 Booking.h 中,將粗體字所示的程式碼加入
CBooking
宣告的結尾:class ATL_NO_VTABLE CBooking : public IBooking
{
...
public:
STDMETHOD(Reserve)(void);
STDMETHOD(NewBooking)(BSTR fromCity, BSTR toCity, BYTE day,
BYTE month);
STDMETHOD(CheckAvailability)(BYTE* result);
private:
CString from;
CString to;
int day;
int month;
}
**若要建立 MFC DLL 專案**
- 在 [方案總管] 中,用滑鼠右鍵按一下方案節點。在快速鍵功能表中按一下 [加入],
- 然後再按一下 [新增專案]。
出現 [加入新的專案] 對話方塊。 - 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下 [MFC]。
- 在 [樣板] 窗格中,按一下 [MFC DLL]。在 [名稱] 欄位中輸入 TravelPolicy,
- 再選取 [加入至方案]。請按一下 [確定]。 會出現 MFC DLL 精靈。
- 按一下 [完成] 以接受預設值 .
*在本章節中,您會將現有原生 C++ MFC 應用程式 ReservationDemo 轉換--
--為 Managed 程式碼,再用 /clr 編譯器選項來編譯 .
*若要使用 /clr 編譯器選項來編譯*
- 在 [方案總管] 中,用滑鼠右鍵按一下 [ReservationDemo],再按一下 [屬性]。
[屬性頁] 對話方塊就會出現。 - 展開 [C/C++] 節點。
- 在 [命令列] 中,請於 [其他選項] 方塊中輸入 /clr。
- 在 [程式碼產生] 中,將 [基礎 Runtime 檢查] 設為 [預設值],
- 並將 [啟用最少重建] 設為「否」。
- 在 [一般] 中選取 [偵錯資訊格式],並將它變更為 [程式資料庫 (/Zi)]。
- 按一下 [確定],關閉這個對話方塊。
- 在 [建置] 功能表上,按一下 [建置方案]。
- 在 [偵錯] 功能表上,按一下 [啟動但不偵錯]。
CFlight
。CFlight
將處理航班資訊,並使用 Unmanaged CReservation
類別來處理實際的預留機位 為了讓 Managed 類別能夠和 Unmanaged 類別互動,
您必須為 Unmanaged 類別另外使用 Managed 包裝函式 (
CReservationWrapper
). ****若要建立 Managed 包裝函式類別**
- 在 [類別檢視] 中,用滑鼠右鍵按一下 [ReservationDemo] 專案節點。
- 在快速鍵功能表中按一下 [加入],然後再按一下 [加入類別]。 出現加入類別精靈。
- 選取 [泛用 C++ 類別],並輸入 CReservationWrapper 做為類別名稱。按一下 [完成]。
- 在 ReservationWrapper.h 中加入下列 #include 陳述式:
5).在 ReservationWrapper.h 中將下列成員加入至類別:
CReservation * r;
int Reserve(void);
6).在 ReservationWrapper.cpp 中,以下列程式碼來取代檔案的全部內容:
#include "StdAfx.h"
#include ".\reservationwrapper.h"
#using <mscorlib.dll>
using namespace System;
using namespace System::Runtime::InteropServices;
CReservationWrapper::CReservationWrapper(void)
{
System::String * strFrom = S"from";
System::String * strTo = S"to";
CString csFromCity ((char*)(void*)
Marshal::StringToHGlobalAnsi(strFrom));
CString csToCity ((char*)(void*)
Marshal::StringToHGlobalAnsi(strTo));
r = new CReservation(&csFromCity, &csToCity, 17,1,2,2);
}
CReservationWrapper::Reserve()
{
int res = r->Reserve();
return res;
}
CReservationWrapper::~CReservationWrapper(void)
{
delete r;
}
5*若要建立 Managed 類別*
- 在 [類別檢視] 中,用滑鼠右鍵按一下 [ReservationDemo] 專案節點。
- 在快速鍵功能表中按一下 [加入],然後再按一下 [加入類別]。 出現加入類別精靈。
- 選取 [泛用 C++ 類別],再輸入 CFlight 做為類別名稱。按一下 [完成]。
- 將 Flight.h 中的類別定義修改成如下所示
{
public:
CFlight();
void Reserve();
};
5).在 Flight.cpp 中,以下列程式碼來取代檔案的全部內容:
#include "StdAfx.h"
#include "Flight.h"
#include "ReservationWrapper.h"
#using <mscorlib.dll>
CFlight::CFlight(void)
{
}
void CFlight::Reserve()
{
CReservationWrapper *res = new CReservationWrapper();
res->Reserve();
}
若要修改 CEmployee 以使用 CFlight
1).在 Employee.cpp 中加入下列 #include 陳述式:
#include <vcclr.h>
#include "Flight.h"
2).在 Employee.cpp 中,修改
MakeReservation
的實作以執行------個體化
CFlight
物件為如下所示 (粗體字程式碼代表變更處)。請注意程式碼如何使用 gcroot 來包含 Managed 類別:
int CEmployee::MakeReservation (CString *from, CString *to, int day1,
int month1, int day2, int month2)
{
gcroot<CFlight*> flight;
flight->Reserve();
}
3).在 Reservation.cpp 中,將
Reserve
實作中的 if 陳述式修改為如下所示(粗體字程式碼代表變更處):
if (b->CheckAvailability())
{
b->Reserve();
return res;
}
else
return res + 10;
}
4).在 [方案總管] 中,用滑鼠右鍵按一下 [ReservationDemo] 專案節點
5).
- 在快速鍵功能表上,按一下 [建置]。
EmployeeCodes
和 EmployeeData
) 提供員工資訊以用來擷取員工的資訊。第一個服務會取得員工 ID 的資訊;第二個服務則會取得員工的其他資料。
這兩個服務都會使用 IJW 呼叫一個原生 DLL (
EmployeeDLL
) 以取得所需資訊。
若要建立 EmployeeDLL 原生 C++ DLL 以提供員工資訊
- 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。
- 出現 [新增專案] 對話方塊。
- 在 [專案類型] 窗格中,按一下 [Visual C++ 專案],然後在 [範本] 窗格中,
- 按一下 [Win32 專案]。在 [名稱] 方塊中輸入 EmployeeDLL,
- 再選取 [加入至方案]。按一下 [確定]。
- 修改 EmployeeDLL.cpp 檔中的程式碼
extern "C" __declspec(dllexport) int EmployeeID(LPSTR name)
{
return (int) *name;
}
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
4).
- 在 [方案總管] 中,用滑鼠右鍵按一下專案。在快速鍵功能表上,按一下 [建置]。
若要建立 EmployeeCodes XML Web Service
- 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。 出現 [新增專案] 對話方塊。
- 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下 [.NET]。
- 在 [樣板] 窗格中按一下 [ASP.NET Web 服務]。
- 在 [名稱] 欄位中輸入 EmployeeCodes,再選取 [加入至方案]。按一下 [確定]。
- EmployeeCodesClass.h 會出現在 [設計] 檢視中。用滑鼠右鍵按一下 [設計工具],
- 並在快速鍵功能表中按一下 [檢視程式碼]。
- EmployeeDataClass.h 會出現在 [編輯] 檢視中。
- 以下列程式碼來取代 EmployeeCodesClass.h 中的全部內容:
#pragma once
using namespace System;
using namespace System::Web;
using namespace System::Web::Services;
namespace EmployeeCodes
{
public __gc
class EmployeeCodesClass : public WebService
{
public:
[System::Web::Services::WebMethod]
int EmployeeLevel(String* name);
};
}
5).以下列程式碼來取代 EmployeeCodesClass.cpp 中的全部內容:
// EmployeeCodesClass.cpp
#include "StdAfx.h"
#include "EmployeeCodesClass.h"
#include "Global.asax.h"
using namespace System::Runtime::InteropServices;
[DllImport("EmployeeDLL", CharSet=CharSet::Ansi)]
extern "C" int EmployeeID(String* name);
namespace EmployeeCodes
{
int EmployeeCodesClass::EmployeeLevel(String* name)
{
return EmployeeID(name);
}
};
若要建立 EmployeeData XML Web Service
- 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。 出現 [新增專案] 對話方塊。
- 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下 [.NET]。
- 在 [樣板] 窗格中按一下 [ASP.NET Web 服務]。
- 在 [名稱] 欄位中輸入 EmployeeCodes,再選取 [加入至方案]。按一下 [確定]。
- EmployeeDataClass.h 會出現在 [設計] 檢視中。用滑鼠右鍵按一下 [設計工具],
- 並在快速鍵功能表中按一下 [檢視程式碼]。
- EmployeeDataClass.h 會出現在 [編輯] 檢視中。
- 以下列程式碼來取代 EmployeeDataClass.h 中的全部內容:
#pragma once
using namespace System;
using namespace System::Web;
using namespace System::Web::Services;
namespace EmployeeData
{
public __gc
class EmployeeDataClass : public WebService
{
public:
[System::Web::Services::WebMethod]
int EmployeeLadder(String* name);
};
}
5).以下列程式碼來取代 EmployeeDataClass.cpp 中的全部內容:
// EmployeeDataClass.cpp
#include "StdAfx.h"
#include "EmployeeDataClass.h"
#include "Global.asax.h"
using namespace System::Runtime::InteropServices;
[DllImport("EmployeeDLL", CharSet=CharSet::Ansi)]
extern "C" int EmployeeID(String* name);
namespace EmployeeData
{
int EmployeeDataClass::EmployeeLadder(String* name)
{
return EmployeeID(name);
}
};
6).
在 [建置] 功能表上,按一下 [建置方案]。這樣就把 XML Web Service 部署到本機電腦上。
若要將 XML Web Service 的參考加入 MFC 應用程式
- 在 [方案總管] 中,用滑鼠右鍵按一下 [ReservationDemo] 專案。
- 在快速鍵功能表上按一下 [加入 Web 參考]。 [加入 Web 參考] 對話方塊就會出現。
- 按一下 [本機電腦上的 Web 服務],再選取 EmployeeCodes 的 XML Web Service。
- XML Web Service 說明會出現在對話方塊的主窗格中。按一下 [加入參考]。
- 針對 EmployeeData 重複執行步驟 1 至 3。
- 修改 Employee.cpp 以便搭配 XML Web Service 使用。加入下列 #include 陳述式:
#include "localhost.h"
#include "localhost1.h"
6).將
CEmployee
建構函式修改為如下所示 (粗體字程式碼代表變更處): CEmployee::CEmployee(CString *name)
{
employeeName = *name;
reservation = NULL;
int res;
localhost::EmployeeCodesClass *c = new
localhost::EmployeeCodesClass();
res = c->EmployeeLevel(S"app");
localhost1::EmployeeDataClass *c1 = new
localhost1::EmployeeDataClass();
res = c1->EmployeeLadder(S"paa");
}
7).在 [建置] 功能表上,按一下 [建置方案] .
8).針對每一 XML Web Service 將
EmployeeDLL.dll
複製到 Inetpub 目錄。例如,如果您的 Inetpub 目錄位於 C: 磁碟機,則完整目錄就會是:
C:\Inetpub\wwwroot\EmployeeCodes\bin
C:\Inetpub\wwwroot\EmployeeData\bin
以 Windows Form 取代使用者介面
下一步就是使用 Windows Form 來取代 MFC 使用者介面。在本章節中,您將建立新的 Windows Form 應用程式,
其中會使用到 MFC 應用程式中的預留機位引擎。
若要建立基底表單
- 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。 出現 [新增專案] 對話方塊。
- 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下 [.NET]。
- 在 [樣板] 窗格中按一下 [類別程式庫 (.NET)]。
- 在 [名稱] 欄位中輸入 ReservationApp,再選取 [加入至方案]。按一下 [確定]。
- 在 [ReservationApp] 專案上按一下滑鼠右鍵。在快速鍵功能表上,按一下 [加入],
- 再按一下 [加入項目]。 會出現 [加入項目] 對話方塊。
- 按一下 [Windows Form (.NET)],並將新表單命名為 ParentForm。按一下 [開啟]。
- 在 [檢視] 功能表上按一下 [工具箱]。
- 在 [工具箱] 中開啟 [Windows Form]。將按鈕從 [工具箱] 拉至表單中,
- 並將 Button1 的 [文字] 屬性設為 [取消]。
- 連按兩下 [取消] 按鈕以加入事件處理常式。
- 將下列程式碼插入
button1_click
事件:Close();
- 在 [建置] 功能表上,按一下 [建置方案]。
若要建立繼承表單
- 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。
- 出現 [新增專案] 對話方塊。
- 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下 [.NET]。
- 在 [範本] 窗格中按一下 [Windows Form 應用程式 (.NET)]。
- 在 [名稱] 欄位中輸入 ChildForm,再選取 [加入至方案]。請按一下 [確定]。
- 讓
Form1
繼承父表單。開啟 Form1.h 並將下面這一行:public __gc class Form1 : public System::Windows::Forms::Form
public __gc class Form1 : public ReservationApp::ParentForm
- 在 [方案總管] 中,用滑鼠右鍵按一下 [ChildForm] 專案。
- 在快速鍵功能表中按一下 [加入參考]。 [加入參考] 對話方塊出現。
- 從清單中選取 [ReservationApp],再按一下 [確定]。
- [ReservationApp] 會出現在 [方案總管] 的 [參考] 清單中。
- 從 [工具箱] 中,將按鈕從工具箱拉到 [設計] 檢視中 ChildForm 專案的 Form1.h 內。
- 在 [屬性] 視窗中,將 Button1 的 [文字] 屬性設為 [確定]。
- 從 [工具箱] 中,拉下三個下拉式清單方塊控制項,以及代表員工名稱、
- 來源機場和目的地機場的三個標籤。
- 拉下兩個 DatePicker ActiveX 控制項:一個代表出發日期,另一個代表返回日期.
若要將表單連接到預留機位引擎
現在您已建立了表單的配置,所以就可以將表單連接到預留機位引擎。 - 將下列檔案從 ReservationDemo 目錄複製到 ChildForm 目錄:
Employee.cpp Employee.h Flight.cpp Flight.h Reservation.cpp Reservation.h localhost.h localhost1.h
- 將 TravelPolicy.dll 和 BookingObject.dll 複製到 ReservationApp\Debug 目錄。
- 在 [方案總管] 中,用滑鼠右鍵按一下 [ChildForm] 專案。
- 在快速鍵功能表中按一下 [加入現有項目]。 此時會出現 [加入現有項目] 對話方塊。
- 選取 Employee.cpp、Employee.h、Flight.cpp、Flight.h、Reservation.cpp 和
- Reservation.h。另外再從 ReservationDemo\Debug 中加入 TravelPolicy.lib。
- 以下列程式碼取代 ChildForm\Flight.cpp 中的程式碼:
#include "StdAfx.h" #include "Flight.h" #include "Reservation.h" #using <mscorlib.dll> using namespace System; using namespace System::Runtime::InteropServices; CFlight::CFlight(void) { } void CFlight::Reserve() { System::String * strFrom = S"from"; System::String * strTo = S"to"; CString csFromCity ((char*)(void*) Marshal::StringToHGlobalAnsi(strFrom)); CString csToCity ((char*)(void*) Marshal::StringToHGlobalAnsi(strTo)); CReservation* r = new CReservation( &csFromCity, &csToCity, 17,1,2,2); int res = r->Reserve(); };
在ChildForm\Reservation.h 中加入:
#include <atlstr.h>
在 ChildForm\Form1.h 中加入下列 #include 陳述式:
#pragma once #include Employee.h ... using namespace System;
在 ChildForm\Form1.h 的 [設計] 檢視中,連按兩下 [確定] 按鈕以加入事件處理常式 .
將下列程式碼加入至 button2_click 事件處理常式:
CString name(comboBox1->Text); CEmployee employee(&name); CString FromCity(comboBox2->Text); CString ToCity(comboBox3->Text); employee.MakeReservation(&FromCity, &ToCity, dateTimePicker1->Value.Day, dateTimePicker1->Value.Month, dateTimePicker1->Value.Day, dateTimePicker1->Value.Month);
- 在 [方案總管] 中,用滑鼠右鍵按一下 [ChildForm] 專案。
- 在快速鍵功能表上按一下 [設定為起始專案]。
- 以滑鼠右鍵再按一下專案,並選取 [屬性]。[屬性頁] 對話方塊就會出現。
- 選取 [偵錯],再將 [偵錯工具類型] 設為 [僅限 Managed]。按一下 [確定]。
- 在 [建置] 功能表上,按一下 [建置方案]。
- 在 Flight.cpp 中,於下列這一行上設定中斷點:
int res = r->Reserve();15.從 [偵錯] 功能表中按一下 [啟動] 以執行該應用程式。16.按一下 [確定] 按鈕。程式會執行到您設定的中斷點處。17.當程式執行到中斷點時,請在 [偵錯] 功能表上按一下 [逐步執行],並確定應用程式能夠運作,然後再選取 [跳離函式] 和 [不進入函式]。在 [快速監看式] 視窗中,確認res
的值為 -13 .以 Windows Form 取代使用者介面下一步就是使用 Windows Form 來取代 MFC 使用者介面。在本章節中,
您將建立新的 Windows Form 應用程式,其中會使用到 MFC 應用程式中的預留機位引擎。若要建立基底表單
- 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。 出現 [新增專案] 對話方塊。
- 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,
- 然後再按一下 [.NET]。在 [樣板] 窗格中按一下 [類別程式庫 (.NET)]。
- 在 [名稱] 欄位中輸入 ReservationApp,再選取 [加入至方案]。按一下 [確定]。
- 在 [ReservationApp] 專案上按一下滑鼠右鍵。在快速鍵功能表上,
- 按一下 [加入],再按一下 [加入項目]。 會出現 [加入項目] 對話方塊。
- 按一下 [Windows Form (.NET)],並將新表單命名為 ParentForm。按一下 [開啟]。
- 在 [檢視] 功能表上按一下 [工具箱]。
- 在 [工具箱] 中開啟 [Windows Form]。將按鈕從 [工具箱] 拉至表單中,
- 並將 Button1 的 [文字] 屬性設為 [取消]。
- 連按兩下 [取消] 按鈕以加入事件處理常式。
- 將下列程式碼插入
button1_click
事件:Close();- 在 [建置] 功能表上,按一下 [建置方案]。
若要建立繼承表單拉下兩個 DatePicker ActiveX 控制項:一個代表出發日期,另一個代表返回日期。
- 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。 出現 [新增專案] 對話方塊。
- 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下 [.NET]。
- 在 [範本] 窗格中按一下 [Windows Form 應用程式 (.NET)]。
- 在 [名稱] 欄位中輸入 ChildForm,再選取 [加入至方案]。請按一下 [確定]。
- 讓
Form1
繼承父表單。開啟 Form1.h 並將下面這一行:變更為:public __gc class Form1 : public System::Windows::Forms::Formpublic __gc class Form1 : public ReservationApp::ParentForm- 在 [方案總管] 中,用滑鼠右鍵按一下 [ChildForm] 專案。
- 在快速鍵功能表中按一下 [加入參考]。 [加入參考] 對話方塊出現。
- 從清單中選取 [ReservationApp],再按一下 [確定]。
- [ReservationApp] 會出現在 [方案總管] 的 [參考] 清單中。
- 從 [工具箱] 中,將按鈕從工具箱拉到 [設計] 檢視中 ChildForm 專案的 Form1.h 內。
- 在 [屬性] 視窗中,將 Button1 的 [文字] 屬性設為 [確定]。
- 從 [工具箱] 中,拉下三個下拉式清單方塊控制項,以及代表員工名稱、
- 來源機場和目的地機場的三個標籤。
若要將表單連接到預留機位引擎現在您已建立了表單的配置,所以就可以將表單連接到預留機位引擎。
- 將下列檔案從 ReservationDemo 目錄複製到 ChildForm 目錄:
Employee.cpp Employee.h Flight.cpp Flight.h Reservation.cpp Reservation.h localhost.h localhost1.h- 將 TravelPolicy.dll 和 BookingObject.dll 複製到 ReservationApp\Debug 目錄。
- 在 [方案總管] 中,用滑鼠右鍵按一下 [ChildForm] 專案。
- 在快速鍵功能表中按一下 [加入現有項目]。 此時會出現 [加入現有項目] 對話方塊。
- 選取 Employee.cpp、Employee.h、Flight.cpp、Flight.h、Reservation.cpp
- 和 Reservation.h。另外再從 ReservationDemo\Debug 中加入 TravelPolicy.lib。
- 以下列程式碼取代 ChildForm\Flight.cpp 中的程式碼:
#include "StdAfx.h" #include "Flight.h" #include "Reservation.h" #using <mscorlib.dll> using namespace System; using namespace System::Runtime::InteropServices; CFlight::CFlight(void) { } void CFlight::Reserve() { System::String * strFrom = S"from"; System::String * strTo = S"to"; CString csFromCity ((char*)(void*) Marshal::StringToHGlobalAnsi(strFrom)); CString csToCity ((char*)(void*) Marshal::StringToHGlobalAnsi(strTo)); CReservation* r = new CReservation( &csFromCity, &csToCity, 17,1,2,2); int res = r->Reserve(); };- 在ChildForm\Reservation.h 中加入:
#include <atlstr.h>- 在 ChildForm\Form1.h 中加入下列 #include 陳述式:
#pragma once #include Employee.h ... using namespace System;- 在 ChildForm\Form1.h 的 [設計] 檢視中,連按兩下 [確定] 按鈕以加入事件處理常式。
- 將下列程式碼加入至 button2_click 事件處理常式:
CString name(comboBox1->Text); CEmployee employee(&name); CString FromCity(comboBox2->Text); CString ToCity(comboBox3->Text); employee.MakeReservation(&FromCity, &ToCity, dateTimePicker1->Value.Day, dateTimePicker1->Value.Month, dateTimePicker1->Value.Day, dateTimePicker1->Value.Month);- 在 [方案總管] 中,用滑鼠右鍵按一下 [ChildForm] 專案。
- 在快速鍵功能表上按一下 [設定為起始專案]。
- 以滑鼠右鍵再按一下專案,並選取 [屬性]。 [屬性頁] 對話方塊就會出現。
- 選取 [偵錯],再將 [偵錯工具類型] 設為 [僅限 Managed]。按一下 [確定]。
- 在 [建置] 功能表上,按一下 [建置方案]。
- 在 Flight.cpp 中,於下列這一行上設定中斷點:
int res = r->Reserve();- 從 [偵錯] 功能表中按一下 [啟動] 以執行該應用程式。
- 按一下 [確定] 按鈕。 程式會執行到您設定的中斷點處。
- 當程式執行到中斷點時,請在 [偵錯] 功能表上按一下 [逐步執行],
- 並確定應用程式能夠運作,然後再選取 [跳離函式] 和 [不進入函式]。
- 在 [快速監看式] 視窗中,確認
res
的值為 -13。連接到 SQL Server 資料庫
在本章節中,您將會設定應用程式以 SQL Server 資料庫的資料填滿員工的下拉式清單方塊。首先,您必須建立資料連接。若要存取資料庫的資料
- 在 [檢視] 功能表上按一下 [伺服器總管]。
- 在 [伺服器總管] 中以滑鼠右鍵按一下 [資料連接] 節點,並選取 [加入連接]。
- 此時會顯示 [資料連結內容] 對話方塊。
- 指定您擁有帳戶或存取權限的伺服器名稱。選取 [使用 Windows NT 整合安全]。
- 選取資料庫,例如:Pubs 或 Northwind。按一下 [確定] 以建立連接,
- 它會出現在 [伺服器總管] 中。
- 在 [伺服器總管] 中,先展開該資料庫節點,再展開 [表格] 節點,
- 然後再選取適合的表格 (例如作者),並將它拉到 Form1 的 [設計] 檢視中。
- 如此將會建立兩個物件:sqlConnection1 和 sqlDataAdapter1。
- 用滑鼠右鍵按一下 [sqlDataAdapter1] 物件,再按一下 [設定資料配接器]。
- 出現 [設定資料配接器] 對話方塊。
- 按一下 [下一步]。若它不是預設的資料庫,則請先指定您的資料庫,再按一下 [下一步]。
- 選取 [使用SQL 陳述式],再按一下 [下一步]。
- 選擇 [查詢產生器],再選取您想要操作的欄位。按一下 [確定],然後再按一下 [完成]。
- 在 Form1 的 [設計] 檢視中,用滑鼠右鍵按一下 [sqlDataAdapter1],
- 並從其內容功能表中選取 [產生資料集]。 [產生資料集] 對話方塊將出現。
- 選擇名稱為 DataSet1 (預設值) 的新資料集,其中包含作者的表格,
- 並確定已選取 [將此資料集加入設計工具中]。
若要設定表單控制項以使用產生的資料集
- 在 Form1 的 [設計] 檢視中,按一下員工姓名的下拉式清單方塊。
- 在 [屬性] 視窗中,將 DataSource 設為 dataSet11.authors,
- 並將 DisplayMember 設定為 au_lname。
- 連按兩下該表單以便將
Form1_Load
事件加入。將下列程式碼加入至事件:dataSet11->Clear( ); sqlDataAdapter1->Fill(dataSet11);- 在 [建置] 功能表上,按一下 [建置方案]。
注意 若無法建置方案,請將#include "Dataset1.h"
從 stdafx.h
移到 ChildForm\Form1.cpp 中#include "stdafx.h."
之後。將預留機位引擎移植到 Managed 類別
在本章節中,您會將預留機位引擎移植成完全的 Managed,以展示 Managed 和 Unmanaged 程式碼之間的互通性。您必須把新的 Managed 類別修改為可與差旅規定 DLL 和預訂機位的 COM 物件互通。若要執行這項作業,則您必須依下列程式碼 (粗體字程式碼代表變更處) 所述來編輯標頭和實作檔案。Employee.h// Employee.h #pragma once #include "reservation.h" __gc class CEmployee { protected: CReservation* reservation; System::String* employeeName; public: CEmployee(System::String* name); ~CEmployee(void); virtual int MakeReservation (System::String* from,System::String* to, int day1, int month1, int day2, int month2); };Employee.cpp--------------------------------------------------------------------------------// Employee.cpp #include "StdAfx.h" #include <vcclr.h> #include "employee.h" #include "Flight.h" #define __FLTUSED__ #include "localhost.h" #include "localhost1.h" CEmployee::CEmployee(System::String* name) { employeeName = name; reservation = NULL; int res; localhost::EmployeeCodesClass *c = new localhost::EmployeeCodesClass(); res = c->EmployeeLevel(S"app"); localhost1::EmployeeDataClass *c1 = new localhost1::EmployeeDataClass(); res = c1->EmployeeLadder(S"paa"); } int CEmployee::MakeReservation (System::String* from, System::String* to, int day1, int month1, int day2, int month2) { CFlight* flight; flight->Reserve(); return 1; } CEmployee::~CEmployee(void) { }Reservation.h--------------------------------------------------------------------------------// Reservation.h #pragma once __gc class CReservation { protected: __gc struct CityInfo { System::String* city; int departDay; int departMonth; }; CityInfo* fromCity, * toCity; public: CReservation(System::String* from, System::String* to, int d1, int m1, int d2, int m2); ~CReservation(void); virtual int Reserve (); protected: virtual int GetFlightPolicy (int level); };Reservation.cpp------------------------------------------------------------------------------------// Reservation.cpp #include "StdAfx.h" #include "reservation.h" #import "..\\bookingobject\\_bookingobject.tlb" no_namespace #using <mscorlib.dll> using namespace System; using namespace System::Runtime::InteropServices; CReservation::CReservation(System::String* from, System::String* to, int d1, int m1, int d2, int m2) { fromCity = new CityInfo(); toCity = new CityInfo(); fromCity->city = from; fromCity->departDay = d1; fromCity->departMonth = m1; toCity->city = to; toCity->departDay = d2; toCity->departMonth = m2; } CReservation::~CReservation(void) { } int CReservation::Reserve () { IBookingPtr b(__uuidof(CBooking)); BSTR bstrFromCity = static_cast<BSTR> (Marshal::StringToBSTR(fromCity->city).ToPointer()); BSTR bstrToCity = static_cast<BSTR> (Marshal::StringToBSTR( toCity->city).ToPointer()); b->NewBooking(bstrFromCity, bstrToCity, fromCity->departDay, fromCity->departMonth); int res = GetFlightPolicy(1); if (b->CheckAvailability()) { b->Reserve(); return res; } else return res + 10; } __declspec( dllimport ) int GetFlightClass (int, int); int CReservation::GetFlightPolicy (int level) { return GetFlightClass(level, fromCity->departDay-toCity->departDay); }Flight.cpp-------------------------------------------------------------------------------// Flight.cpp #include "StdAfx.h" #include ".\\flight.h" #include "Reservation.h" #using <mscorlib.dll> using namespace System; using namespace System::Runtime::InteropServices; CFlight::CFlight(void) { } void CFlight::Reserve() { System::String * strFrom = S"from"; System::String * strTo = S"to"; CReservation* r = new CReservation( strFrom, strTo, 17, 1, 2, 2); int res = r->Reserve(); }Form1.h// ChildForm\Form1.h // button2_click handler System::String* name(comboBox1->Text); CEmployee* employee = new CEmployee(name); System::String* FromCity(comboBox2->Text); System::String* ToCity(comboBox3->Text); employee->MakeReservation(FromCity, ToCity, dateTimePicker1->Value.Day, dateTimePicker1->Value.Month, dateTimePicker1->Value.Day, dateTimePicker1->Value.Month);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&