The Delphi Bug List

Entry No.
516
VCL - Standard - Menus - TMenuItem
If you assign an image list to a TMainMenu, and the height of your imagelist is small compared to the height of your menu text, the text gets cramped together and some of the text actually gets chopped off.
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/AN/AN/AN/AN/AExistsExistsExistsExistsExistsExistsExistsExistsExistsN/A
Description
Reported by Luu Tran; checked by Reinier Sterkenburg
D4 is not respecting the system metrics settings for menu items. It seems only to consider the height of the bitmap and not the text and proper vertical spacing between menu items.

To reproduce, create an imagelist with dimension 16x16 or so. In Windows Control panel, use Large Font display, and set menu text to MS Sans Serif 10. You will see your D4 menus with bitmaps are cramped vertically, compared to regular menus.

User-contributed comments
Luu Tran
24 Nov 2001  09:30 PM GMT
The problem is procedure TMenuItem.MeasureItem only looks at the ImageList's height when ImageList is assigned and doesn't bother with the system's setting. This is fine normally but if your menu font is bigger than the glyphs, the text gets bunched together and doesn't look right. To see what I mean, go to Control Panel and change the menu font to something large, like 16pt then look at the menus in the Delphi IDE.

Here's a VCL hack to remedy this cosmetic bug

Delphi 4, update 3

Menus.pas

procedure TMenuItem.MeasureItem(ACanvas: TCanvas; var Width, Height: Integer);

---old
  if GetParentComponent is TMainMenu then
  begin
    TopLevel := True;
    GetMenuSize;
  end


---new
  GetMenuSize;  always call getmenusize!
  if GetParentComponent is TMainMenu then
  begin
    TopLevel := True;
  end

---old
  else if Assigned(ImageList) and ((ImageIndex > -1) or not TopLevel) then
  begin
    Width := ImageList.Width;
    if not TopLevel then
      Height := ImageList.Height;
    DrawGlyph := True;
  end

---new
  else if Assigned(ImageList) and ((ImageIndex > -1) or not TopLevel) then
  begin
    Width:=ImageList.Width;
    if not TopLevel then
// use ImageList's height only if larger than system's menu height!
      if ImageList.Height>Height then Height:=ImageList.Height;
    DrawGlyph := True;
  end


Next, modify DrawItem to center the glyph vertically should it be smaller than the menuitem.

procedure TMenuItem.DrawItem(ACanvas: TCanvas; ARect: TRect; Selected: Boolean);

---old
      if ParentMenu is TMenu then
        Alignment := paLeft
      else if ParentMenu is TPopupMenu then
        Alignment := TPopupMenu(ParentMenu).Alignment
      else
        Alignment := paLeft;
      GlyphRect.Left := ARect.Left + 1;
      GlyphRect.Top := ARect.Top + //1

---new
      if ParentMenu is TMenu then
        Alignment := paLeft
      else if ParentMenu is TPopupMenu then
        Alignment := TPopupMenu(ParentMenu).Alignment
      else
        Alignment := paLeft;
      GlyphRect.Left := ARect.Left + 1;
      GlyphRect.Top := ARect.Top + 
        (Max( ImageList.Height, ARect.Bottom-ARect.Top+1) -  ImageList.Height) 
div 2;



Note: you need to add Math to the uses clause to use the Max function

CAVEATS: This SEEMS to work. I haven't done anything in the case of bitmap glyphs instead of ImageList. So far, I haven't seen any ill effect but that's always a possibility when hacking the VCL!
Latest update of this entry: 2002-04-03

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.