提供無視窗啟用
視窗建立程式碼(也就是呼叫 CreateWindow
時所發生的一切),執行成本高昂。 維護螢幕上視窗的控制項必須管理視窗的訊息。 因此,無視窗控制項與視窗型控制項相較之下速度更快。
無視窗控制項與視窗型控制項不同的另一項優點在於,無視窗控制項支援透明繪製及非矩形螢幕區域。 常見的透明控制項範例是具有透明背景的文字控制項。 控制項會繪製文字,但不會繪製背景,因此文字後方的所有內容都可清楚看見。 新式的表單通常會採用非矩形控制項,例如箭號和圓形按鈕。
假設已寫入可支援無視窗物件的容器,控制項通常不需要自己的視窗,而是改用其容器的視窗服務。 無視窗控制項可與舊的容器回溯相容。 在未撰寫為支援無視窗控制項的舊容器中,無視窗控制項會在作用時建立視窗。
由於無視窗控制項沒有自己的視窗,因此具有視窗的容器會負責提供控制項自己的視窗所提供的服務。 例如,如果控制項需要查詢鍵盤焦點、擷取滑鼠或取得裝置內容,這些作業就會交由容器管理。 容器會使用 IOleInPlaceObjectWindowless
介面,將傳送至本身所屬視窗的使用者輸入訊息路由傳送至適當的無視窗控制項 (請參閱 ActiveX SDK 以取得此介面的描述。) COleControl
成員函式會從容器叫用這些服務。
若要讓控制項使用無視窗啟用,請在 COleControl::GetControlFlags 所 傳回的旗標集合中包含 windowlessActivate 旗標。 例如:
DWORD CMyAxOptCtrl::GetControlFlags()
{
DWORD dwFlags = COleControl::GetControlFlags();
// The control can activate without creating a window.
dwFlags |= windowlessActivate;
return dwFlags;
}
如果您在 MFC ActiveX 控制項精靈的 [控制項設定 ] 頁面上選取 [無視窗啟用 ] 選項,就會自動產生包含此旗標的程式碼。
啟用無視窗啟用之後,容器會將輸入訊息委派至控制項的 IOleInPlaceObjectWindowless
介面。 這個介面的 COleControl
實作會在適當調整滑鼠座標之後,透過您控制項的訊息對應分派訊息。 您可以將對應的項目加入至訊息對應,如此就可以像處理一般視窗訊息一樣地處理訊息。 在這些訊息的處理常式中,請避免使用 m_hWnd 成員變數(或任何使用它的成員函式),而不先檢查其值是否為 Null 。
COleControl
提供了適時從容器中叫用滑鼠擷取、鍵盤焦點、捲動和其他視窗服務的成員函式,包括:
在無視窗控制項中,您應一律使用 COleControl
成員函式,而不要使用對應的 CWnd
成員函式,或其相關的 Win32 API 函式。
您可能想將無視窗控制項做為 OLE 拖放作業的目標。 通常這會需要將控制項的視窗登錄為置放目標。 由於控制項沒有自己的視窗,因此容器會使用其視窗做為置放目標。 控制項會提供 IDropTarget
介面的實作,讓容器能夠在適當時委派呼叫。 若要將此介面公開至容器,請覆寫 COleControl::GetWindowlessDropTarget 。 例如:
IDropTarget* CMyAxOptCtrl::GetWindowlessDropTarget()
{
m_DropTarget.m_xDropTarget.AddRef();
return &m_DropTarget.m_xDropTarget;
}