================================
HOOPS/Winforms Integration Guide
================================

Introduction
============

The HOOPS/Winforms integration consists a connection between HOOPS/3dGS and the Winforms 'Panel' and 'Form' GUI objects. This document describes how to use the HOOPS/Winforms integration to build a .NET Winforms application that incorporates the HOOPS/3DF components. Some familiarity with .NET Winforms, HOOPS/3dGS and HOOPS/MVO is assumed.

Developers should start by compiling and running the basic *csharp_simple* application as the starting point for their application. This is the primary example for .NET developers wishing to incorporate the HOOPS/3DF components into either existing or new .NET applications. The readable source code  is located in your *<hoops>/demo/dotnet/csharp_simple* and *<hoops>/demo/dotnet/vb_simple* directories.


Compilation and Runtime Information
===================================

The following steps are required to compile and run a HOOPS/Winforms based application: 

* **Compiling**: Your application must reference the HOOPS/3DF C# wrapper classes.

	* *hoops_cs.dll*
	* *hics_cs.dll*
	* *hoops_mvo_cs.dll*
	* *hoops_stream_cs.dll*
	* *hoops_panel.dll*


* **Executing**: Ensure that the following native .DLLs are in your application's directory or in your PATH.

	* *hoops_vc.dll*
	* *hcs.dll*
	* *hics.dll*
	* *hoops_mvo_mgk_vc.dll*
	* *hcsmvo.dll*
	* *hoops_stream_vc.dll*
	* *hcsstream.dll*
	* *hoops_panel.dll*
	
		

The above files are located in your *<VISUALIZE_INSTALL_DIR>/bin/nt_x64_v<version>* directory.


Component Object Relationships
==============================

This section discusses the relationship between .NET Winforms and HOOPS/3DF components. Building an application with both these toolkits minimally involves using the following objects from each component.

Winforms
--------

A .NET Winforms application typically has a master Form object, which contains child forms. Each child form may contain a Panel.

HOOPS/Winforms
--------------

There should be at least one set of the ``HNPanel`` and ``HNForm`` objects, where the panel gets attached to the form. You usually create a custom panel and form derived from ``HNPanel`` and ``HNForm``. The ``HNPanel`` and ``HNForm`` classes are found in *<hoops>/Dev_Tools/hoops_winforms/source/*.

HOOPS/MVO
---------

``HBaseModel``, ``HBaseView``, and an operator class derived from ``HBaseOperator``. Applications that want to implement selection of geometry will also need a ``HSelectionSet`` object. These objects are all connected by private data members which store pointers to other objects in the following manner: 

.. image:: images/HOOPS_winforms_arch.gif


Steps to Building an Application with .NET Winforms and HOOPS
=============================================================

Programming with an object oriented GUI framework like .NET Winforms involves creating a set of objects and defining the ways in which they are connected, the manner in which they send and receive messages, and then launching the framework's event loop. Building an application using .NET Winforms and HOOPS/3DF specifically requires creation and initialization of:

* :ref:`NET Winforms application objects <prog_guide/misc/winforms_integration:Creating and Initializing the Application>`
* :ref:`HOOPS/Winforms objects <prog_guide/misc/winforms_integration:Creating and Initializing HOOPS/Winforms Objects>` 
* :ref:`HOOPS/MVO objects <prog_guide/misc/winforms_integration:Creating and Initializing HOOPS/MVO Objects>`



Creating and Initializing the Application
=========================================

A .NET Winforms application usually creates a master Form object which implements the function ``Main()``. The *csharp_simple* application does this in it's primary *csharp_simple.cs* source file as follows::

	public class SimpleAppForm : Form
	{
	   ...
	  
		/*! Entry point for the application*/
		static void Main()
		{
			SimpleAppForm hoops = new SimpleAppForm();
			Application.Run(hoops);
		}
		
		...
	}


Creating and Initializing HOOPS/Winforms Objects
================================================

The HOOPS/Winforms integration consists of a customized .NET Winforms 'Form' and 'Panel' called ``HNForm`` and ``HNPanel``, as diagrammed up above. (Again, the Panel will get attached to the form.) As  many pairs of these objects can be created as needed to implement the GUI's design. Your application should define custom HNForm and HNPanel classes, as shown in *csharp_simple* source.

Custom ``HNPanel`` definition taken from the *csharp_simple* project's *SimpleHNPanel.cs* source file::

	public class SimpleHNPanel : HNPanel
	{
		// Constructor which calls the Init() method of the class  
		public SimpleHNPanel(): base()
		{
			Init();
		}


		// This method will set up the default HOOPS/MVO view for the panel and attach a HOOPS/MVO default operator 
		public new void Init()
		{
			// contents reviewed later
		}
		
		...
	}

