EvoCorp Home    Delphi::Advance

 

 

   

 

TMouseMonitorThread

Have you ever developed an ActiveX form, or for that matter any other Internet Explorer form (such as an "Explorer Bar") that contained controls that just didn't seem to interact with the mouse properly? A classic example is the use of "flat" TSpeedButtons; when the mouse is moved over a "flat" TSpeedButton on an ActiveX form the button doesn't highlight that it has focus by means of showing its border.

The reason for this is simple. In a "normal" Delphi application, the Delphi TApplication class maintains an message processing and idle loop whereby controls that do not descend from TWinControl are still able to receive and therefore react to system messages. However in an ActiveX control, the TApplication class simply isn't instantiated properly and as a result the Delphi VCL is only able to respond to a subset of messages. Here's why that is:

The Windows system identifies separate "windows" (or controls) on screen by assigning a unique window handle (HWND) to each window, enabling each each window to receive and therefore react to any messages sent by the system. In Delphi, the TWinControl class contains the mechanics required to obtain and maintain window handles and as such any control that inherits from TWinControl has the ability to respond to system messages without the use of the TApplication control.

Unfortunately overuse of window handles within your application can degrade performance across your entire system so Borland created another class, TGraphicControl, that doesn't personally require a window handle but can be used within your application as though it had one.

So what does this mean? Quite simply if your control inherits from TGraphicControl and not TWinControl (TSpeedButton is a good example) and is being used from within an ActiveX control then your control no longer has the ability to receive system generated messages, such as mouse movement. To work around this we have to either use controls that inherit from TWinControl, or develop something that can process and deliver mouse information to your TGraphicControl controls.

In developing WebCaliber, an Internet Explorer "Explorer Bar" that uses a customized set of XP-style TSpeedButtons I chose to tackle the second option, as presented later in this code :)

This code demonstrates the following:

  How to implement a thread that continually monitors mouse movement, forwarding mouse enter and exit information to non windowed controls.
  How to implement monitoring of component destruction so that controls can be destroyed without confusing the mouse monitor thread.

This class does not show how to implement the following:

  How to activate hints within your ActiveX control.

Initializing your Thread

Although the code attached to this document contains all the necessary bits and pieces required to perform mouse monitoring in your ActiveX application, it does not show you how to create the thread in the first place.

The basic premise of using this class is that you have to define a mouse monitor variable somewhere in your application and as soon as your application is visually ready create an instance of that class.

For example:

uses
  // TMouseMonitorThread is located in the file
  // AxMouseMonitor.pas

  SysUtils, Windows...., AxMouseMonitor;

type
  TMyActiveXForm = class(TActiveForm)
  private
    FMouseMonitor: TMouseMonitorThread;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;
...
constructor TMyActiveXForm.Create(AOwner: TComponent);
begin
  inherited;
  FMouseMonitor := TMouseMonitorThread.Create;
end;
...
destructor TMyActiveXForm.Destroy;
begin
  if Assigned(FMouseMonitor) then
    FreeAndNil(FMouseMonitor);
  inherited;
end;

Requirements

Any version of Delphi that enables you to create ActiveX forms or controls.

Download Code

AxMouseMonitor.pas can be downloaded here.

Microsoft Internet Explorer is a registered trademark of Microsoft Corporation.