动态创建无级子菜单:乾坤大挪移无极紫菜汤

首先是创建控件的声明与参数编写规则:

            /*快捷菜单*/
            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(子菜单名);
            }
        }

 

以上是示例图文并茂的详细讲解,若还有疑问的话@我.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值