• WorldWind学习系列三:简单功能分析——主窗体的键盘监听处理及拷贝和粘贴位置坐标功能


      在分析功能时发现,各功能都有自己的快捷键相应,比如今天要分析的 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.1
    worldwind://goto/world=Earth&lat=-41.38362&lon=101.15747&alt=48652548&dir=0.2
    worldwind://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学习系列一:顺利起航篇

        

  • 相关阅读:
    Cookie
    webSocket+HeadBeat
    Javascript-多个数组是否有一样值
    后缀补全用得好,提前下班没烦恼
    Nginx 究竟如何处理事件?
    9 个习惯助你在新的一年更有精力
    一篇文章带你了解 ZooKeeper 架构
    浅析 Nginx 网络事件
    ZooKeeper 入门看这篇就够了
    如何优雅地关闭worker进程?
  • 原文地址:https://www.cnblogs.com/wuhenke/p/1622404.html
Copyright © 2020-2023  润新知