`
pascal4123
  • 浏览: 114617 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Delphi有关菜单的几个技巧(ZZ)

    博客分类:
  • GP
阅读更多

 

 

学习使用Delphi中,遇到了一些关于菜单的编程问题,其中一些比较由代表性或比较实用,先把它从笔记中整理出来,与大家分享,请多多指教。 

 

 

-- 1 将菜单项移到菜单栏的最右边 

 

  在一些应用程序中,常把一些特殊的菜单项放在菜单栏的最右边(如WPS2000 中的"定制界面"菜单,一些应用程序的帮助菜单),这些菜单项放在菜单栏(menu bar)的右边比较好。Delphi中虽然没有直接提供把菜单放在菜单栏右边的函数,但是Delphi的Windows单元封装了可以实现这种效果的Windows API函数(ModifyMenu、GetMenuItemInfo)。因此,我们在Delphi中可以直接使这些函数来实现这种效果。 

  使用ModifyMenu和GetMenuItemInfo都可以将菜单项移到菜单栏的最右边,那么选那个较好呢?

据 Windows SDK 文档: ModifyMenu函数可以改变一个已经存在的菜单项的设置,这个函数用于指定一个菜单的标题、显示外观等项目,不过,ModifyMenu函数现在已经被功能更强大的SetMenuItemInfo函数取代。虽然如此,如果你的程序不需要SetMenuItemInfo函数提供的扩展功能,你仍旧可以继续使用ModifyMenu函数。 

  ModifyMenu函数支持 Windows 32、9x、NT/2000。 

  SetMenuItemInfo函数支持 Windows 9x、NT/2000,不支持windows 32(较早版本也不支持NT/2000)。 

  另外,SetMenuItemInfo函数功能比ModifyMenu函数强大,不过使用函数SetMenuItemInfo需要的参数也比ModifyMenu函数复杂的多。所以这里我依然使用比较简单的ModifyMenu函数来实现。 

  ModifyMenu函数原型为: 

  BOOL ModifyMenu( 

    HMENU hMnu, // handle of menu 

    UINT uPosition, // menu item to modify 

    UINT uFlags, // menu item flags 

    UINT uIDNewItem, // menu item identifier or handle of drop-down menu or submenu 

    LPCTSTR lpNewItem // menu item content 

    ); 

  第一个参数hMENU 指的是要修改的菜单的句柄(如:MainMenu1.Handle); 

  第二个参数uPosition 指的是要修改的菜单项索引值(菜单栏左边第一个其值为零,从左向右递增,最大值为菜单项的总数减一); 

  第三个参数uFlags指的是(第二个参数所指的菜单项修改后的)新菜单项的状态; 

  第四个参数uIDNewItem 是指向新菜单的句柄; 

  第五个参数lpNewItem指的是新菜单的标题。 

  举例如下: 

  创建一个带有菜单的新工程,设其MainMenu组件的名字为MainMenu1,其中要移到菜单栏的最右边的那个菜单的名字为Help1。 

  在窗体的OnCreate时间的处理程序中加入以下代码 

  procedure TForm1.FormCreate(Sender: TObject); 

  begin 

   ModifyMenu(MainMenu1.Handle,2, 

       MF_BYPOSITION or MF_HELP, 

       Help1.Handle,Pchar(Help1.Caption)); 

      //其中:MF_HELP 参数决定菜单项(Help1)在窗口的最右端显示。 

  end; 

  然后运行,看看效果如何 

 

-- 2 定制系统菜单 

 

  常见的应用程序的主窗体中,利用鼠标左键点击左上角的图标,会弹出一个系统菜单,这个菜单一定程度上给了我们很大方便,问题是那些都是缺省的系统菜单命令,对于我们来说没有太大的帮助。当然,我们可以自己定制系统菜单,加上我们需要的东西,在Delphi 中,窗体组件并没有提供系统菜单对应的组件,所以定制系统菜单时就有我们自己动手用Windows API函数来实现。Windows API函数中,常用于对菜单操作的函数有: 

  AppendMenu 在现有的菜单项尾部插入一个新菜单项; 

  DeleteMenu 删除菜单中一个现有的菜单项,并清除该项; 

  RemoveMenu 在现有的菜单项中删除某一项; 

  InsertMenu 在现有的菜单项中插入一个新项; 

  ModifyMenu 修改一个现有菜单项; 

  这些函数用法都是类似的上面已经说了ModifyMenu函数的用法,下面仅用AppendMenu函数在系统菜单中添加一个关于菜单来说明,虽然它本身是没有什么意义的,但希望可以起到抛砖引玉的作用。 

  AppendMenu 函数原型: 

  BOOL AppendMenu( 

     HMENU hMenu, // 要定制的菜单句柄 

     UINT uFlags, // 怎样定制菜单项 

     UINT uIDNewItem, // 要定制的菜单项标识或子菜单句柄 

     LPCTSTR lpNewItem // 要定制的菜单项(字串) 

    ); 

  在 AppendMenu 函数里,lpNewItem 和 uIDNewItem 参数依赖 uFlags 的不同标志而有所变化。 

  唯一限制:系统菜单中添加的菜单项的ID值(uIDNewItem)必须小于 $F000(十进制:61440);否则会与Windows系统菜单命令所使用的ID值相冲突。还要记住当为这些新菜单在窗口过程中处理WM_SYSCOMMAND消息时,必须把其它的WM_SYSCOMMAND消息发给DefWindowsProc(在Delphi中秩序在事件处理程序最后加入一句 Inherited;),否则,嘿嘿,你试试就知道了。 

  首先创建一个新工程,因为要用到Menus单元中的内容,故在文件Unit1.pas的uses语句中加入Menus。 

  uses 

   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls,  Menus; 

  然后在窗体Form1的OnCreate事件处理过程加入以下代码: 

  procedure TForm1.FormCreate(Sender: TObject); 

  var hSysMenu:hMENU; 

  begin 

   hSysMenu:=GetSystemMenu(Handle,False);//得到系统菜单句柄 

   AppendMenu(hSysMenu,MF_SEPARATOR,0,'');//添加一个分隔符 

   AppendMenu(hSysMenu,MF_STRING,3,'关于(&A)'); 

  end; 

  在TForm1的类型定义中,添加系统菜单中新建菜单项的OnClick事件的处理过程的声明(即对消息WM_SYSCOMMAND的处理声明): 

  type 

   TForm1 = class(TForm) 

    procedure FormCreate(Sender: TObject); 

   private 

    procedure SysMenuCommand(var Msg:TWMMENUSELECT); 

     message WM_SYSCOMMAND; 

    { Private declarations } 

   public 

    { Public declarations } 

   end; 

  接着按Shift+Ctrl+C完成类声明。在其中填入以下代码: 

  procedure TForm1.SysMenuCommand(var Msg: TWMMENUSELECT); 

  begin 

   if Msg.IDItem=3 then 

     MessageBox(0,'A Poor-Person''s Menu Program'+#13+ 

          ' Copyright Skyey ,2000','Skyey', 

         MB_OK+MB_ICONINFORMATION); 

   Inherited; 

  end; 

  编译、运行程序,测试其效果。 

  附:uFlags 一些定义值://选译自Delphi 5带的Windows SDK 帮助 

  MF_BITMAP 指明该菜单项是一位图,在 lpNewItem 参数代表位图句柄 

  MF_CHECKED 在菜单项的前面放上一个"选中"标记 

  MF_DISABLED 屏蔽该菜单项,但不使它变成灰色 

  MF_ENABLED 使该菜单项有效,与 MF_DISABLED 相反 

  MF_GRAYED 除了有 MF_DISABLED 的作用以外,还把该菜单项变灰 

  MF_MENUBREAK 把该菜单与现有菜单并排放在一起 

  MF_MENUBARBREAK 与MF_MENUBREAK 相同,除了在中间放一条竖线外 

  MF_OWNERDRAW 表明该菜单项为自绘菜单项,还必须处理一切的显示、更新问题 

  MF_POPUP 该菜单项为一子菜单,uIDNewItem 参数代表其句柄 

  MF_SEPARATOR 在菜单项画上一分割线 

  MF_STRING 该菜单项是一文本字串,lpNewItem 是其内容 

  MF_UNCHECKED 取消该菜单项前面的"选中"标记 

  以下几组标志中每组的标志不能同时使用: 

  < 1> MF_DISABLED, MF_ENABLED, and MF_GRAYED 

  < 2> MF_BITMAP, MF_STRING, and MF_OWNERDRAW 

  < 3> MF_MENUBARBREAK and MF_MENUBREAK 

  < 4> MF_CHECKED and MF_UNCHECKED 

 

-- 3 为菜单动态定义快捷键 

 

  其实就是改变菜单的ShortCut属性,在程序中加入一个HotKey组件,然后把其HotKey属性赋给菜单的ShortCut属性即可。如: 

  procedure TForm1.BtnChange1Click(Sender: TObject); 

  begin 

   New1.ShortCut:=Hotkey1.HotKey; 

  end; 

  如果你只需要程序自行更改有限的几个快捷键而不需要用户自己改变,那么也可以不用HotKey组件,直接把一个TShortCut类型的数值赋给菜单的ShortCut属性即可。如: 

  procedure TForm1.BtnChange1Click(Sender: TObject); 

  begin 

   New1.ShortCut:= 32833;//就是Alt+A 

  end; 

  一个快捷键的值可以按下面的方法在设计时得到:先在设计时改变菜单的ShortCut属性的为你需要的快捷键,然后在窗体上-> 右键-> View as Text,在DFM文件中找到那个组件,那个ShortCut后面的就是。如:需要Ctrl+Alt+N 

  object New1: TMenuItem 

   Caption = '&New' 

   ShortCut = 49230 //就是这个 

   OnClick = New1Click 

  end 

 

-- 4 动态改变菜单 

 

  就是改变菜单项的Enabled属性和Visible属性。这两个属性既可以在设计时改变,也可以在运行时改变。 

  如果将Enabled属性设置为False,则菜单项呈灰色状态,不可用;如果设置为True,则菜单项处于正常能用的状态。 

  如果将Visible属性设置为False,则该菜单项在运行时不显示;如果设置为True,则该菜单项显示。 

  如:New1.Enabled:=False;//New菜单项变成灰色,菜单现在不可用 

  New1.Enabled:=True; //New菜单项现在可以使用 

  New1.Visible:=False //New菜单项现在不显示 

  New1.Visible:=True; //New菜单项现在显示 

  唯一需要注意的是:Visible和Enabled属性时两个互相独立的属性,二者互不干扰,如果一个菜单拥有一个快捷键且其Enabled属性为True,即使其Visible属性为False(即运行时不可见),仍可以用快捷键来访问。 

  在程序运行期间,修改菜单项的这两个属性,即可以动态地改变菜单显示。 

 

-- 5 获取用户错误按键信息 

 

  如果用户按Alt和一个与菜单项不匹配的字符时,或者当显示弹出式菜单而用户按下一个与弹出式菜单里的项不匹配的字符键时。我们怎么知道用户按错了键,又怎么知道用户按了那个键呢? 

  事实上,当发生上面假设的情况时,Windows会发出一个WM_MENUCHAR消息,通常我们不需要处理这个消息,Windows程序通常会把它传给DefWindowProc,它一般给Windows返回0,即使Windows发出一个短的蜂鸣声。如果我们需要处理上面假设的情况时,只要拦截这个消息就可以了。 

  让我们先了解一下这个消息的参数: 

  WM_MENUCHAR 

   LOWORD(wParam); //即用户按键的ASCII码 

   HIWORD(wParam); //选择码 

   lParam; // 菜单句柄 

  选择码含义: 

  0: 不显示弹出菜单; 

  MF_POPUP: 显示下拉菜单、子菜单、快捷菜单(弹出式菜单) 

  MF_SYSMENU: 显示系统弹出式菜单 

  消息返回值: 

  0: 通知Windows丢弃用户按的这个字符并发出一个短的蜂鸣声; 

  1: 通知Windows应该关闭当前活动菜单; 

  2: 通知Windows返回一个相对于菜单项的零基点的低位字,它由Windows决定。 

  了解这一点后,让我们具体做一下: 

  创建一个带有菜单的新工程,在窗体上放一个Memo组件(Name:Memo1)在窗体的公有变量后加入消息的声明部分: 

  public 

   procedure MMenuChar(var Msg:TMessage);message WM_MENUCHAR; 

   { Public declarations } 

  end; 

  按Shift+Ctrl+C完成类声明。在其中填入以下代码: 

  procedure TForm1.MMenuChar(var Msg: TMessage); 

  begin 

   Memo1.Lines.Add(Chr(LOWORD(Msg.WParam))); 

   Memo1.Lines.Add(IntToStr(HIWORD(Msg.WParam))); 

   Msg.Result:=0; 

  end; 

  编译、链接并运行程序,测试其效果。


分享到:
评论

相关推荐

    delphi导航菜单范例

    在Delphi编程环境中,创建一个导航菜单是构建用户界面(UI)的重要部分。导航菜单通常包含一系列选项,帮助用户在应用程序的不同功能之间轻松切换。在这个"Delphi导航菜单范例"中,我们可以学习如何利用Delphi的VCL...

    delphi 权限菜单 例程

    在Delphi编程环境中,设计一个权限菜单是管理用户访问控制的关键步骤。这涉及到根据用户的权限级别来决定他们能看到哪些功能或菜单项。本例程专为Delphi新手提供,旨在帮助初学者理解如何实现这样的系统。 首先,...

    Delphi改变菜单栏高度及字号

    在Delphi中,菜单栏的高度不是直接由一个属性控制的,而是由系统默认的大小和字体大小共同决定。因此,我们可以通过修改字体的大小间接影响菜单栏的高度。以下是一个示例代码: ```delphi procedure TForm1....

    一个相当不错的Delphi TreeView树控菜单.rar

    一个Delphi编写的相当不错的TreeView树控菜单,类似于Windows资源管理器中的树状菜单。  ParentFolder: IShellFolder; // 节点对应的文件夹的父文件夹的IShellFolder接口  Pidl, FullPidl: PItemIDList;// 节点...

    delphi左侧推拉式菜单实例代码

    在Delphi编程环境中,开发一个左侧推拉式菜单的实例是一项常见的任务,尤其适用于构建具有现代用户界面的应用程序。这个实例代码提供了一个简单的解决方案,它适用于初学者学习Delphi UI设计,同时也为经验丰富的...

    delphi 特效菜单 改变字体和颜色

    "delphi 特效菜单 改变字体和颜色"这个主题聚焦于如何通过编程技术来定制菜单项的显示效果,使其更加吸引人。下面我们将深入探讨如何在Delphi中实现这一功能。 首先,菜单项在Delphi中的基本元素是TMenuItem组件,...

    Delphi Edit右键系统菜单加自定义菜单项

    "Delphi Edit右键系统菜单加自定义菜单项" 是一个典型的增强用户界面交互的例子。在这个话题中,我们将深入探讨如何在Delphi中的TEdit控件上添加自定义的右键菜单,同时保持原有的系统菜单功能。 首先,我们要理解...

    DELPHI动态菜单

    DELPHI动态菜单

    delphi CxGrid菜单源码

    这个"delphi CxGrid菜单源码"提供了一种方式,让开发者能够自定义和扩展Delphi中的CxGrid控件,使其功能更加丰富,特别是在用户界面交互和数据展示方面。 CxGrid组件提供了多种特性,例如: 1. **多层视图**:...

    delphi推拉式菜单实例

    本实例将探讨如何在Delphi中实现一个推拉式菜单。 首先,我们需要了解Delphi中的菜单系统。在Delphi中,菜单通常由TMainMenu组件来创建和管理。TMainMenu是一个可视化组件,可以在表单设计时直接拖放到表单上。你...

    用Delphi制作动态菜单 .rar_delphi 动态菜单_delphi 菜单_delphi菜单_动态菜单

    在Delphi中,我们主要通过TMainMenu和TPopupMenu组件以及它们的相关方法和属性来实现动态菜单的创建和管理。 首先,了解TMainMenu组件。它是Delphi中用于构建菜单栏的主要控件。你可以直接在设计时通过拖放操作添加...

    Delphi中添如何添加右键菜单

    在Delphi中添加右键菜单是一项常见的任务,它涉及到Windows API和组件的使用。下面将详细解释这个过程,包括所需的步骤、使用的API函数以及如何在Delphi程序中实现这一功能。 1. **基本概念** 右键菜单,也称为上...

    Delphi 开发 Android 桌面图标长按快捷菜单

    这是使用Delphi 开发Android 程序需要桌面图标长按快捷菜单的功能实现程序 1. 包含全部源代码 2. 是在Delphi 11.1 下创建的工程,编译通过 3. 其他版本的Delphi 是没有问题的,但是可能需要重新创建工程

    delphi自定义控件菜单PopupMenu

    本篇文章将深入探讨如何在Delphi中创建自定义控件菜单,特别是dbPopupMenu和downbutton右键菜单这两个控件。 首先,dbPopupMenu是数据库关联的弹出菜单,它允许开发者根据数据库中的数据动态生成菜单项。创建这样一...

    带左侧展开菜单的Delphi漂亮界面..rar

    在本文中,我们将深入探讨如何在Delphi中创建一个具有左侧展开菜单的漂亮用户界面。Delphi是一款强大的Object Pascal编程环境,它提供了丰富的组件库和工具,使得开发出美观、功能丰富的应用程序变得容易。 首先,...

    资源管理器树状菜单,Delphi源代码.rar

    资源管理器树状菜单,Delphi源代码,也就是Windows资源管理器中的展开树菜单,通过这个菜单你或许能了解到:  几个对项目标识符进行操作的函数、将二进制表示的项目标识符列表转换成有可识的项目名、获得每个文件夹...

    delphi 控制系统菜单.rar

    要创建一个控制系统菜单,你需要了解以下几个关键知识点: 1. **菜单编辑器**:Delphi提供了一个内置的菜单编辑器,你可以通过这个工具来可视化地创建和编辑菜单项。在菜单编辑器中,你可以添加、删除、重命名和...

    漂亮的Delphi窗体菜单,下拉形式..rar

    本资源“漂亮的Delphi窗体菜单,下拉形式”显然是一个关于如何在Delphi中创建美观且功能丰富的下拉式菜单的示例或教程。以下是对这个主题的详细讲解: 在Delphi中,窗体菜单通常是通过`TMainMenu`组件来创建和管理...

    Delphi菜单设计器组件

    2. **自定义属性**:在Delphi菜单设计器中,每个菜单项都可以拥有自己的属性,如文本、图标、快捷键、状态(启用/禁用)等。开发者可以根据需求自定义这些属性,以满足不同应用场景的需求。 3. **事件处理**:组件...

Global site tag (gtag.js) - Google Analytics