delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
497 Users Online NOW
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi



Loremo - the 1.5 liter car coming in 2009




Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (32)


Give your menu Office XP styleComponent available for this articleFormat this article printer-friendly!Bookmark function is only available for registered users!
Or your own style
Product:
Delphi 5.x (or higher)
Category:
GUI
Skill Level:
Scoring:
Last Update:
06/21/2001
Search Keys:
delphi delphi3000 article borland vcl code-snippet menu GUI Graphics
Times Scored:
16
Visits:
20399
Uploader: Khaled Shagrouni
Company:
Reference: www.shagrouni.com
Component Download: http://www.shagrouni.com/download/ccmenu.zip
 
Question/Problem/Abstract:
How to simulate Office XP menu look and feel
Answer:



This code simulate Office XP menu look and feel, without loosing any of the menu standard functionality, RightToLeft has been taking in account in the code.

You can alter the code to give your own colors and fonts.

Note: Make sure that OnerRedraw and ParentBidiMode properties of the menu are true.

The following code is a complete form unit, with a MainMenu and ImageList.

You can download/see the example project from: http://www.shagrouni.com/english/software/menu.html

(New: XP Menu is a component now). To download:
http://www.shagrouni.com/english/software/xpmenu.html

=================
unit fMenu;

interface

uses
  Windows, SysUtils, Classes, Graphics, Controls, Forms, Menus, ImgList;

type
  TForm1 = class(TForm)
    ImageList1: TImageList;
    MainMenu1: TMainMenu;
    FileMenu: TMenuItem;
    procedure DrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
      Selected: Boolean);
    procedure FormCreate(Sender: TObject);
  private
    procedure MenueDrawItemX(xMenu: TMenu);
  public
  end;
procedure MenueDrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
  Selected: Boolean);

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  MenueDrawItemX(Menu);
end;

procedure TForm1.DrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
  Selected: Boolean);
begin
  MenueDrawItem(Sender, ACanvas, ARect, Selected);
end;

procedure TForm1.MenueDrawItemX(xMenu: TMenu);
var
  i: integer;
  B: TBitmap;
  FMenuItem: TMenuItem;
begin
  B := TBitmap.Create;
  B.Width := 1;
  B.Height := 1;

  for i := 0 to ComponentCount - 1 do
    if Components[i] is TMenuItem then
      begin
        FMenuItem := TMenuItem(Components[i]);
        FMenuItem.OnDrawItem := DrawItem;
        if (FMenuItem.ImageIndex = -1) and
           (FMenuItem.Bitmap.width = 0) and (xMenu <> nil) then
          if FMenuItem.GetParentComponent.Name <> xMenu.Name then
            FMenuItem.Bitmap.Assign(b);
      end;

  B.Free;
  DrawMenuBar(handle);


end;


procedure MenueDrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
  Selected: Boolean);
var
  txt: string;
  B: TBitmap;

  IConRect, TextRect: TRect;
  FBackColor, FIconBackColor, FSelectedBkColor, FFontColor, FSelectedFontColor,
    FDisabledFontColor, FSeparatorColor, FCheckedColor: TColor;

  i, X1, X2: integer;
  TextFormat: integer;
  HasImgLstBitmap: boolean;
  FMenuItem: TMenuItem;
  FMenu: TMenu;

