Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Most components that present a user interface , have an item in the navigation tree that . This item often presents a panel when the item is clicked but it can also simply fire an event that you handle in a custom manner.

Adding a tree item

When you are ready to create your user interface, the The first thing that you typically do is add an item to the navigation tree. 

...

Info

When creating your framework you have to wait until the ComponentUIAPI interface has been registered before you can use its functions. Your component will get a COMPONENT_NOTIFY_NEWINTERFACE message with a UUID of UIFRAMEWORK_INTERFACE_UUID when the host component framework is ready to be used.

 

The example below shows some code that creates an item in the navigation tree. Later on we show code to handle an activation event and create the window for the panel that is shown when the item is selected.

Code Block
static NavigationItemUIInterface notificationInterface;

NavHandle CreateTreeItem()
{
	// Set up our notification interface so we can receive messages relating to the the navigation item we will insert into the tree
	memset(&gDataUI,0,sizeof(NavigationItemUIInterface));
	notificationInterface.dwSize					= sizeof(NavigationItemUIInterface);
	notificationInterface.NavItemCreateWindow		= NavItemCreateWindow;						// Called when the framework wants a window from us
	notificationInterface.NavItemDrawItem			= NULL;
	notificationInterface.NavItemNotify				= NavItemNotify;							// For receiving general messages
	notificationInterface.NavItemGetHelpContent		= NavItemGetHelpContent;					// For dynamic help content in the help pane of the UI
	notificationInterface.NavItemFreeHelpContent	= NavItemFreeHelpContent;
	notificationInterface.NavItemShowContextHelp	= NavItemShowContextHelp;					// For F1 help
	notificationInterface.NavItemKeyboardNavigate 	= NavItemKeyboardNavigate;					// To handle custom keyboard navigation within our panel. (optional)


	// Get the correct location to insert our new item under. In this case it will be the "Control Panel" node. This has a well known alias that we can use.
 
	NAVSETITEM controlPanelItem;
	if ( !NavGetItem(_T("{ControlPanel}"), &controlPanelItem) )
	{
		return NULL;										// Couldn't find it, so we won't go any further
	}

	NAVSETITEM treeItem;
	memset(&treeItem, 0, treeItem);
	treeItem.size = sizeof(NAVSETITEM);
	treeItem.flags = NI_FLAG_CUSTOMCONTAINER;				// This is a custom container where we control the panel. 
	treeItem.lParam = NULL;									// Set any special context data that you want to be sent with messages to the notificationInterface
	treeItem.strLabel = L"Ad Blocker";
	treeItem.strDescription = L"This component adds an HTTP Filter that blocks advertising";
	treeItem.hModule = AfxGetResourceHandle();				// Where to get resources from
	treeItem.nIconId = iconResourceId;						// Some resource id of the icon to display in the navigation tree
	treeItem.EventMask = 0;									// No special events. NI_EVENT_ACTIVATE, NI_EVENT_DEACTIVATE are always sent. See NavInsertItem for more information
	treeItem.pInterface = notificationInterface;			// The interface we are wanting to use to handle events from this item
	treeItem.strAlias = L"{MyCompanyAdBlocker}";			// Adds an alias. Makes it easier to find and compare navigation items later.
	if ( !NavInsertItem(controlPanelItem.hItem, L"MyCompanyAdBlockerPath", &treeItem) ) 	// The path "MyCompanyAdBlockerPath" is an internal name the user never sees but must be unique under a particular root.
	{
		return NULL;
	}
	return treeItem.hItem;

...

The pInterface member above points to an interface that will be called used to handle events relating to your inserted item. The most common of these are NI_EVENT_ACTIVATE an NIand NI_EVENT_DEACTIVATE which are called when the user selects your item in the tree and when they click away to another item. 

Code Block
// CallbackInterface function that handles notification messages relating to our navigation item. This is apart member of athe NavigationItemUIInterface object that is passed to NavInsertItem.
UINT NavItemNotify(NAVITEMNOTIFY* pN)
{
 	if ( pN->nMsg == NI_EVENT_ACTIVATE )
	{
		CreateTaskItems();
		return 0;
	}
 
 	if ( pN->nMsg == NI_EVENT_DEACTIVATE )
	{
		DeleteTaskItems();
		return 0;
	}
 
	return 0;
}

...

When the WMC needs you to create the window relating to your navigation tree item then it calls the NavigationItemUIInterface interface function NavItemCreateWindow. In this function you need to return the HWND associated with your window.

Code Block
MyPanel *myPanel = nullptr;
 
static HWND NavItemCreateWindow(NAVCREATEITEM* pCs)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	if ( myPanel == nullptr )
	{	
		myPanel = new MyPanel();
		myPanel->Create(pCs->hParent, CRect(pCs->rcWnd));			// The parent window and required rect for your window is passed in the NAVCREATEITEM structure
	}
	return myPanel->GetHwnd();
}

Destroying your panel

When the WMC disconnects from a WinGate Engine, the entire window hierarchy is destroyed and all GUI components are unloaded. However, If you need to close your window under your control you can do so at any appropriate time such as in your component's Stop() function or when it receives a COMPONENT_NOTIFY_PREDISCONNECT message in it's Notify callback.

...