JD wrote:
Quote
Wiljo < XXXX@XXXXX.COM >wrote:
>[...] The check mark icons indicate if items of the
>hierarchy are visible or not.
That seems to me to be counter-intuitive because a check mark
is used to indicated selection. If you're using it to indicate
that items are not present in the menu, thats one thing but if
they are indeed there but in a submenu, that's what the menu-
arrow is for.
I guess I didn't make myself clear enough. We are developing a CAD
program, where all objects are stored in a hierarchical structure. The
item check mark in the menu indicates whether the associated object in
the OpenGL window is visible or not. To me that doesn't seem
counter-intuitive, all OpenGL drawable items will be visible in the
popup menu, and the check mark shows whether or not they are actually
visible in the window. So one can change the visibility state of a
particual item.
Quote
>To make owner drawing of items possible, I have created a
>class that just contains that OnOwnerDraw function. Then the
>address of the function can be assigned using a static
>instance of that class.
It is correct that events need to be members of a class but
why a seperate class when this will do:
void __fastcall TForm1::DrawMenuItem(TObject *Sender, TCanvas *ACanvas, const TRect &ARect, bool Selected )
{
//
}
As I wrote in my post, we don't create/call the PopupMenu from inside a
form. We create a global Popup menu and add items dynamically,
independantly of any form or class. So we can't just assign
TForm1::DrawMenuItem, because we don't have a meaningful Form object to
use for it.
The check mark was there when I dynamically add simple items withou an
ImageList. But when I create a popup menu to show the current OpenGL
visibility states of the object tree hierarchy, I added an ImageList
along with it, and the check mark icon was lost. We draw all kinds of
different things in the OpenGL window, and we want their type indicated
with a little icon from that ImageList.
Only by using a seperate CMenuOwnerDraw class and correct member
function, it is possible to owner draw every menu item with check mark,
individual icon and caption.
Quote
>[...] the chevron ">" for the submenu is not shown for the
>selected item. All other submenu items do show a chevron.
I don't see this behavior (XP). In fact, I don't even need to
draw the menu arrow because the OS draws it after I'm finished.
I also see that it is drawn, but white instead of black. And on a white
background, one doesn't see the chevron at all. I must mention that this
only occurs for the item that has focus, all other visible items are
drawn correctly. It is the focused item, that has a submenu, that
doesn't draw the chevron.
Quote
>I draw this chevron at the correct position, but nothing is
>shown. If I move the chevron image a couple of pixels to the
>left, something is shown, but the original chevron seems to
>be obscuring it in reverse colors.
You're going to have to post your code.
Okay then, here it is:
static TPopupMenu *sapPopupMenu;
static TImageList *sapStateImages;
void FC COwnerDrawMenuItem
::mOnDrawItem ( System::TObject *Sender,
Graphics::TCanvas *ApCanvas,
const Types::TRect &ArcRect,
Windows::TOwnerDrawState State
)
{
TMenuItem *pMenuItem = dynamic_cast<TMenuItem *>( Sender );
if( pMenuItem != NULL )
{
//* Now take care of drawing the item itself
if( pMenuItem->Caption == "-" )
{
int cy = ArcRect.Top + ArcRect.Height() / 2;
//* Draw the seperator
ApCanvas->Pen->Color = clDkGray;
ApCanvas->MoveTo( ArcRect.Left, cy - 2 );
ApCanvas->LineTo( ArcRect.Right, cy - 2 );
}
else
{
TRect itemRect = ArcRect;
mDrawCheckMark( &itemRect, ApCanvas, pMenuItem );
mDrawImage( &itemRect, ApCanvas, pMenuItem->ImageIndex );
//* Create a small space between the icons and the text
itemRect.Left = itemRect.Left + 4;
ApCanvas->TextOut( itemRect.Left, itemRect.Top,
pMenuItem->Caption );
//* Draw the submenu chevron.
if( State.Contains( odSelected )
&& pMenuItem->Count>0 )
{
itemRect.Left = ArcRect.Right - 16;
sapStateImages->Draw( ApCanvas, itemRect.Left,
itemRect.Top, STATE_MENU_CHEVRON, true );
///////////
//* WJ20060912: Somehow it is not drawn, or obscured
///////////
}
}
}
}
//---------------------------------------------------------------------------
void COwnerDrawMenuItem
::mDrawCheckMark ( TRect *ApRect,
TCanvas *ApCanvas,
TMenuItem *ApMenuItem
)
{
if( ApMenuItem->Count == 0 )
{
sapStateImages->Draw( ApCanvas, ApRect->Left,
ApRect->Top, ApMenuItem->Checked
? STATE_CHECKMARK_ON : STATE_CHECKMARK_OFF, true );
}
ApRect->Left = ApRect->Left + 16;
}
//---------------------------------------------------------------------------
void COwnerDrawMenuItem
::mDrawImage ( TRect *ApRect,
TCanvas *ApCanvas,
int AImageIndex
)
{
if( NULL != sapPopupMenu->Images
&& AImageIndex>= 0 )
{
sapPopupMenu->Images->Draw( ApCanvas, ApRect->Left, ApRect->Top,
AImageIndex, true );
//* ApRect->Left is updated with the width of the image
ApRect->Left = ApRect->Left + sapPopupMenu->Images->Width;
}
}
//---------------------------------------------------------------------------
void FC COwnerDrawMenuItem
::mOnMeasureItem ( System::TObject *Sender,
Graphics::TCanvas *ApCanvas,
int &Width,
int &Height
)
{
TMenuItem *pMenuItem = dynamic_cast<TMenuItem *>( Sender );
if( pMenuItem != NULL )
{
SIZE size = ApCanvas->TextExtent( pMenuItem->Caption );
Height = 19;
Width = 3 * 16 + 4 + size.cx;
//* Three icons: checkmark, custom and chevron,
//* the caption and a small space
}
}
// The sapPopupMenu is created and initialized:
bool gbCreatePopupMenu( TImageList *ApImageList )
{
sapPopupMenu = new( HERE ) TPopupMenu( NULL );
sapPopupMenu->AutoHotkeys = maManual;
if( ApImageList != NULL )
{
sapPopupMenu->Images = ApImageList;
sapPopupMenu->OwnerDraw = true;
}
return sapPopupMenu != NULL;
}
And every item is also correctly initialized.
The problem is in the mOnDrawItem function where the chevron is drawn,
but doesn't become visible for the item that has focus.
I hope someone can help me solve this problem!
thx,
Wiljo.