begin
  FMenuItem := TMenuItem(Sender);
  FMenu := FMenuItem.Parent.GetParentMenu;

  FBackColor := $00E1E1E1;
  FIconBackColor := $00D1D1D1;
  FSelectedBkColor := $00DCCFC7;

  FFontColor := clBlack;
  FSelectedFontColor := clNavy;
  FDisabledFontColor := clGray;
  FSeparatorColor := $00D1D1D1;
  FCheckedColor := clGray;

  if FMenu.IsRightToLeft then
    begin
      X1 := ARect.Right - 20;
      X2 := ARect.Right;
    end
  else
    begin
      X1 := ARect.Left;
      X2 := ARect.Left + 20;
    end;
  IConRect := Rect(X1, ARect.Top, X2, ARect.Bottom);

  TextRect := ARect;
  txt := ' ' + FMenuItem.Caption;

  B := TBitmap.Create;

  B.Transparent := True;
  B.TransparentMode := tmAuto;

  HasImgLstBitmap := false;
  if (FMenuItem.Parent.GetParentMenu.Images <>  nil) or
     (FMenuItem.Parent.SubMenuImages <> nil) then
    begin
      if FMenuItem.ImageIndex <> -1 then
        HasImgLstBitmap := true
      else
        HasImgLstBitmap := false;
    end;

  if HasImgLstBitmap then
    begin
      if FMenuItem.Parent.SubMenuImages <> nil then
        FMenuItem.Parent.SubMenuImages.GetBitmap(FMenuItem.ImageIndex, B)
      else
        FMenuItem.Parent.GetParentMenu.Images.GetBitmap(FMenuItem.ImageIndex, B)
    end
  else
    if FMenuItem.Bitmap.Width > 0 then
      B.Assign(TBitmap(FMenuItem.Bitmap));

  if FMenu.IsRightToLeft then
    begin
      X1 := ARect.Left;
      X2 := ARect.Right - 20;
    end
  else
    begin
      X1 := ARect.Left + 20;
      X2 := ARect.Right;
    end;
  TextRect := Rect(X1, ARect.Top, X2, ARect.Bottom);

  ACanvas.brush.color := FBackColor;
  ACanvas.FillRect(TextRect);

  if FMenu is TMainMenu then
    for i := 0 to FMenuItem.GetParentMenu.Items.Count - 1 do
      if FMenuItem.GetParentMenu.Items[i] = FMenuItem then
        begin
          ACanvas.brush.color := FIConBackColor;
          ACanvas.FillRect(ARect);
          if (FMenuItem.ImageIndex = -1) and (FMenuItem.Bitmap.width = 0) then
            begin
              TextRect := ARect;
              break;
            end;
        end;

  ACanvas.brush.color := FIconBackColor;
  ACanvas.FillRect(IconRect);

  if FMenuItem.Enabled then
    ACanvas.Font.Color := FFontColor
  else
    ACanvas.Font.Color := FDisabledFontColor;

  if Selected then
    begin
      ACanvas.brush.Style := bsSolid;
      ACanvas.brush.color := FSelectedBkColor;
      ACanvas.FillRect(TextRect);

      ACanvas.Pen.color := FSelectedFontColor;

      ACanvas.Brush.Style := bsClear;
      ACanvas.RoundRect(TextRect.Left, TextRect.top, TextRect.Right,
                        TextRect.Bottom, 6, 6);

      if FMenuItem.Enabled then
        ACanvas.Font.Color := FSelectedFontColor;
    end;

  X1 := IConRect.Left + 2;
  if B <> nil then
    ACanvas.Draw(X1, IConRect.top + 1, B);

  if FMenuItem.Checked then
    begin
      ACanvas.Pen.color := FCheckedColor;
      ACanvas.Brush.Style := bsClear;
      ACanvas.RoundRect(IconRect.Left, IconRect.top, IconRect.Right,
                        IconRect.Bottom, 3, 3);
    end;

  if not FMenuItem.IsLine then
    begin
      SetBkMode(ACanvas.Handle, TRANSPARENT);

      ACanvas.Font.Name := 'Tahoma';
      if FMenu.IsRightToLeft then
        ACanvas.Font.Charset := ARABIC_CHARSET;

      if FMenu.IsRightToLeft then
        TextFormat := DT_RIGHT + DT_RTLREADING
      else
        TextFormat := 0;


      if FMenuItem.Default then
        begin
          Inc(TextRect.Left, 1);
          Inc(TextRect.Right, 1);
          Inc(TextRect.Top, 1);
          ACanvas.Font.color := clGray;
          DrawtextEx(ACanvas.Handle,
                     PChar(txt),
                     Length(txt),
                     TextRect, TextFormat, nil);

          Dec(TextRect.Left, 1);
          Dec(TextRect.Right, 1);
          Dec(TextRect.Top, 1);

          ACanvas.Font.color := FFontColor;
        end;

      DrawtextEx(ACanvas.Handle,
                 PChar(txt),
                 Length(txt),
                 TextRect, TextFormat, nil);

      txt := ShortCutToText(FMenuItem.ShortCut) +  ' ';

      if FMenu.IsRightToLeft then
        TextFormat := DT_LEFT
      else
        TextFormat := DT_RIGHT;

      DrawtextEx(ACanvas.Handle,
                 PChar(txt),
                 Length(txt),
                 TextRect, TextFormat, nil);
    end
  else
    begin
      ACanvas.Pen.Color := FSeparatorColor;
      ACanvas.MoveTo(ARect.Left + 10,
                     TextRect.Top +
                     Round((TextRect.Bottom - TextRect.Top) / 2));
      ACanvas.LineTo(ARect.Right - 2,
                     TextRect.Top +
                     Round((TextRect.Bottom - TextRect.Top) / 2))
    end;


  B.free;


