bwind

OpenGL in its own window within an ArcMap extension

Discussion created by bwind on Aug 12, 2013
Latest reply on Dec 1, 2015 by aricraimundo
This request for help follows from the good suggestion by Alexander Gray of The Forum to begin
a separate thread around my original post here:
http://forums.arcgis.com/threads/63628-get-reference-to-a-dockable-window-controls?p=319538&highlight=opengl#post319538
[As a related aside in reply to Alexander's other comment..  Although our development machines
are 64-bit we are successfully compiling all of our builds for a 32-bit target architecture, for
which example applications other than our ArcMap extension work okay with OpenGL.]

After another couple of days of trying to integrate OpenGL with the ArcObject "dockable window",
the challenges to doing this seem a little greater than we had first imagined.

Our OpenGL draw code was greatly simplified and in-lined directly into the class itself that extends
the ArcObject "dockable window."  For those whom it might help to understand this distinction,
formerly our setup was a .Net UserControl containing a Panel object for which a
System.Drawing.Graphics object was created and from that the device context ("dc") for OpenGL
obtained from it via GetHdc().  This control was then pasted into the ArcObject dockable window
control class, itself a subclass of UserControl.  Now, instead, the device context is obtained directly
in said dockable window class that Implements IDockableWindowDef so that the one unified class
now contains the OpenGL code in-lined within it.  The device context is obtained as follows:
dc = User.GetDC(Me.Handle)
For utmost simplicity for subsequent drawing, the overridden OnPaint method now merely
1) activates the rendering context (rc) with Tao.Platform.Windows.Wgl.wglMakeCurrent(dc, rc), where rc was created in the usual OpenGL way using dc
2) sets the OpenGL viewport to be the extents of the Width and Height of the dockable window
3) sets the glClearColor to green
4) then just issues glClear. 

If all is as it should be, this new setup described should paint the dockable window green.  And
the dockable window should remain green permanently as long as it is visible.  What we actually
see is as follows.

When we first show the dockable window it is green.  If the dockable window is floating and not
docked, as happens to be the case when we first create it, any interaction at all whatsoever with
the main ArcMap application window causes the green dockable window to turn white.  This means
that in response to this user interaction event, OpenGL drawing suddenly does not work in the
undocked dockable window.  The same is true when clicking on other application windows that are
neither ArcMap nor this new dockable window--the dockable window loses the OpenGL rendering
and "whites-out" as though not drawn.  However our undocked dockable window lost the OpenGL,
it can be made green (i.e., to be drawn complete with OpenGL rendering again) subsequently by
interacting with it.  But going back and interacting with the main window or outside of the ArcMap
process windows always causes the same behavior of the OpenGL in the undocked dockable
window to stop being drawn.  For clarity, let us call this Issue #1.

Question regarding Issue #1:  Is there perhaps a snag with the main ArcMap application window
taking and not relinquishing the device context, and if so any workaround to allow context to be
shared when utilizing an Arc dockable window?  [Note:  I am relatively new both to Arc and OpenGL
low-level programming, so any specific pointers are welcome especially if there is something obvious
being overlooked here which there may well be.]

Secondly, Issue #2:  When the dockable window is not docked, resizes of it also cause the OpenGL
to flicker as noted in my original post.  Let us refer to this as Issue #2, which may or may not be
related to Issue #1.  We had a notion to work around this Issue #2 by causing Paint to happen
only upon ResizeEnd if posslbe, but this seems not possible because the ResizeEnd event is
unavailable to a mere UserControl--it looks only to be available to a Form object.  The only other
suggested workaround that we found (on older Forms programming message boards) was perhaps
to use the Application.Idle event somehow but this seems error-prone, cumbersome, and possibly
wasteful besides that it might be more relevant only for older Frameworks and most of all, we don't
see how exactly to do this within an ArcMap extension.

All of this being said, when the dockable window is docked in the main application window, Issues #1
and #2 go away completely.

As an alternative, we have not yet tried to load our plain (i.e., non-dockable) Form instead as
opposed to one of these "dockable windows."  Using the dockable window option seemed most
desirable because we already have several such windows all with related integrated functionality
that we must manage within our extension and did not want to add yet another that must float apart
from the rest.  Ideally, we also may wish to permit a user of our extension to add more than one
instance of this OpenGL window, but only if we can get one of them to function properly to be sure.

Thanks very much ahead for any assistance.  As you can see, we have a lot of investigation
invested in finding a good solution.

Brad

Outcomes