ArcMap下停靠欄的設計與實現

本例要實現的是如何創建定製的可停靠窗口(Dockable Window),目前用C# AddIn寫這個很方便,但是市面上用C++,MFC寫停靠欄的就很少了。本例爲方便大家學習而寫。

其實步驟很簡單。

1、實現IdockableWindowDef接口(參見實例);

用戶通過在類模塊中實現IDockableWindowDef接口來創建定製的可停靠窗口(Dockable Window)。IDockableWindowDef接口包括Caption、ChildHWND,UserData及Name等屬性和OnCreate、OnDestroy事件。

·ChildHWND屬性表示可停靠窗口包含的Window的Handle。

·OnCreate事件的參數hook傳入ArcGIS的Application實例。

下面是一個實現IDockableWindowDef 的類,主要看get_ChildHWND,這裏實現了窗口句柄Hwnd的返回。

lass ATL_NO_VTABLE CCArcMatrixOneChkResDocView :
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CCArcMatrixOneChkResDocView, &CLSID_CArcMatrixOneChkResDocView>,
	public ICArcMatrixOneChkResDocView,
	public IDockableWindowDef
{
public:
	CCArcMatrixOneChkResDocView()
	{

	}

	DECLARE_REGISTRY_RESOURCEID(IDR_CARCMATRIXONECHKRESDOCVIEW)

	DECLARE_NOT_AGGREGATABLE(CCArcMatrixOneChkResDocView)

	BEGIN_COM_MAP(CCArcMatrixOneChkResDocView)
		COM_INTERFACE_ENTRY(ICArcMatrixOneChkResDocView)
		COM_INTERFACE_ENTRY(IDockableWindowDef)
	END_COM_MAP()



	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		m_pHookllelper = NULL;
		m_pApplication = NULL;
		m_DlgChkResultView = NULL;
		return S_OK;
	}

	void FinalRelease()
	{
		m_pHookllelper = NULL;
		m_pApplication = NULL;
	}

public:
	IHookHelperPtr m_pHookllelper;	
	IApplicationPtr m_pApplication; 
	CDlgChkResultView* m_DlgChkResultView;


	// IDockableWindowDef Methods
public:
	STDMETHOD(OnCreate)(LPDISPATCH hook)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		if (m_pHookllelper != NULL)
		{
			m_pHookllelper->putref_Hook(NULL);
			m_pHookllelper = NULL;
		}
		m_pHookllelper.CreateInstance(CLSID_HookHelper);
		if (!m_pHookllelper) return E_POINTER;
		HRESULT hr = m_pHookllelper->putref_Hook(hook);
		if (FAILED(hr))
		{
			return S_FALSE;
		}
		GpHookllelper = m_pHookllelper;

		if (m_pApplication != NULL)
		{
			m_pApplication = NULL;
		}
		ATLASSERT(hook!=NULL);
		m_pApplication = hook;
		OLE_HANDLE oleHandle;
		AfxOleInit();
		m_pApplication->get_hWnd(&oleHandle);
		CWnd *pwnd = new CWnd();
		pwnd->Attach((HWND)oleHandle);


		return S_OK;
	}
	STDMETHOD(get_ChildHWND)(OLE_HANDLE * hWnd)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		if (hWnd == NULL)	return E_POINTER;
		if (m_DlgChkResultView!=NULL && m_DlgChkResultView->m_hWnd != NULL && ::IsWindow(m_DlgChkResultView->m_hWnd) && ::IsWindowVisible(m_DlgChkResultView->m_hWnd))
		{
			m_DlgChkResultView->ShowWindow(SW_HIDE);
		}
		else
		{
			if (m_DlgChkResultView == NULL)
			{
				m_DlgChkResultView = new CDlgChkResultView();
				m_DlgChkResultView->Create(IDD_DIALOG_RESULTVIEW);
			}	
			m_DlgChkResultView->ShowWindow(SW_HIDE);
		}

		if (m_DlgChkResultView != NULL)
		{
			*hWnd = (OLE_HANDLE ) m_DlgChkResultView->GetSafeHwnd();
		}
		else
		{
			*hWnd = NULL;
		}
		return S_OK;
	}
	STDMETHOD(get_Name)(BSTR * Name)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		if (Name == NULL)
		{
			return E_NOTIMPL;
		}
		CString strName;
		strName.LoadStringW(IDS_CHECKRESULT);
		*Name = strName.AllocSysString();
		return S_OK;
	}
	STDMETHOD(get_Caption)(BSTR * Caption)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		if (Caption == NULL)
		{
			return E_NOTIMPL;
		}
		CString strCaption;
		strCaption.LoadStringW(IDS_CHECKRESULT);
		*Caption = strCaption.AllocSysString();
		return S_OK;
	}
	STDMETHOD(OnDestroy)()
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		m_pApplication = NULL;
		m_pHookllelper = NULL;
		return S_OK;
	}
	STDMETHOD(get_UserData)(VARIANT * data)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		return S_OK;
	}
};

 

