0

I have run into an issue a couple of weeks ago that appear to have no logical explanation. I'm building an application with Delphi 2007 using AlphaControls and a WebBrowser component placed on a form. The TWebBrowser fetches a banner from the web and displays it into the UI. bad thing is that as soon as the form with the banner is displayed, I get the "Could not obtain OLE Control window handle", while the browser is being displayed outside of the form, in the top left corner of the desktop.

I've been trying basically anything to figure it out, but the debugger does not provide too much information about what's going on (that's all I get: First chance exception at $770C4B32. Exception class EOleError with message 'Could not obtain OLE control window handle'. Process project1.exe (3700)). Funny thing is that the same TWebBrowser on Form1 of a new project works without any issues.

Any thoughts on that would be highly appreciated.

Sertac Akyuz
  • 54,131
  • 4
  • 102
  • 169
Bogdan Botezatu
  • 579
  • 1
  • 9
  • 25

2 Answers2

0

It is caused by the html form being closed. The vendor's forums show some code that will fix the problem. http://www.bsalsa.com/forum/showthread.php?t=255

Set Cancel to True in the OnWindowClosing event and navigate to an empty page if it is the main webbrowser. In case your webbrowser is a popup window, you may want to close the form the EWB is on.

procedure TForm2.EmbeddedWB1WindowClosing(ASender: TObject; IsChildWindow: WordBool; var Cancel: WordBool);
begin
  Cancel := True;
  (ASender as TEmbeddedWB).GoAboutBlank;
end;
David Moorhouse
  • 1,573
  • 3
  • 14
  • 19
0

TWebBrowser is still being focused as ActiveControl and TOleControl.HookControlWndProc is being called on a ActiveControl which is no longer in the memory. As a result EOleError exception is raised because the window handle cannot be obtained. You can avoid this by setting ActiveControl to nil (changing the active control focus) prior to shutting down the application.

 ActiveControl := nil;

This is the function which causes the exception (OleCtrls.pas):

procedure TOleControl.HookControlWndProc;
var
  WndHandle: HWnd;
begin
  if (FOleInPlaceObject <> nil) and (WindowHandle = 0) then
  begin
    WndHandle := 0;
    FOleInPlaceObject.GetWindow(WndHandle);
    
    // Exception is raised here because WndHandle could not be obtained
    if WndHandle = 0 then raise EOleError.CreateRes(@SNoWindowHandle);

    WindowHandle := WndHandle;
    DefWndProc := Pointer(GetWindowLong(WindowHandle, GWL_WNDPROC));
    CreationControl := Self;
    SetWindowLong(WindowHandle, GWL_WNDPROC, Longint(@InitWndProc));
    SendMessage(WindowHandle, WM_NULL, 0, 0);
  end;
end;

Another way is to trap WM_PARENTNOTIFY message with the parameter WM_DESTROY when the destroy message is being sent to TWebBrowser handle because the parent form (where TWebBrowser is nested in) gets a WM_PARENTNOTIFY message:

procedure ParentNotify(var Msg: TMessage); message WM_PARENTNOTIFY;

implementation of message handler:

procedure TMyForm.ParentNotify(Var Msg: TMessage);
begin
if (Msg.WParamLo = WM_DESTROY) and (Msg.LParam = mywebbrowser.Handle) then close;
end; 
Coder12345
  • 3,431
  • 3
  • 33
  • 73