![桌面GIS應(yīng)用程序框架的建立_第1頁(yè)](http://file4.renrendoc.com/view/02b71ea3fcee09dd928aaaa48aa3446e/02b71ea3fcee09dd928aaaa48aa3446e1.gif)
![桌面GIS應(yīng)用程序框架的建立_第2頁(yè)](http://file4.renrendoc.com/view/02b71ea3fcee09dd928aaaa48aa3446e/02b71ea3fcee09dd928aaaa48aa3446e2.gif)
![桌面GIS應(yīng)用程序框架的建立_第3頁(yè)](http://file4.renrendoc.com/view/02b71ea3fcee09dd928aaaa48aa3446e/02b71ea3fcee09dd928aaaa48aa3446e3.gif)
![桌面GIS應(yīng)用程序框架的建立_第4頁(yè)](http://file4.renrendoc.com/view/02b71ea3fcee09dd928aaaa48aa3446e/02b71ea3fcee09dd928aaaa48aa3446e4.gif)
![桌面GIS應(yīng)用程序框架的建立_第5頁(yè)](http://file4.renrendoc.com/view/02b71ea3fcee09dd928aaaa48aa3446e/02b71ea3fcee09dd928aaaa48aa3446e5.gif)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第一講:桌面GIS應(yīng)用程序框架的建立本講主要是使用MapControl、PageLayoutControl、ToolbarControl,TOCControl四個(gè)控件建立起基本的桌面GIS應(yīng)用程序框架。最終成果預(yù)覽如下:1、新建項(xiàng)目啟動(dòng)VS2005,選擇’’文件I新建I項(xiàng)目”,在項(xiàng)目類型中選擇VisualC#,再選擇Windows應(yīng)用程序模板,輸入名稱“3sdnMap”,點(diǎn)擊確定。在解決方案管理器中將“Forml.cs”重命名為“3sdnMap.cs”,在設(shè)計(jì)視圖中,選中窗體,將其屬性中的“Text”改為“3sdnMap”。2、添加控件選擇工具箱中的“菜單和工具欄IMenuStrip”,將其拖入窗體。選擇工具箱中的"ArcGISWindowsForms"節(jié),將"ToolbarControl”控件拖入窗體,并將其屬性中的Dock設(shè)置為Top。選擇工具箱中的“菜單和工具欄IStatusStrip”,將其拖入到窗體。選擇工具箱中的“容器ISplitContainer”容器拖入窗體,并將其屬性中的Dock設(shè)置為Fill。將TabContro!控件拖入Pane”,將Alignment屬性設(shè)置為Bottom,Dock屬性設(shè)置為Fill。點(diǎn)擊TabPages屬性右邊的按鈕,彈出TabPage集合編輯器,將tabPagel的Name設(shè)置為tabPageLayer,Text設(shè)置為圖層,將tabPage2的Name設(shè)置為tabPageProperty,Text設(shè)置為屬性。如下所示。選擇“圖層”選項(xiàng)卡,拖入TOCControl控件,設(shè)置Dock屬性為FilL選擇"屬性”選項(xiàng)卡,拖入DataGridView控件,設(shè)置Dock屬性為Fill。拖入TabContro!控件到Panel2,設(shè)置Dock屬性為Filし并上述類似的方法,將兩個(gè)選項(xiàng)卡的Name和Text分別設(shè)置為:(tabPageMap、地圖,(tabPageLayout,制版)。選擇“地圖”選項(xiàng)卡,拖入MapControl控件,設(shè)置Dock屬性為Fill。選擇“制版”選項(xiàng)卡,拖入PageLayoutControl控件,設(shè)置Dock屬性為Fill。最后將LicenseContro!控件拖入到窗體的任意地方。按F5編譯運(yùn)行,可以看到剛オ布局好的程序界面了。3、控件綁定通過(guò)以上步驟添加的控件還只是單獨(dú)存在,而我們的程序需要各控件間協(xié)同工作,因此要進(jìn)行控件綁定。分別右擊ToolbarControl、TOCControl控件,將Buddy設(shè)置為axMapControll,如下圖所示。
屬性這樣,工具條和圖層控件就與地圖控件關(guān)聯(lián)了。4、添加工具此時(shí),工具條中還沒(méi)有任何工具,添加的方法也很簡(jiǎn)單。右擊ToolbarControl,選擇“屬性lltems”,點(diǎn)擊Add,選擇Commands選項(xiàng)卡中的Generic,雙擊Open、SaveAs、Redo、Undo即可將相應(yīng)工具添加到工具條。常見(jiàn)的工具有:MapNavigation中的導(dǎo)航工具,MapInquiry中的查詢工具,F(xiàn)eatureSelection中的選擇工具,你可以根據(jù)需要酌情添加工具。5、編譯運(yùn)行按F5即可編譯運(yùn)行程序,至此桌面GIS應(yīng)用程序框架基本框架已經(jīng)搭建好了,你可以通過(guò)工具條的工具打開地圖文檔,瀏覽地圖了,效果如開篇所示.第二講菜單的添加及其實(shí)現(xiàn)在上一講中,我們實(shí)現(xiàn)了應(yīng)用程序基本框架,其中有個(gè)小錯(cuò)誤,在此先跟大家說(shuō)明下。在“屬性”選項(xiàng)卡中,我們當(dāng)時(shí)添加的是DataGridView控件,這個(gè)控件是用來(lái)顯示數(shù)據(jù)表的,而專門用于屬性的查詢和設(shè)置的控件是PropertyGrid控件。因此請(qǐng)你刪除“屬性”選項(xiàng)卡中的DataGridView控件,再把位于“工具箱I所有Windows窗體IPropertyGrid”(如果沒(méi)有,右擊選擇“選擇項(xiàng)”以添加此控件)控件拖到該選項(xiàng)卡。在這ー講中,主要講解菜單的添加和實(shí)現(xiàn)。1、1、添加菜單在設(shè)計(jì)視圖中,單擊菜單欄,會(huì)出現(xiàn)“請(qǐng)?jiān)诖颂庢I入”的提示,單擊提示就可以鍵入菜單名稱,如“文件”,再單擊“文件”,即可輸入其下拉子菜單,如下所示:Tips:每創(chuàng)建一個(gè)菜單,請(qǐng)?jiān)谄鋵傩悦姘逯性O(shè)置Name屬性,而且不要為中文,因此Name值將是此菜單響應(yīng)函數(shù)的函數(shù)名的一部分,帶中文的函數(shù)名,總是不好吧。本講中,我們將添加新建(New)、打開(Open)、添加數(shù)據(jù)(AddData)、保存(Save)、另存為(SaveAs)、退出(Exit)這些菜單,()內(nèi)為相應(yīng)的Name屬性值。Tips:你可以在屬性面板中的Text屬性中,把菜單名設(shè)置為中英文形式,如“打開Open”,帶下劃線的〇表示此項(xiàng)菜單的快捷鍵是字母〇,設(shè)置方法是在相應(yīng)字母前加上“&”銅如打開&Open”。但這種快捷鍵只在打開此下拉菜單時(shí)オ有效,即當(dāng)你單擊“文件”菜單彈出下拉菜單時(shí),按下字母〇就可以定位到“打開”菜單。還有一種在程序運(yùn)行時(shí)都有效的全局快捷鍵,可以在屬性面板中的“ShortCutKeys”中設(shè)置。你還可以在屬性面板中的Image屬性中設(shè)置你喜歡的菜單圖標(biāo)。單擊!mage那一行右邊的按鈕,彈出如下菜單。選擇“項(xiàng)目資源文件”,再單擊導(dǎo)入就可以選擇你的圖標(biāo)了。最終效果如下所示。
最終效果如下所示。第3sdnlap文件j|ontrol地畫 制版@ArcGISIontrol地畫 制版@ArcGISIName::」打開Qpen胡添加數(shù)據(jù)AddDataメ保存Save也另存為SaveAs觸退出Exit!口舌在此]7スW注意,在解決方案面板中,選中剛オ添加的所有圖標(biāo),在其屬性面板中將生成操作設(shè)置為“嵌入的資源”,這一點(diǎn)很重要!2、實(shí)現(xiàn)相關(guān)菜單首先定義指針(寫在publicpartialclassForml:Form下面即可):privateESRI.ArcGIS.Controls.IMapControl3m_mapControl=null;privateESRI.ArcGIS.Controls.IPageLayoutControl2m_pageLayoutControl=null:privateIMapDocumentpMapDocument;若以上指針無(wú)效,請(qǐng)?zhí)砑右韵乱?usingESRI.ArcGIS.Carto;usingESRI.ArcGIS.Controls;usingESRI.ArcGIS.esriSystem;usingESRI.ArcGIS.Display;usingESRI.ArcGIS.Geometry;usingESRI.ArcGIS.SystemUI;在設(shè)計(jì)視圖中的屬性面板中,選擇Forml,即主窗體,單擊事件按鈕(閃電形狀的那個(gè)按鈕),打到“Load”事件并雙擊,添加此事件。在Forml.Load函數(shù)中初始化這些指針://取得MapControl和PageLayoutControl的弓I用m_mapControl=(IMapControl3)this.axMapControl1.Object;m_pageLayoutControl=(IPageLayoutControl2)this.axPageLayoutControl1.Object;依次雙擊每個(gè)菜單項(xiàng),添加菜單響應(yīng)函數(shù)。實(shí)現(xiàn)代碼如下:III<summary>//Z新建地圖命令I(lǐng)II</summary>///<paramname=,'sender,'></param>///<paramname=uen></param>privatevoidNew_Click(objectsender,EventArgse)//本命令涉及到M叩Control和PageLayoutControl同步問(wèn)題,將在下ー講中實(shí)現(xiàn)///<summary>III打開地圖文檔Mxd命令I(lǐng)II</summary>III<paramname=',senderH></param>///<paramname=',eM></param>privatevoidOpen_Click(objectsender,EventArgse)//本命令涉及到MapControl和PageLayoutControl同步問(wèn)題,將在下ー講中實(shí)現(xiàn))III<summary>///添加數(shù)據(jù)命令I(lǐng)II</summary>///<paramname=',sender,'></param>///<paramname=',eM></param>privatevoidAddData_Click(objectsender,EventArgse){intcurrentLayerCount=this.axMapControl1.LayerCount;ICommandpCommand=newControlsAddDataCommandClass();pCommand.OnCreate(this.axMapControl1.Object);pCommand.OnClick();}///<summary>//Z保存地圖文檔命令///</summary>III<paramname=nsender"></param>///<paramname=',eM></param>privatevoidSave_Click(objectsender,EventArgse){//首先確認(rèn)當(dāng)前地圖文檔是否有效if (null != m_pageLayoutControl.DocumentFilename &&m_mapControl.CheckMxFile(m_pageLayoutControl.DocumentFilename)){/Z創(chuàng)建一個(gè)新的地圖文檔實(shí)例IMapDocumentmapDoc=newMapDocumentClass();/Z打開當(dāng)前地圖文檔mapDoc.Open(m_pageLayoutControl.DocumentFilename,string.Empty);/Z用PageLayout中的文檔替換當(dāng)前文檔中的PageLayout部分mapDoc.ReplaceContents((IMxdContents)m_pageLayoutControLPageLayout);/Z保存地圖文檔mapDoc.Save(mapDoc.UsesRelativePaths,false);mapDoc.Close();}}///<summary>〃ノ另存為地圖文檔命令///</summary>III<paramname=',sender,,></param>///<paramname="e"></param>privatevoidSaveAs_Click(objectsender,EventArgse){〃調(diào)用另存為命令I(lǐng)Commandcommand=newControlsSaveAsDocCommandClass();command.OnCreate(m__controlsSynchronizer.ActiveControl);command.OnClick();}///<summary>//Z退出程序///</summary>///<paramname=',senderH></param>///<paramname=ueH></param>privatevoidExit_Click(objectsender,EventArgse){Application.Exit();)3、編譯運(yùn)行按F5編譯運(yùn)行程序。也許你會(huì)發(fā)現(xiàn),菜單命令的實(shí)現(xiàn)方式都是類型的。沒(méi)錯(cuò),在AE9.2中,內(nèi)置了許多常用的Command和Tool,如ControlsAddDataCommandClassヽControlsMapZoomlnToolClassヽControlsMapPanToolClass等等,這些內(nèi)置對(duì)象在ESRI.ArcGIS.Controls命名空間中,你可以對(duì)象瀏覽器中查看。而且這些內(nèi)置對(duì)象的調(diào)用方式都類似,如下所示:/Z定義ICommandcommand=newControlsSaveAsDocCommandClass();/Z創(chuàng)建command.OnCreate(m_controlsSynchronizer.ActiveControl);/Z調(diào)用command.OnClick();第三講MapControl與PageLayoutControl同步在ArcMap中,能夠很方面地進(jìn)行MapView和LayoutView兩種視圖的切換,而且二者之間的數(shù)據(jù)是同步顯示的。關(guān)于兩種視圖同步的實(shí)現(xiàn)方法有多種,可以使用ObjectCopy對(duì)象進(jìn)行數(shù)據(jù)硬拷貝,而比較簡(jiǎn)單的方法莫過(guò)于二者共享一份地圖了,這也是最常用的方法。1、新建同步類ControlsSynchronizer在解決方案面板中右擊項(xiàng)目名,選擇“添加I類”,在類別中選擇“VisualC#項(xiàng)目項(xiàng)”,在模板中選擇“類”,輸入類名“ConlrolsSynchronizer.cs”,將以下代碼覆蓋自動(dòng)生成的代碼:usingSystem;usingSystem.Drawing;usingSystem.Collections;usingSystem.ComponentModel;usingSystem.Windows.Forms;usingSystem.IO;usingSystem.Runtime.InteropServices;usingESRI.ArcGIS.esriSystem;usingESRI.ArcGIS.Carto;usingESRI.ArcGIS.Controls;usingESRLArcGIS.SystemUI;namespace_sdnMap///<summary>///ThisclassisusedtosynchronizeagvenPageLayoutControlandaMapControl.///Wheninitialized,theusermustpassthereferenceofthesecontroltotheclass,bindIllthecontroltogetherbycalling'BindControls'whichinturnsetsajoinedMapreferencedIIIbybothcontrol;andsetallthebuddycontrolsjoinedbetweenthesetwocontrols.///WhenalternatingbetweentheMapControlandPageLayoutControl,youshouldactivatethevisiblecontrol///anddeactivatetheotherbycallingActivateXXX.IllThiscalssislimitedtoasituationwherethecontrolsarenotsimultaneouslyvisible.///</summary>publicclassControlsSynchronizer{#regionclassmembersprivateIMapControl3m_mapControl=null;privateIPageLayoutControl2m_pageLayoutControl=null;privateIToolm_mapActiveTool=null;privateIToolm_pageLayoutActivelbol=null;privateboolm_IsMapCtrlactive=true;privateArrayListm_frameworkControls=null;#endregion#regionconstructor///<summary>//Z默認(rèn)構(gòu)造函數(shù)III</summary>publicControlsSynchronizer()(〃初始化ArrayListm_frameworkConlrols=newArrayList();)///<summary>//Z構(gòu)造函數(shù)///</summary>///<paramname="mapControl,'></param>///<paramname="pageLayoutContro「x/param>publicControlsSynchronizer(IMapControl3mapControl,IPageLayoutControl2pageLayoutControl):this()(〃為類成員賦值m_mapControl=mapControl;m_pageLayoutControl=pageLayoutControl;}#endregion#regionpropertiesIII<summary>III取得或設(shè)置MapControlIII</summary>publicIMapControl3MapControlget{returnm_mapControl;}set{m_mapControl=value;})///<summary>///取得或設(shè)置PageLayoutControlIII</summary>publicIPageLayoutControl2PageLayoutControl(get{returnm_pageLayoutControl;}set{m_pageLayoutControl=value;)}///<summary>///取得當(dāng)前ActiveView的類型///</summary>publicstringActiveViewType(get{if(mJsMapCtrlactive)return"MapControド;elsereturnnPageLayoutControl;))///<summary>//Z取得當(dāng)前活動(dòng)的ControlIII</summary>publicobjectActiveControlIget{if(m_mapControl==nullIIm_pageLayoutControl==null)thrownewException(uControlsSynchronizer::ActiveControl:\r\nEitherMapControlorPageLayoutControlarenotinitialized!1');if(mJsMapCtrlactive)returnm_mapControl.Object;elsereturnm_pageLayoutControl.Object;))#endregion#regionMethodsIII<summary>///激活MapControl并解除thePagleLayoutControlIII</summary>publicvoidActivateMapO(tryif(m_pageLayoutControl=nullIIm_mapControI==null)thrownewException("ControlsSynchronizer::ActivateMap:\r\nEitherMapControlorPageLayoutControlarenotinitialized!1');〃緩存當(dāng)前PageLayout的CurrentToolif(m_pageLayoutControl.CurrentTool!=null)m_pageLayoutActiveTool=m_pageLayoutControl.CurrentTool;〃解除PagleLayoutm_pageLayoutControi.ActiveView.Deactivate();〃激活MapControlm_mapControLActiveView.Activate(m_mapControl.hWnd);〃將之前MapControl最后使用的tool,作為活動(dòng)的tool?賦給MapControl的CurrentToolif(m_mapActiveTool!=null)m_mapControl.CurrentTool=m_mapActivelbol;m_IsMapCtriactive=true;〃為每ー個(gè)的frameworkcontrols,設(shè)置Buddycontrol為MapControlthis.SetBuddies(m_mapControl.Object);)catch(Exceptionex){thrownewException(string.Format("ControlsSynchronizer二ActivateMap:\r\n{0}",ex.Message));})///<summary>///激活PagleLayoutContro!并減活M叩Cotrol///</summary>publicvoidActivatePageLayout(){try{if(m_pageLayoutControl==nullIIm_mapControl==null)thrownewException("ControlsSynchronizer::ActivatePageLayout:\r\nEitherMapControlorPageLayoutControlarenotinitialized!");〃緩存當(dāng)前MapContro)的CurrentToolif(m_mapControl.CurrentTool!=null)m_mapActiveTool=m_mapControl.CurrentTool;〃解除MapControlm_mapControl.ActiveView.Deactivate();〃激活PageLayoutControlm_pageLayoutControi.ActiveView.Activate(m_pageLayoutControl.hWnd);〃將之前PageLayoutControl最后使用的tool,作為活動(dòng)的tool,賦給PageLayoutContro!的CurrentToolif(m_pageLayoutActiveTool!=null)m_pageLayoutControl.CurrentTool=m_pageLayoutActiveTool;mJsMapCtrlactive=false;〃為每ー個(gè)的frameworkcontrols,設(shè)置Buddycontrol為PageLayoutControlthis.SetBuddies(m_pageLayoutControI.Object);)catch(Exceptionex){throw newException(string.Format("ControlsSynchronizer::ActivatePageLayout:\r\n{0}",ex.Message));))///<summary>//Z給予ー個(gè)地圖,置換PageLayoutControl和M叩Control的focusmap///</summary>III<paramname="newMap"x/param>publicvoidReplaceMap(IMapnewMap)(if(newMap==null)thrownewException("ControlsSynchronizer::ReplaceMap:\r\nNewmapforreplacementisnotinitialized!");if(m_pageLayoutControl==nullIIm_mapControl=null)thrownewException("ControlsSynchronizer::ReplaceMap:\r\nEitherMapControlorPageLayoutControlarenotinitialized!");//createanewinstanceofIMapscollectionwhichisneededbythePageLayout〃創(chuàng)建一個(gè)PageLayout需要用到的,新的IMapscollection的實(shí)例IMapsmaps=newMaps();//addthenewmaptotheMapscollection〃把新的地圖加到Mapscollection里頭去maps.Add(newMap);boolblsMapActive=m_IsMapCtrlactive;//callreplacemaponthePageLayoutinordertoreplacethefocusmap//wemustcallActivatePageLayout,sinceitisthecontrolwecall'ReplaceMaps'〃調(diào)用PageLayout的replacemap來(lái)置換focusimp/Z我們必須調(diào)用ActivatePageLayout,因?yàn)樗悄莻€(gè)我們可以調(diào)用"ReplaceMaps"的Controlthis.ActivatePageLayout();rn_pageLayoutControl.PageLayout.ReplaceMaps(maps);//assignthenewmaptotheMapControl〃把新的地圖賦給MapControlm_mapControl.Map=newMap;//resettheactivetools〃重設(shè)activetoolsm_pageLayoutActiveTool=null;m_mapActiveTool=null;//makesurethatthelastactivecontrolisactivated〃確認(rèn)之前活動(dòng)的control被激活if(blsMapActive)(this.ActivateMap();m_mapControl.ActiveView.Refresh();)else(this.ActivatePageLayout();m_pageLayoutControl.ActiveView.Refresh();))///<summary>///bindtheMapControlandPageLayoutControltogetherbyassigninganewjointfocusmap///指定共同的Map來(lái)把MapControl和PageLayoutContro!綁在ー起III</summary>III<paramname="mapControlM></param>///<paramname=npageLayoutControl"></param>III<paramname=HactivateMapFirst">trueiftheMapControlsupposedtobeactivatedfirst,如果MapControl被首先激活,則為true</param>publicvoidBindControls(IMapControl3mapControl,IPageLayoutControl2pageLayoutControl,boolactivateMapFirst)(if(mapControl==nullIIpageLayoutControl==null)thrownewException(HControlsSynchronizer::BindControls:\r\nEitherMapControlorPageLayoutControlarenotinitialized!1');m_mapControl=MapControl;m_pageLayoutControl=pageLayoutControl;this.BindControls(activateMapFirst);}///<summary>///bindtheMapControlandPageLayoutControltogetherbyassigninganewjointfocusmapIII指定共同的Map來(lái)把MapControl和PageLayoutContro!綁在ー起III</summary>III<paramname="activateMapFirst">trueiftheMapControlsupposedtobeactivatedfirst,如果MapControl被首先激活,則為true</param>publicvoidBindControls(boolactivateMapFirst)(if(m_pageLayoutControl==nullIIm_mapControl=null)thrownewException("ControlsSynchronizer::BindControls:\r\nEitherMapControlorPageLayoutControlarenotinitialized!");//createanewinstanceofIMap〃創(chuàng)造IMap的ー個(gè)實(shí)例IMapnewMap=newMapClass。;newMap.Name="Map";//createanewinstanceofIMapscollectionwhichisneededbythePageLayout〃創(chuàng)造ー個(gè)新的IMapscollection的實(shí)例,這是PageLayout所需要的IMapsmaps=newMaps();//addthenewMapinstancetotheMapscollection〃把新的Map實(shí)例賦給Mapscollectionmaps.Add(newMap);//callreplacemaponthePageLayoutinordertoreplacethefocusmap〃調(diào)用PageLayout的replacemap來(lái)置換focusmapm_pageLayoutControLPageLayout.ReplaceMaps(maps);//assignthenewmaptotheMapControl〃把新的m叩賦給MapControlm_mapControl.Map=newMap;//resettheactivetools〃重設(shè)activetoolsm_pageLayoutActiveTool=null;m_mapActiveTool=null;//makesurethatthelastactivecontrolisactivated〃確定最后活動(dòng)的control被激活if(activateMapFirst)this.ActivateMapO;elsethis.ActivatePageLayout();1///<summary>///bypassingtheapplication'stoolbarsandTOCtothesynchronizationclass,itsavesyouthe///managementofthebuddycontroleachtimetheactivecontrolchanges.Thismethodadstheframework///controltoanarray;oncetheactivecontrolchanges,theclassiteratesthroughthearrayand///callesSetBuddyControloneachofthestoredframeworkcontrol.///</summary>///<paramname="control"></param>publicvoidAddFrameworkControl(objectcontrol)(if(control==null)thrownew Exception("ControlsSynchronizer::AddFrameworkControl:\r\nAddedcontrolisnotinitialized!");m_frameworkControls.Add(control);}///<summary>///RemoveaframeworkcontrolfromthemanagedlistofcontrolsIII</summary>///<paramname="contro1"></param>publicvoidRemoveFrameworkControl(objectcontrol)(if(control=null)thrownewException("ControlsSynchronizer::RemoveFrameworkControl:\r\nControltoberemovedisnotinitialized!");m_frameworkControls.Remove(control);)///<summary>IIIRemoveaframeworkcontrolfromthemanagedlistofcontrolsbyspecifyingitsindexinthelist///</summary>III<paramname="index"></param>publicvoidRemoveFrameworkControlAt(intindex)(if(m_frameworkControls.Count<index)thrownewException(uControlsSynchronizer::RemoveFrameworkControlAt:\r\nIndexisoutofrange!");m_frameworkControls.RemoveAt(index);}///<summary>///whentheactivecontrolchanges,theclassiteratesthroughthearrayoftheframeworkcontrols///andcallesSetBuddyControloneachofthecontrols.///</summary>III<paramname="buddyH>theactivecontrol</param>privatevoidSetBuddies(objectbuddy)(try{if(buddy==null)thrownewException(HControlsSynchronizer::SetBuddies:\r\nTargetBuddyControlisnotinitialized!'*);foreach(objectobjinm_frameworkControls)(if(objisIToolbarControl)(((IToolbarControl)obj).SetBuddyControl(buddy);)elseif(objisITOCControl)(((ITOCControl)obj).SetBuddyControl(buddy);}})catch(Exceptionex){thrownewException(string.Format(*'ControlsSynchronizer::SetBuddies:\r\n{0}",ex.Message));))#endregion}}2、新建Maps類在同步類中,要用到Maps類,用于管理地圖對(duì)象。與新建同步類ControlsSynchronizer類似,我們新建一Maps類,其所有代碼如下所示:usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;usingSystem.Text;usingSystem.Runtime.InteropServices;usingESRI.ArcGIS.Carto;namespace_sdnMap{[Guid(nf27d8789-fbbc-4801-be78-0e3cd8fff9d5n)][ClassInterface(ClassInterfaceType.None)][ProgId(,LsdnMap.Mapsn)]publicclassMaps:IMaps,IDisposable{//classmember-usinginternallyanArrayListtomanagetheMapscollectionprivateArrayListm_array=null;#regionclassconstructorpublicMaps()(m_array=newArrayList();}#endregion#regionIDisposableMembers///<summary>///DisposethecollectionIII</summary>publicvoidDispose()(if(m_array!=null)(m_array.Clear();m_array=null;))#endregion#regionIMapsMembers///<summary>///RemovetheMapatthegivenindexIII</summary>///<paramname=nIndexn></param>publicvoidRemoveAt(intIndex)(if(Index>m_array.CountIIIndex<0)thrownewException(MMaps::RemoveAt:\r\nIndexisoutofrange!");m_array.RemoveAt(Index);}III<summary>///ResettheMapsarrayIII</summary>publicvoidReset()m_array.Clear();///<summary>///GelthenumberofMapsinthecollection///</summary>publicintCount(get{returnm_array.Count;))III<summary>///ReturntheMapatthegivenindexIII</summary>///<paramname=nIndexn></param>///<returns></retums>publicIMapget_Item(intIndex)(if(Index>m_array.CountIIIndex<0)thrownewException(MMaps::get_Item:\r\nIndexisoutofrange!°);returnm_array[Index]asIMap;!///<summary>///RemovetheinstanceofthegivenMap///</summary>///<paramname=MMapM></param>publicvoidRemove(IMapMap)(m_array.Remove(Map);}III<summary>///CreateanewMap,addittothecollectionandreturnittothecaller///</summary>III<returns></returns>publicIMapCreate()(IMapnewMap=newM叩Class。;m_array.Add(newMap);returnnewMap;)///<summary>///AddthegivenMaptothecollection///</summary>///<paramname="Map"></param>publicvoidAdd(IMapMap)if(Map==null)thrownewException(MMaps::Add:\r\nNewMapismotinitialized!");m_array.Add(Map);)#endregion)}3、新建打開文檔類OpenNewM叩Document由于從工具欄自帶的打開按鈕打開地圖文檔的時(shí)候,不會(huì)自動(dòng)進(jìn)行兩種視圖之間的同步,所以我們要自己派生一個(gè)OpenNewM叩Document類,用于打開地圖文檔。右擊項(xiàng)目名,選擇“添加I類”,再選擇ArcGIS類別中的BaseCommand模板,輸入類名為uOpenNewMapDocument.cs首先添加引用:usingSystem.Windows.Forms;usingESRl.ArcGIS.Carto;再添加如下成員變量:privateControlsSynchronizerm_controlsSynchronizer=null;修改默認(rèn)的構(gòu)造函數(shù)如下所示:〃添加參數(shù)publicOpenNewMapDocument(ControlsSynchronizerControlsSynchronizer)(////TODO:DefinevaluesforthepublicpropertiesH〃設(shè)定相關(guān)屬性值base.m_category="Generic";//localizabletextbase.m_caption="Open";//localizabletextbase.m_message="ThisshouldworkinArcMap/MapControl/PageLayoutControl";//localizabletextbase.m_toolTip="Open";//localizabletextbase.m_name="Generic_Open"; //uniqueid,non-localizable(e.g."MyCategory_MyCommand")〃初始化m_controlsSynchronizerm_controlsSynchronizer=ControlsSynchronizer;try{////TODO:changebitmapnameifnecessary//stringbitmapResourceName=GetType().Name+".bmp";base.m_bitmap=newBitmap(GetType(),bitmapResourceName);}catch(Exceptionex)System.Diagnostics.Trace.WriteLine(ex.Message,"InvalidBitmap");再在OnClick函數(shù)中添加如下代碼:publicoverridevoidOnClick()(//TODO:AddOpenNewMapDocument.OnClickimplementationOpenFileDialogdig=newOpenFileDialogO;dlg.Filter="MapDocuments(*.mxd)l*.mxd";dig.Multiselect=false;dlg.Title="OpenMapDocument*';if(dlg.ShowDialog()==DialogResult.OK)(stringdocName=dlg.FileName;IMapDocumentmapDoc=newMapDocumentClass();if (mapDoc.get_IsPresent(docName)&&!mapDoc.get_IsPasswordProtected(docName)){mapDoc.Open(docName,string.Empty);IMapmap=mapDoc.get_Map(0);m_controlsSynchronizer.ReplaceMap(map);mapDoc.Close();))}在添加類時(shí),模板會(huì)自動(dòng)添加一個(gè)名為“OpenNewMapDocument.bmp”的圖標(biāo),你可以自己修改或者替換為打開的文件夾的圖標(biāo)。4、兩種視圖的同步在3sdnMap.cs中添加成員變量,即同步類對(duì)象:privateControlsSynchronizerm_controlsSynchronizer=null;在Forml.Load函數(shù)中進(jìn)行初始化工作:〃初始化controlssynchronizationcalssm_controlsSynchronizer=newControlsSynchronizer(m_mapControl,m_pageLayoutControl);〃把M叩Control和PageLayoutContro!綁定起來(lái)(兩個(gè)都指向同一個(gè)Map),然后設(shè)置MapControl為活動(dòng)的Controlm_controlsSynchronizer.BindControls(true);〃為了在切換MapControl和PageLayoutControl視圖同步,要添加FrameworkControlm_controlsSynchronizer.AddFrameworkControl(axToolbarControll.Object);m_controlsSynchronizer.AddFrameworkControl(this.axTOCControll.Object);//添加打開命令按鈕到工具條OpenNewMapDocumentopenMapDoc=newOpenNewMapDocument(m_controlsSynchronizer);axToolbarControl1.AddItem(openMapDoc, -1, 0, false, -1,esriCommandStyles.esriCommandStylelconOnly);因?yàn)槲覀冏詣?dòng)派生了打開文檔類,并自己將其添加到工具條,所以我們就不需要工具條原來(lái)的“打開”按鈕了,可以Toolbarcontrol的屬性中將其刪除。下面,我們可完成上一講遺留的功能了。III<summary>//Z新建地圖命令I(lǐng)II</summary>///<paramname=nsendernx/param>///<paramname=',e,,x/param>privatevoidNew_Ciick(objectsender,EventArgse)(〃詢問(wèn)是否保存當(dāng)前地圖DialogResultres=MessageBox.Show(H是否保存當(dāng)前地圖?","提示",MessageBoxButtons.YesNo,MessageBoxIcon.Question);if(res==DialogResult.Yes)(〃如果要保存,調(diào)用另存為對(duì)話框ICommandcommand=newControlsSaveAsDocCommandClass();if(m_mapControl!=null)command.OnCreate(m_controlsSynchronizer.MapControl.Object);elsecommand.OnCreate(m_controlsSynchronizer.PageLayoutControLObject);command.OnClick();)〃創(chuàng)建新的地圖實(shí)例IMapmap=newMapClass();map.Name="Map";m_controlsSynchronizer.MapControl.DocumentFilename=string.Empty;〃更新新建地圖實(shí)例的共享地圖文檔m_controlsSynchronizer.ReplaceMap(map);}///<summary>//Z打開地圖文檔Mxd命令I(lǐng)II</summary>///<paramname="sender”>v/param>III<paramname="e"x/param>privatevoidOpen_Click(objectsender,EventArgse)(if(this.axMapControll.LayerCount>0){DialogResultresult=MessageBox.Show("是否保存當(dāng)前地圖?","警告",MessageBoxButtons.YesNoCancel,MessageBoxIcon.Question);if(result==DialogResult.Cancel)return;if(result==DialogResult.Yes)this.Save_Click(null,null);)OpenNewMapDocumentopenMapDoc=newOpenNewMapDocument(m_controlsSynchronizer);openMapDoc.OnCreate(m_controlsSynchronizer.MapControI.Object);openMapDoc.OnClick();)在添加數(shù)據(jù)AddData時(shí),我們也要進(jìn)行地圖共享,故在AddData_Click函數(shù)后面添加如下代碼:IM叩pMap=this.axMapControl1.Map;this.m_controlsSynchronizer.ReplaceMap(pMap);在另存為地圖文檔時(shí),有可能會(huì)丟失數(shù)據(jù),因此我們需要提示用戶以確認(rèn)操作,故需修改SaveAs_Click函數(shù),如下所示:III<summary>///另存為地圖文檔命令I(lǐng)II</summary>///<paramname=Msendern></param>///<paramname=MeHx/param>privatevoidSaveAs_Click(objectsender,EventArgse)(〃如果當(dāng)前視圖為MapContro!時(shí),提示用戶另存為操作將丟失PageLayoutContro!中的設(shè)置if(m_controlsSynchronizer.ActiveControlisIMapControl3)(if(MessageBox.Show("另存為地圖文檔將丟失制版視圖的設(shè)置、r\n您要繼續(xù)嗎?ヽ"提示”,MessageBoxButtons.YesNo,MessageBoxIcon.Question)==DialogResult.No)return;)〃調(diào)用另存為命令I(lǐng)Commandcommand=newControlsSaveAsDocCommandClass();command.OnCreate(m_controlsSynchronizer.ActiveControl);command.OnClick();)在切換視圖時(shí),我們要激活相關(guān)的視圖,故在設(shè)計(jì)視圖的屬性面板中選擇tabControl2控件,再選擇事件按鈕,找到“SelectedlndexChanged”事件雙擊添加之。其實(shí)現(xiàn)代碼如下所示:III<summary>//Z切換地圖和制版視圖III</summary>///<paramname二"sender”x/param>///<paramname=ne,,x/param>privatevoidtabControl2_SelectedIndexChanged(objectsender,EventArgse)(if(this.tabControl2.SelectedIndex==0){〃激活MapControlm_controlsSynchronizer.ActivateMap();}else{〃激活PageLayoutControlm_controlsSynchronizer.ActivatePageLayout();)}5、編譯運(yùn)行按F5編譯運(yùn)行程序,至此我們完成了M叩Control和PageLayoutContro!兩種視圖的同步工作。第四講狀態(tài)欄信息的添加與實(shí)現(xiàn)在上一講中,我們完成了M叩Control和PageLayoutContro!兩種視圖的同步工作,本講我們將完成狀態(tài)欄信息的添加與實(shí)現(xiàn)。應(yīng)用程序的狀態(tài)欄一般用來(lái)顯示程序的當(dāng)前狀態(tài),當(dāng)前所使用的工具。GIS應(yīng)用程序一般也在狀態(tài)欄顯示當(dāng)前光標(biāo)的坐標(biāo)、比例尺等信息。學(xué)習(xí)完本講內(nèi)容,您將學(xué)會(huì)狀態(tài)欄編程的基本方法,并且能夠在我們的程序的狀態(tài)欄中添加且顯示以下信息:當(dāng)前所用工具信息當(dāng)前比例尺當(dāng)前坐標(biāo)1、添加狀態(tài)欄項(xiàng)目在設(shè)計(jì)視圖中,點(diǎn)擊窗體中的狀態(tài)欄,在其屬性面板中找到“Items”項(xiàng),單擊其右邊的按鈕,在下拉框中選擇“StatusLabel”,單擊“添加按鈕”,依次添加四個(gè)StatusLabel,依次修改屬性參數(shù)如下表所示:序號(hào)Name屬性Text屬性Spring屬性說(shuō)明1MessageLabel就緒False當(dāng)前所用工具信息2BlankTrue占位3ScaleLabel比例尺False當(dāng)前比例尺4CoordinateLabel當(dāng)前坐標(biāo)False當(dāng)前坐標(biāo)設(shè)置好之后如下圖所示:Tips:我們?cè)O(shè)計(jì)出的狀態(tài)欄最終如下所示:就緒 「(Blank) F比例尺 V當(dāng)前坐標(biāo)Spring屬性表示可以按狀態(tài)欄剩余空間自動(dòng)伸縮。所以加入Blank項(xiàng)目,只是為了占個(gè)位子,以達(dá)到ScaleLabe!和CoordinateLabel項(xiàng)目右對(duì)齊而MessageLabe!項(xiàng)目左對(duì)齊的目的。2、顯示當(dāng)前所用工具信息首先添加axToolbarControl!的OnMouseMove事件(相信大家看了以上的教程,已經(jīng)知道怎么添加事件了吧,還不知道的建議再溫習(xí)下前幾講的內(nèi)容)。在其事件響應(yīng)函數(shù)代碼如下:private void axToolbarControl1_OnMouseMove(object sender,IToolbarControlEvents_OnMouseMoveEvente)/Z取得鼠標(biāo)所在工具的索引號(hào)intindex=axToolbarControl1.HitTest(e.x,e.y,false);if(index!=-1)(/Z取得鼠標(biāo)所在工具的ToolbaritemIToolbarltemtoolbaritem=axToolbarControl1.Getltem(index);/Z設(shè)置狀態(tài)欄信息MessageLabel.Text=toolbarltem.Command.Message;}else{MessageLabel.Text="就緒”;)}3、顯示當(dāng)前比例尺添加axMapControl!的OnMouseMove事件,其代碼如下:privatevoidaxMapControl1_OnMouseMove(objectsender,IMapControlEvents2_OnMouseMoveEvente)(/Z顯示當(dāng)前比例尺ScaleLabeLText="比例尺1:"+((long)this.axMapControl1.MapScale).ToString();}4、顯示當(dāng)前坐標(biāo)顯示當(dāng)前坐標(biāo)也是 axMapControl!的OnMouseMove事件中響應(yīng),故只要在axMapControl1_OnMouseMove函數(shù)中添加如下代碼即可:/Z顯示當(dāng)前坐標(biāo)CoordinateLabel.Text="當(dāng)前坐標(biāo)X="+e.mapX.ToStringO+“Y二"+e.mapY.ToStringO+"”+this.axMapControl1.MapUnits;按F5編譯運(yùn)行,可以看到,我們的程序已經(jīng)能夠正常工作了。但是細(xì)心的你可能會(huì)發(fā)現(xiàn),當(dāng)前坐標(biāo)的后面的坐標(biāo)單位為"esriUnknownUnits"或"esriMetersM之類,即系統(tǒng)在正常單位的前面加上了“esri)追求完美的我們自然看得不舒服。那就進(jìn)行簡(jiǎn)單的替換吧。首先定義個(gè)全局坐標(biāo)單位變量sMapUnits?如下所示:privatestringsMapUnits;再Forml_Load函數(shù)中進(jìn)行初始化:sMapUnits="Unknown',;添加axMapControl!控件的OnMapReplaced事件,在事件響應(yīng)函數(shù)中進(jìn)行坐標(biāo)單位替換,代碼如下:privatevoidaxMapControl1_OnMapReplaced(objectsender,IMapControlEvents2_OnMapReplacedEvente){esriUnitsmapUnits=axM叩Control1.MapUnits;switch(mapUnits){caseesriUnits.esriCentimeters:sMapUnits="Centimeters";break;caseesriUnits.esriDecimalDegrees:sMapUnits="DecimalDegrees";break;caseesriUnits.esriDecimeters:sMapUnits="Decimeters*';break;caseesriUnits.esriFeet:sM叩Units="Feet";break;caseesriUnits.esrilnches:sMapUnits="Inches";break;caseesriUnits.esriKiiometers:sMapUnits="Kilometers";break;caseesriUnits.esriMeters:sMapUnits="Meters*';break;caseesriUnits.esriMiles:sMapUnits="Miles";break;caseesriUnits.esriMillimeters:sMapUnits="Millimeters";break;caseesriUnits.esriNauticalMiles:sMapUnits="NauticalMiles";break;caseesriUnits.esriPoints:sMapUnits="Points";break;caseesriUnits.esriUnknownUnits:sMapUnits="Unknown";break;caseesriUnits.esriYards:sMapUnits="Yards";break;)}5、編譯運(yùn)行按F5編譯運(yùn)行程序。如果你足夠細(xì)心的話,相信你已經(jīng)成功了!在本講中,介紹中StatusStrip控件的基本使用方法和AE中當(dāng)所用工具信息、當(dāng)前比例尺和當(dāng)前坐標(biāo)的顯示調(diào)用方法。第五講鷹眼的實(shí)現(xiàn)在上一講中,我們實(shí)現(xiàn)了狀態(tài)欄的相關(guān)信息顯示,在這ー講中我們將要實(shí)現(xiàn)鷹眼功能。所謂的鷹眼,就是ー個(gè)縮略地圖,上面有一個(gè)矩形框,矩形框區(qū)域就是當(dāng)前顯示的地圖區(qū)域,拖動(dòng)矩形框可以改變當(dāng)前地圖顯示的位置,改變矩形框的大小,可以改變當(dāng)前地圖的顯示區(qū)域大小,從起到導(dǎo)航的作用。鷹眼是地圖瀏覽中常用的功能之一。關(guān)于鷹眼的實(shí)現(xiàn)方式,最常用的是用一個(gè)MapContro!控件顯示地圖全圖,并在上面畫一個(gè)紅色矩形框表示當(dāng)前地圖的顯示范圍,并實(shí)現(xiàn)鷹眼MapControl與主窗體的MapControl互動(dòng)。本講最終效果如下所示:
3sdnlapBE?3sdnlapBE?文件ロう0図や?a0安工椚????事?里 ?昌觸t^b.p 地圖t^b.p 地圖q制版就緒 比例尺1:0當(dāng)前坐標(biāo)X=116.414499840194Y=30.5723584832011Unknown圖1鷹眼效果1、添加鷹眼控件由于本教程在第一講中沒(méi)有預(yù)先考慮到鷹眼所放的位置,故我們要先稍微調(diào)整一下程序框架,并添加一個(gè)MapControl用于顯示鷹眼。在本教程中,我們將鷹眼放在圖層控件的下方,調(diào)整方法如下:(1)在設(shè)計(jì)視圖中,選擇tabControll控件,即放圖層和屬性的那個(gè)容器,將其Dock屬性設(shè)為None,并用鼠標(biāo)拖拽將其縮小。把工具箱中的SplitContainer控件拖到窗體的左窗格,即放在tabControl1控件的旁邊。并將其Orientation屬性設(shè)置為Horizontal〇(2)選中tabControll控件,按Ctrl+X剪切,再選中剛才粘貼到SplitContainer2的Panel1中,如圖2所示。操作完成后效果如圖3所示。
圖2圖3(3)再選中SplitContainer2控件(如果不好選中,直接以屬性面板中選擇SplitContainer2),將其Dock屬性設(shè)置為Fill?再選中tabControll,將其Dock屬性也設(shè)置為Fill0(4)從工具箱中選擇MapContro!控件并拖到SplitContainer2的Panel2,作為鷹眼控件。最終效果如圖4所示。圖42、鷹眼的實(shí)現(xiàn)(1)載入地圖到鷹眼控件當(dāng)?shù)貓D載入到主Map控件時(shí),同時(shí)也載入到鷹眼控件,在axMapControll_OnMapReplaced事件響應(yīng)函數(shù)(此函數(shù)上一講中已經(jīng)添加了)中添加如下代碼:privatevoidaxMapControll_OnMapReplaced(objectsender,IMapControlEvents2_OnMapReplacedEvente){//前面代碼省略//當(dāng)主地圖顯示控件的地圖更換時(shí),鷹眼中的地圖也跟隨更換this.axM叩Control2.Map=newMapClass();//添加主地圖控件中的所有圖層到鷹眼控件中for(inti=1;i<=this.axMapControl1.LayerCount;i++)(this.axMapControl2.AddLayer(this.axMapContr
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025-2030年土壤微生物多樣性監(jiān)測(cè)儀行業(yè)跨境出海戰(zhàn)略研究報(bào)告
- 2025-2030年手持式電吹風(fēng)行業(yè)深度調(diào)研及發(fā)展戰(zhàn)略咨詢報(bào)告
- 2025-2030年土壤緊實(shí)度與水分綜合測(cè)定儀行業(yè)深度調(diào)研及發(fā)展戰(zhàn)略咨詢報(bào)告
- 2025-2030年聲波驅(qū)散器與定向音響系統(tǒng)行業(yè)跨境出海戰(zhàn)略研究報(bào)告
- 2025-2030年商用大容量電熱水機(jī)行業(yè)深度調(diào)研及發(fā)展戰(zhàn)略咨詢報(bào)告
- 二零二五年度攤位租賃合同模板:特色商業(yè)街區(qū)攤位租賃
- 2025-2030年數(shù)字化藝術(shù)畫作展覽行業(yè)深度調(diào)研及發(fā)展戰(zhàn)略咨詢報(bào)告
- 2025-2030年手工風(fēng)箏制作行業(yè)深度調(diào)研及發(fā)展戰(zhàn)略咨詢報(bào)告
- 2025-2030年商用咖啡機(jī)遠(yuǎn)程維護(hù)平臺(tái)行業(yè)深度調(diào)研及發(fā)展戰(zhàn)略咨詢報(bào)告
- 2025年度蘋果產(chǎn)業(yè)園區(qū)建設(shè)與運(yùn)營(yíng)管理合同4篇
- 學(xué)校保潔服務(wù)投標(biāo)方案(技術(shù)標(biāo))
- 《社區(qū)工作者培訓(xùn)課件 新浪版》
- 教育信息化背景下的學(xué)術(shù)研究趨勢(shì)
- 人教版小學(xué)數(shù)學(xué)(2024)一年級(jí)下冊(cè)第五單元100以內(nèi)的筆算加、減法綜合素養(yǎng)測(cè)評(píng) B卷(含答案)
- 2024-2025學(xué)年北京市豐臺(tái)區(qū)高三語(yǔ)文上學(xué)期期末試卷及答案解析
- 2024年度體育賽事贊助合同:運(yùn)動(dòng)員代言與贊助權(quán)益2篇
- 2025屆西藏林芝一中高三第二次診斷性檢測(cè)英語(yǔ)試卷含解析
- 開封市第一屆職業(yè)技能大賽健康照護(hù)項(xiàng)目技術(shù)文件(國(guó)賽)
- 公路電子收費(fèi)系統(tǒng)安裝合同范本
- 醫(yī)院培訓(xùn)課件:《傷口評(píng)估與測(cè)量》
- 2021年全國(guó)高考物理真題試卷及解析(全國(guó)已卷)
評(píng)論
0/150
提交評(píng)論