自绘菜单

本文介绍了一种使用Delphi自定义弹出菜单的方法,通过继承TPopupMenu类并实现OwnerDraw功能来绘制个性化菜单项。文章详细展示了如何创建菜单项、设置外观样式以及响应点击事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#ifndef __TPOPMENU__
#define __TPOPMENU__
class TPopmenuUI :public TPopupMenu
{
    private:

      TFont *m_pFntText;
      COLORREF m_clrNormal, m_clrHover, m_clrBreak, m_clrFrame;

      TCanvas * TmpCanvas;
      void DrawMenuBorder(TCanvas *ACanvas,unsigned int color);//画边框
    protected:
    public:
      __fastcall TPopmenuUI(Classes::TComponent* AOwner);

      __fastcall ~TPopmenuUI(){};

      void CreateCustomMenuItem( String strCaption, TNotifyEvent aClickEvent=NULL,Word SCCut = 0,
      int subIndex=-1, bool bEnbaled=true, bool bChecked=false, int iTag=-1 );
      void ClearMenuItem();

      void __fastcall OwnerDrawItem(TObject* Sender, TCanvas* ACanvas, const TRect &ARect, TOwnerDrawState State);
      void __fastcall OwnerMeasureItem(TObject* Sender, TCanvas* ACanvas, int &Width, int &Height);
      void __fastcall MenuOwerDrawAdvancedDrawItem(TObject *Sender, TCanvas *ACanvas,
					TRect &ARect, TOwnerDrawState State);

};
void TPopmenuUI::CreateCustomMenuItem( String strCaption,TNotifyEvent aClickEvent,Word SCCut,
int subIndex, bool bEnabled, bool bChecked, int iTag )
{
    TMenuItem * pItem = new TMenuItem( this );//创建菜单内容
    pItem->ShortCut = 0;
    pItem->Caption = strCaption;

    pItem->OnAdvancedDrawItem = OwnerDrawItem;
    pItem->OnMeasureItem = OwnerMeasureItem;

    pItem->OnClick = aClickEvent;
    pItem->Checked = bChecked;
    pItem->Enabled = bEnabled;

    pItem->Tag = iTag;


    if( subIndex==-1 )
       Items->Add( pItem );
    else
       Items->Items[subIndex]->Add( pItem );
}

void __fastcall TPopmenuUI::OwnerDrawItem(TObject* Sender, TCanvas* ACanvas, const TRect &ARect, TOwnerDrawState State)
{
    //绘制背景
    if( State.Contains(odSelected) && !State.Contains(odDisabled) ) //鼠标选中
    {
        //鼠标滑对时,高亮项
        m_pFntText->Color = 0x231400;
        ACanvas->Brush->Color = 0xECDDBC;
        ACanvas->FillRect(TRect(ARect.left,ARect.top,ARect.right,ARect.Bottom));

        //图标区域
        //ACanvas->Brush->Color = 0xF4F2F1;
        //ACanvas->FillRect(TRect(ARect.Left,ARect.Top,21,ARect.Bottom));
    }
    else
    {
        if( State.Contains(odDisabled) )
        {
            //禁用项
            m_pFntText->Color = 0xBABABA;
        }
        else
        {
            //常规项
            m_pFntText->Color = 0x231400;//文字颜色
        }

        ACanvas->Brush->Color = 0xF9F9F9; //背景色
        ACanvas->FillRect(TRect(ARect.left,ARect.top,ARect.right,ARect.Bottom));

        DrawMenuBorder(ACanvas,0x99A8AC);
    }

    if( ((TMenuItem *)Sender)->IsLine() )
    {
        ACanvas->Pen->Color = 0xE5E5E5;
        ACanvas->MoveTo( ARect.left+27, ARect.top+4 );
        ACanvas->LineTo( ARect.right-6, ARect.top+4 );
    }
    else
    {
        TFont *oldFont = ACanvas->Font;
        ACanvas->Font->Assign(m_pFntText);
        ACanvas->Brush->Style = bsClear;

        ACanvas->TextRect( ARect, ARect.left+27, ARect.top+3, ((TMenuItem *)Sender)->Caption.SubString(1,9));   //输出菜单文字
        ACanvas->Font = oldFont;
    }

}

void __fastcall TPopmenuUI::OwnerMeasureItem(TObject* Sender, TCanvas* ACanvas, int &Width, int &Height)
{
    if( ((TMenuItem *)Sender)->IsLine())
    {
       Height = 10;
    }
    else
      Height =21;       //设置为足够高以容纳你的菜单项

    Width  =200;        //设置为足够宽以容纳你的菜单项
}

__fastcall TPopmenuUI::TPopmenuUI(Classes::TComponent* AOwner):TPopupMenu(AOwner)
{
    m_pFntText = new TFont;
	OwnerDraw = true;
}
void TPopmenuUI::DrawMenuBorder(TCanvas *ACanvas,unsigned int color)//画边框
{
    HWND hMenu = WindowFromDC(ACanvas->Handle);
    //Border flat...
    if ( hMenu != Handle &&  hMenu != 0 )
    {
              TmpCanvas = new TCanvas;

              TRect rect;

              TmpCanvas->Handle = GetDC(0);

              
              GetWindowRect(hMenu, &rect);

              //画外框
              InflateRect(&rect, -1, -1);
              TmpCanvas->Pen->Color = clRed;
              TmpCanvas->FrameRect(TRect(rect.Left,rect.top,rect.right,rect.Bottom));
              //图标区域
              TmpCanvas->Brush->Color = 0xF4F2F1;
              TmpCanvas->FillRect(TRect(rect.Left+1,rect.top+1,rect.left+27,rect.Bottom));

              TmpCanvas->Pen->Color = 0xE7E7E7;
              TmpCanvas->Pen->Width = 1;
              TmpCanvas->MoveTo(rect.Left+27,rect.top+1);
              TmpCanvas->LineTo(rect.Left+27,rect.Bottom);

    }
}
#endif

调用方法如下:

__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
     //创建菜单
     TPopmenuUI * pMenu = new TPopmenuUI(this);

     pMenu->CreateCustomMenuItem("功能菜单1",TPopmenuUIOnClick);
     pMenu->CreateCustomMenuItem("功能菜单2:");
     pMenu->CreateCustomMenuItem("-");
     pMenu->CreateCustomMenuItem("功能菜单3:");
     pMenu->CreateCustomMenuItem("功能菜单4",NULL,112);

     this->PopupMenu = pMenu;
}
void __fastcall TForm1::TPopmenuUIOnClick(TObject * Sender)
{
    ShowMessage("点击功能菜单一");
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值