在分析功能时发现,各功能都有自己的快捷键相应,比如今天要分析的 Copy Coordinates (Ctrl+C)和Paste Coordinates (Ctrl+P),以及主窗体的全屏功能也是通过快捷键(Alt+Enter)。这就使我需要彻底分析一下主窗体的键盘监听处理啦。
主窗体的键盘监听处理
与WorldWind学习系列三:功能分析——截屏功能和“关于”窗体分析 中AboutDialog.cs分析类似,WorldWind主窗体也是重载了OnKeyUp,使窗体接受键盘响应。
936行 protected override void OnKeyUp(KeyEventArgs e) { if ( this .webBrowserPanel.IsTyping()) // 如果是在“网页窗体”(稍后介绍)里输入地址,则主窗体处不相应键盘事件,将 e.Handled = true; 表示已经处理事件 啦。 e.Handled = true ; else e.Handled = HandleKeyUp(e); //此处HandleKeyUp()是真正处理主窗口的键盘响应 base .OnKeyUp(e); }
HandleKeyUp函数
真正处理键盘响应函数 /// <summary> /// Handles key up events. /// </summary> /// <param name="e"></param> /// <returns> Returns true if the key is handled. </returns> protected bool HandleKeyUp(KeyEventArgs e) { // keep keypresses inside browser url bar if (e.Handled) return true ; if (e.Alt) //处理Alt 组合键 { // Alt key down switch (e.KeyCode) { case Keys.A: menuItemAlwaysOnTop_Click( this ,e); return true ; case Keys.Q: using ( PropertyBrowserForm worldWindSettings = new PropertyBrowserForm( Settings, " World Wind Settings " ) ) { worldWindSettings.Icon = this .Icon; worldWindSettings.ShowDialog(); } return true ; case Keys.W: menuItemOptions_Click( this , EventArgs.Empty); return true ; case Keys.Enter: // 实现全屏功能,稍后看看如何实现?? this .FullScreen = ! this .FullScreen; return true ; case Keys.F4: Close(); return true ; } } else if (e.Control) //处理Ctrl组合键 { // Control key down switch (e.KeyCode) { case Keys.C: case Keys.Insert: //调用拷贝坐标功能,即Copy Coordinates (Ctrl+C) menuItemCoordsToClipboard_Click( this , e); return true ; case Keys.F: return true ; case Keys.H: if (progressMonitor != null ) { bool wasVisible = progressMonitor.Visible; progressMonitor.Close(); progressMonitor.Dispose(); progressMonitor = null ; if (wasVisible) return true ; } progressMonitor = new ProgressMonitor(); progressMonitor.Icon = this .Icon; progressMonitor.Show(); return true ; case Keys.I: menuItemConfigWizard_Click( this ,e); return true ; case Keys.N: menuItemOptions_Click( this ,e); return true ; case Keys.T: //控制工具栏的显示。 menuItemShowToolbar_Click( this ,e); return true ; case Keys.V: // 粘贴坐标,并转向粘贴的坐标位置。今天分析 menuItemEditPaste_Click( this ,e); return true ; case Keys.S: //保存截屏,已经分析 menuItemSaveScreenShot_Click( this , e); return true ; } } else if (e.Shift) { // Shift key down switch (e.KeyCode) { case Keys.Insert: menuItemEditPaste_Click( this ,e); return true ; case Keys.S: menuItemSunShading_Click( this , e); return true ; case Keys.A: menuItemAtmosphericScattering_Click( this , e); return true ; } } else { // Other or no modifier key switch (e.KeyCode) { // case Keys.B: // menuItemWMS_Click(this, e); // return true; case Keys.G: return true ; case Keys.L: menuItemLayerManager_Click( this , e); return true ; case Keys.P: if ( this .pathMaker == null ) { this .pathMaker = new PathMaker( this .worldWindow); this .pathMaker.Icon = this .Icon; } this .pathMaker.Visible = ! this .pathMaker.Visible; return true ; case Keys.V: if ( this .placeBuilderDialog == null ) { this .placeBuilderDialog = new PlaceBuilder( this .worldWindow ); this .placeBuilderDialog.Icon = this .Icon; } this .placeBuilderDialog.Visible = ! this .placeBuilderDialog.Visible; return true ; case Keys.Escape: //退出全屏快捷键 ESC if ( this .FullScreen) { this .FullScreen = false ; return true ; } break ; case Keys.D1: case Keys.NumPad1: this .VerticalExaggeration = 1.0f ; return true ; case Keys.D2: case Keys.NumPad2: this .VerticalExaggeration = 2.0f ; return true ; case Keys.D3: case Keys.NumPad3: this .VerticalExaggeration = 3.0f ; return true ; case Keys.D4: case Keys.NumPad4: this .VerticalExaggeration = 4.0f ; return true ; case Keys.D5: case Keys.NumPad5: this .VerticalExaggeration = 5.0f ; return true ; case Keys.D6: case Keys.NumPad6: this .VerticalExaggeration = 6.0f ; return true ; case Keys.D7: case Keys.NumPad7: this .VerticalExaggeration = 7.0f ; return true ; case Keys.D8: case Keys.NumPad8: this .VerticalExaggeration = 8.0f ; return true ; case Keys.D9: case Keys.NumPad9: this .VerticalExaggeration = 9.0f ; return true ; case Keys.D0: case Keys.NumPad0: this .VerticalExaggeration = 0.0f ; return true ; case Keys.F1: this .menuItemAnimatedEarth_Click( this ,e); return true ; case Keys.F2: this .menuItemModisHotSpots_Click( this ,e); return true ; case Keys.F5: this .menuItemRefreshCurrentView_Click( this ,e); return true ; case Keys.F6: return true ; case Keys.F7: this .menuItemShowLatLonLines_Click( this ,e); return true ; case Keys.F8: this .menuItemPlanetAxis_Click( this ,e); return true ; case Keys.F9: this .menuItemShowCrosshairs_Click( this ,e); return true ; case Keys.F10: this .menuItemShowPosition_Click( this ,e); return true ; case Keys.F11: this .menuItemConstantMotion_Click( this ,e); return true ; case Keys.F12: this .menuItemPointGoTo_Click( this ,e); return true ; } } return false ; }
从上面,我们可以温故和强化窗体键盘响应功能如何实现的知识点。不再多说了。
我们看看如何实现全屏功能的,FullScreen属性控制的?注意不是函数,我想这是它值得我们学习的优点。
全屏属性 private bool FullScreen { get { return this .FormBorderStyle == FormBorderStyle.None; } set { if (value) { // Enter full-screen. this .normalWindowState = this .WindowState; this .WindowState = FormWindowState.Normal; this .FormBorderStyle = FormBorderStyle.None; this .Menu = null ; this .WindowState = FormWindowState.Maximized; } else { // Go back to normal this .WindowState = normalWindowState; this .FormBorderStyle = FormBorderStyle.Sizable; this .Menu = mainMenu; } } }
原来Fullscreen属性只是封装了Form原有的 FormBorderStyle和WindowState,同时在里面控制了主菜单Menu的显示与否。这里就是写好属性的妙用,可以学习一下,写出更好的属性控制,而不是简单的带参数的函数控制。
拷贝位置坐标功能
WorldWind.cs 1790
拷贝代码 private void menuItemCoordsToClipboard_Click( object sender, System.EventArgs e){ if ( this .worldWindow.CurrentWorld == null ) return ;WorldWindUri uri = new WorldWindUri(worldWindow.CurrentWorld.Name,worldWindow.DrawArgs.WorldCamera); //构建保存当前状态的WorldWindUri对象 string uriString = uri.ToString();Clipboard.SetDataObject(uriString, true );// 调用Form类的Clipboard.SetDataObject()方法,将字符串拷贝到粘贴板上 }WorldWindUri对象保存的字符串例如为:
worldwind://goto/world=Earth&lat=34.25320&lon=-101.57184&alt=48652548&dir=0.1worldwind://goto/world=Earth&lat=-41.38362&lon=101.15747&alt=48652548&dir=0.2worldwind://goto/world=Earth&lat=-89.89754&lon=136.64324&alt=48652548&dir=-7.2
我们应该学会使用Form类的Clipboard.SetDataObject()方法 实现自己的拷贝功能,如拷贝图片等复杂对象。
粘贴位置坐标功能
粘贴坐标信息,并重新定位 2150 void menuItemEditPaste_Click( object sender, System.EventArgs e) { //获取拷贝的对象 IDataObject iData = Clipboard.GetDataObject(); if ( ! iData.GetDataPresent(DataFormats.Text)) return ; //获取拷贝的字符串 string clipBoardString = ( string )iData.GetData(DataFormats.Text); try { //通过字符串,解析还原出对象。这原理很像对象XML序列化 worldWindUri = WorldWindUri.Parse(clipBoardString); ProcessWorldWindUri(); } catch (UriFormatException caught) { MessageBox.Show(caught.Message, " Unable to paste - you are not stupid! " , MessageBoxButtons.OK, MessageBoxIcon.Warning); }
2439 ProcessWorldWindUri()方法分析 private void ProcessWorldWindUri() { if (worldWindUri.RawUrl.IndexOf("wmsimage") >= 0) ProcessWmsEncodedUri();
if (worldWindUri.RawUrl.IndexOf("install") >= 0) ProcessInstallEncodedUri();
worldWindow.Goto(worldWindUri); //根据worldWindUri对象,实现定位 worldWindUri = null; }
worldWindow.Goto实现最终是调用WorldWindow类的 GotoLatLon()。
转到特定的经纬度位置 WorldWindow类的 GotoLatLon()转到特定的位置 524 /// <summary> /// Moves to specified location. /// </summary> /// <param name="latitude"> Latitude in degrees of target position. (-90 - 90). </param> /// <param name="longitude"> Longitude in degrees of target position. (-180 - 180). </param> /// <param name="heading"> Camera heading in degrees (0-360) or double.NaN for no change. </param> /// <param name="altitude"> Camera altitude in meters or double.NaN for no change. </param> /// <param name="perpendicularViewRange"></param> /// <param name="tilt"> Camera tilt in degrees (-90 - 90) or double.NaN for no change. </param> public void GotoLatLon( double latitude, double longitude, double heading, double altitude, double perpendicularViewRange, double tilt) { if ( ! double .IsNaN(perpendicularViewRange)) altitude = m_World.EquatorialRadius * Math.Sin(MathEngine.DegreesToRadians(perpendicularViewRange * 0.5 )); if (altitude < 1 ) altitude = 1 ; this .drawArgs.WorldCamera.SetPosition(latitude, longitude, heading, altitude, tilt); } 关键是: this .drawArgs.WorldCamera.SetPosition(latitude, longitude, heading, altitude, tilt)其中调用了Camera.cs中的SetPosition函数,其中主要代码 Point3d p = Quaternion4d.QuaternionToEuler(m_Orientation); _latitude.Radians = p.Y; _longitude.Radians = p.X; _heading.Radians = p.Z;此中用到Quaternion4d和Point3d类。
希望网友能有所收获,其他部分:
WorldWind学习系列三:功能分析——截屏功能和“关于”窗体分析
WorldWind学习系列二:擒贼先擒王篇2
WorldWind学习系列二:擒贼先擒王篇1
WorldWind学习系列一:顺利起航篇
转载于:https://www.cnblogs.com/wuhenke/archive/2009/12/12/1622404.html
相关资源:数据结构—成绩单生成器