end;

end.





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
TDBNavigator and XPMenu
    Hartmut Schlichter (Sep 3 2004 12:14PM)

I compiled XPMenu with C++Builder 4.
It works fine except with a TDBNavigator component.

Place a TDBNavigator component on your form and activate XPMenu by code. Up to now it works. Now deactivate the TDBNavigator component. The TDBNavigator component is now invisible and an exception is raised.

Respond

RE: TDBNavigator and XPMenu
mahdi lotfizade (Feb 7 2005 9:23AM)

Thank you from your components
Respond

File not found: 'System.pas'
    why (May 15 2004 1:28PM)

Compile XpMenu.pas In C++Builder6.0,and this Message.Why?
[Pascal Fatal Error] pasall.tmp(1): File not found: 'System.pas'

Taiji02
From China

Respond

RE: File not found: 'System.pas'
Andrea (Feb 25 2005 6:45PM)

A mi me paso lo mismo despues de instalar una libreria para manejar pdf.

Para solucionarlo reinstale el delphi, sobre el que tenia.

Al reinstalar me respeto todas las librerias ya instaladas y se soluciono el tema.

Suerte :)

Andrea
Respond

C++ Builder
    eL (Jan 22 2004 10:49AM)

Hello its great, but how implement it to C++ Builder 6.0????
Respond

RE: C++ Builder
sdvf xvbb (Feb 2 2008 5:03PM)

scrubs
Respond

ÈçºÎʹ²Ëµ¥ÓÐXPЧ¹û
    anonymus (Jun 12 2003 9:05AM)

ÎÒʹÓÃÄãÃǵÄXPmenuΪʲô±ðµÄ¿ÉÒÔÓ¦Ó㬶ø²Ëµ¥ÐУ¿
Äܸø³öÒ»¸öÀý×Ó¡£
Respond

RE: ÈçºÎʹ²Ëµ¥ÓÐXPЧ¹û
AndyYau (Feb 29 2004 2:45AM)

ÎÒÒ²ÏëÖªµÀ°¢£¬ÄãÖªµÀÁËÂð£¿Èç¹ûÄãÖªµÀ£¬ÇëÄãÒ²¸æËßÎÒ°Ñ
Respond

Recommend to mend the partial code of XPMenu
    Benjamin wang (Oct 18 2002 8:34AM)

I found that there were many bugs in some fields of XPMenu Component Code, for example:
   B := TBitmap.Create;
   ....
   ....
   B.Free;
and so on.
So I recommend to change the above code into the below:
  B := nil;
  B := TBitmap.Create;
  try
     .....;
     .....;
  finally
     B.Free;
  end;

This step can protect the bitmap object from the crash.
Respond

My MainMenu can not display properly
    Benjamin wang (Oct 16 2002 9:54AM)

