The Delphi Bug List

Entry No.
624
VCL - Win32 - ComCtrls - TStatusBar
Items from menus are drawn on top of owner-drawn status panels.
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 4.03 5.0 5.01 6.0 6.01 6.02 Kylix 1.0
N/AAbsentAbsentAbsentAbsentExistsExistsExistsExistsExistsExistsExistsUnknownUnknownN/A
Description
Reported by Andrei Lobanov; checked by Jordan Russell
There is a bug in the Forms.pas unit (Delphi 5 with update pack 1)

This can be tested with the following:

  • Create a new application, create main menu and add some menu items.
  • Insert TStatusBar and create in this status bar two or more panels and set TStatusBar.SimplePanel := False.
  • Select some of status bar panels and set for each of these status panels Style := psOwnerDraw.
  • Run this application and you will be surprised to see the main menu items drawn in the status bar panels (starting from Panels[1]).

This can be reproduced only under Windows NT 4.0. Same application running on a Windows 98 machine do not expose such behaviour.

This seems to be a TStatusBar bug, but actually this bug is coming from incorrect message handling in Forms.pas:

procedure TCustomForm.WndProc(var Message: TMessage);
...
      WM_DRAWITEM:
        with PDrawItemStruct(Message.LParam)^ do
          if (CtlType = ODT_MENU) and Assigned(Menu) then
          begin
            { here is main menu drawing }
          end;
Solution / workaround
The correct way for message handling is:
      WM_DRAWITEM:
        if Message.WParam = 0 then
        with PDrawItemStruct(Message.LParam)^ do
          if (CtlType = ODT_MENU) and Assigned(Menu) then
          begin
            { here is main menu drawing }
          end;

But for this solution forms.pas must be modified.

The workaround itself:
When implementing owner-drawn status panels the following code can be used in form unit containing custom-drawn status bar:

TForm1=class(TForm)
 ...
  protected
    procedure WndProc(var Message: TMessage); override;
 ...

procedure TForm1.WndProc(var Message: TMessage);
begin
  if (Message.Msg = wm_DrawItem) and
     (Message.WParam <> 0) and
     (Message.LParam <> 0) then
    with PDrawItemStruct(Message.LParam)^ do
      if (CtlType = ODT_MENU) then
     CtlType := 0;
  inherited;
end;

Parameter CtlType is not used when Windows notifies with WM_DRAWITEM for status panels, but under WinNT4.0 this parameter is equal to ODT_MENU (1) and menu item is drawn inside of status panel rectangle.

Note from checker:
On my NT 4.0 (SP6) system, WParam was 0, not ODT_MENU. I suppose the version of COMCTL32.DLL probably determines whether this bug appears.

User-contributed comments
Jeff Laing
03 Jul 2001  11:04 PM GMT
Very quick fix - put the status bar on a Panel not directly on the form. I reported this to Borland last February (2000)
jeff
Latest update of this entry: 2001-07-04

Post a comment on this bug


Index page
Delphi Bug List home page
The Delphi Bug Lists are presently maintained by Jordan Russell, who has taken over this task from Reinier Sterkenburg since August 2000.
All feedback is appreciated. See also the feedback section of the Delphi Bug List home page.