Handling TerraExplorer Events

This example shows how to handle event messages, sent from TerraExplorer, from within a C++/ATL client. The following client handles the _ITerraExplorerEvents4::OnFrame() method in which it moves the plane to the left or to the right according to the user input and also handles the  _ITerraExplorerEvents4::OnTerraExplorerMessage() method to intercept object text messages before they are displayed in one of the TerraExplorer containers.

 

Note: This code is part of an EXE client written in C++/ATL. The “#import” directive in this sample indicates raw_interfaces_onl,y meaning that no smart pointers are used (and therefore the client takes care of releasing the interface pointers himself). In order to handle the events, the client derives from IDispEventImpl ATL base template, and calls DispEventAdvise() to establish a connection with the TerraExplorer ITerraExplorerEvents4 interface.

 

// PlanePanel.h : Declaration of the CPlanePanel

 

#ifndef __PLANEPANEL_H_

#define __PLANEPANEL_H_

 

#include "resource.h"       // main symbols

#include <atlhost.h>

 

#import "C:\Program Files\Skyline\TerraExplorer Pro\TerraExplorerX.dll" raw_interfaces_only, no_namespace, named_guids

 

/////////////////////////////////////////////////////////////////////////////

// CPlanePanel

class CPlanePanel :

public CAxDialogImpl<CPlanePanel>,

public IDispEventImpl<0 ,CPlanePanel, &DIID__ITerraExplorerEvents4, &LIBID_TerraExplorerX, 1, 0>

{

public:

CPlanePanel()

{

   m_pITerraExplorer4 = NULL;

   m_pIPlane5      = NULL;

}

~CPlanePanel()

{

}

 

enum { IDD = IDD_PLANEPANEL };

 

BEGIN_MSG_MAP(CPlanePanel)

MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)

COMMAND_ID_HANDLER(IDOK, OnOK)

COMMAND_ID_HANDLER(IDCANCEL, OnCancel)

END_MSG_MAP()

 

BEGIN_SINK_MAP(CPlanePanel)

   SINK_ENTRY_EX(/*nID =*/ 0, DIID__ITerraExplorerEvents4 ,/*dispid =*/ 3, OnFrame)

   SINK_ENTRY_EX(/*nID =*/ 0, DIID__ITerraExplorerEvents4 ,/*dispid =*/ 4, OnTerraExplorerMessage)

END_SINK_MAP()

 

LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)

{

   // Create the TerraExplorer CoClass object and get an interface

// pointer to m_pITerraExplorer4.

   HRESULT hRes = CoCreateInstance(CLSID_TerraExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_ITerraExplorer4, (void**)&m_pITerraExplorer4);

   if (FAILED(hRes))

   {

    ::MessageBox(NULL, "CoCreateInstance CLSID_TerraExplorer Failed", "Error", MB_OK);

    return 1;

   } 

 

// Establish a connection with the TerraExplorer event source.

   DispEventAdvise(m_pITerraExplorer4);

 

   hRes = m_pITerraExplorer4->QueryInterface(IID_IPlane5, (void**)&m_pIPlane5);

   if (FAILED(hRes))

   {

    ::MessageBox(NULL, "QueryInterface IID_IPlane5 Failed", "Error", MB_OK);

    return 1;

   }

 

   return 1;  // Let the system set the focus.

}

 

LRESULT OnOK(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)

{

   CleanUp();

   DestroyWindow();

   PostQuitMessage(0);

   return 0;

}

 

LRESULT OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)

{

   CleanUp();

   DestroyWindow();

   PostQuitMessage(0);

   return 0;

}

 

// OnTerraExplorerMessage event handler

HRESULT __stdcall OnTerraExplorerMessage(BSTR TEMessageID, BSTR SourceObjectID, VARIANTARG *pHandled)

