C# 选项卡高度不反映自定义/userpaint TabControl上的高DPI

C# 选项卡高度不反映自定义/userpaint TabControl上的高DPI,c#,winforms,tabcontrol,highdpi,C#,Winforms,Tabcontrol,Highdpi,我已经编写了一个定制的TabControl类,但是我无法使选项卡在高DPI屏幕上调整其高度。在缩放比例为200%的屏幕上,实际选项卡页面及其控件覆盖了选项卡的一半,如下所示: 显然,TabControl没有调整选项卡高度以适应较大的字体,因此,实际页面的顶部太高,覆盖了我的选项卡。我可以做些什么来强制调整选项卡 表单的AutoScaleMode设置为Dpi,除此之外,其他一切看起来都很好。我的目标是.NET4.5.2,并且清单文件中的dpiAware设置被设置为true 以下是自定义TabCo

我已经编写了一个定制的TabControl类,但是我无法使选项卡在高DPI屏幕上调整其高度。在缩放比例为200%的屏幕上,实际选项卡页面及其控件覆盖了选项卡的一半,如下所示:

显然,TabControl没有调整选项卡高度以适应较大的字体,因此,实际页面的顶部太高,覆盖了我的选项卡。我可以做些什么来强制调整选项卡

表单的AutoScaleMode设置为Dpi,除此之外,其他一切看起来都很好。我的目标是.NET4.5.2,并且清单文件中的dpiAware设置被设置为true

以下是自定义TabControl的代码:

/// <summary>
/// A TabControl without 3D borders and other annoyances. Taken from
/// https://stackoverflow.com/questions/27469886/change-color-of-unused-space-of-tabcontrol/27472230
/// 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);
    }
}
//
///没有3D边框和其他麻烦的选项卡控件。取自
/// https://stackoverflow.com/questions/27469886/change-color-of-unused-space-of-tabcontrol/27472230
///和修改。
/// 
公共类CleanTabControl:TabControl
{
私有类本地方法
{
[DllImport(“user32.dll”)]公共静态外部IntPtr SendMessage(IntPtr hWnd、int Msg、IntPtr wParam、IntPtr lParam);
}
私有常量int WM_SETFONT=0x30;
私有常量int WM_FONTCHANGE=0x1d;
private int hoverTab=-1;
公共事件鼠标eventhandler CloseClick;
公共控制()
{
//完全接管绘画,我们需要透明度和双缓冲
设置样式(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor,true);
DoubleBuffered=ResizeRedraw=true;
}
受保护的重写void OnCreateControl()
{
//为制表符提供正确宽度所必需的
base.OnCreateControl();
OnFontChanged(EventArgs.Empty);
}
受保护的覆盖无效OnFontChanged(事件参数e)
{
//为制表符提供正确宽度所必需的
基数(e);
IntPtr hFont=Font.ToHfont();
发送消息(Handle,WM_SETFONT,hFont,(IntPtr)-1);
NativeMethods.SendMessage(Handle、WM_FONTCHANGE、IntPtr.Zero、IntPtr.Zero);
UpdateStyles();
}
公共覆盖颜色背景色
{
//覆盖TabControl.BackColor,我们需要透明度
获取{return Color.Transparent;}
设置{base.BackColor=Color.Transparent;}
}
受保护的覆盖无效OnPaint(PaintEventArgs e)
{
//…大量的绘画代码
}
鼠标单击时受保护的覆盖无效(鼠标目标e)
{
base.OnMouseClick(e);
如果(SelectedTab!=null)
{
if(GetImageRectangle(SelectedIndex).Contains(如位置))
CloseClick(这个,e);
}
}
MouseMove上的受保护覆盖无效(MouseEventArgs e)
{
基地移动(e);
hoverTab=-1;
for(int i=0;i

}我找到了解决办法。在OnCreateControl()中,添加:


其中DpiRatio是比例因子(例如,200%的比例为2)。

因此该问题只在高dpi监视器上显示,而不在其他监视器上显示?是的,没错。在普通显示器上,选项卡高度为19像素,页面区域从y=19开始。在高dpi显示器上,这些数字应该是~38像素以适应较大的字体,但仍然是19。
ItemSize = new Size(ItemSize.Width, ItemSize.Height * DpiRatio);