Thursday, April 23, 2009

ActiveX modal dialogs are pushed behind Internet Explorer's browser window

It has been long since my last article but I must tell you, I have been spending my time doing some beautiful programming lately and, while I was away, Microsoft decided to put another browser out in the world.

For most programmers that have an ActiveX window embedded in a web page, showing a modal dialog from an ActiveX control in internet Explorer 7 was a challenge and here is but one of the hot discussions we had about the topic.

But.. hey, Microsoft did it again and now they're not just multithreading it away.. they're creating a process for each tab you open. We'll not discuss the good, the bad and the ugly of this idea, but your modal dialogs will pop up behind the browser window one more time, and they will stay there !

Here is how the people who know IE say you should go about determining which IE tabs goes to which Iexplore.exe process when using Internet Explorer 8 :
http://blogs.msdn.com/askie/archive/2009/03/20/how-to-i-determine-which-ie-tabs-go-to-which-iexplore-exe-process-when-using-internet-explorer-8.aspx

Now that sheds some light but how do show modal .. in my code ?

Here is an example of my solution for a bunch of ActiveXes I have developed in Delphi an I needed to make compatible with IE8 :

function FormShowModal(aForm: TCustomForm): TModalResult;
begin
try

EnableProcessWindows(MainHandle, False);
SetWindowPos(aForm.Handle, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
Result := aForm.ShowModal ;
finally
EnableProcessWindows(MainHandle, True);
end;
end;


procedure EnableProcessWindows(aHandle : HWND; disableWindow : Boolean);
var
aParentHandle : HWND;
begin
aParentHandle := GetParent(aHandle);
while (NULL <> aParentHandle) and (aParentHandle <> 0) do
begin
EnableWindow(aParentHandle, disableWindow);
aParentHandle := GetParent(aParentHandle);
end ;
end;


Where the MainHandle is the handle of the main form of your application. For an ActiveX, this is the ActiveForm's handle. I let you decide the best way to retrieve or pass that around.

I must tell you that the same solution works beautifully on IE7 and even inside a standalone executable so.. feel free to translate it into any other programming language you are using and go ahead and sell for IE8 too.

Now why did I do the SetWindowPos call ? Well if you click on the taskbar buttons, you will find that the dialog may still go behind the browser window and come back on top but I believe this is totally acceptable.

Write a comment if you found any other solution to this.
  

Thursday, April 23, 2009

ActiveX modal dialogs are pushed behind Internet Explorer's browser window

It has been long since my last article but I must tell you, I have been spending my time doing some beautiful programming lately and, while I was away, Microsoft decided to put another browser out in the world.

For most programmers that have an ActiveX window embedded in a web page, showing a modal dialog from an ActiveX control in internet Explorer 7 was a challenge and here is but one of the hot discussions we had about the topic.

But.. hey, Microsoft did it again and now they're not just multithreading it away.. they're creating a process for each tab you open. We'll not discuss the good, the bad and the ugly of this idea, but your modal dialogs will pop up behind the browser window one more time, and they will stay there !

Here is how the people who know IE say you should go about determining which IE tabs goes to which Iexplore.exe process when using Internet Explorer 8 :
http://blogs.msdn.com/askie/archive/2009/03/20/how-to-i-determine-which-ie-tabs-go-to-which-iexplore-exe-process-when-using-internet-explorer-8.aspx

Now that sheds some light but how do show modal .. in my code ?

Here is an example of my solution for a bunch of ActiveXes I have developed in Delphi an I needed to make compatible with IE8 :

function FormShowModal(aForm: TCustomForm): TModalResult;
begin
try

EnableProcessWindows(MainHandle, False);
SetWindowPos(aForm.Handle, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
Result := aForm.ShowModal ;
finally
EnableProcessWindows(MainHandle, True);
end;
end;


procedure EnableProcessWindows(aHandle : HWND; disableWindow : Boolean);
var
aParentHandle : HWND;
begin
aParentHandle := GetParent(aHandle);
while (NULL <> aParentHandle) and (aParentHandle <> 0) do
begin
EnableWindow(aParentHandle, disableWindow);
aParentHandle := GetParent(aParentHandle);
end ;
end;


Where the MainHandle is the handle of the main form of your application. For an ActiveX, this is the ActiveForm's handle. I let you decide the best way to retrieve or pass that around.

I must tell you that the same solution works beautifully on IE7 and even inside a standalone executable so.. feel free to translate it into any other programming language you are using and go ahead and sell for IE8 too.

Now why did I do the SetWindowPos call ? Well if you click on the taskbar buttons, you will find that the dialog may still go behind the browser window and come back on top but I believe this is totally acceptable.

Write a comment if you found any other solution to this.