{

// Get an interface pointer to the object manager.

   IObjectManager51* pIObjManager = NULL;

   HRESULT hRes = m_pITerraExplorer4->QueryInterface(IID_IObjectManager51, (void**)&pIObjManager);

   if (FAILED(hRes))

   {

    ::MessageBox(NULL, "QueryInterface() failed to get IObjectManager51 interface", "Error", MB_OK);

    return S_OK;

   }

 

// Get the TEMessageID object

   // IMPORTANT: Do not try to pass a casted ITerraExplorerMessage5 pointer here.

// It can be dangerous (especially if this client is implemented out-of-process).

   ITerraExplorerObject5* pITEObject = NULL;

   hRes = pIObjManager->GetObject(TEMessageID, &pITEObject);

   if (FAILED(hRes))

   {

    ::MessageBox(NULL, "GetObject() failed to get TEMessageID object from the object manager", "Error", MB_OK);

    pIObjManager->Release();

    return S_OK;

   }

 

   // This is supposed to be a message object, so QueryInterface for ITerraExplorerMessage5

   ITerraExplorerMessage5* pIMessage = NULL;

   hRes = pITEObject->QueryInterface(IID_ITerraExplorerMessage5, (void**)&pIMessage);

// We no longer need to hold the interface to the object manager.

   pIObjManager->Release();

   // Since we QueryInterface pITEObject for ITerraExplorerMessage5, we no longer need it.

   pITEObject->Release();

 

   if (FAILED(hRes))

   {

    ::MessageBox(NULL, "QueryInterface() failed to get ITerraExplorerMessage5 interface", "Error", MB_OK);

    return S_OK;

   }

 

   // Check the content of this message object.

   MsgType MessageType;

   pIMessage->get_Type(&MessageType);

   if (MessageType == TYPE_TEXT)

   {

    // This is a text message. Display it in a message box instead of its original container.

    BSTR Text = NULL;

    pIMessage->get_Text(&Text);

    _bstr_t MsgText = Text;

    ::MessageBox(NULL, MsgText, "Message from TE", MB_OK);

    if (pHandled != NULL)

    {

// Setting this to TRUE, lets TerraExplorer know that we handled the message in

// the client and we do not wish for it to display the message itself.

      if (pHandled->vt & VT_BOOL)

       pHandled->boolVal = VARIANT_TRUE;

    }

   }

   pIMessage->Release(); // Releasing the message object.

   return 0;

}

 

// OnFrame event handler

HRESULT __stdcall OnFrame()

{

   // Check if the user is pressing the "turn right" button.

   if (SendDlgItemMessage(IDC_RIGHT, BM_GETSTATE, 0,0) == 108)

   {

    // Turn the plane 5 degrees to the right.

 

    // The last parameter is a combination of

// IGNORE_POSITION

// IGNORE_PITCH

// IGNORE_ROLL

// NEW_ANGLES_RELATIVE_TO_CURRENT_ANGLES

// IGNORE_CAMERA_YAW

// IGNORE_CAMERA_PITCH.

 

    m_pIPlane5->MovePosition(0, 0, 0, 5, 0, 0, 0, 0, 3383);

   }

  

   // Check if the user is pressing the "turn left" button

   if (SendDlgItemMessage(IDC_LEFT, BM_GETSTATE, 0,0) == 108)

   {

    // Turn the plane 5 degrees to the left.

    m_pIPlane5->MovePosition(0, 0, 0, -5, 0, 0, 0, 0, 3383);

   }

 

   return 0;

}

 

protected:

 

void CleanUp()

{

   if (m_pITerraExplorer4 != NULL)

   {

    // Before we release the ITerraExplorer4 interface,

// break the connection with the TerraExplorer event source.

    DispEventUnadvise(m_pITerraExplorer4);

 

    m_pITerraExplorer4->Release();

    m_pITerraExplorer4 = NULL;

   }

 

   if (m_pIPlane5 != NULL)

   {

    m_pIPlane5->Release();

    m_pIPlane5 = NULL;

   }

}

 

ITerraExplorer* m_pITerraExplorer4;

IPlane5*  m_pIPlane5;

 

};

 

#endif //__PLANEPANEL_H_