利用C++Builder自定义Windows窗体“系统菜单”

安徽合肥智能机械研究所张建军

-------------------------------------------------------------------------------

    在开发Windows应用程序时,软件人员希望所编制的程序具有风格独特的用户界面,为此不惜采用一些占用系统内存资源颇多的第三方OCX控件,结果导致程序运行速度变慢或者打包后的安装程序体积太大的缺点。其实,如果我们仔细研究一下Windows提供的几百个WinAPI,就不难发现,通过直接调用API函数,发送、接收或者拦截系统消息等方法,同样可以实现在某些情况下只能依靠调用OCX才能达到的界面效果。

例如:为我们所熟知的屏幕抓图软件HyperSnap,在其强大的屏幕抓图功能背后,还具有一项比较特殊的界面效果。

通常情况下,当用鼠标点击一个Windows窗体左上角的Icon时,所看到的系统菜单一般都是固定不变的。

HyperSnap的窗体改变了标准“系统菜单”,增加了多个新菜单项,并分别赋予它们不同的功能。其实这种效果的实现并不复杂,主要通过调用GetSystemMenu、AppendMenu等API函数完成。下面,我们就以C++Builder为例,讨论一下如何在自己的应用程序中实现类似HyperSnap的界面效果,并给出完整代码实例。

1.API函数介绍

⑴ GetSystemMenu

① 功能:

允许访问(拷贝或修改)系统菜单,普通Windows窗体如果未改变其菜单项状态,自动采用标准Windows菜单,即“恢复”、“移动”、“最大化”、“最小化”、“关闭”等。

②     原形:

HMENU GetSystemMenu(

HWND hWnd,

BOOL bRevert

);

③     入口参数:

HWND为预改变系统菜单的窗体句柄。

bRevert为标志。

当bRevert为假,GetSystemMenu返回HWND代表窗体的拷贝,初始状态下,拷贝与原窗体一致,但允许修改。

当bRevert为真,GetSystemMenu将HWND代表的窗体菜单恢复默认状态,之前对菜单的修改被取消。

④     返回值:

当bRevert为假,返回HWND代表的窗体拷贝的句柄,当bRevert为真,返

回值为Null。

⑵ AppendMenu

①功能:

在指定菜单的最后插入一个菜单项,并可规定该菜单项的文字内容、外观和触发事件。

②     原形:

BOOL AppendMenu(

HMENU hMenu

UINT uFlags

UINT uIDNewItem

LPCTSTR lpNewItem

);

③     入口参数:

hMenu为欲增加菜单项的菜单句柄。

uFlags为新增菜单项的标志,可以是几种系统常量的组合。

UIDNewItem为新增菜单项的标识。

lpNewItem为新增菜单项的文字内容,可取MF_STRING、MF_SEPARATOR等值。

④     返回值:

成功返回0,失败返回非0。

⑶ WM_SYSCOMMAND

当点击菜单项时触发的系统消息。

编程实例

⑴ 新建工程

在C++ Builder 5.0 IDE 中新建工程Project1,Project1中包含Form1。

⑵ Form_Click事件

void __fastcall TForm1::FormClick(TObject *Sender)

{

ChangeSystemMenu(Form1, "-", 0);

ChangeSystemMenu(Form1, "自定义项目...", 99);

Application->OnMessage = Form1->RegisterMsg;//指定窗体消息处理函数

}

⑶ 自定义消息处理过程

void __fastcall TForm1::RegisterMsg(tagMSG &Msg, bool &Handled)

{

if (Msg.message == WM_SYSCOMMAND)

if (Msg.wParam == 99)

ShowMessage("你点击了自定义菜单");//自定义菜单响应代码

}

⑷ 改变系统菜单过程

void __fastcall ChangeSystemMenu(TForm *Form, AnsiString Item, Word ItemID)

{

void* NormalSystemMenu;

void* MinSystemMenu;

char* AItem = new char[255];

PChar PItem;

NormalSystemMenu = GetSystemMenu(Form->Handle, false);

MinSystemMenu = GetSystemMenu(Application->Handle, false);

if (Item == "-")

{

AppendMenu(NormalSystemMenu, MF_SEPARATOR, 0, 0);//增加菜单分隔线

AppendMenu(MinSystemMenu, MF_SEPARATOR, 0, 0);//增加菜单分隔线

}

else

{

PItem = StrPCopy(AItem, Item);

AppendMenu(NormalSystemMenu, MF_STRING, ItemID, PItem);//增加菜单项文字

AppendMenu(MinSystemMenu, MF_STRING, ItemID, PItem);//增加菜单项文字

}

}

实例代码

⑴ Unit1.h文件

//---------------------------------------------------------------------------

#ifndef unitAppendMenuH

#define unitAppendMenuH

//---------------------------------------------------------------------------

#include <Classes.hpp>

#include <Controls.hpp>

#include <StdCtrls.hpp>

#include <Forms.hpp>

//---------------------------------------------------------------------------

class TForm1 : public TForm

{

__published:    // IDE-managed Components

void __fastcall RegisterMsg(tagMSG &Msg, bool &Handled);//自定义菜单响应事件

void __fastcall FormClick(TObject *Sender);

private:    // User declarations

public:     // User declarations

__fastcall TForm1(TComponent* Owner);

};

//---------------------------------------------------------------------------

extern PACKAGE TForm1 *Form1;

//---------------------------------------------------------------------------

#endif

⑵ Unit1.cpp文件

//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include "unitAppendMenu.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

TForm1 *Form1;

//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//---------------------------------------------------------------------------

void __fastcall ChangeSystemMenu(TForm *Form, AnsiString Item, Word ItemID)

{

void* NormalSystemMenu;

void* MinSystemMenu;

char* AItem = new char[255];

PChar PItem;

NormalSystemMenu = GetSystemMenu(Form->Handle, false);

MinSystemMenu = GetSystemMenu(Application->Handle, false);

if (Item == "-")

{

AppendMenu(NormalSystemMenu, MF_SEPARATOR, 0, 0);//增加菜单分隔线

AppendMenu(MinSystemMenu, MF_SEPARATOR, 0, 0);//增加菜单分隔线

}

else

{

PItem = StrPCopy(AItem, Item);

AppendMenu(NormalSystemMenu, MF_STRING, ItemID, PItem);//增加菜单项文字

AppendMenu(MinSystemMenu, MF_STRING, ItemID, PItem);//增加菜单项文字

}

}

//---------------------------------------------------------------------------

void __fastcall TForm1::RegisterMsg(tagMSG &Msg, bool &Handled)

{

if (Msg.message == WM_SYSCOMMAND)

if (Msg.wParam == 99)

ShowMessage("你点击了自定义菜单");//自定义菜单响应代码

}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormClick(TObject *Sender)

{

ChangeSystemMenu(Form1, "-", 0);

ChangeSystemMenu(Form1, "自定义项目...", 99);

Application->OnMessage = Form1->RegisterMsg;//指定窗体消息处理函数

}

//---------------------------------------------------------------------------

4.实例效果

以上代码在Win98、C++Builder 5.0环境下调试通过,所实现的界面效果如图1所示。

图1.本文代码实现的自定义窗体“系统菜单”

------------------------------------------------------------------------------

利用C++Builder自定义Windows窗体“系统菜单”相关推荐

  1. 自定义Windows 10开始菜单的10种方法

    Windows 10 finally brought back the Start menu, and it's more customizable than ever. Here's a quick ...

  2. 利用U盘安装Windows XP系统?

    好多人系统坏了就找Windows 的安装光盘.当找不到光盘,或者机器根本就没有光盘的时候,就束手无策.其实,可以利用U盘首先启动Windows PE,然后在Windows PE的运行环境内直接安装Wi ...

  3. 利用QCommonStyle绘制自定义的窗体部件

    Qt自带的例子affine中的ArthurStyle类继承自QCommonStyle,实现了绘制自定义窗体部件的功能,是学习自定义控件的好例子. 工程存放的路径在:Examples\Qt-XX.XX. ...

  4. C# Windows 窗体的.Net 框架绘图技术

    当编写一个典型的Windows 窗体程序时,窗体和控件的绘制.效果等操作是不需要特别加以考虑的.这是为什么呢?因为通过使用 .Net 框架,开发人员可以拖动一系列的控件到窗体上,并书写一些简单的与事件 ...

  5. 【MSDN文摘】使用自定义验证组件库扩展 Windows 窗体: Form Scope

    使用自定义验证组件库扩展 Windows 窗体,第 2 部分(Windows 窗体探索) 发布日期: 5/28/2004 | 更新日期: 5/28/2004 Michael Weinhardt www ...

  6. [MFC]利用CMenu手工(非资源脚本)处理菜单、系统菜单

    1. 创建菜单: 1) 主要利用CMenu的三个成员函数CreateMenu.CreatePopupMenu.AppendMenu.SetMenu创建菜单: 2) BOOL CMenu::Create ...

  7. Windows窗体的所有菜单

    简介仅仅使用一行简单的程序,你就能够使你的Windows窗体的所有菜单和上下文菜单具有office2003的菜单外观.同样地,你也可以只用一行程序,就能为你的菜单加上漂亮的图标.本文实现的是一个具有该 ...

  8. 利用Windows 2003系统中实现两个网段的路由

    利用Windows 2003系统中实现两个网段的路由 当一个局域网中存在两个以上网段时,分属于不同网段内的主机彼此互不可见.为了解决这个问 题,就必须在不同的网段之间设置路由器.如果花费上万元资金购买 ...

  9. C#创建Windows窗体应用程序实例9【菜单设计】

      都实例9了?你还不会创建项目?不会操作步骤?不会写代码?请进入下方链接学习吧! C#创建Windows窗体应用程序实例1https://blog.csdn.net/qq_45037155/arti ...

最新文章

  1. 一份520页的机器学习笔记!附下载链接
  2. 逻辑斯蒂回归(logisic regression)和SVM的异同
  3. leetcode算法题--复数乘法
  4. crossdomain 可用
  5. 生成多个 SSH-Key 、生成多个公钥和私钥
  6. python 3.6.5编译安装_Linux系统安装Python3.6.5
  7. 在集设把优秀的设计合集,轻松追寻设计灵感
  8. java 事件监听应用_Spring Boot应用事件监听示例详解
  9. You (root) are not allowed to access to (crontab) because of pam configuration
  10. python中pandas库里的read_table和read_csv的区别
  11. Linux命令之iconv命令
  12. 西门子S7-200smart PLC远程下载程序的方法
  13. Qt手动设置Kits套件
  14. 句法结构解析和Transition_based方法
  15. c 语言 农历,农历转阴历 c语言
  16. 构建gcc交叉编译工具链
  17. 用户手册应当由谁写?
  18. pandas爬取数据示例网页
  19. 国科大学习资料--模式识别与机器学习(黄庆明)--第二次作业答案
  20. tdk怎么设置_网站的TDK如何设置及优化

热门文章

  1. 开发到底喜欢看怎样的需求文档
  2. 2020品牌情商指数报告
  3. 专题导读:大数据整理
  4. 作者:王学志(1979-),男,中国科学院计算机网络信息中心副研究员
  5. 2016中国国际大数据大会预热活动启航,首场沙龙聚焦精准营销
  6. 作者:李明,男,中兴通讯股份有限公司产品经理。
  7. Tomcat 申请证书配置https
  8. 工作中由于任务分配注意问题
  9. 【数据结构与算法】二叉树结点最小深度求解算法
  10. 面积计算(洛谷P5681题题解,Java语言描述)