About the Custom scene navigation commands Sample
[C#]
Fly.cs
using System; using System.Drawing; using ESRI.ArcGIS.Analyst3D; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.Controls; using ESRI.ArcGIS.ADF.BaseClasses; using ESRI.ArcGIS.ADF.CATIDs; using System.Runtime.InteropServices; namespace sceneTools { [ClassInterface(ClassInterfaceType.None)] [Guid("485BE349-31DA-4cd5-B6A4-69E4758F2541")] public sealed class Fly : BaseTool { [DllImport("user32")] public static extern int SetCursor(int hCursor); [DllImport("user32")] public static extern int GetClientRect(int hwnd, ref Rectangle lpRect); #region COM Registration Function(s) [ComRegisterFunction()] [ComVisible(false)] static void RegisterFunction(Type registerType) { // Required for ArcGIS Component Category Registrar support ArcGISCategoryRegistration(registerType); // // TODO: Add any COM registration code here // } [ComUnregisterFunction()] [ComVisible(false)] static void UnregisterFunction(Type registerType) { // Required for ArcGIS Component Category Registrar support ArcGISCategoryUnregistration(registerType); // // TODO: Add any COM unregistration code here // } #region ArcGIS Component Category Registrar generated code /// <summary> /// Required method for ArcGIS Component Category registration - /// Do not modify the contents of this method with the code editor. /// </summary> private static void ArcGISCategoryRegistration(Type registerType) { string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID); ControlsCommands.Register(regKey); } /// <summary> /// Required method for ArcGIS Component Category unregistration - /// Do not modify the contents of this method with the code editor. /// </summary> private static void ArcGISCategoryUnregistration(Type registerType) { string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID); ControlsCommands.Unregister(regKey); } #endregion #endregion private ISceneHookHelper m_pSceneHookHelper; private bool m_bInUse; bool bCancel = false; private long m_lMouseX; private long m_lMouseY; private double m_dMotion; //speed of the scene fly through in scene units private IPoint m_pPointObs; //observer private IPoint m_pPointTgt; //target private double m_dDistance; //distance between target and observer private double m_dElevation; //normal fly angles in radians private double m_dAzimut; //normal fly angles in radians private int m_iSpeed; private System.Windows.Forms.Cursor m_flyCur; private System.Windows.Forms.Cursor m_moveFlyCur; public Fly() { base.m_category = "Sample_SceneControl(C#)"; base.m_caption = "Fly"; base.m_toolTip = "Fly"; base.m_name = "Sample_SceneControl(C#)/Fly"; base.m_message = "Flies through the scene"; //Load resources string[] res = GetType().Assembly.GetManifestResourceNames(); if(res.GetLength(0) > 0) { base.m_bitmap = new System.Drawing.Bitmap(GetType().Assembly.GetManifestResourceStream("sceneTools.fly.bmp")); } m_flyCur = new System.Windows.Forms.Cursor(GetType().Assembly.GetManifestResourceStream("sceneTools.fly.cur")); m_moveFlyCur = new System.Windows.Forms.Cursor(GetType().Assembly.GetManifestResourceStream("sceneTools.fly1.cur")); m_pSceneHookHelper = new SceneHookHelperClass (); m_iSpeed = 0; } public override void OnCreate(object hook) { m_pSceneHookHelper.Hook = hook; } public override bool Enabled { get { //Disable if orthographic (2D) view if (m_pSceneHookHelper.Hook == null || m_pSceneHookHelper.Scene == null) { return false; } else { ICamera pCamera = (ICamera) m_pSceneHookHelper.Camera; if(pCamera.ProjectionType == esri3DProjectionType.esriOrthoProjection) return false; else return true; } } } public override int Cursor { get { if(m_bInUse) return m_moveFlyCur.Handle.ToInt32(); else return m_flyCur.Handle.ToInt32(); } } public override bool Deactivate() { return true; } public override void OnMouseUp(int Button, int Shift, int X, int Y) { if (! m_bInUse) { m_lMouseX = X; m_lMouseY = Y; if(m_iSpeed == 0) StartFlight(); } else { //Set the speed if (Button == 1) m_iSpeed = m_iSpeed + 1; else if (Button == 2) m_iSpeed = m_iSpeed - 1; //Start or end the flight if (m_iSpeed == 0) EndFlight(); else StartFlight(); } } public override void OnMouseMove(int Button, int Shift, int X, int Y) { if (! m_bInUse) return; m_lMouseX = X; m_lMouseY = Y; } public override void OnKeyUp(int keyCode, int Shift) { if(m_bInUse == true) { //Slow down the speed of the fly through if(keyCode == 40 || keyCode == 37) m_dMotion = m_dMotion / 2; //Speed up the speed of the fly through else if (keyCode == 38 || keyCode == 39) m_dMotion = m_dMotion * 2; else if (keyCode == 27) bCancel = true; } } public void StartFlight() { m_bInUse = true; //Get the extent of the scene graph IEnvelope pEnvelope; pEnvelope = m_pSceneHookHelper.SceneGraph.Extent; if (pEnvelope.IsEmpty) return; //Query the coordinates of the extent double dXmin, dXmax, dYmin, dYmax; pEnvelope.QueryCoords(out dXmin, out dYmin, out dXmax, out dYmax); //Set the speed of the scene if((dXmax - dXmin) > (dYmax - dYmin)) m_dMotion = (dXmax - dXmin)/100; else m_dMotion = (dYmax - dYmin) / 100; //Get camera's current observer and target ICamera pCamera = (ICamera) m_pSceneHookHelper.Camera; m_pPointObs = pCamera.Observer; m_pPointTgt = pCamera.Target; //Get the differences between the observer and target double dx, dy, dz; dx = m_pPointTgt.X - m_pPointObs.X; dy = m_pPointTgt.Y - m_pPointObs.Y; dz = m_pPointTgt.Z - m_pPointObs.Z; //Determine the elevation and azimuth in radians and //the distance between the target and observer m_dElevation = Math.Atan(dz/ Math.Sqrt(dx*dx + dy*dy)); m_dAzimut = Math.Atan(dy / dx); m_dDistance = Math.Sqrt((dx*dx) + (dy*dy) + (dz*dz)); //Windows API call to set cursor SetCursor(m_moveFlyCur.Handle.ToInt32()); //Continue the flight Flight(); } public void Flight() { //Get IMessageDispatcher interface IMessageDispatcher pMessageDispatcher; pMessageDispatcher = new MessageDispatcherClass(); //Set the ESC key to be seen as a cancel action pMessageDispatcher.CancelOnClick = false; pMessageDispatcher.CancelOnEscPress = true; //Get the scene graph ISceneGraph pSceneGraph = (ISceneGraph) m_pSceneHookHelper.SceneGraph; //Get the scene viewer ISceneViewer pSceneViewer = (ISceneViewer) m_pSceneHookHelper.ActiveViewer; //Get the camera ICamera pCamera = (ICamera) m_pSceneHookHelper.Camera; bCancel = false; do { //Get the elapsed time double dlastFrameDuration, dMeanFrameRate; pSceneGraph.GetDrawingTimeInfo(out dlastFrameDuration, out dMeanFrameRate); if(dlastFrameDuration < 0.01) dlastFrameDuration = 0.01; if(dlastFrameDuration > 1) dlastFrameDuration = 1; //Windows API call to get windows client coordinates Rectangle rect = new Rectangle(); if (GetClientRect(m_pSceneHookHelper.ActiveViewer.hWnd, ref rect) == 0) return; //Get normal vectors double dXMouseNormal, dYMouseNormal; dXMouseNormal = 2 * ((double)m_lMouseX / (double)rect.Right) - 1; dYMouseNormal = 2 * ((double)m_lMouseY / (double)rect.Bottom) - 1; //Set elevation and azimuth in radians for normal rotation m_dElevation = m_dElevation - (dlastFrameDuration * dYMouseNormal * Math.Abs(dYMouseNormal)); m_dAzimut = m_dAzimut - (dlastFrameDuration * dXMouseNormal * Math.Abs(dXMouseNormal)); if(m_dElevation > 0.45 * 3.141592) m_dElevation = 0.45 * 3.141592; if(m_dElevation < -0.45 * 3.141592) m_dElevation = -0.45 * 3.141592; if(m_dAzimut < 0) m_dAzimut = m_dAzimut + (2 * 3.141592); if(m_dAzimut > 2 * 3.141592) m_dAzimut = m_dAzimut - (2 * 3.141592); double dx, dy, dz; dx = Math.Cos(m_dElevation) * Math.Cos(m_dAzimut); dy = Math.Cos(m_dElevation) * Math.Sin(m_dAzimut); dz = Math.Sin(m_dElevation); //Change the viewing directions (target) m_pPointTgt.X = m_pPointObs.X + (m_dDistance * dx); m_pPointTgt.Y = m_pPointObs.Y + (m_dDistance * dy); m_pPointTgt.Z = m_pPointObs.Z + (m_dDistance * dz); //Move the camera in the viewing directions m_pPointObs.X = m_pPointObs.X + (dlastFrameDuration * (2 ^ m_iSpeed) * m_dMotion * dx); m_pPointObs.Y = m_pPointObs.Y + (dlastFrameDuration * (2 ^ m_iSpeed) * m_dMotion * dy); m_pPointTgt.X = m_pPointTgt.X + (dlastFrameDuration * (2 ^ m_iSpeed) * m_dMotion * dx); m_pPointTgt.Y = m_pPointTgt.Y + (dlastFrameDuration * (2 ^ m_iSpeed) * m_dMotion * dy); m_pPointObs.Z = m_pPointObs.Z + (dlastFrameDuration * (2 ^ m_iSpeed) * m_dMotion * dz); m_pPointTgt.Z = m_pPointTgt.Z + (dlastFrameDuration * (2 ^ m_iSpeed) * m_dMotion * dz); pCamera.Observer = m_pPointObs; pCamera.Target = m_pPointTgt; //Set the angle of the camera about the line of sight between the observer and target pCamera.RollAngle = 10 * dXMouseNormal * Math.Abs(dXMouseNormal); //Redraw the scene viewer pSceneViewer.Redraw(true); object objCancel; //Dispatch any waiting messages: OnMouseMove / OnMouseUp / OnKeyUp events //object objCancel = bCancel as object; pMessageDispatcher.Dispatch(m_pSceneHookHelper.ActiveViewer.hWnd, false, out objCancel); //End flight if ESC key pressed if (bCancel == true) EndFlight(); } while(m_bInUse == true && bCancel == false); bCancel = false; } public void EndFlight() { m_bInUse = false; //Get the scene graph ISceneGraph pSceneGraph = (ISceneGraph) m_pSceneHookHelper.SceneGraph; IPoint pPointTgt; pPointTgt = new PointClass(); object pOwner, pObject; Rectangle rect = new Rectangle(); //Windows API call to get windows client coordinates if(GetClientRect(m_pSceneHookHelper.ActiveViewer.hWnd, ref rect) != 0) { //Translate coordinates into a 3D point pSceneGraph.Locate(pSceneGraph.ActiveViewer, rect.Right / 2, rect.Bottom / 2, esriScenePickMode.esriScenePickAll, true, out pPointTgt, out pOwner, out pObject); } //Get the camera ICamera pCamera = (ICamera) m_pSceneHookHelper.Camera; if(pPointTgt != null) { //Reposition target and observer pCamera.Target = pPointTgt; pCamera.Observer = m_pPointObs; } //Set the angle of the camera about the line //of sight between the observer and target pCamera.RollAngle = 0; pCamera.PropertiesChanged(); //Windows API call to set cursor SetCursor(m_moveFlyCur.Handle.ToInt32()); m_iSpeed = 0; } public override void OnKeyDown(int keyCode, int Shift) { if(keyCode == 27) //ESC is pressed { bCancel = true; } } } }
[Visual Basic .NET]
Fly.vb
Imports System.Drawing Imports ESRI.ArcGIS.Analyst3D Imports ESRI.ArcGIS.GeomeTry Imports ESRI.ArcGIS.Controls Imports ESRI.ArcGIS.ADF.BaseClasses Imports ESRI.ArcGIS.ADF.CATIDs Imports System.Runtime.InteropServices <ComClass(Fly.ClassId, Fly.InterfaceId, Fly.EventsId)> _ Public NotInheritable Class Fly Inherits BaseTool #Region "COM GUIDs" ' These GUIDs provide the COM identity for this class ' and its COM interfaces. If you change them, existing ' clients will no longer be able to access the class. Public Const ClassId As String = "C74AE939-B3B1-4F28-9E79-D172CF1F2043" Public Const InterfaceId As String = "86B05C26-D3C0-49E9-957D-7F54B35C8940" Public Const EventsId As String = "E419FD47-DA90-45B7-8563-BD4D9D023555" #End Region #Region "COM Registration Function(s)" <ComRegisterFunction(), ComVisibleAttribute(False)> _ Public Shared Sub RegisterFunction(ByVal registerType As Type) ' Required for ArcGIS Component Category Registrar support ArcGISCategoryRegistration(registerType) 'Add any COM registration code after the ArcGISCategoryRegistration() call End Sub <ComUnregisterFunction(), ComVisibleAttribute(False)> _ Public Shared Sub UnregisterFunction(ByVal registerType As Type) ' Required for ArcGIS Component Category Registrar support ArcGISCategoryUnregistration(registerType) 'Add any COM unregistration code after the ArcGISCategoryUnregistration() call End Sub #Region "ArcGIS Component Category Registrar generated code" ''' <summary> ''' Required method for ArcGIS Component Category registration - ''' Do not modify the contents of this method with the code editor. ''' </summary> Private Shared Sub ArcGISCategoryRegistration(ByVal registerType As Type) Dim regKey As String = String.Format("HKEY_CLASSES_ROOT\CLSID\{{{0}}}", registerType.GUID) ControlsCommands.Register(regKey) End Sub ''' <summary> ''' Required method for ArcGIS Component Category unregistration - ''' Do not modify the contents of this method with the code editor. ''' </summary> Private Shared Sub ArcGISCategoryUnregistration(ByVal registerType As Type) Dim regKey As String = String.Format("HKEY_CLASSES_ROOT\CLSID\{{{0}}}", registerType.GUID) ControlsCommands.Unregister(regKey) End Sub #End Region #End Region Declare Function GetClientRect Lib "user32" (ByVal hwnd As Integer, ByRef lpRect As Rectangle) As Integer Declare Function SetCursor Lib "user32" (ByVal hCursor As Integer) As Integer Private m_pSceneHookHelper As ISceneHookHelper Private m_bInUse As Boolean Dim bCancel As Boolean = False Private m_lMouseX As Long Private m_lMouseY As Long Private m_dMotion As Double 'speed of the scene fly through in scene units Private m_pPointObs As IPoint 'observer Private m_pPointTgt As IPoint 'target Private m_dDistance As Double 'distance between target and observer Private m_dElevation As Double 'normal fly angles in radians Private m_dAzimut As Double 'normal fly angles in radians Private m_iSpeed As Integer 'speed of a flight Private m_flyCur As System.Windows.Forms.Cursor Private m_moveFlyCur As System.Windows.Forms.Cursor ' A creatable COM class must have a Public Sub New() ' with no parameters, otherwise, the class will not be ' registered in the COM registry and cannot be created ' via CreateObject. Public Sub New() MyBase.New() MyBase.m_category = "Sample_SceneControl(VB.NET)" MyBase.m_caption = "Fly" MyBase.m_toolTip = "Fly" MyBase.m_name = "Sample_SceneControl(VB.NET)/Fly" MyBase.m_message = "Flies through the scene" 'Load resources Dim res() As String = GetType(Fly).Assembly.GetManifestResourceNames() If res.GetLength(0) > 0 Then MyBase.m_bitmap = New System.Drawing.Bitmap(GetType(Fly).Assembly.GetManifestResourceStream("SceneToolsVB.fly.bmp")) End If m_flyCur = New System.Windows.Forms.Cursor(GetType(Fly).Assembly.GetManifestResourceStream("SceneToolsVB.fly.cur")) m_moveFlyCur = New System.Windows.Forms.Cursor(GetType(Fly).Assembly.GetManifestResourceStream("SceneToolsVB.fly1.cur")) m_pSceneHookHelper = New SceneHookHelperClass m_iSpeed = 0 End Sub Public Overrides Sub OnCreate(ByVal hook As Object) m_pSceneHookHelper.Hook = hook End Sub Public Overrides ReadOnly Property Enabled() As Boolean Get 'Disable if orthographic (2D) view If m_pSceneHookHelper.Hook Is Nothing Or m_pSceneHookHelper.Scene Is Nothing Then Return False Else Dim pCamera As ICamera = CType(m_pSceneHookHelper.Camera, ICamera) If pCamera.ProjectionType = esri3DProjectionType.esriOrthoProjection Then Return False Else Return True End If End If End Get End Property Public Overrides ReadOnly Property Cursor() As Integer Get If (m_bInUse) Then Return m_moveFlyCur.Handle.ToInt32() Else Return m_flyCur.Handle.ToInt32() End If End Get End Property Public Overrides Function Deactivate() As Boolean Return True End Function Public Overrides Sub OnMouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Integer, ByVal Y As Integer) If (Not m_bInUse) Then m_lMouseX = X m_lMouseY = Y If (m_iSpeed = 0) Then StartFlight() End If Else 'Set the speed If (Button = 1) Then m_iSpeed += 1 ElseIf (Button = 2) Then m_iSpeed -= 1 End If 'Start or end the flight If (m_iSpeed = 0) Then EndFlight() Else StartFlight() End If End If End Sub Public Overrides Sub OnMouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Integer, ByVal Y As Integer) If (Not m_bInUse) Then Return End If m_lMouseX = X m_lMouseY = Y End Sub Public Overrides Sub OnKeyUp(ByVal keyCode As Integer, ByVal Shift As Integer) If (m_bInUse) Then 'Slow down the speed of the fly through If (keyCode = 40 Or keyCode = 37) Then m_dMotion = m_dMotion / 2 'Speed up the speed of the fly through ElseIf (keyCode = 38 Or keyCode = 39) Then m_dMotion = m_dMotion * 2 End If End If End Sub Public Sub StartFlight() m_bInUse = True 'Get the extent of the scene graph Dim pEnvelope As IEnvelope pEnvelope = m_pSceneHookHelper.SceneGraph.Extent If (pEnvelope.IsEmpty) Then Return End If 'Query the coordinates of the extent Dim dXmin, dXmax, dYmin, dYmax As Double pEnvelope.QueryCoords(dXmin, dYmin, dXmax, dYmax) 'Set the speed of the scene If ((dXmax - dXmin) > (dYmax - dYmin)) Then m_dMotion = (dXmax - dXmin) / 100 Else m_dMotion = (dYmax - dYmin) / 100 End If 'Get camera's current observer and target Dim pCamera As ICamera = CType(m_pSceneHookHelper.Camera, ICamera) m_pPointObs = pCamera.Observer m_pPointTgt = pCamera.Target 'Get the differences between the observer and target Dim dx, dy, dz As Double dx = m_pPointTgt.X - m_pPointObs.X dy = m_pPointTgt.Y - m_pPointObs.Y dz = m_pPointTgt.Z - m_pPointObs.Z 'Determine the elevation and azimuth in radians and 'the distance between the target and observer m_dElevation = Math.Atan(dz / Math.Sqrt(dx * dx + dy * dy)) m_dAzimut = Math.Atan(dy / dx) m_dDistance = Math.Sqrt((dx * dx) + (dy * dy) + (dz * dz)) 'Windows API call to set cursor SetCursor(m_moveFlyCur.Handle.ToInt32()) 'Continue the flight Flight() End Sub Public Sub Flight() 'Get IMessageDispatcher interface Dim pMessageDispatcher As IMessageDispatcher pMessageDispatcher = New MessageDispatcherClass 'Set the ESC key to be seen as a cancel action pMessageDispatcher.CancelOnClick = False pMessageDispatcher.CancelOnEscPress = True 'Get the scene graph Dim pSceneGraph As ISceneGraph = CType(m_pSceneHookHelper.SceneGraph, ISceneGraph) 'Get the scene viewer Dim pSceneViewer As ISceneViewer = CType(m_pSceneHookHelper.ActiveViewer, ISceneViewer) 'Get the camera Dim pCamera As ICamera = CType(m_pSceneHookHelper.Camera, ICamera) bCancel = False Do 'Get the elapsed time Dim dlastFrameDuration, dMeanFrameRate As Double pSceneGraph.GetDrawingTimeInfo(dlastFrameDuration, dMeanFrameRate) If (dlastFrameDuration < 0.01) Then dlastFrameDuration = 0.01 End If If (dlastFrameDuration > 1) Then dlastFrameDuration = 1 End If 'Windows API call to get windows client coordinates Dim rect As Rectangle rect = New Rectangle If (GetClientRect(m_pSceneHookHelper.ActiveViewer.hWnd, rect) = 0) Then Return End If 'Get normal vectors Dim dXMouseNormal, dYMouseNormal As Double dXMouseNormal = 2 * (m_lMouseX / rect.Right) - 1 'should be double dYMouseNormal = 2 * (m_lMouseY / rect.Bottom) - 1 'Set elevation and azimuth in radians for normal rotation m_dElevation = m_dElevation - (dlastFrameDuration * dYMouseNormal * Math.Abs(dYMouseNormal)) m_dAzimut = m_dAzimut - (dlastFrameDuration * dXMouseNormal * Math.Abs(dXMouseNormal)) If (m_dElevation > 0.45 * 3.141592) Then m_dElevation = 0.45 * 3.141592 End If If (m_dElevation < -0.45 * 3.141592) Then m_dElevation = -0.45 * 3.141592 End If If (m_dAzimut < 0) Then m_dAzimut = m_dAzimut + (2 * 3.141592) End If If (m_dAzimut > 2 * 3.141592) Then m_dAzimut = m_dAzimut - (2 * 3.141592) End If Dim dx, dy, dz As Double dx = Math.Cos(m_dElevation) * Math.Cos(m_dAzimut) dy = Math.Cos(m_dElevation) * Math.Sin(m_dAzimut) dz = Math.Sin(m_dElevation) 'Change the viewing directions (target) m_pPointTgt.X = m_pPointObs.X + (m_dDistance * dx) m_pPointTgt.Y = m_pPointObs.Y + (m_dDistance * dy) m_pPointTgt.Z = m_pPointObs.Z + (m_dDistance * dz) 'Move the camera in the viewing directions m_pPointObs.X = m_pPointObs.X + (dlastFrameDuration * (2 ^ m_iSpeed) * m_dMotion * dx) m_pPointObs.Y = m_pPointObs.Y + (dlastFrameDuration * (2 ^ m_iSpeed) * m_dMotion * dy) m_pPointTgt.X = m_pPointTgt.X + (dlastFrameDuration * (2 ^ m_iSpeed) * m_dMotion * dx) m_pPointTgt.Y = m_pPointTgt.Y + (dlastFrameDuration * (2 ^ m_iSpeed) * m_dMotion * dy) m_pPointObs.Z = m_pPointObs.Z + (dlastFrameDuration * (2 ^ m_iSpeed) * m_dMotion * dz) m_pPointTgt.Z = m_pPointTgt.Z + (dlastFrameDuration * (2 ^ m_iSpeed) * m_dMotion * dz) pCamera.Observer = m_pPointObs pCamera.Target = m_pPointTgt 'Set the angle of the camera about the line of sight between the observer and target pCamera.RollAngle = 10 * dXMouseNormal * Math.Abs(dXMouseNormal) 'Redraw the scene viewer pSceneViewer.Redraw(True) Dim objCancel As Object = Nothing 'Dispatch any waiting messages: OnMouseMove / OnMouseUp / OnKeyUp events 'object objCancel = bCancel as object; pMessageDispatcher.Dispatch(m_pSceneHookHelper.ActiveViewer.hWnd, False, objCancel) 'End flight if ESC key pressed If (bCancel = True) Then EndFlight() End If Loop While m_bInUse = True And bCancel = False SetCursor(m_flyCur.Handle.ToInt32()) bCancel = False End Sub Public Sub EndFlight() m_bInUse = False 'Get the scene graph Dim pSceneGraph As ISceneGraph = CType(m_pSceneHookHelper.SceneGraph, ISceneGraph) Dim pPointTgt As IPoint pPointTgt = New PointClass Dim pOwner As Object = Nothing, pObject As Object = Nothing Dim rect As Rectangle rect = New Rectangle 'Windows API call to get windows client coordinates If (GetClientRect(m_pSceneHookHelper.ActiveViewer.hWnd, rect) <> 0) Then 'Translate coordinates into a 3D point pSceneGraph.Locate(pSceneGraph.ActiveViewer, rect.Right / 2, rect.Bottom / 2, esriScenePickMode.esriScenePickAll, True, pPointTgt, pOwner, pObject) End If 'Get the camera Dim pCamera As ICamera = CType(m_pSceneHookHelper.Camera, ICamera) If (Not pPointTgt Is Nothing) Then 'Reposition target and observer pCamera.Target = pPointTgt pCamera.Observer = m_pPointObs End If 'Set the angle of the camera about the line 'of sight between the observer and target pCamera.RollAngle = 0 pCamera.PropertiesChanged() 'Windows API call to set cursor SetCursor(m_moveFlyCur.Handle.ToInt32()) m_iSpeed = 0 End Sub Public Overrides Sub OnKeyDown(ByVal keyCode As Integer, ByVal Shift As Integer) If (keyCode = 27) Then 'ESC is pressed bCancel = True End If End Sub End Class