Out of question, XPMenu is really an excellent component, even if which
is the best, it still contain some bugs not found.
In my projection, I found a bug!
when I drop a xpmenu component into my form which has contained a
MainMenu on which the property of OwnerDraw set to be True and also
I have set the property of active switch True in the xpmenu. At that time,
what funny happens, In Design Component State xpmenu has become
my MainMenu' style into Office XP' style , But in running state, I found
the style of my MainMenu were not be changed a bit!!!
I referenced the example of xpmenu supported by the website and not found any differencs between its and mine, could you give me a hand or
a reasonable interpretation. Thank you very much.

Benjamin wang
in China
Respond

Flatmenu when selected only
    Elizalde Baguinon (Jul 24 2002 10:19AM)

I have set the component to Flatmenu=True...

...but I only get a flat menu (not the top menu) when I selected them and
also when I transfer from a topmenu to another top menu....

How do we remedy this?

Respond

Why I can't comment?
    Tony Guo (May 20 2002 3:52PM)

Why?Why?Why?Why?Why?Why?Why?Why?Why?
Respond

My modification based on version 2.1
    Tony Guo (May 20 2002 3:47PM)

First of all,i regard XPMenu as an excellent component.I makes my program look very nice.But I found some bugs and I have fixed them based on version 2.1.The bugs are list as followings.
a) Memory leak,when I used memory leak checker along with the project,the dectecter told me that memory leak in XPMenu unit(Instance of TControlSubClass),This didn't happen very often,but always with some of my form.So I add a container (TList) in TXPMenu to contain all the instances of TControlSubClass,when the instances of TControlSubClass 's Destroy method was called,I removed itself from the container.And when the XPMenu's Destroy called,I emptied the container.
b) in TControlSubClass.ControlSubClass,the original source code use try ... except .. end ,structure.This will eat the exception raised in WindowProc,If my project use exception to quit a transaction and use application.OnException to handle the exception,the exception will never catched,so i revise the source code to try .. finally .. end structure.
c) When i create a form dynamically and show it later , i saw some of the Edit box disappear and when I hide - show the form , it appeared.So I used a trick to fix this problem.Maybe this only hapen to me. ^_^

Respond

menu disappears
    anthony roy (Jan 7 2002 7:05PM)

This xp menu system is excellent, but we have a small problem on one of our apps.  When we change the menu from menu1 to menu2 a different set of menu's the xpmenu no longer works.  We have tried setting xpmenu active to false ect

delphi5 update 2

14/12/2001
XPMenu for Delphi
Author: Khaled Shagrouni
URL: http://www.shagrouni.com
e-mail: shagrouni@hotmail.com
Version 2.0, Dec 14, 2001

thanks in advance
Respond

XPMenu works in Delphi 6, Confirmed
    M R (Aug 29 2001 6:52AM)

I downloaded, and installed XPMenu and it works great in Delphi 6. I can only comment on two minor discrepancies, as following:

[1] The checked property on a TMenuItem shows a check but           modifications to the Checked property do not hide the check-mark when XPMenu is enabled.

[2] Tests on another computer of a compiled Delphi 6 .exe noted that the menu encountered serious graphical errors. I have not yet localized the cause though, it could be that person's computer.

Otherwise great job, and to anyone else who uses Delphi 6 or maybe 5, give it whirl.
Respond

xpmenu
    Blue Devil (Jun 22 2001 12:24PM)

it is possible to use xpmenu with
delphi 4 ???
Respond

RE: xpmenu
Khaled Shagrouni (Jun 22 2001 4:50PM)

I am going to update the component to work with Delphi 4. Please check my pags later.
Khaled
Respond

XP Menu Component
    Khaled Shagrouni (Jun 19 2001 10:05PM)

XPMenu now is a component. Please check:
http://www.shagrouni.com/english/software/xpmenu.html
Respond

One Question
    Rick Dement (Jun 14 2001 4:05PM)

First of all this is awesome...
I just was wondering if there is a way to get the remaining right portion of the menu, past the menu items, to be a different color.
Respond

problem with texts in popupmenu
    Login (May 29 2001 5:30PM)