Here is custom ``HNForm`` definition taken from the *csharp_simple* project's *SimpleHNForm.cs* source file. Note that it creates the custom ``HNPanel`` object and initializes the form::

	public class SimpleHNForm : HNForm
	{
		...

		// Sets up the panel and window 
		public void Init(object sender, EventArgs e)
		{
			// set up the panel that HOOPS will draw into
			m_pHNPanel = new SimpleHNPanel();

			Instance = (this.IsMdiChild) ? ((HForm)this.MdiParent).win_count : 0;
				
			// first set up the window, then set the axis triad options
			Init_Form();
			
			m_pHNPanel.m_pHView.Update();
			m_pHNPanel.m_pHView.SetAxisMode(AxisMode.AxisOn);
			m_pHNPanel.m_pHView.AdjustAxisWindow();
			
			...
		}
		
		...
	}

Finally, we can note that the ``fileNew`` and ``fileOpen`` methods of main app object (``SimpleAppForm``, again located in *csharp_simple.cs*) will create the custom ``HNForm`` object::

	public class SimpleAppForm : Form
	{
			...
			
			private void fileNewMenu_Click(object sender, EventArgs e)
			{
				SimpleHNForm frmchild = new SimpleHNForm();
				frmchild.MdiParent = this;
				frmchild.Show();
				win_count++;
			}


			private void fileOpenMenu_Click(object sender, EventArgs e)
			{
				OpenFileDialog dlg = new OpenFileDialog();
				dlg.Title = "Open";
				dlg.Filter = "HMF/HSF files (*.hmf, *.hsf)|*.hmf;*.hsf" +
							 "|All files (*.*)|*.*";

				if (dlg.ShowDialog() == DialogResult.OK)
				{
					SimpleHNForm frmchild = new SimpleHNForm();
					frmchild.MdiParent = this;
					frmchild.Show();

					frmchild.LoadFile(dlg);
					win_count++;
				}
				dlg.Dispose();
			}
			
			...
	}


Creating and Initializing HOOPS/MVO Objects
===========================================

HDB
---

One global pointer to a HOOPS/MVO HDB object should be declared and initialized in your application's main class. The *csharp_simple* app does this in the main ``SimpleAppForm`` constructor (located in *csharp_simple.cs*)::

	public class SimpleAppForm : Form
	{
		...
		
		// Constructor which initializes hoops database and GUI features of the main window */
		public SimpleAppForm()
		{
			win_count = 1;

			m_pHDB = new HDB();
			m_pHDB.Init();    

			...
		}
		
		...
	}


HBaseModel
----------

Multiple ``HBaseModel`` objects can be created as needed. The *csharp_simple* app creates one for every ``SimpleHNPanel`` object (i.e., there is a one-to-one mapping of ``HBaseModel`` to ``SimpleHNPanel`` objects) and does so in the ``SimpleHNPanel::Init``::

	public class SimpleHNPanel : HNPanel
	{
	  ...

	  public new void Init()
	  {
		...

		m_pHModel = new HSimpleModel();
		m_pHModel.Init();

		...
	  }

	}
  

HBaseView
---------

Multiple ``HBaseView`` objects can be created as needed, with one object usually being created for each ``HNPanel``. The ``HBaseView`` needs a valid native GUI window id passed to its constructor on object creation; this information is used to connect a HOOPS/3dGS output driver instance to a HNPanel. This requires that the ``HNPanel``, to which the ``HBaseView`` will be attached, already exist prior to creating the ``HBaseView`` object.
  
Your app should create the ``HBaseView`` object in your overloaded ``HNPanel::Init`` method. Here is the *csharp_simple* example taken from *csharp_simple.cs*:: 

	public class SimpleHNPanel : HNPanel
	{
		...

		public new void Init()
		{
			...

			m_pHView = new HSimpleView(m_pHModel, "?picture" + SimpleHNForm.Instance, "opengl", "", winid);
			m_pHView.Init();
			 
			...
		}

	}


HSelectionSet
-------------

The ``HBaseView`` class and ``HNPanel`` class contain pointers to a ``HSelectionSet`` object. A selection set class would typically be created and initialized during ``HNPanel`` initialization. After creation, it's important to pass the ``HSelectionSet`` operator into ``HBaseView`` by calling ``HBaseView::SetSelection``. The *csharp_simple* app does this in the overloaded method of ``HNPanel::Init`` method::

	public class SimpleHNPanel : HNPanel
	{
		...

		public new void Init()
		{
			...

			// view and model initialization goes here, and was discussed previously
			
			// Set up the custom HSelectionSet object
			m_pHSelection = new HSimpleSelectionSet(m_pHView);
			m_pHView.SetSelection(m_pHSelection);
			m_pHView.GetSelection().Init();
			 
			...
		}

	}


HBaseOperator
-------------

The ``HBaseView`` class and ``HNPanel`` class contains pointers to a ``HBaseOperator`` object. A default operator would typically be created and initialized during ``HNPanel`` initialization. After creating, you should set it to be the current operator by calling the utility method ``HNPanel::SetCurrentOperator``. The *csharp_simple* app does this in the overloaded method of ``HNPanel::Init`` method::

	public class SimpleHNPanel : HNPanel
	{
		...

		public new void Init()
		{
			...
			
			// Set the default operator
			m_pHOperator = new HOpCameraManipulate(m_pHView);
			m_pHView.SetCurrentOperator((HBaseOperator)m_pHOperator);
			 
			...
		}

	}
