Tab 高度不反映 custom/userpaint TabControl 上的高 DPI
Tab height does not reflect high DPI on custom/userpaint TabControl
我已经编写了一个自定义 TabControl class,但是我无法让选项卡在高 DPI 屏幕上调整它们的高度。在缩放比例为 200% 的屏幕上,选项卡被实际选项卡页面及其控件半覆盖,如下所示:
显然 TabControl 没有调整选项卡高度以适应较大的字体,因此,实际页面的顶部太高并盖住了我的选项卡。我可以做些什么来强制选项卡适应?
表单将 AutoScaleMode 设置为 Dpi,其他一切看起来都很好,除了这个。我的目标是 .NET 4.5.2,清单文件中的 dpiAware 设置设置为 true。
这是我的自定义 TabControl 代码:
/// <summary>
/// A TabControl without 3D borders and other annoyances. Taken from
///
/// and modified.
/// </summary>
public class CleanTabControl : TabControl
{
private class NativeMethods
{
[DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
}
private const int WM_SETFONT = 0x30;
private const int WM_FONTCHANGE = 0x1d;
private int hoverTab = -1;
public event MouseEventHandler CloseClick;
public CleanTabControl()
{
// Take over the painting completely, we want transparency and double-buffering
SetStyle(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true);
DoubleBuffered = ResizeRedraw = true;
}
protected override void OnCreateControl()
{
// Necessary to give tabs the correct width
base.OnCreateControl();
OnFontChanged(EventArgs.Empty);
}
protected override void OnFontChanged(EventArgs e)
{
// Necessary to give tabs the correct width
base.OnFontChanged(e);
IntPtr hFont = Font.ToHfont();
NativeMethods.SendMessage(Handle, WM_SETFONT, hFont, (IntPtr)(-1));
NativeMethods.SendMessage(Handle, WM_FONTCHANGE, IntPtr.Zero, IntPtr.Zero);
UpdateStyles();
}
public override Color BackColor
{
// Override TabControl.BackColor, we need transparency
get { return Color.Transparent; }
set { base.BackColor = Color.Transparent; }
}
protected override void OnPaint(PaintEventArgs e)
{
// ... lot of painting code
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
if (SelectedTab != null)
{
if (GetImageRectangle(SelectedIndex).Contains(e.Location))
CloseClick(this, e);
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
hoverTab = -1;
for (int i = 0; i < TabCount; i++)
{
if (GetTabRect(i).Contains(e.Location))
{
if (GetImageRectangle(i).Contains(e.Location))
TabPages[i].ImageIndex = 1;
else
{
hoverTab = i;
TabPages[i].ImageIndex = 0;
}
}
else
TabPages[i].ImageIndex = 0;
}
Invalidate();
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
hoverTab = -1;
for (int i = 0; i < TabCount; i++)
{
TabPages[i].ImageIndex = 0;
}
Invalidate();
}
private Rectangle GetImageRectangle(int index)
{
Rectangle r = GetTabRect(index);
int width = ImageList.ImageSize.Width;
int height = ImageList.ImageSize.Height;
int x = r.Right - width - Padding.X;
int y = (r.Top + r.Height - height) / 2 + 1;
if (index != SelectedIndex)
y += 1;
return new Rectangle(x, y, width, height);
}
}
}
我找到了解决方案。在 OnCreateControl() 中,添加:
ItemSize = new Size(ItemSize.Width, ItemSize.Height * DpiRatio);
其中 DpiRatio 是比例因子(例如 2 表示 200% 比例)。
我已经编写了一个自定义 TabControl class,但是我无法让选项卡在高 DPI 屏幕上调整它们的高度。在缩放比例为 200% 的屏幕上,选项卡被实际选项卡页面及其控件半覆盖,如下所示:
显然 TabControl 没有调整选项卡高度以适应较大的字体,因此,实际页面的顶部太高并盖住了我的选项卡。我可以做些什么来强制选项卡适应?
表单将 AutoScaleMode 设置为 Dpi,其他一切看起来都很好,除了这个。我的目标是 .NET 4.5.2,清单文件中的 dpiAware 设置设置为 true。
这是我的自定义 TabControl 代码:
/// <summary>
/// A TabControl without 3D borders and other annoyances. Taken from
///
/// and modified.
/// </summary>
public class CleanTabControl : TabControl
{
private class NativeMethods
{
[DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
}
private const int WM_SETFONT = 0x30;
private const int WM_FONTCHANGE = 0x1d;
private int hoverTab = -1;
public event MouseEventHandler CloseClick;
public CleanTabControl()
{
// Take over the painting completely, we want transparency and double-buffering
SetStyle(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true);
DoubleBuffered = ResizeRedraw = true;
}
protected override void OnCreateControl()
{
// Necessary to give tabs the correct width
base.OnCreateControl();
OnFontChanged(EventArgs.Empty);
}
protected override void OnFontChanged(EventArgs e)
{
// Necessary to give tabs the correct width
base.OnFontChanged(e);
IntPtr hFont = Font.ToHfont();
NativeMethods.SendMessage(Handle, WM_SETFONT, hFont, (IntPtr)(-1));
NativeMethods.SendMessage(Handle, WM_FONTCHANGE, IntPtr.Zero, IntPtr.Zero);
UpdateStyles();
}
public override Color BackColor
{
// Override TabControl.BackColor, we need transparency
get { return Color.Transparent; }
set { base.BackColor = Color.Transparent; }
}
protected override void OnPaint(PaintEventArgs e)
{
// ... lot of painting code
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
if (SelectedTab != null)
{
if (GetImageRectangle(SelectedIndex).Contains(e.Location))
CloseClick(this, e);
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
hoverTab = -1;
for (int i = 0; i < TabCount; i++)
{
if (GetTabRect(i).Contains(e.Location))
{
if (GetImageRectangle(i).Contains(e.Location))
TabPages[i].ImageIndex = 1;
else
{
hoverTab = i;
TabPages[i].ImageIndex = 0;
}
}
else
TabPages[i].ImageIndex = 0;
}
Invalidate();
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
hoverTab = -1;
for (int i = 0; i < TabCount; i++)
{
TabPages[i].ImageIndex = 0;
}
Invalidate();
}
private Rectangle GetImageRectangle(int index)
{
Rectangle r = GetTabRect(index);
int width = ImageList.ImageSize.Width;
int height = ImageList.ImageSize.Height;
int x = r.Right - width - Padding.X;
int y = (r.Top + r.Height - height) / 2 + 1;
if (index != SelectedIndex)
y += 1;
return new Rectangle(x, y, width, height);
}
}
}
我找到了解决方案。在 OnCreateControl() 中,添加:
ItemSize = new Size(ItemSize.Width, ItemSize.Height * DpiRatio);
其中 DpiRatio 是比例因子(例如 2 表示 200% 比例)。