上下文菜单滚动按钮

3
我目前正在开发一个Windows触摸应用程序。一些WinForm代码仍然存在。您可以看到滚动/箭头按钮的高度对于触摸按钮来说太小了。有没有办法将高度增加到35/40像素?
以下链接是VS2012 c#示例项目下载页面。 在这里下载示例 谢谢。

不,ContextMenuStrip没有将此作为选项公开。设计一个可以用粗手指操作的触摸界面确实需要放弃您熟悉的小玩意儿。这包括上下文菜单,调用右键单击事件通常会给用户带来困难。您需要使用可用宽度,设计子菜单。 - Hans Passant
触摸屏应用?选择WPF并自定义一切。 - Abdul Saleem
将此代码转换为WPF不是一个选择。该应用程序的大部分已更改为WPF,但在我们当前的时间表内将该部分切换是不可能的。 - cricardol
@HansPassant 这个上下文菜单不是通过右键单击显示的。它是通过单击自定义按钮显示的。 - cricardol
为什么不放弃使用ContextMenuStrip,创建自定义控件呢?这样你就可以按照自己的想法设计它,例如使箭头变大等。 - ravenx30
1个回答

4
这个解决方案列举了ContextMenuStrip的子窗口。可能会出现两个子窗口(滚动按钮)或零个子窗口。
用于滚动按钮的控件是标签, 默认使用小的9x5图像。 图像将更新为较大的图像(使用Marlett字体),然后设置AutoSize为true,这会导致标签自动调整大小。 编辑:更改实现为扩展方法以获得更好的灵活性。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Opulos.Core.UI {

///<summary>Extension class to increase the size of the scroll up-down arrows on a drop down context menu or tool strip menu. The default up-down arrows are only 5 pixels high.</summary>
public static class ToolStripEx {

    private static Hashtable htData = new Hashtable();

    private class Data {
        public bool needsUpdate = true;
        public bool disposeLastImage = false;
        public ToolStrip toolStrip = null;
        public List<Image> currentImages = new List<Image>();
    }

    public static void BigButtons(this ToolStrip toolStrip) {
        htData[toolStrip] = new Data() { toolStrip = toolStrip };
        toolStrip.VisibleChanged += toolStrip_VisibleChanged;
        toolStrip.ForeColorChanged += toolStrip_ForeColorChanged;
        toolStrip.Disposed += toolStrip_Disposed;
    }

    static void toolStrip_Disposed(object sender, EventArgs e) {
        Data d = (Data) htData[sender];
        if (d != null && d.currentImages != null) {
            foreach (var img in d.currentImages)
                img.Dispose();
            d.currentImages = null;
            htData.Remove(sender);
        }
    }

    static void toolStrip_ForeColorChanged(object sender, EventArgs e) {
        Data d = (Data) htData[sender];
        d.needsUpdate = true;
        UpdateImages(d);
    }

    static void toolStrip_VisibleChanged(object sender, EventArgs e) {
        Data d = (Data) htData[sender];
        UpdateImages(d);
    }

    private static void UpdateImages(Data d) {
        if (!d.needsUpdate)
            return;

        d.toolStrip.BeginInvoke((Action) delegate {
            try {
                var list = GetChildWindows(d.toolStrip.Handle);
                if (list.Count == 0)
                    return;

                List<Image> newImages = new List<Image>();
                int k = 0;

                foreach (var i in list) {
                    var c = Control.FromHandle(i) as Label;
                    if (c != null && d.needsUpdate) {
                        String glyph = (k == 0 ? "t" : "u");
                        using (Font f = new System.Drawing.Font("Marlett", 20f)) {
                            Size s = TextRenderer.MeasureText("t", f);
                            var oldImage = c.Image;
                            c.Image = new Bitmap(s.Width, s.Height);
                            newImages.Add(c.Image);
                            // avoid disposing the default image
                            // might cause problems, not sure
                            if (d.disposeLastImage)
                                oldImage.Dispose();
                            using (Graphics g = Graphics.FromImage(c.Image)) {
                                using (Brush b = new SolidBrush(d.toolStrip.ForeColor))
                                    g.DrawString(glyph, f, b, 0, 0);
                            }
                            c.AutoSize = true;
                        }
                        k++;
                    }
                }
                if (newImages.Count > 0) {
                    d.needsUpdate = false;
                    d.disposeLastImage = true;
                    d.currentImages = newImages;
                }
            } catch {} // protect against crash (just in case)
        });
    }

    private static List<IntPtr> GetChildWindows(IntPtr parent) {
        List<IntPtr> result = new List<IntPtr>();
        GCHandle listHandle = GCHandle.Alloc(result);
        try {
            EnumChildWindows(parent, enumProc, GCHandle.ToIntPtr(listHandle));
        } finally {
            if (listHandle.IsAllocated)
                listHandle.Free();
        }
        return result;
    }

    private delegate bool EnumChildProc(IntPtr hWnd, IntPtr lParam);
    private static EnumChildProc enumProc = new EnumChildProc(CallChildEnumProc);
    private static bool CallChildEnumProc(IntPtr hWnd, IntPtr lParam) {
        GCHandle gch = GCHandle.FromIntPtr(lParam);
        List<IntPtr> list = gch.Target as List<IntPtr>;
        if (list == null)
            throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");

        list.Add(hWnd);
        return true;
    }

    [DllImport("user32.dll")]
    private static extern bool EnumChildWindows(IntPtr hWndParent, EnumChildProc lpEnumFunc, IntPtr lParam);
}
}

        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            var cms = new ContextMenuStrip();
            cms.BigButtons();
            for (int i = 0; i < 20; i++)
                cms.Items.Add(new ToolStripMenuItem("Item " + i));
            cms.MaximumSize = new Size(200, 400);
            Form f = new Form();
            f.ContextMenuStrip = cms;
            Application.Run(f);
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接