ContextMenuStrip 向上或向下滚动按钮
ContextMenuStrip scroll up or down button
我目前正在开发 windows 触摸应用程序。一些 winForm 代码仍然存在。如您所见,scroll/arrow 按钮的高度对于触摸按钮来说确实太小了。有没有办法将高度增加到 35/40 像素?
下面link是一个VS2012 c#实例工程下载页面。
download example here
谢谢。
此解决方案枚举了 ContextMenuStrip
的 child windows。可能会出现两个 child windows(滚动按钮)或零个 child windows.
用于滚动按钮的控件是一个标签,默认使用一个 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);
}
我目前正在开发 windows 触摸应用程序。一些 winForm 代码仍然存在。如您所见,scroll/arrow 按钮的高度对于触摸按钮来说确实太小了。有没有办法将高度增加到 35/40 像素?
下面link是一个VS2012 c#实例工程下载页面。 download example here
谢谢。
此解决方案枚举了 ContextMenuStrip
的 child windows。可能会出现两个 child windows(滚动按钮)或零个 child windows.
用于滚动按钮的控件是一个标签,默认使用一个 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);
}