Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

MenuItems appear in OwnerDraw-Panels of StatusBar

71 views
Skip to first unread message

Simon Stelling

unread,
Jan 16, 2001, 12:01:10 PM1/16/01
to
Hello,

Do you have a TForm containing a TStatusBar and a TMenu?
And are there any psOwnerDraw-Panels in your TStatusBar?
Do you experience strange display bugs? Yes?


I took the following facts from a posting of Jan Sprengers
(from the newsgroup borland.public.delphi.ide,
subject was "Re: Menu and Owner draw statusbar",
dated 9-jan-2001),
and ported them from Delphi to Borland C++ Builder/VCL.


Problem description:
Owner-drawn TStatusBar panels sometimes display the text of a menu item
of the same form.


Cause:
The owner-drawn TStatusBar triggers a WM_DRAWITEM message on the parent
window. This message is also caught by the TCustomForm.WndProc procedure
to allow for owner-drawn menus. Here is part of the relevant VCL code:
...
WM_DRAWITEM:
with PDrawItemStruct(Message.LParam)^ do
if (CtlType = ODT_MENU) and Assigned(Menu) then
...

The problem is that the CtlType field of the DRAWITEMSTRUCT contains
random information when triggered for the TStatusBar, which sometimes -
this depends on the application's memory usage - happens to be the
ODT_MENU value.

CtlType doesn't appear to have a specific value for a status window.
This looks like a Windows bug, but it is actually documented in the
Win32.HLP (search key: "Owner-Drawn Status Windows"):

"When a status window needs to draw an owner-drawn part, it sends the
WM_DRAWITEM message to the parent window. The wParam parameter of the
message is the child window identifier of the status window, and the
lParam parameter is a pointer to a DRAWITEMSTRUCT structure. The parent
window uses the information in the structure to draw the part. For an
owner-drawn part of a status window, DRAWITEMSTRUCT contains the
following information.

Member Description
CtlType Undefined; do not use.
CtlID Child-window identifier of the status window.
itemID Zero-based index of the part to be drawn.
itemAction Undefined; do not use.
itemState Undefined; do not use.
hwndItem Handle to the status window.
hDC Handle to the device context of the status window.
rcItem Coordinates of the window part to be drawn. The coordinates are
relative to the upper left corner of the status window.
itemData Application-defined 32-bit value specified in the
lParam parameter of the SB_SETTEXT message."


Work-around:

Override the WndProc method on the form that contains both a TMenu and a
TStatusBar and add this code:

void __fastcall TMyForm::WndProc(Messages::TMessage &Message)
{

if (Message.Msg == WM_DRAWITEM)
{
HWND hwndStatusBar = MyStatusBar->Handle;
if (hwndStatusBar == (HWND) Message.WParam)
{
DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *) Message.LParam;
if (dis->CtlType == ODT_MENU)
{
dis->CtlType = ODT_STATIC;
}
}
}
TForm::WndProc (Message);
}


I was glad when I found this work-around. Many thanks, Jan!

Simon Stelling

--
Simon Stelling mailto:simon.s...@sdm.de
sd&m AG http://www.sdm.de
software design & management
Thomas-Dehler-Str. 27, 81737 Muenchen, Germany
Tel +49 89 63812-558, Fax -220

jcmont...@gmail.com

unread,
Jun 15, 2014, 12:18:58 PM6/15/14
to
Thanks Simon,
I convert an old application from Codegear 2007 to XE6 and this bug is still alive !... So, I reintroduce your code in my program and it works fine. Thanks again.

Jean-Claude

0 new messages