The Solaris and Linux SDK also provides a set of Motif widgets that may be used to embed the ArcGIS controls in a Motif application. Due to the limitations of Motif, this code will only run on Solaris and Linux systems. If visual components are needed on Windows, you will need to use Visual C++, the COM API, and ActiveX controls.
Header files
To use the Motif ArcGIS controls, you will need to include both the ArcGIS Engine header file, ArcSDK.h, and the ArcGIS Engine Motif controls header file, Ao/AoMotifControls.h.
Control types and their details
Control
|
MwNprogID
|
Interface type
|
GlobeControl
|
AoPROGID_GlobeControl
|
IGlobeControl
|
MapControl
|
AoPROGID_MapControl
|
IMapControl3
|
PageLayoutControl
|
AoPROGID_PageLayoutControl
|
IPageLayoutControl
|
ReaderControl
|
AoPROGID_ReaderControl
|
IARControl
|
SceneControl
|
AoPROGID_SceneControl
|
ISceneControl
|
TOCControl
|
AoPROGID_TOCControl
|
ITOCControl
|
ToolbarControl
|
AoPROGID_ToolbarControl
|
IToolbarControl
|
API functions and arguments
- For each ArcGIS Engine Control interface there is a smart pointer defined for you. Instead of IMapControl3* you can use IMapControlPtr.
- MwCtlAppMainLoop replaces XtAppMainLoop
extern
"C"
void MwCtlAppMainLoop(XtAppContext app);
- MwCtlGetInterface is used to get the control's interface pointer.
HRESULT MwCtlGetInterface(Widget w, IUnknown **ppUnk);
- mwCtlWidgetClass—argument to give the widget class for all ActiveX control widgets
- MwNprogID—argument to pair with AoPROGID_<ControlName>Control
- MwCtlSetCursor is used to set a custom cursor for the Motif control widget.
HRESULT MwCtlSetCursor(HCURSOR cur);
Control widget creation example
The following example demonstrates creating a MapControl that fills the entire Motif form mainForm (defined outside this code snippet) and retrieves a smart pointer for the control. The #define statements are necessary to prevent type name conflicts between X and ArcGIS Engine.
[Motif C++]
// Motif Headers
#define String esriXString
#define Cursor esriXCursor
#define Object esriXObject
#define ObjectClass esriXObjectClass
#include <Xm/Xm.h>
#include <Xm/MainW.h>
#include <Xm/Form.h>
#include <Xm/Protocols.h>
#undef String
#undef Cursor
#undef Object
#undef ObjectClass
// ArcObjects Headers// Engine#include <ArcSDK.h>
// Controls#include <Ao/AoMotifControls.h>
int main(int argc, char *argv[])
{
// other code goes before this
Widget mapWidget = XtVaCreateWidget("mapWidget", mwCtlWidgetClass, mainForm,
XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM,
MwNprogID, AoPROGID_MapControl, NULL);
IMapControl3Ptr ipMapControl;
HRESULT hr = MwCtlGetInterface(mapWidget, (IUnknown **) &ipMapControl);
// additional code follows here
}
#define and Types for Motif
In most of the Motif samples, you will see code similar to the following:
[Motif C++]
#define String esriXString
#define Cursor esriXCursor
#define Object esriXObject
#define ObjectClass esriXObjectClass
#include <Xm/Xm.h>
#include <Xm/MainW.h>
#include <Xm/Form.h>
#include <Xm/Protocols.h>
#undef String
#undef Cursor
#undef Object
#undef ObjectClass
Because the type names String, Cursor, Object, and ObjectClass are used by both ArcGIS and X, all included X headers have been placed between these #define-#undef pairs to rename those types and resolve the conflict. Any other X headers must also be included in this manner. If your code uses any of those X types, you can simply substitute the original name with the replacement shown above as long as you are passing them to functions with external "C" linkage (eg. X functions).
If you pass arguments using these renamed types to C++ functions or methods, you will likely encounter compilation errors due to the compiler's name mangling scheme, which generally uses argument types to produce function and method symbol names. In this case, you must carefully segregate this code into compilation units (compiled files) separate from your ArcGIS code.
Setting the size of a control widget
If you would like to set your control widget to have a specific size, you will need to do this after the widget itself is created. DO NOT use XmNheight and XmNwidth in the XtVaCreateWidget section. Due to internal limitations, that will cause undetermined behavior in the controls. Instead, set the size of your widget after it is created with a call to XtVaSetValues. For example, to set the above mapControl to be 200x200, add the line:
[Motif C++]
XtVaSetValues(mapWidget, XmNheight, 200, XmNwidth, 200, NULL);
after the call to XtVaCreateWidget.