Hi, i want to code a program that create a menu dynamically, and why not :) with Office XP menu style.
I have a problem, texts arent showed normally, example : Item1 (is the caption of an item), is displayed Ite1 (humm, itsnt the true)
well, ive put here the code (excluding the procs that create the office xp menu), and an url to download the program himself compiled

procedure TForm1.FormCreate(Sender: TObject);
var
  i, j: integer; //loop vars
  NewItem: TMenuItem; //the first level item
  NewSub: TMenuItem; //the second level item
  IniFile: TIniFile; //the ini file that store everythings
  List: TStringList; //the string list that will store sublevels items name
  PopupMenu1: TPopupMenu; //the popupmenu
begin
  PopupMenu1 := TPopupMenu.Create(self);
  Form1.PopupMenu := PopupMenu1;
  PopupMenu1.r
    PopupMenu1.OwnerDraw := True;
//PopupMenu1.UseRightToLeftAlignment := True;
  IniFile := TIniFile.Create('popup.ini');
  List := TStringList.Create;
  IniFile.ReadSection('Sections', Sections.Items);
  for i := 0 to Sections.Items.Count - 1 do
  begin
    NewItem := TMenuItem.Create(PopupMenu1); //cré l'item
    NewItem.Caption := Sections.Items[i]; //lit le titre du nouvel item ds le listbox
    NewItem.OnDrawItem := Form1.DrawItem;
    PopupMenu1.Items.Add(NewItem); //ajoute le nouveau item ds le popupmenu
    IniFile.ReadSection(Sections.Items[i], list); //lit le contenu de la section portant le
              //nom de l'item
    for j := 0 to list.count - 1 do
    begin
      NewSub := TMenuItem.Create(NewItem);
      NewSub.Caption := List.Strings[i];
      NewSub.OnDrawItem := Form1.DrawItem;
      NewItem.Add(NewSub);
    end;
  end;
end;
here is the url : http://logisofts.multimania.com/popup.exe
thanks for all!!
Respond

RE: problem with texts in popupmenu
Khaled Shagrouni (May 31 2001 3:12PM)

You have to assign a dummy bitmap to each item
NewItem.Bitmap.Assign(b);
      
Respond

Impressive
    Patrick Robinson (May 25 2001 3:13AM)

Thanks I was wondering how I was going to get that right.
Tight code I can learn from too.
Respond

Error found
    Wim te Groen (May 10 2001 4:13AM)

First i wanna say it is beautifull! :)
But.....
If you place a TreeView with allign to client then the 'always-vibile-menuitems' ( file, edit, language, help etc. ) are not in the Xp style, but the subitems are good.Can you fix that?
Tnx :)
And again, it looks very great!
Respond

RE: Error found
Khaled Shagrouni (May 11 2001 3:34PM)

Please make sure that OnerRedraw of the Main menu is true.
Respond

RE: RE: Error found
Wim te Groen (May 12 2001 12:26PM)

Okido! :)
Its ok now
Thnx a lot!
Respond

RE: RE: Error found
dsfkgfds (Mar 30 2005 1:11AM)

zdsflkgj hello out there where is everyone
Respond

Nice Article
    Ashraf Fathy (May 9 2001 3:09AM)

Thank You Ya Khaled .. Hope to see more out of your basket
Respond

Great
    Patrick van Dissel (May 9 2001 2:51AM)

Thanks, I love the Office XP style :D
Too bad that Borland didn't implentated it into Delphi 6 :(
Respond

RE: Great
Markus Klingseisen (May 10 2001 4:22AM)

Don't worry. Even Microsoft didn't include it in VS.NET ,-)
Respond

RE: RE: Great
Benjamin wang (Oct 16 2002 9:30AM)

Never mind, what we us need is XPMenu, isn't it? that's enough.:)
Respond

Wrong URL.
    Christian Cristofori (May 9 2001 2:20AM)

The URL is not:
http://www.shagrouni.com/download/ccmenue.zip
but
http://www.shagrouni.com/download/ccmenu.zip

Great! Bye!
Respond

RE: Wrong URL.
Khaled Shagrouni (May 10 2001 9:10PM)

Thank you for the note.
Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
D. Wischnewski
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)