首先是创建控件的声明与参数编写规则:
/*快捷菜单*/
ContextMenuStrip 测试快捷 = new ContextMenuStrip();
/*主菜单 = 名称|图标索引*/
/*子菜单子参数:乾坤大挪移 = 上级菜单索引|移动菜单索引:移一个菜单主菜单下位索引-1*/
/*事件数组*/
/*加载赋值*/
九九乘法表举例:
/*九九乘法表-紫菜汤-顺序排列,创建菜单上显示的文本*/
string[] 九九乘法表 = new string[81]; int 索引 = 0;
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
九九乘法表[索引] = i.ToString() + "×" + j.ToString() + "=" + (i * j).ToString() + "|";
索引++;
}
}
九九乘法表乾坤大挪移参数 = new string[81]为了体现就不自动生成了,创建子菜单各级位置参数:
string[] 九九乘法表乾坤大挪移参数 = new string[] {
"0|1", "0|0|1", "0|0|0|1", "0|0|0|0|1", "0|0|0|0|0|1", "0|0|0|0|0|0|1", "0|0|0|0|0|0|0|1", "0|0|0|0|0|0|0|0|1",
"1|2", "1|0|2", "1|0|0|2", "1|0|0|0|2", "1|0|0|0|0|2", "1|0|0|0|0|0|2", "1|0|0|0|0|0|0|2", "1|0|0|0|0|0|0|0|2",
"2|3", "2|0|3", "2|0|0|3", "2|0|0|0|3", "2|0|0|0|0|3", "2|0|0|0|0|0|3", "2|0|0|0|0|0|0|3", "2|0|0|0|0|0|0|0|3",
"3|4", "3|0|4", "3|0|0|4", "3|0|0|0|4", "3|0|0|0|0|4", "3|0|0|0|0|0|4", "3|0|0|0|0|0|0|4", "3|0|0|0|0|0|0|0|4",
"4|5", "4|0|5", "4|0|0|5", "4|0|0|0|5", "4|0|0|0|0|5", "4|0|0|0|0|0|5", "4|0|0|0|0|0|0|5", "4|0|0|0|0|0|0|0|5",
"5|6", "5|0|6", "5|0|0|6", "5|0|0|0|6", "5|0|0|0|0|6", "5|0|0|0|0|0|6", "5|0|0|0|0|0|0|6", "5|0|0|0|0|0|0|0|6",
"6|7", "6|0|7", "6|0|0|7", "6|0|0|0|7", "6|0|0|0|0|7", "6|0|0|0|0|0|7", "6|0|0|0|0|0|0|7", "6|0|0|0|0|0|0|0|7",
"7|8", "7|0|8", "7|0|0|8", "7|0|0|0|8", "7|0|0|0|0|8", "7|0|0|0|0|0|8", "7|0|0|0|0|0|0|8", "7|0|0|0|0|0|0|0|8",
"8|9", "8|0|9", "8|0|0|9", "8|0|0|0|9", "8|0|0|0|0|9", "8|0|0|0|0|0|9", "8|0|0|0|0|0|0|9", "8|0|0|0|0|0|0|0|9"
};
调用的两种方式:异步委托请参看线程与委托一文:
//快捷菜单(测试快捷, 九九乘法表, null);
//乾坤大挪移(测试快捷, 九九乘法表乾坤大挪移参数);
//this.BeginInvoke(new 快捷(快捷菜单), 测试快捷, 九九乘法表, null);
//this.BeginInvoke(new 乾坤挪移(乾坤大挪移), 测试快捷, 九九乘法表乾坤大挪移参数);
//this.ContextMenuStrip = 测试快捷;
生成菜单及子菜单的主要代码:
private void 快捷菜单(ContextMenuStrip 菜单名, string[] 参数, EventHandler[] 事件)
{
int 计数 = 0;
foreach (string 元素 in 参数)
{
string[] 列表 = 元素.Split('|');
if (列表[0].Length > 0) 菜单名.Items.Add(列表[0]);
if (列表[1].Length > 0) 菜单名.Items[计数].Image = 图标集.Images[int.Parse(列表[1])];
if (事件 != null) if (事件[计数] != null) 菜单名.Items[计数].Click += new EventHandler(事件[计数]);
计数++;
}
菜单名.Items[0].BackColor = System.Drawing.Color.Aqua;
//return 菜单名;//ContextMenuStrip
}
private void 乾坤大挪移(ContextMenuStrip 菜单名, string[] 子参数)
{
foreach (string 元素 in 子参数)
{
string[] 列表 = 元素.Split('|');
ToolStripDropDownItem 菜单位置 = (ToolStripDropDownItem)菜单名.Items[int.Parse(列表[0])];
if (列表.Length > 2)//无极紫菜汤
for (int 无极 = 1; 无极 < 列表.Length - 1; 无极++)
{ 菜单位置 = 无极之菜单(菜单位置, int.Parse(列表[无极])); }
ToolStripItem 子菜单名 = 菜单名.Items[int.Parse(列表[列表.Length - 1])];
菜单位置.DropDownItems.Add(子菜单名);
}
}
private ToolStripDropDownItem 无极之菜单(ToolStripDropDownItem 级, int 位置)
{
ToolStripDropDownItem 无极 = (ToolStripDropDownItem)级.DropDownItems[位置];
return 无极;
}
快捷菜单事件数组代码:
EventHandler[] 主体快捷事件 = new EventHandler[] { null, null, 曲线QToolStripMenuItem_Click, 选项OToolStripMenuItem_Click, 农历NToolStripMenuItem_Click, null, null, 农历ToolStripMenuItem3_Click, (sender1, e1) => { 选项卡.SelectedIndex = 选项卡.TabPages.IndexOfKey("附件"); }, 退出XToolStripMenuItem_Click };
需要说明的是菜单事件必须与菜单名称对应,数量相等,没事件的可以写null;
通常光菜汤写一大堆代码确实头大,这几天不知怎么啦,跟这些菜汤干上了,功夫不负有心人,下午终于归纳导出:乾坤大挪移无极紫菜汤;这些天经过一番推理,证明这种写法是合理而且容易理解思路清晰。
知道写得不好,欢迎提提建议,我只想用我的方法来写,证明写程序是很灵活的,也是头脑所想的,只要有办法,可以心想事成。
举例:/*九九乘法表-紫菜汤-梯形排列*/
string[] 九九乘法表 = new string[45]; int 索引 = 0;
for (int i = 1; i <= 9; i++)
{
for (int j = i; j <= 9; j++)
{
九九乘法表[索引] = i.ToString() + "×" + j.ToString() + "=" + (i * j).ToString() + "|";
索引++;
}
}
string[] 九九乘法表乾坤大挪移参数 = new string[] {
"1|9", "2|9", "3|9", "4|9", "5|9", "6|9", "7|9", "8|9",
"2|0|9", "3|0|9", "4|0|9", "5|0|9", "6|0|9", "7|0|9", "8|0|9",
"3|0|0|9", "4|0|0|9", "5|0|0|9", "6|0|0|9", "7|0|0|9", "8|0|0|9",
"4|0|0|0|9", "5|0|0|0|9", "6|0|0|0|9", "7|0|0|0|9", "8|0|0|0|9",
"5|0|0|0|0|9", "6|0|0|0|0|9", "7|0|0|0|0|9", "8|0|0|0|0|9",
"6|0|0|0|0|0|9", "7|0|0|0|0|0|9", "8|0|0|0|0|0|9",
"7|0|0|0|0|0|0|9", "8|0|0|0|0|0|0|9",
"8|0|0|0|0|0|0|0|9"
};
/*下列的就不做出排列了,留给有兴趣的人去玩。*/
for (int i = 1, j = 1; j <= 9; i++)
{
九九乘法表[索引] = i.ToString() + "×" + j.ToString() + "=" + (i * j).ToString() + "|";
if (j == i) { i = 0; j++; }
索引++;
}
/*下列递归算法:递归就是不断压入栈的过程,从9一直压入栈中到1;条件满足后,执行是从最后压入栈取出开始。九九乘法表递归(9);*/
ArrayList 九九乘法表 = new ArrayList();
public void 九九乘法表递归(int 数值)
{
if (数值 <= 0) return;
九九乘法表递归(数值 - 1);
for (int 递归 = 1; 递归 <= 数值; 递归++)
{ 九九乘法表.Add(数值 + "×" + 递归 + "=" + (递归 * 数值).ToString() + "|"); }
}
2018-10当6年多后复用此代码时,遇到了一些曲折,最后还是成功调用,只因为当时发布是未详细说明一些参数是怎么写的,今补充与修改代码,[快捷菜单]用于创建1个菜单及以上调用,[子菜单乾坤大挪移]用于有子菜单时调用,之下是创建于调用:
private void 快捷菜单(ContextMenuStrip 菜单名, string[] 文本图标, EventHandler[] 事件)
{
循环 = 0;
foreach (string 元素 in 文本图标)
{
string[] 列表 = 元素.Split('|');
if (列表[0].Length > 0) 菜单名.Items.Add(列表[0]);
if (列表[1].Length > 0) 菜单名.Items[循环].Image = 图标集.Images[int.Parse(列表[1])];
if (事件 != null) if (事件[循环] != null) 菜单名.Items[循环].Click += new EventHandler(事件[循环]);
循环++;
}
菜单名.Items[0].BackColor = System.Drawing.Color.Aqua;
}
private void 子菜单乾坤大挪移(ContextMenuStrip 菜单名, string[] 级位置)
{
Func<ToolStripDropDownItem, int, ToolStripDropDownItem> 无极之菜单 = delegate(ToolStripDropDownItem 级, int 位置)
{
ToolStripDropDownItem 无极 = (ToolStripDropDownItem)级.DropDownItems[位置];
return 无极;
};
foreach (string 元素 in 级位置)
{
string[] 列表 = 元素.Split('|'); 循环 = 1;
ToolStripDropDownItem 菜单位置 = (ToolStripDropDownItem)菜单名.Items[int.Parse(列表[0])];
if (列表.Length > 2)//无极紫菜汤
while (列表.Length - 1 > 循环) 菜单位置 = 无极之菜单(菜单位置, int.Parse(列表[循环++]));
ToolStripItem 子菜单名 = 菜单名.Items[int.Parse(列表[列表.Length - 1])];
菜单位置.DropDownItems.Add(子菜单名);
}
}
创建控件声明与异步调用:
ContextMenuStrip 快捷 = new ContextMenuStrip();
this.BeginInvoke(new Action<ContextMenuStrip, string[], EventHandler[]>((菜单名, 文本图标, 事件) => 快捷菜单(菜单名, 文本图标, 事件)), 快捷, new string[] { "转化|1"/*名称|图标索引*/ }, 快捷事件);
if (快捷事件.Length > 1) this.BeginInvoke(new Action<ContextMenuStrip, string[]>((菜单名, 级位置) => 子菜单乾坤大挪移(菜单名, 级位置)), 快捷, new string[] { "0|1"/*上级菜单索引|子级菜单索引*/ });
this.ContextMenuStrip = 快捷;
另一个工程例子:
/*主菜单=名称|图标索引*/
string[] 主体快捷参数 = new string[] { "浩瀚个人珍藏|28", "-|", "曲线(&Q)|16", "存档(&W)|33", "农历(&L)|0", "附件(&F)|23", "外挂农历|0", "金额转换(&Z)|6", "农历(简体)|0", "农历(繁体)|0", "更新数据|25", "数据引导|9", "导出XML|24", "XML导入|25", "-|", "退出(&X)|1" };
string[] 富文本快捷参数 = new string[] { "浩瀚个人珍藏|28", "关于作者|11", "-|", "文件|18", "新建|25", "打开|34", "保存|35", "编辑|19", "复制|36", "粘贴|38", "剪切|37", "图片|3", "选定导出|3", "批量导出|3", "插入图片|3", "剪裁图片|26", "浏览图片|26", "浏览剪裁|26", "-|", "退出|1" };
/*子菜单子参数:乾坤大挪移=循环上级位置|获取子菜单索引:移一位主菜单下位索引-1*/
string[] 主体乾坤大挪移参数 = new string[] { "4|6", "5|6", "4|6", "4|6", "7|8", "7|8" };
string[] 富文本乾坤大挪移参数 = new string[] { "0|1", "2|3", "2|3", "2|3", "3|4", "3|4", "3|4", "4|5", "4|5", "4|5", "4|5", "4|5", "4|5" };
/*事件*/
EventHandler[] 主体快捷事件 = new EventHandler[] { null, null, 曲线QToolStripMenuItem_Click, 选项OToolStripMenuItem_Click, 农历NToolStripMenuItem_Click, null, 农历ToolStripMenuItem3_Click, (sender1, e1) => 选项卡.SelectedIndex = 选项卡.TabPages.IndexOfKey("附件"), 农历简体ToolStripMenuItem_Click, 农历繁体ToolStripMenuItem_Click, (无, 参) => 更新数据(), null, (无, 参) => 保存XML(), (无, 参) => 读取XML(), null, 退出XToolStripMenuItem_Click };
EventHandler[] 富文本快捷事件 = new EventHandler[] { null, 关于AToolStripMenuItem_Click, null, null, 新建NToolStripButton1_Click, 打开OToolStripButton1_Click, 另存SToolStripButton_Click, null, 复制CToolStripButton1_Click, 粘贴PToolStripButton1_Click, 剪切UToolStripButton1_Click, null, 导出图片_Click, 批量图片_Click, 插入图片_Click, 剪裁图片_Click, 浏览图片_Click, 浏览剪裁图片_Click, null, 退出XToolStripMenuItem_Click };
/*加载赋值*/
string[] 菜单背景 = new string[] { "6|\\剪裁图片\\0.bmp", "7|\\剪裁图片\\0.bmp", "8|\\剪裁图片\\1.bmp", "9|\\剪裁图片\\2.bmp" };
this.BeginInvoke(new Action<ContextMenuStrip, string[], EventHandler[], string[]>((菜单名, 参数, 事件, 背景图) => 快捷菜单(菜单名, 参数, 事件, 背景图)), 主体快捷菜单, 主体快捷参数, 主体快捷事件, 菜单背景);
this.BeginInvoke(new Action<ContextMenuStrip, string[]>((菜单名, 子参数) => 乾坤大挪移(菜单名, 子参数)), 主体快捷菜单, 主体乾坤大挪移参数);
this.BeginInvoke(new Action(delegate() { 主体快捷菜单.Items[6].Visible = false; 主体快捷菜单.Items[7].Visible = false; this.ContextMenuStrip = 主体快捷菜单; }));
生成一级主菜单:
生成一级主菜单一级子菜单:
'
二级主菜单一级子菜单:
this.BeginInvoke(new Action<ContextMenuStrip, string[], EventHandler[]>((菜单名, 文本图标, 事件) => 快捷菜单(菜单名, 文本图标, 事件)), 快捷, new string[] { "浩瀚|0", "转化|1", "退出|9" }, 快捷事件);
if (快捷事件.Length > 1) this.BeginInvoke(new Action<ContextMenuStrip, string[]>((菜单名, 级位置) => 子菜单乾坤大挪移(菜单名, 级位置)), 快捷, new string[] { "0|1" });
this.ContextMenuStrip = 快捷;
EventHandler[] 快捷事件 = new EventHandler[] { null, 转化_Click, (sender1, e1) => { Application.Exit(); this.Dispose(true); this.Close(); } };
this.BeginInvoke(new Action<ContextMenuStrip, string[], EventHandler[]>((菜单名, 文本图标, 事件) => 快捷菜单(菜单名, 文本图标, 事件)), 快捷, new string[] { "浩瀚|0", "转化|1", "退出|9" }, 快捷事件);
if (快捷事件.Length > 1) this.BeginInvoke(new Action<ContextMenuStrip, string[]>((菜单名, 级位置) => 子菜单乾坤大挪移(菜单名, 级位置)), 快捷, new string[] { "0|1" });
this.ContextMenuStrip = 快捷;
之上把退出事件直接写在事件数组内代码.
任意添加菜单,但要注意事件也要相应添加:
EventHandler[] 快捷事件 = new EventHandler[] { null, 提取数据_Click, 保存标记_Click, (sender1, e1) => { Application.Exit(); this.Dispose(true); this.Close(); } };
this.BeginInvoke(new Action<ContextMenuStrip, string[], EventHandler[]>((菜单名, 文本图标, 事件) => 快捷菜单(菜单名, 文本图标, 事件)), 快捷, new string[] { "浩瀚|0", "提取数据|1", "保存标记|2", "退出|9" }, 快捷事件);
if (快捷事件.Length > 1) this.BeginInvoke(new Action<ContextMenuStrip, string[]>((菜单名, 级位置) => 子菜单乾坤大挪移(菜单名, 级位置)), 快捷, new string[] { "0|1" });
this.ContextMenuStrip = 快捷;
任意添加主快捷与子快捷菜单:
下面讲解如何编写3个参数
1.事件参数
EventHandler[] 快捷事件 = new EventHandler[] { null, 提取数据_Click, null, 保存分割_Click, 保存数据_Click, (sender1, e1) => { Application.Exit(); this.Dispose(true); this.Close(); } };
2.名称参数
this.BeginInvoke(new Action<ContextMenuStrip, string[], EventHandler[]>((菜单名, 文本图标, 事件) => 快捷菜单(菜单名, 文本图标, 事件)), 快捷, new string[] { "浩瀚|0", "提取数据|1", "保存选项|2", "分割标记|3", "数据文件|4", "退出|9" }, 快捷事件);
3.位置参数(子菜单)
if (快捷事件.Length > 1) this.BeginInvoke(new Action<ContextMenuStrip, string[]>((菜单名, 级位置) => 子菜单乾坤大挪移(菜单名, 级位置)), 快捷, new string[] { "0|1", "1|2", "1|2" });
这里要讲解的是子菜单参数的编写:
图中数组的第一个参数是生成第一个主子菜单0和1表示名称数组的数组序号,用 | 符号隔开,0序作为主,1作为子;
图中数组的第二个参数是生成第二个主子菜单1和2表示名称数组的数组序号,用 | 符号隔开,请注意名称数据序号由于上一级调用序号1去做子菜单了,因此不是2和3,而是应该-1,2-1=1作为主,后续的2作为子,因此写为1|2,后面的类推;
图中数组的第三个参数是生成第二个子菜单的第二项1和2表示名称数组的数组序号,用 | 符号隔开,为何和第二个是一样的?由于要在第二主生成子的第二项,同上面一样1作为主,接着的序号2作为子菜单.
这样就生成了上面图示的3级主,二级子,二项子的菜单了.
假如要把"数据文件"子菜单改到上一级子菜单的第二项,那只要修改位置参数就可以了,即把位置参数数组的第三项改为"0|2"即把主的序号改为0就把第二主子菜单的第二项移动到第一主子菜单中的第二项去了,如下图示:
让我们来还原为无子菜单来看看创建了几个菜单:
再让我们来看生成一级子菜单"0|1"后的主菜单序号的变化:
再看看生成二级子菜单"1|2"后的主菜单序号:
再看看生成二级子菜单二项"1|2"后的主菜单序号:
再来看看生成多级子菜单:
if (快捷事件.Length > 1) this.BeginInvoke(new Action<ContextMenuStrip, string[]>((菜单名, 级位置) => 子菜单乾坤大挪移(菜单名, 级位置)), 快捷, new string[] { "0|1", "0|0|1", "0|0|0|1", "0|0|0|0|1" });
修改名称参数分隔符为" "这样书写比较方便,同时修改子菜单参数为无分隔符,使用了字符串转为字符串数组的写法:
EventHandler[] 快捷事件 = new EventHandler[] { null, 提取数据_Click, null, 保存分割_Click, 保存数据_Click, (sender1, e1) => { Application.Exit(); this.Dispose(true); this.Close(); } };
this.BeginInvoke(new Action<ContextMenuStrip, string[], EventHandler[]>((菜单名, 文本图标, 事件) => 快捷菜单(菜单名, 文本图标, 事件)), 快捷, new string[] { "浩瀚 0", "提取数据 1", "保存选项 2", "分割标记 3", "数据文件 4", "退出 9" }, 快捷事件);
if (快捷事件.Length > 1) this.BeginInvoke(new Action<ContextMenuStrip, string[]>((菜单名, 级位置) => 子菜单乾坤大挪移(菜单名, 级位置)), 快捷, new string[] { "01", "12", "12" });
this.ContextMenuStrip = 快捷;
private void 快捷菜单(ContextMenuStrip 菜单名, string[] 文本图标, EventHandler[] 事件)
{
循环 = 0;
foreach (string 元素 in 文本图标)
{
string[] 列表 = 元素.Split(' ');
if (列表[0].Length > 0) 菜单名.Items.Add(列表[0]);
if (列表[1].Length > 0) 菜单名.Items[循环].Image = 图标集.Images[int.Parse(列表[1])];
if (事件 != null) if (事件[循环] != null) 菜单名.Items[循环].Click += new EventHandler(事件[循环]); 循环++;
}
菜单名.Items[0].BackColor = System.Drawing.Color.Aqua;
}
private void 子菜单乾坤大挪移(ContextMenuStrip 菜单名, string[] 级位置)
{
Func<ToolStripDropDownItem, int, ToolStripDropDownItem> 无极之菜单 = delegate(ToolStripDropDownItem 级, int 位置)
{
ToolStripDropDownItem 无极 = (ToolStripDropDownItem)级.DropDownItems[位置];
return 无极;
};
foreach (string 元素 in 级位置)
{
string[] 列表 = 元素.Select(名 => 名.ToString()).ToArray(); 循环 = 1;
ToolStripDropDownItem 菜单位置 = (ToolStripDropDownItem)菜单名.Items[int.Parse(列表[0])];
if (列表.Length > 2)//无极紫菜汤
while (列表.Length - 1 > 循环) 菜单位置 = 无极之菜单(菜单位置, int.Parse(列表[循环++]));
ToolStripItem 子菜单名 = 菜单名.Items[int.Parse(列表[列表.Length - 1])];
菜单位置.DropDownItems.Add(子菜单名);
}
}
以上是示例图文并茂的详细讲解,若还有疑问的话@我.