WorldWind學習系列三:簡單功能分析——主窗體的鍵盤監聽處理及拷貝和粘貼位置座標功能

原文轉自:http://www.cnblogs.com/wuhenke/archive/2009/12/12/1622404.html

在分析功能時發現,各功能都有自己的快捷鍵相應,比如今天要分析的 Copy Coordinates (Ctrl+C)和Paste Coordinates (Ctrl+P),以及主窗體的全屏功能也是通過快捷鍵(Alt+Enter)。這就使我需要徹底分析一下主窗體的鍵盤監聽處理啦。

主窗體的鍵盤監聽處理     

     與WorldWind學習系列三:功能分析——截屏功能和“關於”窗體分析 中AboutDialog.cs分析類似,WorldWind主窗體也是重載了OnKeyUp,使窗體接受鍵盤響應。

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->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函數 

真正處理鍵盤響應函數 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->                /// <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屬性控制的?注意不是函數,我想這是它值得我們學習的優點。

全屏屬性 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->        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

拷貝代碼 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->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()方法 實現自己的拷貝功能,如拷貝圖片等複雜對象。

粘貼位置座標功能

粘貼座標信息,並重新定位 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->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);
            }


 

粘貼座標信息,並重新定位 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->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);
            }


worldWindow.Goto實現最終是調用WorldWindow類的 GotoLatLon()

轉到特定的經緯度位置 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->WorldWindow類的 GotoLatLon()轉到特定的位置

        /// <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類。


 

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