Eugene Astafiev

How to program IE add-on, toolbar / bar, menu in C#, VB.NET, C++

When I started developing IE add-ons I found out that Internet Explorer might generate a huge number of threads and processes and that my add-on is created in each of those threads. However, my plug-in contains data that should be accessible for all instances of the IE add-on. In this post, I will tell you how to make communication between IE add-on instances easy using Add-in Express for Internet Explorer.

Let’s run Internet Explorer version 6 or 7. Now run Windows Task Manager and go to the Processes tab, find the IE process. You see that you have one running process of Internet Explorer. Run a new instance of Internet Explorer using a shortcut or typing “explore” in the Run menu of the Start button. And have a look at Task Manager again. Now you see that you have two different IE processes running on your machine. In other words, you have two windows of Internet Explorer in different processes.

Close either of the IE windows and press Ctrl+N in the other. Check up Task Manager again. Now you see that you have one running IE process. But you have two IE windows. Interesting, isn’t it? The point is that you opened a new frame of Internet Explorer, but not a new instance. IE 7 behaves in the same manner. Let’s make sure. Click on the New Tab button to create a new tab or use the Ctrl+T shortcut. Check Task Manager for IE processes. You see that you still have one IE process. Naturally, each tab and window is created in a separate thread of execution. What is more, a new instance of your IE add-on is created for every such tab.

With Add-in Express you have a few ways to communicate with various add-on instances.

Communicating with IE add-ons in the same process

In Add-in Express, an IE module corresponds to the Internet Explorer add-on. That is, to access another instance or instances of the add-on, you need to find the corresponding IE modules. Then you can access the page and browser window (frame) using the appropriate properties of the module.

Every IE thread has its own ID Thread ID (see the ThreadId property of the module). Using the thread ID you can easily get the module instance of your IE plug-in. Having the module object you can do various things on your own. Consider the following code in the class definition of the module:

int threadId = this.ThreadID;
AddinExpress.IE.ADXIEModule module = this.GetModuleByThread(threadId);

You can also get the module by index in the collection:

int threadId = this.GetModuleIndex();
AddinExpress.IE.ADXIEModule module = this.GetModuleByIndex(threadId);

Please note that using the thread id you can avoid the non-existing index error. For example, you’ve closed a tab and are trying to get the module by index which you saved earlier. You will have an exception, because there isn’t such an index in the collection.

To get the module, you can also use the CurrentInstance property that returns a System.Collections.SortedList collection:

System.Collections.SortedList listOfModules=
AddinExpress.IE.ADXIEModule.CurrentInstance;

The key in the collection is a thread ID of the add-on. But this collection is not thread-safe, so you’d better use GetModuleByThread and GetModuleByIndex.

Communicating with IE add-ons in different processes

In this case, you can’t get a module using GetModuleByThread and GetModuleByIndex, because the modules you need to access are located in another process. But you can use windows messages to communicate between processes. Fortunately, the IE the module contains methods for this task. First, you need to specify message Id constants that identify your messages. For example, consider the following code:

// declare the following constants at the module level
private static int WM_USER = 0x0400;
private static int WM_EXAMPLE = WM_USER+1000;
...
// add an event handler to the OnSendMessage event
private void IEModule_OnSendMessage(AddinExpress.IE.ADXIESendMessageEventArgs e)
      {
         if (e.Message == WM_EXAMPLE)
         {
            System.Windows.Forms.MessageBox.Show(this.ThreadID.ToString());
         }
      }

When you call one of the SendMessage methods provided by the IE module, the method generates a windows message and puts it to the message queue of the corresponding window. When OS permits, the message will be processed and the IE module will generate the OnSendMessage event. The code above produces a message box for each IE module that is run on the PC.

There are some forms of SendMessage methods:

 -  public void SendMessage(int message, IntPtr wParam, IntPtr lParam);

It sends a custom message to the internal window of Internet Explorer. When the message is received, the Add-in Module raises the OnSendMessage event.

 -  public void SendMessageToAll(int message, IntPtr wParam, IntPtr lParam);

It sends a custom message to the all windows of Internet Explorer. When the message is received, the Add-in Module raises the OnSendMessage event.

 -  public void SendMessageToInstance(IntPtr nativeHandle, int message, IntPtr wParam, IntPtr lParam);

Sends a custom message to the specified window of IE. When the message is received, the Add-in Module raises the OnSendMessage event.

Which of the above methods to use? It depends. When I was programming the Advanced Search for Internet Explorer plug-in I had to report to other add-on instances that the current instance (the current thread of execution, which may be a tab or a window) was closing in order to update the Search Results tree. The solution is to use the SendMessageToAll method and the OnSendMessage event handler. It is a non-trivial event for IE add-ons, to trigger which you need to call one of the functions specified above. To handle this event you just need to monitor the id of the message in the OnSendMessage event handler of the add-on module.

Tips on how to program IE plug-ins

To show a tab. Sometimes you need to activate a tab in an IE window. For example, in the Advanced Search add-on, when you press on the tree node to highlight the found element, you are taken to the tab that the element belongs to. In this case, the add-in finds the module of the tab that should be activated, and calls the TabActivate method that activates the tab.

To show an IE toolbar programmatically. Let’s assume that you added a toolbar item to the IE add-on project and named it œMyIEToolBar1 .The following code shows / hides the toolbar. In particular, you can use such code, for example, in the event handler of your custom keyboard shortcut.

     // getting the add-on module by thread ID
     IEModule module = AddinExpress.IE.ADXIEModule.CurrentInstance[this.ThreadID] as IEModule;
            if (module != null)
            {
		 // getting the toolbar type
                Type t = typeof(MyIEToolBar1);
                int index = module.ToolBars.IndexOf(t.FullName);
                if (index >= 0)
                {
		     // getting an instace of the toolbar by index
                    AddinExpress.IE.ADXIEToolBarItem item = module.ToolBars[index];
                    object g = t.GUID.ToString("B");
                    object dummy = null;
                    if (item.ToolBarObj == null)
                    {				
                        object bShow = true;
		         // showing the IE toolbar
                        IEApp.ShowBrowserBar(ref g, ref bShow, ref dummy);
                    }
                    else
                    {
                        MyIEToolBar1 dm = item.ToolBarObj as MyIEToolBar1;
                        if (dm != null)
                        {
                            if (!dm.Visible)
                            {
                                object bShow = true;
				  // showing the IE toolbar
                                IEApp.ShowBrowserBar(ref g, ref bShow, ref dummy);
                            }
                            else
                            {
                                object bShow = false;
			          // hiding the IE toolbar
                                IEApp.ShowBrowserBar(ref g, ref bShow, ref dummy);
                            }
                        }
                    }
                }
     }

It’s easy to change the code above in order to show / hide an IE bar: you just need to replace the types of the module and toolbar / bar with those that you have in your add-on. Also use the Bars collection instead of Toolbars.

All the sources above belong to the Advanced Search for Internet Explorer (you can download it here) and to other samples distributed with Add-in Express for Internet Explorer.

Eugene Astafiev
Add-in Express Team

5 Comments

Post a comment

Have any questions? Ask us right now!