Delphi MainMenu的自绘

1. 整条 MainMenu 的背景

Windows 本身有提供API,让我们定制 MainMenu 的背景,那就是通过 SetMenuInfo

BOOL SetMenuInfo(
HMENU hmenu, LPCMENUINFO lpcmi );

参数:

hmenu , 要自绘的 MainMenu 的 句柄

lpcmi, 指向 MENUINFO 结构体的指针

具体的设置全在 MENUINFO 的 hbrBack 画刷中,通过它便可以设置背景,我们简单的

设置为绿色,代码如下:

var
  MenuData : TMenuInfo;
  brush : HBrush;
begin
  MenuData.cbSize := SizeOf(tagMENUINFO);
  MenuData.fMask := MIM_BACKGROUND;
  MenuData.dwStyle :=  MNS_AUTODISMISS;
  MenuData.cyMax := 0;
  MenuData.hbrBack := CreateSolidBrush($00ff00);
  //MenuData.dwContextHelpID :=
  //MenuData.dwMenuData :=
  SetMenuInfo(mm1.Handle,MenuData);
  Refresh;
end;

2. MainMenu的 Item 的自绘

我想这个很简单,只需设置 MainMenu 的属性为 OwnerDraw为True 便可,具体的自绘在对

应的Item的 OnDrawItem 中便可。

3. 设置弹出的 MainMenu 的形状

首先我们要知道 Menu 这个组件的窗体由系统的建立的,要设置窗体的形状,必须得到窗体

的句柄。这里我们大概只能通过 HOOK 来截取窗体的建立的消息。查询 MSDN 便可知道,

Menu 的对应的窗体名为 #32768  , 我们截取窗体创建的消息 WM_CREATE  ,并判断是否为创建

Menu。我们HOOK 的为 WH_CALLWNDPROC ,其中 传递的 lParam 是 CWPSTRUCT  结构体指

针包含我们想要的窗体句柄,之后我们便可以通过  SetWindowRgn 来设置形状。

具体代码:

首先我们在程序启动时HOOK ,

SetWindowsHookEx(WH_CALLWNDPROC,MenuHookProc,HInstance,GetCurrentThreadId);

之后在MenuHookProc过程中处理:

function MenuHookProc(code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT stdcall;
var
  szClassName : array[0..20] of Char;
  nCount : Integer;
  lpCwp : PCWPStruct;
  Rect : TRECT;
  Rgn : HRGN;
  path : string;
  log : TextFile;
  mCanvas : TCanvas;
  Test : Boolean;
  Test1 : Integer;
  shadow: TFormShadow;
  point1,point2 : TPoint;
  CreateParam : PCreateStruct;
  name : string;
begin
  Test1 := -1;
  Test := False;

  lpCwp := PCWPSTRUCT(lParam);
  nCount := GetClassName(lpCwp^.hwnd,szClassName,20);

  if (wparam = HC_ACTION) and (nCount = 6) and 
    (lstrcmpi(szClassName,'#32768') = 0)
    and (lpCwp^.message = WM_CREATE) then
  begin
    Form2.mmo1.Lines.Add(' WM_CREATE ');
    mHwnd := lpCwp^.hwnd;
    GetWindowRect(lpCwp^.hwnd,Rect);
    if Rgn <> null then
    begin
      DeleteObject(Rgn);
    end;
    Rgn := CreateRoundRectRgn(Rect.left + 3,Rect.top + 3,80,
      Rect.Top + ItemCount * 23 +4,4,4);
    SetWindowRgn(lpCwp^.hwnd,Rgn,True);

    // 透明处理
    SetWindowLong(lpCwp^.hwnd,GWL_EXSTYLE,
      GetWindowLong(lpCwp^.hwnd,GWL_EXSTYLE)
      xor $80000 or WS_CHILD );
    SetLayeredWindowAttributes(lpCwp^.hwnd,0,240,LWA_ALPHA);

    // 设置系统的阴影是否显示 CS_DROPSHADOW
    SystemParametersInfo(SPI_SETDROPSHADOW,0,Test1,0);

    Result :=  CallNextHookEx(m_hMenuHook,code,wParam,lParam);
  end
  else
  begin
    Result :=  CallNextHookEx(m_hMenuHook,code,wParam,lParam);
  end;

 

具体的程序下载:

http://www.kuaipan.cn/file/id_65177958372915831.htm

原文地址:https://www.cnblogs.com/wangmingshuo/p/3354657.html