2、編譯成DLL;

3、調用windows目錄下system32子目錄下的regsvr32.exe用下面的形式註冊編譯好的DLL:

win目錄\system32\regsvr32.exe  <路徑>\<文件名>.dll

 

4、運行<arcmap目錄>\arcexe81\Bin\categories.exe,在打開的Component Catregory Manager中找到ESRI Mx Dockable Window,點擊Add Object…按鈕將上面註冊的DLL文件加入,並選中實現IdockableWindowDef接口的類名即可。

5、實現一個Command命令,獲取DocWindow 並且顯示。OnClick時顯示停靠欄。


class ATL_NO_VTABLE CCArcMatrixOneCheckResultCommand :
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CCArcMatrixOneCheckResultCommand, &CLSID_CArcMatrixOneCheckResultCommand>,
	public IDispatchImpl<ICArcMatrixOneCheckResultCommand, &IID_ICArcMatrixOneCheckResultCommand, &LIBID_ArcMatrixOneLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
	public esriICommand
{
public:
	CCArcMatrixOneCheckResultCommand()
	{

	}

	DECLARE_REGISTRY_RESOURCEID(IDR_CARCMATRIXONECHECKRESULTCOMMAND)

	DECLARE_NOT_AGGREGATABLE(CCArcMatrixOneCheckResultCommand)

	BEGIN_COM_MAP(CCArcMatrixOneCheckResultCommand)
		COM_INTERFACE_ENTRY(ICArcMatrixOneCheckResultCommand)
		COM_INTERFACE_ENTRY(IDispatch)
		COM_INTERFACE_ENTRY(esriICommand)
	END_COM_MAP()



	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		m_hBitmap= ::LoadBitmap(_AtlBaseModule.GetResourceInstance(),MAKEINTRESOURCE(IDB_BITMAP_CHECKRESULTVIEW));
		m_hCursor = (HCURSOR)::LoadCursor(NULL,IDC_CROSS);
		m_pDispath = NULL;
		m_pApplication = NULL;
		m_pDocWnd = NULL;
		m_pHookllelper = NULL;
		m_bChecked = VARIANT_FALSE;
		m_DlgChkResultView = NULL;
		return S_OK;
	}

	void FinalRelease()
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		::DeleteObject(m_hBitmap);
		::DestroyCursor(m_hCursor);
		m_pDispath = NULL;
		m_pApplication = NULL;
		m_pDocWnd = NULL;
		m_pHookllelper = NULL;
		m_DlgChkResultView = NULL;
	}

public:
	HBITMAP m_hBitmap;
	HCURSOR	m_hCursor;
	LPDISPATCH m_pDispath;
	IHookHelperPtr m_pHookllelper;	
	IApplicationPtr m_pApplication;
	IDockableWindowPtr m_pDocWnd;
	VARIANT_BOOL m_bChecked;
	CDlgChkResultView *m_DlgChkResultView;


	// ICommand Methods
