📄 menuitem.cpp
字号:
/**************************************
MenuItem.cpp文件
定义了弹出式菜单类PopMenu和菜单栏MenuBar
为用户提供的方便直观的操作方法
***************************************/
#define mMENUITEMNUM 8
//菜单项结构
typedef struct MenuItem
{
char *Caption; //菜单项名
int iOpera; //菜单项对应的消息类型
};
//弹出式菜单类
class PopMenu:public Item
{
private:
int iMenuItemNum; //菜单项总数
MenuItem MenuItems[mMENUITEMNUM]; //最多支持mMENUITEMNUM个菜单项
int iMaxItemCaptionLen; //最长菜单项名字符串长度
int *iStoreBuf; //指项缓冲区的指针
//该缓冲区用于存储被菜单遮盖的屏幕数据
void MouseClick(int iPose); //鼠标点击响应
void PopOut(); //菜单弹出函数
void ShutUp(); //菜单关闭函数
public:
char *Caption; //菜单名
int iCurMenuItem; //当前菜单项
int iStartPose; //菜单位置
PopMenu(char *cInCaption,...); //菜单初始化
~PopMenu() {if(iCurMenuItem!=-1) ShutUp();}
void ComMsg(Msg TheMsg); //消息接口函数
};
//菜单栏类
class MenuBar:public Item
{
private:
PopMenu* PopMenuArry[8]; //在菜单栏中最多支持8个弹出式菜单
int iMenuNum; //弹出式菜单总数
int iCurrentMenu; //当前激活菜单
void KeyRespond(Msg TheMsg); //键入响应
void SearchClickItem(char cPose); //鼠标点击响应
public:
MenuBar(); //初始化菜单栏
~MenuBar();
void ComMsg(Msg TheMsg); //消息接口函数
};
/*-----------------------------
PopMenu类成员函数定义
-----------------------------*/
//PopMenu构造函数
PopMenu::PopMenu(char *cInCaption,...) //采用不定数目参数
{
va_list ap; //参数表指针
int arg,i,tmp;
va_start(ap,cInCaption); //将参数表指针指向参数表
Caption=cInCaption; //记录菜单名
iMenuItemNum=va_arg(ap,int); //记录菜单项数目
iMaxItemCaptionLen=0;
for(i=0;i<iMenuItemNum;i++)
{
//记录菜单项名和菜单项对应的消息类型
tmp=strlen(MenuItems[i%mMENUITEMNUM].Caption = (char*) va_arg(ap,int));
MenuItems[i%mMENUITEMNUM].iOpera = va_arg(ap,int);
//求出最长的菜单项名
if(tmp>iMaxItemCaptionLen) iMaxItemCaptionLen = tmp;
}
va_end(ap); //结束变参指针
iCurMenuItem=-1;
}
//消息接口函数
void PopMenu::ComMsg(Msg TheMsg)
{
char cKey=TheMsg.iAgu2>>8,cExKey=TheMsg.iAgu2&0xff;
int iEndPose = iStartPose+iMaxItemCaptionLen;
switch(TheMsg.iOpera) //分析消息类型
{
case mKEY: //如果是键盘键入
if (iCurMenuItem == -1) //如果菜单没有打开
{
//如果是键入回车键或“↓”,
//则将菜单弹出,并把第一个菜单项以高亮显示
if((!cKey&&cExKey=='\r')||(cKey&&cExKey==80))
{
PopOut();
iCurMenuItem++;
ChangeColor(iStartPose+1,3+iCurMenuItem,iEndPose,3+iCurMenuItem,BLACK<<4|WHITE);
}
}
else //如果菜单已经打开
{
if(!cKey&&cExKey=='\r') //如果是键入回车键
{
//那么发出当前菜单项的消息
MsgBox.GetMsg(NULL,MenuItems[iCurMenuItem].iOpera);
}
if(cKey) //如果是其他键键入
{
//取消高亮度显示
ChangeColor(iStartPose+1,3+iCurMenuItem,iEndPose,3+iCurMenuItem,LIGHTGRAY<<4|BLACK);
switch(cExKey) //分析键入字符
{
case 72: //如果是“↑”键入,那么当前菜单项上移
iCurMenuItem--;iCurMenuItem=(iCurMenuItem+iMenuItemNum)%iMenuItemNum;
if(*(MenuItems[iCurMenuItem].Caption)=='-') iCurMenuItem--;
break;
case 80: //如果是“↓”键入,那么当前菜单项下移
iCurMenuItem++;iCurMenuItem%=iMenuItemNum;
if(*(MenuItems[iCurMenuItem].Caption)=='-') iCurMenuItem++;
break;
}
//将新的菜单项以高亮度显示
ChangeColor(iStartPose+1,3+iCurMenuItem,iEndPose,3+iCurMenuItem,BLACK<<4|WHITE);
}
}
break;
case mWINLOSFOCUS: //如果是菜单失去焦点
ShutUp(); //那么关闭菜单
break;
case mMOUSECLICK: //如果是鼠标点击
MouseClick(TheMsg.iAgu1); //那么调用鼠标响应程序
}
}
//鼠标点击响应程序
void PopMenu::MouseClick(int iPose)
{
int iClickPosex=iPose>>8,iClickPosey=iPose&0xff;
//如果鼠标点击的位置在菜单之外,那么返回空消息
if(iClickPosex<=iStartPose||iClickPosex>=iStartPose+iMaxItemCaptionLen||
iClickPosey<3||iClickPosey>2+iMenuItemNum)
MsgBox.GetMsg(NULL,mEMPTYMSG);
//如果鼠标点击的位置在菜单之内,那么产生对应消息
else MsgBox.GetMsg(NULL,MenuItems[iClickPosey-3].iOpera);
}
//菜单弹出
void PopMenu::PopOut()
{
int i,j,x=wherex(),y=wherey(),iEndPose=iStartPose+iMaxItemCaptionLen+1;
static int cShowBuf[20];
iStoreBuf = (int *) malloc(sizeof(int)*(iMenuItemNum+2)*(iMaxItemCaptionLen+2));
//保护屏幕信息
gettext(iStartPose,2,iEndPose,iMenuItemNum+3,iStoreBuf);
//绘制菜单
for(j=0;j<iMaxItemCaptionLen+1;j++)
{
if(j==0) cShowBuf[j]=((LIGHTGRAY<<4|BLACK)<<8)|0xff&'
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -