ArcMap下停靠栏的设计与实现

        ArcMap 9.3下的UI风格着实比较粗糙,和国内很多软件UI相比汗颜呀,但是ArcMap在GIS编辑上的重要性是不言而喻的,最近想试着深入一下ArcMap的定制。ArcMap的可定制部分,无外乎菜单,工具栏,以及停靠栏,前二者,一般用户可能都接触过,例子也比较多,各种语言和代码都能找到,停靠栏在网上也能找到,VBA和C#比较多,但是C++开发的代码没有,原因是嵌入窗体到停靠栏中不容易实现。

       在开发自定义的停靠栏之前,说说停靠栏能干吗用。在ArcMap中,TOC控件就是用得最多的停靠栏,还有质量检查控件也是停靠栏。如果用户交互中涉及的属性与图形显示非常相关,强烈建议采用停靠栏的方式,例如在质检过程,如果非常多的信息需要通过图形关系来判断,打开属性表的方式并不是特别方便,应为属性表和Map容易相互遮盖影响交互,特别是在大数据量的情况下交互非常别扭。

       话题涉及到如何开发,很多人在网上问到如何开发,特别是采用C++开发,事实上用C++开发很不容易,因为你需要精确的控制非模式化窗口的每个过程,从创建到销毁都需要手工控制。

      因为9.3的后续版本下(10.0,10.1),ArcMap的风格完全改变到了,风格类似office2007,可能一定程度上会打消9.3下一部分用户的开发需求。但是接触了很多用户后,我发现大部分用户,仍然习惯9.3,而且9.3的用户也巨大。

     开始停靠栏的开发,我们需要准备好开发环境,vc6,ArcMap9.3。如果熟悉ATL更好。

1、准备一个测试用例,我做得很简单,就是一个Command用于激活停靠栏

	STDMETHOD(OnClick)()
	{
		HRESULT hr;
		IDockableWindowManagerPtr 	ipDockableWindowManager;
                  ipDockableWindowManager=m_ipDispatch;
		IUIDPtr ipUID(CLSID_UID);
		hr=ipUID->put_Value(CComVariant("{F884D1F0-C82F-40F1-A2EB-359D51F635F7}"));
		IDockableWindowPtr ipDockableWindow;
		//实例化停靠栏组件
		hr=ipDockableWindowManager->GetDockableWindow(ipUID,&ipDockableWindow);
                  VARIANT_BOOL varVisual;
 	         hr=ipDockableWindow->IsVisible(&varVisual);
 	        //if (varVisual==VARIANT_TRUE)
		{   
			//得到当前停靠栏的大小
			IWindowPositionPtr ipWindowPosition;
                            ipWindowPosition=ipDockableWindow;
			long width;
			long height;
			
			hr=ipDockableWindow->Show(VARIANT_TRUE);
			
			hr=ipDockableWindow->Dock(esriDockBottom);
			
			hr=ipWindowPosition->get_Width(&width);
			hr=ipWindowPosition->get_Height(&height);
		}	
		
		return S_OK;
	}

2、扩展IDockableWindowDef

	STDMETHOD(OnCreate)(IDispatch * hook)
	{
		//传递IApplication;
        HRESULT hr;
        IApplicationPtr ipApplication;
        ipApplication=hook;
		OLE_HANDLE AppOLEHandle;
		hr=ipApplication->get_hWnd(&AppOLEHandle);
    	HWND hwnd=(HWND)AppOLEHandle;
        m_TableForm.Create(hwnd,(LPARAM)(hook));
       // m_TableForm.Create(hwnd);
        ATLTRACE("\n***新建窗口\n");
		return S_OK;
	}

3、建立自己的窗口组件

4、添加自己的属性列表

属性列表是放在属性页中的,属性页被嵌入到每个Tab control中,

        LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
         m_ipDispatch=(IDispatch * )lParam;
         if(m_ipDispatch==NULL)
           return 0;

         USES_CONVERSION;
	   HRESULT hr;
	   //添加tab页
	   //path From dll	   
	   TCHAR szFullPathName[_MAX_PATH];
	   GetModuleFileName((HMODULE)(_Module.m_hInst),szFullPathName,_MAX_PATH);
	   TCHAR drive[_MAX_DRIVE];
	   TCHAR dir[_MAX_DIR];
	   TCHAR fname[_MAX_FNAME];
	   TCHAR ext[_MAX_EXT];
	   _wsplitpath(szFullPathName, drive, dir, fname,ext);
	   TCHAR szPathOfMdb[_MAX_PATH];
	   wcscpy(szPathOfMdb,drive);
	   wcscat(szPathOfMdb,dir);
	   wcscat(szPathOfMdb,_T("diyingli.mdb"));
	   CComBSTR bstrPathOfmdb=szPathOfMdb;       
	   //Open mdb
	   IWorkspaceFactoryPtr ipWSF(CLSID_AccessWorkspaceFactory);
	   IWorkspacePtr ipWorkspace;
	   hr=ipWSF->OpenFromFile(bstrPathOfmdb,NULL,&ipWorkspace);
	   if (FAILED(hr))
	   {
	       ::MessageBox(NULL,_T("没有找到地应力数据库"),_T("错误"),MB_ICONERROR);
	       return 1;
	   }
            //打开数据库加载空间数据表格
	   //esriDTTable
	   IStringArrayPtr ipStringArray(CLSID_StrArray);
	   IEnumDatasetNamePtr ipEnumDatasetName;
            hr=ipWorkspace->get_DatasetNames(esriDTTable,&ipEnumDatasetName);
	   hr=ipEnumDatasetName->Reset();
	   IDatasetNamePtr ipDatasetName;
	   while (!ipEnumDatasetName->Next(&ipDatasetName))
	   {
		   CComBSTR bstrName;
           hr=ipDatasetName->get_Name(&bstrName);
		   hr=ipStringArray->Add(bstrName);
	   }

	   long lStrCount;
	   hr=ipStringArray->get_Count(&lStrCount);

	
           HWND hwnd=GetDlgItem(IDC_TAB1);
	   //Get Name and table Info from gdb
	   for (long i=0;i<lStrCount;i++)
	   {   
		   CComBSTR bstrItemName;
		   hr=ipStringArray->get_Element(i,&bstrItemName);
		   TCITEM tci;
		   tci.mask = TCIF_TEXT;
		   tci.pszText =OLE2T(bstrItemName);
		   tci.cchTextMax = wcslen(OLE2T(bstrItemName)) + 1;
		   tci.iImage = -1;
		   tci.lParam = 0;
		   TabCtrl_InsertItem(hwnd,i,&tci);
           
		    //Add table to tab control
		   ITablePtr ipTable;
		   IFeatureWorkspacePtr ipFWS;
                     ipFWS=ipWorkspace;
		   hr=ipFWS->OpenTable(bstrItemName,&ipTable);
                      //添加属性页
                         AddTableToTabControl(ipTable,hwnd);
	   }
     
	   //发送消息TCN_SELCHANGE
          // 设置Tab第一项属性页为可显示
	   NMHDR   nmhdr; 
	   nmhdr.code = TCN_SELCHANGE;       
	   nmhdr.hwndFrom = hwnd;       
	   nmhdr.idFrom=IDC_TAB1;       
	   ::SendMessage(hwnd,WM_NOTIFY,MAKELONG(TCN_SELCHANGE,0),(LPARAM)(&nmhdr)); 
	return 1;  // Let the system set the focus
}

 

最后的效果就是下面的图了。


 

     

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值