Wednesday, June 29, 2005

Launching GTViewer from other Applications

I was asked last week how can you launch GTViewer from another application. Specifically, the job was to launch GTViewer via GTViewer’s OLE Automation layer, then locate on a specific coordinate. GTViewer has a significant number of methods available via its OLE automation layer; however, all of these methods were originally intended to support the development of application to extend GTViewer’s functionality and always appear as part of GTViewer itself. It took a minor modification to GTViewer to allow this to be done, but the functionality is currently available in version 4.0.0.19. With the addition of only two methods (OpenFile and Show) it becomes possible for other applications to pretty easily launch GTViewer, open a file, and call any of the available methods.

I will present both VB and VC++ code for launching GTViewer, but I will be more detailed on the VB code since I believe that there are more people using VB with GTViewer than VC++.

For VB

The first thing you should do in VB after you create a new project, is select Project/References and browse for the GTViewer.tlb file. This file is delivered with GTViewer and it tells VB how to communicate with GTViewer. After selecting this reference, the intellisense will work in VB for GTViewer types and its methods will show parameters and return types.

Next, you should define three variables in the declaration section. You may or may not use all three, but it is good to have them available:

Dim app As GTViewer.Application
Dim view As GTViewer.view
Dim doc As GTViewer.Document

To launch GTViewer, you use the CreateObject function like the following:

Set app = CreateObject("GTViewer.application")

If GTViewer is already running, it will attach to the running one (only one instance of GTViewer is ever allowed to run for this very reason).

The next step is to turn on the display of GTViewer. The default is to be hidden, so you must explicitly show the application:

app.Show 1


This is all you need to do to get GTViewer running. Now let’s open a file:

app.OpenFile "c:\temp\demo.gtx"

The file can be a .gtm, a .gtx, a .gtw, or a .gts.

The next part is a little tricky. We want to perform some operation on the view, but it takes some time for GTViewer to get the view open and available. One of the Application methods is GetActiveView. We will call this method to get a pointer to the active view that was just created by the OpenFile method; however, we must check to see if it is valid before we try to use it and then try to get it again if it is not.


Set view = app.GetActiveView

Dim count As Integer
count = 10 ' maximum of 10 tried

While view Is Nothing And count > 0
Sleep 250 ' pause a quarter of a second
Set view = app.GetActiveView
count = count - 1
Wend

There are many ways to get a valid view handle, but this seems like the simplest and most straightforward.

Now that we have access to a view, what do we do? I am going to set the view on a particular point that we provide. This job is easy to do with the SetViewCenter method which can location on both system coordinates (internal to GTViewer) or computed coordinates (used by the original data). However, to make this code segment even more usable, I am going to say that our coordinate is a Latitude/Longitude pair. So, we must convert the lat/long values to appropriate values for our data. This is easy to do as well, but there are a few requirements. The FromLatLong method we are going to use depends on the GPS Component being installed and the Coordinate System properly specified in the data (which may or not be done). The FromLatLong method is also part of the Document methods, so we must get a document object to work with:

Set doc = app.GetActiveDocument

Next, if our doc object and view object are valid, we convert the point and call SetViewCenter:

If Not doc Is Nothing And Not view Is Nothing Then

Dim latitude As Double
Dim longitude As Double
Dim x As Double
Dim y As Double

latitude = 34.653138583526
longitude = -86.4846563804903

If doc.FromLatLong(latitude, longitude, 1, x, y) Then
view.SetViewCenter 1, x, y, 1000
End If

End If


I have just hardcoded a lat/long value into the code so that it will have something to locate on.

That’s it! You can use any of the methods GTViewer provides. These methods are documented in GTVx.doc.

For VC++

For the VC++ programmer, I will quickly run through some of the major steps. You will create a new class using the GTViewer.tlb file as the first step. This class is a wrapper for the GTViewer methods and is used like the following:


IAutoMain *m_gtviewer;
.
.
.

double lat =34.653138583526;
double lon = -86.4846563804903;
double zoom = 1000.0;

if (m_gtviewer)
{
delete m_gtviewer;
}

m_gtviewer=new IAutoMain; // Create an instance of GTViewer

COleException e;
if(!m_gtviewer->CreateDispatch("GTViewer.Application", &e))
{
char buf[80];
sprintf(buf, "Error on CreateDispatch(): %ld (%08lx)",
e.m_sc, e.m_sc);
AfxMessageBox(buf, MB_SETFOREGROUND);
return;
}

m_gtviewer->Show(1); // must show the GTViewer app

m_gtviewer->OpenFile(m_file); // Open specified file

long count=10;

LPDISPATCH v=NULL;

while (v==NULL && count>0) // try until a valid dispatch
{
Sleep(250); // sleep a quarter of a second
v = m_gtviewer->GetActiveView(); // Get Dispatch for active view
count--;
}

LPDISPATCH d=NULL;

d = m_gtviewer->GetActiveDocument(); // Get Dispatch for active doc

IDogView view;
IDog doc;

if (v && d) // if a view dispatch was retrieved
{
view.AttachDispatch(v); // attach dispatches
doc.AttachDispatch(d);

long mode=1; // mode 1 = computed coordinates
double x, y;
doc.FromLatLong( lat, lon, mode, &x, &y );
view.SetViewCenter(mode, x, y, zoom);
}

No comments: