-
c语言入门之利用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环境下调试通过
在开发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环境下调试通过
最新更新
Objective-C语法之代码块(block)的使用
VB.NET eBook
Add-in and Automation Development In VB.NET 2003 (F
Add-in and Automation Development In VB.NET 2003 (8
Add-in and Automation Development in VB.NET 2003 (6
Add-in and Automation Development In VB.NET 2003 (5
AddIn Automation Development In VB.NET 2003 (4)
AddIn And Automation Development In VB.NET 2003 (2)
Addin and Automation Development In VB.NET 2003 (3)
AddIn And Automation Development In VB.NET 2003 (1)
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
武装你的WEBAPI-OData入门
武装你的WEBAPI-OData便捷查询
武装你的WEBAPI-OData分页查询
武装你的WEBAPI-OData资源更新Delta
5. 武装你的WEBAPI-OData使用Endpoint 05-09
武装你的WEBAPI-OData之API版本管理
武装你的WEBAPI-OData常见问题
武装你的WEBAPI-OData聚合查询
OData WebAPI实践-OData与EDM
OData WebAPI实践-Non-EDM模式