public:
	STDMETHOD(get_Enabled)(VARIANT_BOOL * Enabled)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		if (Enabled == NULL)
		{
			return E_POINTER;
		}
		*Enabled = VARIANT_TRUE;

		return S_OK;
	}
	STDMETHOD(get_Checked)(VARIANT_BOOL * Checked)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		if (Checked == NULL || m_pDocWnd == NULL  )
		{
			return S_FALSE;
		}
		*Checked = m_bChecked;
		return S_OK;
	}

	STDMETHOD(get_Name)(BSTR * Name)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		if (Name == NULL)
		{
			return E_POINTER;
		}
		CString strName ;
		strName.LoadStringW(IDS_CHECKRESULT);
		*Name = SysAllocString(strName);
		return S_OK;
	}

	STDMETHOD(get_Caption)(BSTR * Caption)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		if (Caption == NULL)
		{
			return E_POINTER;
		}
		CString strCaption ;
		strCaption.LoadStringW(IDS_CHECKRESULT);
		*Caption = SysAllocString(strCaption);
		return S_OK;
	}

	STDMETHOD(get_Tooltip)(BSTR * Tooltip)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		if (Tooltip == NULL)
		{
			return E_POINTER;
		}
		CString strTooltip ;
		strTooltip.LoadStringW(IDS_CHECKRESULT);
		*Tooltip = SysAllocString(strTooltip);
		return S_OK;
	}

	STDMETHOD(get_Message)(BSTR * Message)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		if (Message == NULL)
		{
			return E_POINTER;
		}
		CString strMessage ;
		strMessage.LoadStringW(IDS_CHECKRESULT);
		*Message = SysAllocString(strMessage);
		return S_OK;
	}

	STDMETHOD(get_HelpFile)(BSTR * HelpFile)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		return S_OK;
	}

	STDMETHOD(get_HelpContextID)(long * helpID)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		return S_OK;
	}

	STDMETHOD(get_Bitmap)(OLE_HANDLE * Bitmap)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		if (Bitmap == NULL) 
			return E_POINTER; 
		*Bitmap = (OLE_HANDLE)m_hBitmap; 
		return S_OK; 
	}

	STDMETHOD(get_Category)(BSTR * categoryName)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		if (categoryName == NULL)
		{
			return E_POINTER;
		}
		CString strMessage = StrFromResID(IDS_CATEGORY);
		*categoryName = ::SysAllocString(L"CustomCategory");//strMessage.AllocSysString();
		
		return S_OK;
	}

	STDMETHOD(OnCreate)(LPDISPATCH Hook)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		m_pDispath = Hook;
		m_pApplication = Hook;
		if (m_pHookllelper != NULL)
		{
			m_pHookllelper->putref_Hook(NULL);
			m_pHookllelper = NULL;
		}
		m_pHookllelper.CreateInstance(CLSID_HookHelper);
		if (!m_pHookllelper) return E_POINTER;
		HRESULT hr = m_pHookllelper->putref_Hook(Hook);
		if (FAILED(hr))
		{
			return S_FALSE;
		}
		GpHookllelper = m_pHookllelper;

		return E_NOTIMPL;
	}

	STDMETHOD(OnClick)()
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
		HRESULT hr = S_OK;

		IDockableWindowManagerPtr    ipDockableWindowManager = NULL;
		ipDockableWindowManager = m_pApplication;
		if (!ipDockableWindowManager)
		{
			return S_FALSE;
		}
		IUIDPtr ipUID(CLSID_UID);
		CComBSTR bsVal;
		//9CB364C5,0xF1A2,0x455E,0x9D,0xE3,0x86,0x4A,0x26,0x22,0xCB,0xCE 本工程中實現的 uuid CCArcMatrixOneCheckResultDocView
		ipUID->put_Value(CComVariant("{9CB364C5-F1A2-455E-9DE3-864A2622CBCE}"));
		hr = ipDockableWindowManager->GetDockableWindow(ipUID,&m_pDocWnd);
		if (FAILED(hr) || m_pDocWnd == NULL)
		{
			MessageBox(NULL,_T("getDockWindow failed"),_T("Note"),MB_OK);
			return S_FALSE;
		}

		VARIANT_BOOL varVisual = VARIANT_FALSE;
		if (m_pDocWnd)
		{
			hr = m_pDocWnd->IsVisible(&varVisual);
			if (varVisual == VARIANT_FALSE)
			{
				m_pDocWnd->Show(VARIANT_TRUE);  
				IWindowPositionPtr ipWindowPosition = NULL;  
				ipWindowPosition=m_pDocWnd;  
				long width = 200 ;  
				long height = 100;  

				if (m_pDocWnd)
				{
					hr=m_pDocWnd->Show(VARIANT_TRUE);  
					/*
						esriDockHide = 0,
						esriDockShow = 1,
						esriDockLeft = 2,
						esriDockRight = 4,
						esriDockTop = 8,
						esriDockBottom = 16,
						esriDockFloat = 32,
						esriDockToggle = 64,
						esriDockTabbed = 128,
						esriDockUnPinned = 256
					*/			
					hr=m_pDocWnd->Dock(esriDockTabbed);  
				}
			}
			else
			{
				m_pDocWnd->Show(VARIANT_FALSE); 
			}
			m_pDocWnd->IsVisible(&varVisual);
		}
		else
		{
			AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
			varVisual = VARIANT_FALSE;
			return S_FALSE;
		}

		m_bChecked  = varVisual ;
				return S_OK;
	}
};

 6、打開arcMap註冊命令,測試。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章