Add-in Express™ for Internet Explorer® and Microsoft® .netAdd-in Express Home > Add-in Express for Internet Explorer > Online Guide > IE add-on: tabs, windows, threads, instances and messages How Your Add-on Loads into IE

Shims
Internet Explorer is unmanaged while an Add-in Express based add-on is a managed class library. Therefore, there must be some software located between IE and your add-on; the software, or the shim, follows the rules for IE add-ons and, at appropriate moment, loads the .NET Framework and starts the add-on.
Add-in Express Loader
An Add-in Express based IE add-on is supplied with a special precompiled shim - Add-in Express Loader. The loader supplied as 32-bit and 64-bit DLLs (adxloader.dll, adxloader64.dll) is designed to fulfill the following basic tasks: it loads the .NET Framework, creates a unique AppDomain for the add-on, and loads the add-on into the AppDomain. Advanced options are provided to the developer by the manifest file (adxloader.dll.manifest) that may have the following look:
<?xml version="1.0" encoding="utf-8"?>
<configuration></configuration>
<a name=" MyIEAddon1, PublicKeyToken=f9f39773da5c568a"></a>
<loadersettings privileges="administrator" generatelogfile="true"
shadowcopyenabled="true" configfilename=" MyIEAddon1.dll.config"></loadersettings>
<logfilelocation></logfilelocation>C:\MyLog.txt</logFileLocation>
</loaderSettings>
</configuration>
The loader allows generating a log file containing useful information about errors on the add-in loading stage. The file is located here: My Documents\Add-in Express\adxloader.log. Also, you can disable the Shadow Copy feature of the Add-in Express Loader, which is enabled by default (see Deploying – Shadow Copy?). The privileges attribute accepts the "user" string indicating that the installer generated by an Add-in Express based setup project can be run with non-administrator privileges. The only user-installable IE extension type is IE Bar. All other project types require using the "administrator" string for this attribute.
When an Add-in Express based project is being built, the loader files are copied from the Loader folder of your project to the output directory of the setup project(s).
How your IE Add-on works
IE Module basics
The version of IE is available in IEVersion. IEObj provides the IE application COM object. For the currently loaded mshtml.HTMLDocument, see HTMLDocument (HTMLDocumentObj). Note that COM objects (and all classes defined in mshtml are COM classes) can't cross the process boundaries; so you need to create a method returning information provided by a COM object rather than using the COM object directly in your code.
You use Bars and Toolbars properties to get a collection of <Item> objects (ADXIEBarItem or ADXIEToolBarItem); every <Item> object provides access to an <Obj> property (BarObj or ToolBarObj), which returns an appropriate Add-in Express class type (ADXIEBar or ADXIEToolbar).
Tabbing
The IsTabbedBrowsingEnabled property of the IE module informs you whether tabbing is enabled or not. When the user opens a tab, the OnTabCreated and then OnTabActivated events are raised. At appropriate moments OnTabMoved and OnTabClosed occur. You can activate any given tab programmatically only if ADXIEModule.IsQuickTabsEnabled is true; this means that the Quick Tabs feature in IE7 and IE8 is enabled. To activate a tab, you call TabActivate; this causes OnTabChanging and OnTabChanged events to fire. In IE 6, you use the OnConnect event of the module to get to know when a window is opened and use the HTML Events component to handle the OnActivate event of the Window HTML element.
Note that all tab-related methods work asynchronously. The tab-related methods are TabActivate, TabFirst, TabLast, TabNext and TabPrevious methods that activate the current, first, last, next and previous tabs respectively. Another tab-related method is TabClose. It closes the current tab (also asynchronously).
Windowing and threading
Internet Explorer opens its windows in separate threads. Once an IE window is opened, IE creates an instance of your module, toolbar, or IE bar; the instance fires the OnConnect event; the instance fires the OnDisconnect event when the current tab (window in IE6) is closing. You can identify an instance of the IE module by the ID of the thread that opens that window. Note that ADXIEBar and ADXIEToolbar provide the Module property that you can cast to your module type. Below you will find how different Internet Explorer versions open their windows.
- IE6 opens IE windows in several threads running within several processes.
- IE7 may open several main windows in the same or in different processes if tabbing is enabled and depending on the way you open IE windows; each main window contains tab windows running in threads of their own.
- IE8 may open several main windows. Each of them runs in several threads of the same process and contains tab windows that run in threads of their own if tabbing is enabled and depending on the way you open IE windows as well on the operating system that you use.
And here are some useful properties:
- Process ID - ADXIEModule.ProcessID
- Thread ID - ADXIEModule.ThreadID
- IE main window - ADXIEModule.MainWindowHandle, ADXIEBar.MainWindowHandle, ADXIEToolbar.MainWindowHandle
- IE tab window - ADXIEModule.ParentHandle, ADXIEBar.ParentHandle, ADXIEToolbar.ParentHandle; in IE6, this property returns the same value as MainWindowHandle
- Tabbing is enabled - ADXIEModule.IsTabbedBrowsingEnabled
- IE Module - ADXIEBar.Module, ADXIEToolbar.Module
Instancing
In whatever way a tab (or window in IE 6) is opened, this creates a new instance of the add-on (ADXIEModule). This also creates new instances of toolbars, IE bars, main menu items, and context menu items; all of them work in the same thread. The only thing that works in another thread or even process (IE 8) is the commands that you add on the Command Bar toolbar (IE 7 and IE 8 only); an instance of the commands is created for every main IE window (ADXIEModule.MainWindowHandle).
So, your IE module is created for every IE tab. The total number of module instances is available in the GetModuleCount property. You can access any module instance using either GetModuleByIndex or GetModuleByThread; make sure that you supply these methods with proper values provided by GetModuleIndex and ThreadID.
You can call any public property or method of any module instance even if it runs in other process. This is implemented via Remoting. For that reason, such calls are synchronous. Mshtml-related classes cannot cross process boundaries; you need to create a method that returns the needed information instead.
'...
Public Class MyIEBar1
Inherits AddinExpress.IE.ADXIEBar
Friend WithEvents ListBox1 As System.Windows.Forms.ListBox
Friend WithEvents Button1 As System.Windows.Forms.Button
'...
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'System.Diagnostics.Debugger.Launch()
Me.ListBox1.Items.Clear()
Dim theModule As MyIEAddon1.IEModule = _
CType(Me.Module, MyIEAddon1.IEModule)
For i As Integer = 0 To theModule.GetModuleCount - 1
Dim aModule As MyIEAddon1.IEModule = _
CType(theModule.GetModuleByIndex(i), MyIEAddon1.IEModule)
Me.ListBox1.Items.Add(aModule.GetURL())
Next
End Sub
End Class
'...
Public Class IEModule
Inherits AddinExpress.IE.ADXIEModule
'...
Friend Function GetURL() As String
Return Me.HTMLDocument.url
End Function
End Class
Messaging
The SendMessage, SendMessageToInstance and SendMessageToAll methods provide an asynchronous way to invoke the functionality of the current, specified or of all instances of a module, toolbar, or Explorer bar. This is implemented by sending a custom window message to a hidden add-on, toolbar, or IE bar window via the Win32 API. For that reason SendMessageToInstance provides the nativeHandle parameter, a proper value for which is obtained using the NativeWindowHandle property (available for ADXIEModule, ADXIEBar, and ADXIEToolbar). You can also use the FindNativeWindows method provided by ADXIEModule, ADXIEBar, and ADXIEToolbar. This method allows finding hidden windows that belong to the same main window or process in IE. On the receiver side, you filter incoming messages (there will be a huge lot of non-related window messages!) and invoke the functionality required in the OnSendMessage event.
Note. You may need to use SendMessage (it sends messages to the current IE module) because some things aren't possible to do in a given event.
The code below demonstrates using SendMessageToAll to keep the same state of a checkbox through all instances of an IE bar.
Friend Class MessageConstants
'window messages
Public Shared ReadOnly WM_USER As Integer = 1024
'custom
Public Shared ReadOnly WM_CHECKED As Integer = WM_USER + 10000
Public Shared ReadOnly WM_UNCHECKED As Integer = WM_USER + 10001
End Class
'...
Public Class MyIEBar1
Inherits AddinExpress.IE.ADXIEBar
Friend WithEvents CheckBox1 As System.Windows.Forms.CheckBox
Private IsProgrammaticChange As Boolean = False
'...
Private Sub CheckBox1_CheckedChanged( _
ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles CheckBox1.CheckedChanged
'System.Diagnostics.Debugger.Launch()
If IsProgrammaticChange Then Exit Sub
'do my stuff
If Me.CheckBox1.Checked Then
Me.SendMessageToAll(MessageConstants.WM_CHECKED, _
IntPtr.Zero, IntPtr.Zero)
Else
Me.SendMessageToAll(MessageConstants.WM_UNCHECKED, _
IntPtr.Zero, IntPtr.Zero)
End If
End Sub
Private Sub MyIEBar1_OnSendMessage( _
ByVal e As AddinExpress.IE.ADXIESendMessageEventArgs) _
Handles MyBase.OnSendMessage
If e.Message = MessageConstants.WM_CHECKED Then
IsProgrammaticChange = True
Me.CheckBox1.Checked = True
IsProgrammaticChange = False
ElseIf e.Message = MessageConstants.WM_UNCHECKED Then
IsProgrammaticChange = True
Me.CheckBox1.Checked = False
IsProgrammaticChange = False
End If
End Sub
End Class
Back to Add-in Express for Internet Explorer homepage |