首頁

2013年8月30日 星期五

*MSDN Library*逐步解說~移植現有原生C++ 應用程式使其與 .NET Framework 元件互通**

*MSDN Library*逐步解說~移植現有原生C++ 應用程式使其與---
--- .NET Framework 元件互通**

**在本逐步解說中,您將會用 MFC 建立預訂機票的應用程式,
然後再將其升級為以 .NET Framework 為目標,並使用 Managed Extensions 
 for C++。
MFC 應用程式會處理預訂的工作。使用者介面為 MFC 應用程式,
其引擎是由包含公司差旅規定的 Helper 函式的 DLL (原生 C++) 和處理---
---預訂機位的 COM 物件 (原生 C++) 所構成  **
*注意   若要建立本逐步解說中所描述的應用程式,您必須能夠存取已經---
---安裝 Pubs 或 Northwind 資料庫的資料庫伺服器                           *
**
*在本逐步解說中,您將會           :    
*
  • 建立 MFC 應用程式,並用 Managed Extensions for C++ 來修改。
  • 將應用程式轉換為 Managed 程式碼,並以 /clr 編譯器選項來編譯。
  • 使用 Windows Form 來取代 MFC 使用者介面。
  • 連接到 SQL Server 資料庫,以取得公司所有員工的清單。
  • 將預留機位引擎類別移植到 Managed 類別。
  • 建立新的 Managed 組件,以便與預訂用的 COM 物件互通             *
  • **在您完成本逐步解說後,架構看起來會很像下列圖表:                   
    *應用程式完成後的架構                                 : 
    ***
    *建立 MFC 應用程式
    在本章節中,您將建立具有三個專案 (MFC、ATL COM 和 MFC DLL)---
    --- 的原生 C++ MFC 應用程式,稱之為 ReservationDemo
    然後您可以在後面各章節中再對其進行修改                                    *
    **若要建立 MFC 專案**
    *
    1. 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。
      出現 [新增專案] 對話方塊。
    2. 在 [專案類型] 窗格中按一下 [Visual C++ 專案],然後再按一下 [MFC]。
    3. 在 [範本] 窗格中按一下 [MFC 應用程式]。在 [名稱] 欄位中輸入 ReservationDemo
    4. 然後按一下 [確定]。 出現 MFC 應用程式精靈。
    5. 按一下 [應用程式類型],然後選取 [對話方塊架構]。按一下 [完成]。
    6. 在 [類別檢視] 中用滑鼠右鍵按一下專案節點。在快速鍵功能表上
    7. 按一下 [加入],然後再按一下 [加入類別]。 出現 [加入類別] 對話方塊。
    8. 在 [類別] 窗格中展開 [Visual C++ 專案] 資料夾,然後再按一下 [泛用] 資料夾。
    9. 按一下 [開啟]。 出現泛用 C++ 類別精靈。
    10. 輸入 CEmployee 做為泛用 C++ 類別名稱。這是沒有基底類別的公用類別。
    11. 重複執行步驟 4 和 5,以建立泛用 C++ 類別 CReservation    
    *若要建立 ATL COM 專案 *
    *
    1. 在 [方案總管] 中用滑鼠右鍵按一下方案節點。在快速鍵功能表上按一下  [加入],
    2. 然後再按一下 [新增專案]。 出現 [加入新的專案] 對話方塊。
    3. 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下  [ATL]。
    4. 在 [樣板] 窗格中,按一下 [ATL 專案]。在 [名稱] 欄位中輸入 BookingObject
    5. 然後選取 [加入至方案]。按一下 [確定]。 ATL 專案精靈就會出現。
    6. 按一下 [完成] 以接受預設值。
    7. 在 [類別檢視] 中用滑鼠右鍵按一下專案節點。在快速鍵功能表中按一下  [加入],
    8. 然後再按一下 [加入類別]。 出現 [加入類別] 對話方塊。
    9. 在 [類別] 窗格中展開 [Visual C++ 專案] 資料夾,然後再按一下   [ATL] 資料夾。
    10. 選取 [ATL 簡單物件] 並按一下 [開啟]。 出現 ATL 簡單物件精靈。
    11. 在 [簡短名稱] 欄位輸入 Booking,再按一下 [確定]。
    12. 在 [方案總管] 中連按兩下 Booking.h,將粗體字所示的程式碼加入 IBooking 
    __interface IBooking : IDispatch
    {
       [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 專案**
    1. 在 [方案總管] 中,用滑鼠右鍵按一下方案節點。在快速鍵功能表中按一下 [加入],
    2. 然後再按一下 [新增專案]。
      出現 [加入新的專案] 對話方塊。
    3. 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下 [MFC]。
    4. 在 [樣板] 窗格中,按一下 [MFC DLL]。在 [名稱] 欄位中輸入 TravelPolicy
    5. 再選取 [加入至方案]。請按一下 [確定]。 會出現 MFC DLL 精靈。
    6. 按一下 [完成] 以接受預設值        .
    *將 Unmanaged 程式碼轉換為 Managed 程式碼*
    *在本章節中,您會將現有原生 C++ MFC 應用程式 ReservationDemo 轉換--
    --為 Managed 程式碼,再用 /clr 編譯器選項來編譯  .
    *若要使用 /clr 編譯器選項來編譯*
    1. 在 [方案總管] 中,用滑鼠右鍵按一下 [ReservationDemo],再按一下 [屬性]。
      [屬性頁] 對話方塊就會出現。
    2. 展開 [C/C++] 節點。
    3. 在 [命令列] 中,請於 [其他選項] 方塊中輸入 /clr
    4. 在 [程式碼產生] 中,將 [基礎 Runtime 檢查] 設為 [預設值],
    5. 並將 [啟用最少重建] 設為「否」。
    6. 在 [一般] 中選取 [偵錯資訊格式],並將它變更為 [程式資料庫 (/Zi)]。
    7. 按一下 [確定],關閉這個對話方塊。
    8. 在 [建置] 功能表上,按一下 [建置方案]。
    9. 在 [偵錯] 功能表上,按一下 [啟動但不偵錯]。
    *在本章節中,您將在預留機位引擎內建立新的 Managed 類別名為 CFlight
    CFlight 將處理航班資訊,並使用 Unmanaged CReservation 類別來處理實際的預留機位
    為了讓 Managed 類別能夠和 Unmanaged 類別互動,
    您必須為 Unmanaged 類別另外使用 Managed 包裝函式 (CReservationWrapper).  **

    **若要建立 Managed 包裝函式類別**
    1. 在 [類別檢視] 中,用滑鼠右鍵按一下 [ReservationDemo] 專案節點。
    2. 在快速鍵功能表中按一下 [加入],然後再按一下 [加入類別]。 出現加入類別精靈。
    3. 選取 [泛用 C++ 類別],並輸入 CReservationWrapper 做為類別名稱。按一下 [完成]。
    4. 在 ReservationWrapper.h 中加入下列 #include 陳述式:   
    #include "Reservation.h"               

    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 類別*
    1. 在 [類別檢視] 中,用滑鼠右鍵按一下 [ReservationDemo] 專案節點。
    2. 在快速鍵功能表中按一下 [加入],然後再按一下 [加入類別]。 出現加入類別精靈。
    3. 選取 [泛用 C++ 類別],再輸入 CFlight 做為類別名稱。按一下 [完成]。
    4. 將 Flight.h 中的類別定義修改成如下所示
    __gc class CFlight
    {
    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).
    1. 在快速鍵功能表上,按一下 [建置]。
    在本章節中,您將建立一個 DLL 來為兩個新的 XML Web Service (EmployeeCodesEmployeeData) 提供員工資訊以用來擷取員工的資訊。
    第一個服務會取得員工 ID 的資訊;第二個服務則會取得員工的其他資料。
    這兩個服務都會使用 IJW 呼叫一個原生 DLL (EmployeeDLL) 以取得所需資訊。
    若要建立 EmployeeDLL 原生 C++ DLL 以提供員工資訊
    1. 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。
    2. 出現 [新增專案] 對話方塊。
    3. 在 [專案類型] 窗格中,按一下 [Visual C++ 專案],然後在 [範本] 窗格中,
    4. 按一下 [Win32 專案]。在 [名稱] 方塊中輸入 EmployeeDLL
    5. 再選取 [加入至方案]。按一下 [確定]。
    6. 修改 EmployeeDLL.cpp 檔中的程式碼   
    #include "StdAfx.h"

    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).
    1. 在 [方案總管] 中,用滑鼠右鍵按一下專案。在快速鍵功能表上,按一下 [建置]。
    若要建立 EmployeeCodes XML Web Service
    1. 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。 出現 [新增專案] 對話方塊。
    2. 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下 [.NET]。
    3. 在 [樣板] 窗格中按一下 [ASP.NET Web 服務]。
    4. 在 [名稱] 欄位中輸入 EmployeeCodes,再選取 [加入至方案]。按一下 [確定]。
    5. EmployeeCodesClass.h 會出現在 [設計] 檢視中。用滑鼠右鍵按一下 [設計工具],
    6. 並在快速鍵功能表中按一下 [檢視程式碼]。
    7. EmployeeDataClass.h 會出現在 [編輯] 檢視中。
    8. 以下列程式碼來取代 EmployeeCodesClass.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
    1. 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。 出現 [新增專案] 對話方塊。
    2. 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下 [.NET]。
    3. 在 [樣板] 窗格中按一下 [ASP.NET Web 服務]。
    4. 在 [名稱] 欄位中輸入 EmployeeCodes,再選取 [加入至方案]。按一下 [確定]。
    5. EmployeeDataClass.h 會出現在 [設計] 檢視中。用滑鼠右鍵按一下 [設計工具],
    6. 並在快速鍵功能表中按一下 [檢視程式碼]。
    7. EmployeeDataClass.h 會出現在 [編輯] 檢視中。
    8. 以下列程式碼來取代 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 應用程式
    1. 在 [方案總管] 中,用滑鼠右鍵按一下 [ReservationDemo] 專案。
    2. 在快速鍵功能表上按一下 [加入 Web 參考]。 [加入 Web 參考] 對話方塊就會出現。
    3. 按一下 [本機電腦上的 Web 服務],再選取 EmployeeCodes 的 XML Web Service。
    4. XML Web Service 說明會出現在對話方塊的主窗格中。按一下 [加入參考]。
    5. 針對 EmployeeData 重複執行步驟 1 至 3。
    6. 修改 Employee.cpp 以便搭配 XML Web Service 使用。加入下列 #include 陳述式:         
    #define __FLTUSED__
    #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 應用程式中的預留機位引擎。
    若要建立基底表單
    1. 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。 出現 [新增專案] 對話方塊。
    2. 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下 [.NET]。
    3. 在 [樣板] 窗格中按一下 [類別程式庫 (.NET)]。
    4. 在 [名稱] 欄位中輸入 ReservationApp,再選取 [加入至方案]。按一下 [確定]。
    5. 在 [ReservationApp] 專案上按一下滑鼠右鍵。在快速鍵功能表上,按一下 [加入],
    6. 再按一下 [加入項目]。 會出現 [加入項目] 對話方塊。
    7. 按一下 [Windows Form (.NET)],並將新表單命名為 ParentForm。按一下 [開啟]。
    8. 在 [檢視] 功能表上按一下 [工具箱]。
    9. 在 [工具箱] 中開啟 [Windows Form]。將按鈕從 [工具箱] 拉至表單中,
    10. 並將 Button1 的 [文字] 屬性設為 [取消]
    11. 連按兩下 [取消] 按鈕以加入事件處理常式。
    12. 將下列程式碼插入 button1_click 事件:
      Close();
      
    13. 在 [建置] 功能表上,按一下 [建置方案]。
    若要建立繼承表單
    1. 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。
    2. 出現 [新增專案] 對話方塊。
    3. 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下 [.NET]。
    4. 在 [範本] 窗格中按一下 [Windows Form 應用程式 (.NET)]。
    5. 在 [名稱] 欄位中輸入 ChildForm,再選取 [加入至方案]。請按一下 [確定]。
    6. Form1 繼承父表單。開啟 Form1.h 並將下面這一行:
      public __gc class Form1 : public System::Windows::Forms::Form
      
      變更為:
      public __gc class Form1 : public ReservationApp::ParentForm
      
    7. 在 [方案總管] 中,用滑鼠右鍵按一下 [ChildForm] 專案。
    8. 在快速鍵功能表中按一下 [加入參考]。 [加入參考] 對話方塊出現。
    9. 從清單中選取 [ReservationApp],再按一下 [確定]。
    10.  [ReservationApp] 會出現在 [方案總管] 的 [參考] 清單中。
    11. 從 [工具箱] 中,將按鈕從工具箱拉到 [設計] 檢視中 ChildForm 專案的 Form1.h 內。
    12. 在 [屬性] 視窗中,將 Button1 的 [文字] 屬性設為 [確定]。
    13. 從 [工具箱] 中,拉下三個下拉式清單方塊控制項,以及代表員工名稱、
    14. 來源機場和目的地機場的三個標籤。
    15. 拉下兩個 DatePicker ActiveX 控制項:一個代表出發日期,另一個代表返回日期.
    若要將表單連接到預留機位引擎
    現在您已建立了表單的配置,所以就可以將表單連接到預留機位引擎。
    1. 將下列檔案從 ReservationDemo 目錄複製到 ChildForm 目錄:
      Employee.cpp
      Employee.h
      Flight.cpp
      Flight.h
      Reservation.cpp
      Reservation.h
      localhost.h
      localhost1.h
      
    2. 將 TravelPolicy.dll 和 BookingObject.dll 複製到 ReservationApp\Debug 目錄。
    3. 在 [方案總管] 中,用滑鼠右鍵按一下 [ChildForm] 專案。
    4. 在快速鍵功能表中按一下 [加入現有項目]。 此時會出現 [加入現有項目] 對話方塊。
    5. 選取 Employee.cpp、Employee.h、Flight.cpp、Flight.h、Reservation.cpp 和
    6.  Reservation.h。另外再從 ReservationDemo\Debug 中加入 TravelPolicy.lib。
    7. 以下列程式碼取代 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();
      };
      
    8. 在ChildForm\Reservation.h 中加入: 
      #include <atlstr.h>
      
    9. 在 ChildForm\Form1.h 中加入下列 #include 陳述式: 
      #pragma once
      #include Employee.h
      ...
      using namespace System;
      
    10. 在 ChildForm\Form1.h 的 [設計] 檢視中,連按兩下 [確定] 按鈕以加入事件處理常式 .
    11. 將下列程式碼加入至 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);
      
    12. 在 [方案總管] 中,用滑鼠右鍵按一下 [ChildForm] 專案。
    13. 在快速鍵功能表上按一下 [設定為起始專案]。
    14. 以滑鼠右鍵再按一下專案,並選取 [屬性]。
      [屬性頁] 對話方塊就會出現。
    15. 選取 [偵錯],再將 [偵錯工具類型] 設為 [僅限 Managed]。按一下 [確定]。
    16. 在 [建置] 功能表上,按一下 [建置方案]。
    17. 在 Flight.cpp 中,於下列這一行上設定中斷點:
    int res = r->Reserve();
    15.從 [偵錯] 功能表中按一下 [啟動] 以執行該應用程式。
    16.按一下 [確定] 按鈕。
    程式會執行到您設定的中斷點處。
    17.當程式執行到中斷點時,請在 [偵錯] 功能表上按一下 [逐步執行],並確定應用程式能夠運作,
    然後再選取 [跳離函式] 和 [不進入函式]。在 [快速監看式] 視窗中,確認 res 的值為 -13 .
    以 Windows Form 取代使用者介面
    下一步就是使用 Windows Form 來取代 MFC 使用者介面。在本章節中,
    您將建立新的 Windows Form 應用程式,其中會使用到 MFC 應用程式中的預留機位引擎。
    若要建立基底表單
    1. 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。 出現 [新增專案] 對話方塊。
    2. 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,
    3. 然後再按一下 [.NET]。在 [樣板] 窗格中按一下 [類別程式庫 (.NET)]。
    4. 在 [名稱] 欄位中輸入 ReservationApp,再選取 [加入至方案]。按一下 [確定]。
    5. 在 [ReservationApp] 專案上按一下滑鼠右鍵。在快速鍵功能表上,
    6. 按一下 [加入],再按一下 [加入項目]。 會出現 [加入項目] 對話方塊。
    7. 按一下 [Windows Form (.NET)],並將新表單命名為 ParentForm。按一下 [開啟]。
    8. 在 [檢視] 功能表上按一下 [工具箱]。
    9. 在 [工具箱] 中開啟 [Windows Form]。將按鈕從 [工具箱] 拉至表單中,
    10. 並將 Button1 的 [文字] 屬性設為 [取消]
    11. 連按兩下 [取消] 按鈕以加入事件處理常式。
    12. 將下列程式碼插入 button1_click 事件:
      Close();
      
    13. 在 [建置] 功能表上,按一下 [建置方案]。
    若要建立繼承表單
    1. 按一下 [檔案] 功能表上的 [新增],然後再按一下 [專案]。 出現 [新增專案] 對話方塊。
    2. 在 [專案類型] 窗格上,展開 [Visual C++ 專案] 資料夾,然後再按一下 [.NET]。
    3. 在 [範本] 窗格中按一下 [Windows Form 應用程式 (.NET)]。
    4. 在 [名稱] 欄位中輸入 ChildForm,再選取 [加入至方案]。請按一下 [確定]。
    5. Form1 繼承父表單。開啟 Form1.h 並將下面這一行:
      public __gc class Form1 : public System::Windows::Forms::Form
      
      變更為:
      public __gc class Form1 : public ReservationApp::ParentForm
      
    6. 在 [方案總管] 中,用滑鼠右鍵按一下 [ChildForm] 專案。
    7. 在快速鍵功能表中按一下 [加入參考]。 [加入參考] 對話方塊出現。
    8. 從清單中選取 [ReservationApp],再按一下 [確定]。
    9. [ReservationApp] 會出現在 [方案總管] 的 [參考] 清單中。
    10. 從 [工具箱] 中,將按鈕從工具箱拉到 [設計] 檢視中 ChildForm 專案的 Form1.h 內。
    11. 在 [屬性] 視窗中,將 Button1 的 [文字] 屬性設為 [確定]。
    12. 從 [工具箱] 中,拉下三個下拉式清單方塊控制項,以及代表員工名稱、
    13. 來源機場和目的地機場的三個標籤。
    拉下兩個 DatePicker ActiveX 控制項:一個代表出發日期,另一個代表返回日期。
    若要將表單連接到預留機位引擎
    現在您已建立了表單的配置,所以就可以將表單連接到預留機位引擎。
    1. 將下列檔案從 ReservationDemo 目錄複製到 ChildForm 目錄:
      Employee.cpp
      Employee.h
      Flight.cpp
      Flight.h
      Reservation.cpp
      Reservation.h
      localhost.h
      localhost1.h
      
    2. 將 TravelPolicy.dll 和 BookingObject.dll 複製到 ReservationApp\Debug 目錄。
    3. 在 [方案總管] 中,用滑鼠右鍵按一下 [ChildForm] 專案。
    4. 在快速鍵功能表中按一下 [加入現有項目]。 此時會出現 [加入現有項目] 對話方塊。
    5. 選取 Employee.cpp、Employee.h、Flight.cpp、Flight.h、Reservation.cpp
    6. 和 Reservation.h。另外再從 ReservationDemo\Debug 中加入 TravelPolicy.lib。
    7. 以下列程式碼取代 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();
      };
      
    8. 在ChildForm\Reservation.h 中加入:
      #include <atlstr.h>
      
    9. 在 ChildForm\Form1.h 中加入下列 #include 陳述式:
      #pragma once
      #include Employee.h
      ...
      using namespace System;
      
    10. 在 ChildForm\Form1.h 的 [設計] 檢視中,連按兩下 [確定] 按鈕以加入事件處理常式。
    11. 將下列程式碼加入至 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);
      
    12. 在 [方案總管] 中,用滑鼠右鍵按一下 [ChildForm] 專案。
    13. 在快速鍵功能表上按一下 [設定為起始專案]。
    14. 以滑鼠右鍵再按一下專案,並選取 [屬性]。 [屬性頁] 對話方塊就會出現。
    15. 選取 [偵錯],再將 [偵錯工具類型] 設為 [僅限 Managed]。按一下 [確定]。
    16. 在 [建置] 功能表上,按一下 [建置方案]。
    17. 在 Flight.cpp 中,於下列這一行上設定中斷點:
      int res = r->Reserve();
      
    18. 從 [偵錯] 功能表中按一下 [啟動] 以執行該應用程式。
    19. 按一下 [確定] 按鈕。 程式會執行到您設定的中斷點處。
    20. 當程式執行到中斷點時,請在 [偵錯] 功能表上按一下 [逐步執行],
    21. 並確定應用程式能夠運作,然後再選取 [跳離函式] 和 [不進入函式]。
    22. 在 [快速監看式] 視窗中,確認 res 的值為 -13。

    連接到 SQL Server 資料庫

    在本章節中,您將會設定應用程式以 SQL Server 資料庫的資料填滿員工的下拉式清單方塊。
    首先,您必須建立資料連接。
    若要存取資料庫的資料
    1. 在 [檢視] 功能表上按一下 [伺服器總管]。
    2. 在 [伺服器總管] 中以滑鼠右鍵按一下 [資料連接] 節點,並選取 [加入連接]。
    3. 此時會顯示 [資料連結內容] 對話方塊。
    4. 指定您擁有帳戶或存取權限的伺服器名稱。選取 [使用 Windows NT 整合安全]。
    5. 選取資料庫,例如:Pubs 或 Northwind。按一下 [確定] 以建立連接,
    6. 它會出現在 [伺服器總管] 中。
    7. 在 [伺服器總管] 中,先展開該資料庫節點,再展開 [表格] 節點,
    8. 然後再選取適合的表格 (例如作者),並將它拉到 Form1 的 [設計] 檢視中。
    9. 如此將會建立兩個物件:sqlConnection1 sqlDataAdapter1
    10. 用滑鼠右鍵按一下 [sqlDataAdapter1] 物件,再按一下 [設定資料配接器]。
    11. 出現 [設定資料配接器] 對話方塊。
    12. 按一下 [下一步]。若它不是預設的資料庫,則請先指定您的資料庫,再按一下 [下一步]。
    13. 選取 [使用SQL 陳述式],再按一下 [下一步]。
    14. 選擇 [查詢產生器],再選取您想要操作的欄位。按一下 [確定],然後再按一下 [完成]。
    15. 在 Form1 的 [設計] 檢視中,用滑鼠右鍵按一下 [sqlDataAdapter1],
    16. 並從其內容功能表中選取 [產生資料集]。 [產生資料集] 對話方塊將出現。
    17. 選擇名稱為 DataSet1 (預設值) 的新資料集,其中包含作者的表格,
    18. 並確定已選取 [將此資料集加入設計工具中]。
    若要設定表單控制項以使用產生的資料集
    1. 在 Form1 的 [設計] 檢視中,按一下員工姓名的下拉式清單方塊。
    2. 在 [屬性] 視窗中,將 DataSource 設為 dataSet11.authors
    3. 並將 DisplayMember 設定為 au_lname
    4. 連按兩下該表單以便將 Form1_Load 事件加入。將下列程式碼加入至事件:
      dataSet11->Clear( );
      sqlDataAdapter1->Fill(dataSet11);
      
    5. 在 [建置] 功能表上,按一下 [建置方案]。
      注意   若無法建置方案,請將 #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);
    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

    2013年8月29日 星期四

    **(技巧)善用CODE-可透過程式來執行~T4範本喔**아 ~ T4 템플릿을 통해 실행하는 ** (기술) 코드 사용 프로그램**

    ***(技巧)善用CODE-可透過程式來執行~T4範本喔***
    *KR* ~ T4 템플릿을 통해 실행하는 ** (기술) 코드 사용 프로그램 ****

    **典型T4應用多發生於專案編輯階段,透過存檔動作或PowerShell Script產生程式碼。
    簡單嘗試後,發現T4早已設想周到,在程式中用T4產生文字是小菜一碟, 
    透過Runtime Text Template(執行階段文字範本)即可輕鬆達成, MSDN有篇---
    ---詳細說明可以參考      **
    *KR**일반적인 응용 프로그램은 행동이나 PowerShell 스크립트 아카이브 생성 코드를 통해, 프로젝트 T4 편집 단계에서 발생했습니다. 간단한 시도는, 사려 깊은 T4, T4 프로그램 텍스트 런타임 텍스트 템플릿 (런타임 텍스트 템플릿)를 통해, 케이크의 조각을 사용하여 생성 쉽게 접근 할 ​​수, MSDN 자세한 설명 문서를 참조 수 있습니다 발견했다                   

    **一個簡單範例,從PTT取得文章清單後,透過T4輸出成文字檔。
    首先,在專案中新增一個Runtime Text Template: (在General分類下,直接用關鍵字"template"過濾比較快)                 **
    **간단한 예를 들어, T4를 통해 텍스트 파일로 출력 한 후 PTT 만든 기사 목록입니다  **
    **첫째, 런타임 텍스트 템플릿을 추가하는 프로젝트 (일반 범주에서 직접 사용 키워드 
    "템플릿"필터 빠릅니다)                               **
    ****
    **傳統T4範本不同,每個Runtime T4範本都附加了同名的cs檔案,定義同名的---
    ---類別物件(在本例中RTT4.tt範本,對應的類別名稱即為RTT4),便可在程式碼中
    建立範本物件RTT4,呼叫其.TransformText()方法就能獲得轉換結果                                    **기존의 T4 템플릿이 다른 런타임 T4 템플릿 cs 파일 같은 이름, 클래스 개체 정의  
    (이 경우 RTT4.tt 템플릿을 해당 범주 이름 RTT4입니다)과 동일한 이름을 가진 연결되어, 당신은 코드에서 템플릿을 만들 수 있습니다 객체 RTT4, 그 호출합니다.  
    TransformText () 메소드가 변환 결과를 얻을 수 있습니다                                     **

    ****
    **Runtime T4時,呼叫端常需傳遞參數物件給T4範本,以達到動態變更產生內容的彈性。
    要實現此點,可透過T4類別為partial class的特性,在專案另外加入類別名稱相同---
    ---partial class檔案(即上圖中的RTT4Code.cs),於其中另外定義內部欄位、屬性,
    並透過建構式接收參數。
    範例先要定義文章資料物件:                                   *
    *KR**런타임 T4, 호출자는 종종 유연성을 달성하기 위해 변경하는 동적으로 내용을 
    생성하는 T4 템플릿에 매개 변수 개체를 전달해야합니다. 또한 내부 필드, 속성 
    통해서 구성 주의적 정의하는 같은 이름의 partial 클래스 파일  
     (예 : RTT4Code.cs 위의 그림)를 클래스에 추가하여 프로젝트의 T4 카테고리 
    partial 클래스 속성을 통해이를 달성하기 위해 수신기 매개 변수입니다.
    첫 번째 예는 데이터 객체를 정의                             *
    **
    public class Post
        {
            public string Date;
            public string Author;
            public string Subject;                                *
    *KR*공용 클래스  {공공 문자열 날짜, 공공 문자열 저자, 공공 문자열 제목;           **
     
    **在partial class加入接收List<Post>的建構式,並宣告一個內部欄位posts,用以儲存文章清單      **
    *KR*
    목록 <Post>받는 부분 클래스 생성자에 참여하고, 기사의 목록을 저장하는 데 사용되는 내부 필드 포스트를 선언**
     
    *
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    namespace RuntimeT4
    {
        partial class RTT4
        {
            private List<Post> posts;
            public RTT4(List<Post> posts)
            {
                this.posts = posts;
            }
        }
    }                                                                           *
    **KR**
    시스템을 사용하여, System.Collections.Generic 사용하여, System.Linq에 사용하기; 
     System.Text 사용하여, 네임 스페이스 RuntimeT4 {partial 클래스 RTT4  
    {개인 목록 <Post> 게시물, 
    공공 RTT4 (목록 <Post> 게시물) {this.posts = ; }}}                        *
     
    **T4範本如下,注意其中的this.posts,就是我們在partial class中所定義的內部欄位**
    **아래 T4 템플릿은 예고  this.posts, partial 클래스에서 우리가 정의하는 내부 필드의**
    *
    <#@ template language="C#" #>
    <#@ assembly name="System.Core" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Text" #>
    <#@ import namespace="System.Collections.Generic" #>
    <# 
    int i = 1;
    foreach (var p in this.posts) 
    { #>
    <#= i++ #>.<#= p.Date #> / <#= p.Author #> / <#= p.Subject #>
    <# } #>                                       *
    **KR**<# @ 템플릿 언어 = "C #"#> <# @ 어셈블리 이름 = "System.Core에"#> 
    <# @ 가져 오기 네임 스페이스 = "System.Linq에"#> <# @ 가져 오기 네임 스페이스 =
     "System.Text"#> <# @ 가져 오기 네임 스페이스 = "System.Collections.Generic"#> 
    <# int 전 = 1; foreach는 (this.posts VAR P) {#>. <# = I + + #> <# = p.Date #> / <# =
     p.Author #> / <# = p.Subject #> <#} #>                                                *
     
    **
    呼叫端程式如下(結果抓資料部分比主體多出許多 orz),它會抓回PTT笨版第一頁,
    從HTML取出文章列表交由RTT4範本執行,
    .TransformText()後可得到一個字串,即為產出結果                                       *
    *KR*
    (결과  ORZ보다 많은 기본 데이터 부분을 잡고)는 다음과 같이 프로그램을 호출, 
    그것이 RTT4 HTML 템플릿을 실행하여 문서 목록에서 첫 번째 페이지 캡처 PTT 바보 버전을 제거합니다. 
     TransformText ()는 문자열 뒤에 얻을 
    수 있습니다 결과가 출력됩니다                  
    *class Program
        {
            static void Main(string[] args)
            {
                //連上PTT網站取回文章資料
                  List<Post> posts = GetPTTPosts();
                
                //將文章資料當成參數傳給T4
                RTT4 t = new RTT4(posts);
                //執行TransformText()即可取得結果
        Console.WriteLine(t.TransformText());
                Console.Read();
            }
            //取得PTT文章清單
            static List<Post> GetPTTPosts()
            {
                WebClient wc = new WebClient();
                wc.Encoding = Encoding.GetEncoding(950);
                string h = wc.DownloadString(
                    "http://www.ptt.cc/bbs/StupidClown/index1.html");
                List<Post> posts = new List<Post>();
                string date = null, author = null, subject = null;
                Regex re = new Regex(">(?<t>[^<]+?)<");
                Func<string, string> getInnerText = 
                    s => re.Match(s).Groups["t"].Value;
                foreach (string line in h.Split('\n'))
                {
                    if (line.StartsWith("<td width=\"50\">"))
                        date = getInnerText(line);
                    else if (line.StartsWith("<td width=\"120\">"))
                        author = getInnerText(line);
                    else if (line.StartsWith("<td width=\"500\">"))
                    {
                        subject = getInnerText(line);
                        posts.Add(new Post()
                        {
                            Date = date,
                            Author = author,
                            Subject = subject
                        });
                    }
     
                }
                return posts;
            }                                                            *
    
    
    **
    클래스 프로그램 {정적 무효 메인 (문자열 [] args) {/ / 连 上 PTT 网站 取回 文章 资料 
    목록 <Post>  = GetPTTPosts () / / 将 文章 资料 当成 参数 传给 T4 RTT4 t = 
    새로운 RTT4 (게시물 ) / / 执行 TransformText () 即可 取得 结果 Console.WriteLine으로 
    (t.TransformText ()); Console.Read (); WebClient를} / / 取得 PTT 文章 清单 정적 목록 
     <Post> GetPTTPosts () {WebClient를 화장실 = 새로운 () wc.Encoding = 
     Encoding.GetEncoding (950) 문자열 H = wc.DownloadString 
    ( "http://www.ptt.cc/bbs/StupidClown/index1.html"); 목록 <Post> 게시물 =
     새로운 목록 <Post> () 문자열을 날짜 = NULL, 저자 = NULL, 주제 = NULL; 정규식  = 
     정규식 ( "> (<T> [^ <] +) <??"); Func을 <string, 스트링 getInnerText = S => 
     re.Match (들) 그룹 [ "t"] ;.. foreach는 (h.Split ( '\ N')의 문자열 라인)  
    {(line.StartsWith ( "<TD  = \"50 경우 \ ">")) 날짜 = getInnerText (라인), 
     다른 사람 (line.StartsWith ( "<td width=\"120\">")) 저자 = getInnerText (라인), 
     다른 사람 (line.StartsWith ( "< TD  = \ "500 \"> ")) {대상 = getInnerText (라인), 
     posts.Add (새 포스트 () {날짜 = 날짜, 저자 = 저자,클래스 프로그램 {정적 무효 메인  
    (문자열 [] args) {/ / 连 上 PTT 网站 取回 文章 资料 목록 <Post>  = GetPTTPosts ()  
    / / 将 文章 资料 当成 参数 传给 T4 RTT4 t = 새로운 RTT4 (게시물 ) / / 执行 TransformText  
    () 即可 取得 结果 Console.WriteLine으로 (t.TransformText ()); Console.Read (); WebClient를} 
     / / 取得 PTT 文章 清单 정적 목록 <Post> GetPTTPosts () {WebClient를 화장실 = 새로운 
     () wc.Encoding = Encoding.GetEncoding (950) 문자열 H = wc.DownloadString  
    ( "http://www.ptt.cc/bbs/StupidClown/index1.html"); 목록 <Post> 게시물 = 
     새로운 목록 <Post> () 문자열을 날짜 = NULL, 저자 = NULL, 주제 = NULL; 정규식  = 
     정규식 ( "> (<T> [^ <] +) <??"); Func을 <string, 스트링 getInnerText = S =>  
    re.Match (들) 그룹 [ "t"] ;.. foreach는 (h.Split ( '\ N')의 문자열 라인)  
    {(line.StartsWith ( "<TD  = \"50 경우 \ ">")) 날짜 = getInnerText (라인),
     다른 사람 (line.StartsWith ( "<td width=\"120\">")) 저자 = getInnerText (라인),
     다른 사람 (line.StartsWith ( "< TD  = \ "500 \"> ")) {대상 = getInnerText (라인),
     posts.Add (새 포스트 () {날짜 = 날짜, 저자 = 저자, 
     제목 = 대상});}} 반환 게시물;} 제목 = 대상});}} 반환 게시물;}                        *
    **執行結果:       *
    **집행 결과 :         
    *
    1. 4/23 / vivianJ / 我大概是唯一一個被"阿"過的女生吧
    2. 4/25 / purinfocus / 小護士回憶錄2
    3. 4/27 / EchoMary / 話說今天期中考..
    4. 5/05 / wubaiwife / 是任性還是笨﹖
    5. 5/22 / m0630821 / [閒聊] 油表上的E是?
    6. 6/13 / hohoholalala / 去郵局
    7. 6/22 / cynthia730 / 語無倫次
    8. 6/22 / chachalee / 你真的是我媽嗎?
    9. 6/25 / superlubu / [動畫] 三人成虎大鬧台北第七集  慘劇
    10. 8/04 / keikolin / [耍笨] 我終於當媽了
    11. 8/05 / utou / [動畫]笨蛋的故事
    12. 9/12 / okaoka0709 / [轉錄]Re: [火大] 我的姓真的很特別嗎
    13. 9/25 / Liska / [童年] 中秋節烤肉= =|||
    14.10/03 / JKH945 / [生日+笨夢] 19歲最後一個夢
    15.10/28 / winniechi / [耍笨] 類疊的用法
    16.11/10 / olivetrees / 我弟應該算是最早的詐騙集團
    17.11/10 / keikoYAMADA / 古蹟修護系
    18.12/12 / glenmarlboro / 突然想到一件笨事
    19.12/14 / QQQWERT / [耍笨] 其實...應該很多人做過這種事
    20.12/18 / Chucky9527 / [耍笨] 我的朋友的褲子拉鍊忘了關                   *
    *1. 23분의 4 / vivianJ / 아마 "A"여자, 잘 될 수있는 유일한 사람이야2. 25분의 4 / purinfocus / 간호사 회고록 23. 27분의 4 / EchoMary / 토크 오늘 중간 고사 ..4. 5월 5일 / wubaiwife / 고의 또는 바보입니까?5. 22분의 5 / m0630821 / [채팅] 오일 E 테이블에 무엇입니까?우체국 6. 13분의 6 / hohoholalala /7. 22분의 6 / cynthia730 / 조리8. 22분의 6 / chachalee / 당신은 정말 내 어머니가 어떻게 있습니까?9. 25분의 6 / superlubu / [동영상] 타이거  타이페이 세븐 비극 10. 8 / 04 / keikolin / [바보 재생] 나는 마지막 의 어머니11. 8 / 05 / utou / [애니메이션] 바보의 이야기12 9 / 12 / okaoka0709 / [전사] 재 :. [] 내 마지막 이름은 정말 특별한 당신13. 25분의 9 / LISKA / [아동] 중추절 바베큐 == | | |14.10/03 / JKH945 / [생일 + 바보의 꿈] 마지막  십구년15.10/28 / winniechi / [바보 재생] 클래스 스택 사용16.11/10 / olivetrees / 내 동생 가장 오래된 사기로 간주되어야한다17.11/10 / keikoYAMADA / 유서 복구 시스템18.12/12 / glenmarlboro / 갑자기 멍청한 생각19.12/14 / QQQWERT / 사실 [바보 재생]는 ... 많은 사람들이 그런 일을했을이어야한다20.12/18 / Chucky9527 / [바보 재생] 내 친구 바지 지퍼를 해제하는 것을 잊었다                              *
     
    *學會這招,就能在自己的程式中輕鬆使用T4生Code,以後就不必用StringBuilder硬兜囉!*
    *이 트릭 배웠습니다, ​​당신은 쉽게 T4 원시 코드 사용하여 자신 프로그래밍 할 수 있습니다,
     ​​안녕하세요 모두 StringBuilder 하드 주머니를 사용하지 않습니다!**
    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&