備註
Active Template Library(ATL)將持續獲得支援。 不過,我們不再新增功能或更新文件。
在此步驟中,您會將ClickIn和ClickOut事件新增至 ATL 控制項。 如果使用者在多邊形內按一下,將觸發事件 ClickIn;如果使用者在多邊形外按一下,將觸發事件 ClickOut。 新增事件的工作如下所示:
添加
ClickIn和ClickOut方法產生類型庫
實作連接點介面
新增 ClickIn 和 ClickOut 方法
當您在步驟 2 中建立 ATL 控制項時,選取 [ 連接點 ] 複選框。 這會在 Polygon.idl 檔案中建立 _IPolyCtlEvents 介面。 請注意,介面名稱「介面名稱」以底線開頭。 這是表示介面是內部介面的慣例。 因此,可讓您流覽 COM 物件的程式可以選擇不向使用者顯示介面。 另請注意,選取 [連接點 ] 會在 Polygon.idl 檔案中新增下列這一行,以指出 _IPolyCtlEvents 這是預設的來源介面:
[default, source] dispinterface _IPolyCtlEvents;
來源屬性表示控件是通知的來源,因此它會在容器上呼叫這個介面。
現在,將 ClickIn 和 ClickOut 方法新增至 _IPolyCtlEvents 介面。
新增 ClickIn 和 ClickOut 方法
在 方案總管視窗 中,開啟 Polygon.idl,並在 PolygonLib 程式庫的宣告中
methods:dispInterface_IPolyCtlEvents新增下列程式代碼:[id(1), helpstring("method ClickIn")] void ClickIn([in] LONG x,[in] LONG y); [id(2), helpstring("method ClickOut")] void ClickOut([in] LONG x,[in] LONG y);
ClickIn 和 ClickOut 方法會採用點按的點的 x 和 y 座標做為參數。
生成類型庫
此時產生類型連結庫,因為專案會使用它來取得它建構連接點介面和控件連接點容器介面所需的資訊。
要產生類型庫
重建您的專案。
-或-
以滑鼠右鍵按兩下 方案總管中的 Polygon.idl 檔案,然後按下快捷方式選單上的 [編譯]。
這會建立Polygon.tlb檔案,也就是您的類型連結庫。 Polygon.tlb 檔案無法從 方案總管 看見,因為它是二進位檔,無法直接檢視或編輯。
實作連接點介面
建立控制項的連接點介面和連接點容器介面。 在 COM 中,事件是透過連接點的機制來實作。 若要從 COM 物件接收事件,容器會建立與 COM 物件實作之連接點的諮詢連線。 因為 COM 物件可以有多個連接點,因此 COM 物件也會實作連接點容器介面。 透過這個介面,容器可以判斷支援哪些連接點。
實作連接點的介面稱為 IConnectionPoint,而實作連接點容器的介面稱為 IConnectionPointContainer。
為了協助實施IConnectionPoint,您將使用連接點實施精靈。 此精靈會透過讀取您的型別庫來產生IConnectionPoint介面,並為每個可引發的事件實作函數。
建立連接點
在 方案總管 中,開啟 _IPolyCtlEvents_CP.h,然後在
CProxy_IPolyCtlEvents類別中的public:語句底下新增下列程式碼:VOID Fire_ClickIn(LONG x, LONG y) { T* pT = static_cast<T*>(this); int nConnectionIndex; CComVariant* pvars = new CComVariant[2]; int nConnections = m_vec.GetSize(); for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) { pT->Lock(); CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex); pT->Unlock(); IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p); if (pDispatch != NULL) { pvars[1].vt = VT_I4; pvars[1].lVal = x; pvars[0].vt = VT_I4; pvars[0].lVal = y; DISPPARAMS disp = { pvars, NULL, 2, 0 }; pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL); } } delete[] pvars; } VOID Fire_ClickOut(LONG x, LONG y) { T* pT = static_cast<T*>(this); int nConnectionIndex; CComVariant* pvars = new CComVariant[2]; int nConnections = m_vec.GetSize(); for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) { pT->Lock(); CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex); pT->Unlock(); IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p); if (pDispatch != NULL) { pvars[1].vt = VT_I4; pvars[1].lVal = x; pvars[0].vt = VT_I4; pvars[0].lVal = y; DISPPARAMS disp = { pvars, NULL, 2, 0 }; pDispatch->Invoke(0x2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL); } } delete[] pvars; }
您會看到此檔案有名為 的類別 CProxy_IPolyCtlEvents ,其衍生自 IConnectionPointImpl。 _IPolyCtlEvents_CP.h 現在定義了兩個方法 Fire_ClickIn 和 Fire_ClickOut,這些方法採用兩個座標參數。 當您想要從控件中引發事件時,您可以呼叫這些方法。
藉由建立已選取 [連接點] 選項 的控件,就會為您產生 _IPolyCtlEvents_CP.h 檔案。 它也會新增 CProxy_PolyEvents 和 IConnectionPointContainerImpl 至控制項的多重繼承清單,並藉由將適當的項目新增至 COM 對應,向您公開 IConnectionPointContainer。
您已完成實作程式代碼以支援事件。 現在,新增一些程序代碼,以在適當的時刻引發事件。 請記住,當使用者按兩下控制件中的滑鼠左鍵時,您將會引發 ClickIn 或 ClickOut 事件。 若要瞭解使用者何時按按鈕,請為 WM_LBUTTONDOWN 訊息新增處理程式。
請新增用於處理 WM_LBUTTONDOWN 訊息的處理程式
在 [類別檢視] 中
CPolyCtl,以滑鼠右鍵單擊類別,然後按下快捷方式功能表上的 [ 屬性 ]。在 [ 屬性] 視窗中,按兩下 [訊息] 圖示,然後按下
WM_LBUTTONDOWN左側清單。從出現的下拉式清單中,點擊 <新增> OnLButtonDown。 處理程式
OnLButtonDown宣告會新增至 PolyCtl.h,並將處理程式實作新增至PolyCtl.cpp。
接下來,修改處理程式。
若要修改 OnLButtonDown 方法
變更 PolyCtl.cpp 中包含
OnLButtonDown方法的程式代碼(刪除精靈放置的所有程式代碼),使其看起來像這樣:LRESULT CPolyCtl::OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) { HRGN hRgn; WORD xPos = LOWORD(lParam); // horizontal position of cursor WORD yPos = HIWORD(lParam); // vertical position of cursor CalcPoints(m_rcPos); // Create a region from our list of points hRgn = CreatePolygonRgn(&m_arrPoint[0], m_nSides, WINDING); // If the clicked point is in our polygon then fire the ClickIn // event otherwise we fire the ClickOut event if (PtInRegion(hRgn, xPos, yPos)) Fire_ClickIn(xPos, yPos); else Fire_ClickOut(xPos, yPos); // Delete the region that we created DeleteObject(hRgn); return 0; }
此程式代碼會使用函式中 OnDraw 計算的點來建立區域,以透過呼叫 PtInRegion來偵測使用者的滑鼠點選。
uMsg 參數是所處理 Windows 訊息的標識碼。 這可讓您有一個函式來處理一系列訊息。 wParam 和 lParam 參數是所處理訊息的標準值。 bHandled 參數可讓您指定函式是否處理訊息。 根據預設,值會設定為TRUE,表示函式已處理訊息,但您可以將它設定為 FALSE。 這會導致 ATL 繼續尋找另一個訊息處理程式函式來傳送訊息。
建置和測試控制項
現在測試您的事件。 建置控件,然後再次啟動 ActiveX 控制件測試容器。 這次,請檢視事件記錄檔視窗。 若要將事件路由至輸出視窗,請從 [選項] 功能表中選擇 [記錄],然後選取 [記錄到輸出視窗]。 插入 控件,然後嘗試在視窗中按兩下。 請注意,當您在填滿的多邊形內單擊時會觸發ClickIn,而當您在其外部單擊時會觸發ClickOut。
接下來,您將新增屬性頁。