时间:2019-03-17 标签:c#.NET 2.0 Zoom-Scroll Bar

发布于 2024-11-14 13:16:46 字数 299 浏览 1 评论 0原文

我正在寻找一种允许用户同时缩放和滚动的控件。它基本上需要像 Sony Sound Forge 那样,请参见此屏幕截图的底部: 在此处输入图像描述

它的外观和行为类似于普通滚动条,此外您还可以将边缘拖动到左侧并向右放大/缩小图表。即使为用户提供了放大和滚动的替代方法(例如通过拖动图表本身上的区域),我仍然认为这样的组件很有用,因为它为用户提供了数据中位置和图表位置的直接视觉反馈。已应用的缩放量。

这样的组件是否存在或者我需要自己创建它?欢迎任何帮助。

I am looking for a control that allows users to zoom and scroll at the same time. It basically needs to be something like Sony Sound Forge has, see bottom of this screenshot:
enter image description here

It looks and behaves like a normal scroll bar, with the addition that you can drag the edges to the left and right making the chart zoom in/out. Even if the user would be offered alternative ways to zoom in and scroll (e.g. by dragging an area on the chart itself) I still think such a component is useful because it gives the user a direct visual feedback of the position in the data and the amount of zooming that has been applied.

Does such a component exist or do I need to create it myself? Any help is welcome.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蘑菇王子 2024-11-21 13:16:47

我认为这是非常具体的控制,但我认为它不存在。另外,我认为自己创建它会比搜索它甚至等待有人回答这个问题更快。

要像 Sound Forge 中那样绘制自定义按钮,您可以使用 WinAPI 函数 DrawThemeBackground

我做了一些简短的例子:

在此处输入图像描述

public partial class Form1 : Form
{
    readonly Int32 ScrollBarWidth;
    readonly Int32 ScrollBarHeight;



    public Form1()
    {
        InitializeComponent();

        ScrollBarWidth  = GetSystemMetrics(SM_CYVSCROLL);
        ScrollBarHeight = GetSystemMetrics(SM_CYHSCROLL);
    }



    private void panel1_Paint(object sender, PaintEventArgs e)
    {
        Int32 ZoomMarkerSize = 6;

        Graphics G      = e.Graphics;
        Int32 SBWidth   = ScrollBarWidth;
        Int32 SBHeight  = ScrollBarHeight;

        DrawCustomScrollButton(G, 0, 0, SBWidth, SBHeight, Resources.Plus,
            (int) SCROLLBARSTYLESTATES.SCRBS_NORMAL);
        DrawCustomScrollButton(G, SBWidth, 0, ZoomMarkerSize, SBHeight, null,
            (int) SCROLLBARSTYLESTATES.SCRBS_NORMAL);
        DrawCustomScrollButton(G, SBWidth + ZoomMarkerSize, 0, SBWidth, SBHeight, Resources.Minus,
            (int) SCROLLBARSTYLESTATES.SCRBS_HOT);
    }



    public void DrawCustomScrollButton (Graphics aG, Int32 aX, Int32 aY, Int32 aWidth, Int32 aHeight,
        Image aImage, Int32 aState)
    {
        RECT R = new RECT () { left = aX, top = aY, right = aX + aWidth, bottom = aY + aHeight };
        RECT NotUsed = R;

        IntPtr ThemeHandle  = OpenThemeData(this.Handle, "SCROLLBAR");
        IntPtr HDC          = aG.GetHdc();

        DrawThemeBackground
        (
            ThemeHandle, HDC,
            (int) SCROLLBARPARTS.SBP_THUMBBTNHORZ,
            aState,
            ref R, ref NotUsed
        );

        aG.ReleaseHdc(HDC);
        CloseThemeData(ThemeHandle);

        if (aImage != null)
        {
            aG.DrawImage(aImage,
                aX + ((ScrollBarHeight - aImage.Width   ) / 2),
                aY + ((ScrollBarHeight - aImage.Height  ) / 2));
        }
    }



    public struct RECT
    {
        public Int32 left; 
        public Int32 top; 
        public Int32 right; 
        public Int32 bottom; 
    }

    [DllImport("user32.dll")]
    public static extern int GetSystemMetrics(int smIndex);

    [DllImport("uxtheme.dll", ExactSpelling=true)]
    public extern static Int32 DrawThemeBackground(IntPtr hTheme, IntPtr hdc, int iPartId,
       int iStateId, ref RECT pRect, ref RECT pClipRect);

    [DllImport("uxtheme.dll", ExactSpelling=true, CharSet=CharSet.Unicode)]
    public static extern IntPtr OpenThemeData(IntPtr hWnd, String classList);

    [DllImport("uxtheme.dll", ExactSpelling=true)]
    public extern static Int32 CloseThemeData(IntPtr hTheme);

    public int SM_CYHSCROLL = 3;
    public int SM_CYVSCROLL = 20;

    public int SBP_ARROWBTN = 1;

    public int ABS_UPNORMAL = 1;
    public int ABS_UPHOT = 2;
    public int ABS_UPHOVER = 17;

    public enum ARROWBTNSTATES {
        ABS_UPNORMAL = 1,
        ABS_UPHOT = 2,
        ABS_UPPRESSED = 3,
        ABS_UPDISABLED = 4,
        ABS_DOWNNORMAL = 5,
        ABS_DOWNHOT = 6,
        ABS_DOWNPRESSED = 7,
        ABS_DOWNDISABLED = 8,
        ABS_LEFTNORMAL = 9,
        ABS_LEFTHOT = 10,
        ABS_LEFTPRESSED = 11,
        ABS_LEFTDISABLED = 12,
        ABS_RIGHTNORMAL = 13,
        ABS_RIGHTHOT = 14,
        ABS_RIGHTPRESSED = 15,
        ABS_RIGHTDISABLED = 16,
        ABS_UPHOVER = 17,
        ABS_DOWNHOVER = 18,
        ABS_LEFTHOVER = 19,
        ABS_RIGHTHOVER = 20,
    };

    public enum SCROLLBARSTYLESTATES {
        SCRBS_NORMAL = 1,
        SCRBS_HOT = 2,
        SCRBS_PRESSED = 3,
        SCRBS_DISABLED = 4,
        SCRBS_HOVER = 5,
    };

    public enum SCROLLBARPARTS {
        SBP_ARROWBTN = 1,
        SBP_THUMBBTNHORZ = 2,
        SBP_THUMBBTNVERT = 3,
        SBP_LOWERTRACKHORZ = 4,
        SBP_UPPERTRACKHORZ = 5,
        SBP_LOWERTRACKVERT = 6,
        SBP_UPPERTRACKVERT = 7,
        SBP_GRIPPERHORZ = 8,
        SBP_GRIPPERVERT = 9,
        SBP_SIZEBOX = 10,
    };
}

以下是表单源文件和两个资源测试 PNG 图像:
滚动条-with-zoom-example.zip

检查 MSDN 以获取有关此 API 的其他信息,并检查 PINVOKE.NET 站点以获取函数签名。

编辑

更好的解决方案是使用VisualStyleRenderer类。抱歉第一个复杂的例子。我之前不知道有这个班级。因此,我的 DrawCustomScrollButton 函数应该被替换:

public void DrawCustomScrollButton (Graphics aG, Int32 aX, Int32 aY, Int32 aWidth, Int32 aHeight,
    Image aImage, Int32 aState)
{
    Rectangle R = new Rectangle(aX, aY, aX + aWidth, aY + aHeight);

    VisualStyleRenderer Renderer = new VisualStyleRenderer
    (
        VisualStyleElement.ScrollBar.ThumbButtonHorizontal.Normal
    );

    Renderer.DrawBackground(aG, R);

    if (aImage != null)
    {
        aG.DrawImage(aImage,
            aX + ((ScrollBarHeight - aImage.Width   ) / 2),
            aY + ((ScrollBarHeight - aImage.Height  ) / 2));
    }
}

编辑 2

考虑到您的评论,我重新尝试重新创建此自定义控件。主要想法是使用标准 ScrollBar 并将缩放标记放在其上方(两个面板控件)。乍一看似乎很容易。但将这些组件组合在一起比我想象的要困难。

主要问题是很难改变系统ScrollBar 控件的行为。我发现它不允许处理 Windows 消息队列中我想要覆盖的某些事件。例如 MouseUp 事件和其他一些事件。

最后,我认为唯一正确的方法是从头开始重新创建自己的 ScrollBar 控件副本,其中不会有这些约束。因此,最初我走错了路,不幸的是没有解决你的任务。

无论如何,这是我当前的结果(完整的解决方案):
滚动条-with-zoom-3.zip

I think that is very specific control and I don't think that it exists. Also I think it will be faster to create it by yourself, than search for it or even wait when someone answer this question.

To draw custom buttons like in Sound Forge you may use WinAPI function DrawThemeBackground.

I make some short example:

enter image description here

public partial class Form1 : Form
{
    readonly Int32 ScrollBarWidth;
    readonly Int32 ScrollBarHeight;



    public Form1()
    {
        InitializeComponent();

        ScrollBarWidth  = GetSystemMetrics(SM_CYVSCROLL);
        ScrollBarHeight = GetSystemMetrics(SM_CYHSCROLL);
    }



    private void panel1_Paint(object sender, PaintEventArgs e)
    {
        Int32 ZoomMarkerSize = 6;

        Graphics G      = e.Graphics;
        Int32 SBWidth   = ScrollBarWidth;
        Int32 SBHeight  = ScrollBarHeight;

        DrawCustomScrollButton(G, 0, 0, SBWidth, SBHeight, Resources.Plus,
            (int) SCROLLBARSTYLESTATES.SCRBS_NORMAL);
        DrawCustomScrollButton(G, SBWidth, 0, ZoomMarkerSize, SBHeight, null,
            (int) SCROLLBARSTYLESTATES.SCRBS_NORMAL);
        DrawCustomScrollButton(G, SBWidth + ZoomMarkerSize, 0, SBWidth, SBHeight, Resources.Minus,
            (int) SCROLLBARSTYLESTATES.SCRBS_HOT);
    }



    public void DrawCustomScrollButton (Graphics aG, Int32 aX, Int32 aY, Int32 aWidth, Int32 aHeight,
        Image aImage, Int32 aState)
    {
        RECT R = new RECT () { left = aX, top = aY, right = aX + aWidth, bottom = aY + aHeight };
        RECT NotUsed = R;

        IntPtr ThemeHandle  = OpenThemeData(this.Handle, "SCROLLBAR");
        IntPtr HDC          = aG.GetHdc();

        DrawThemeBackground
        (
            ThemeHandle, HDC,
            (int) SCROLLBARPARTS.SBP_THUMBBTNHORZ,
            aState,
            ref R, ref NotUsed
        );

        aG.ReleaseHdc(HDC);
        CloseThemeData(ThemeHandle);

        if (aImage != null)
        {
            aG.DrawImage(aImage,
                aX + ((ScrollBarHeight - aImage.Width   ) / 2),
                aY + ((ScrollBarHeight - aImage.Height  ) / 2));
        }
    }



    public struct RECT
    {
        public Int32 left; 
        public Int32 top; 
        public Int32 right; 
        public Int32 bottom; 
    }

    [DllImport("user32.dll")]
    public static extern int GetSystemMetrics(int smIndex);

    [DllImport("uxtheme.dll", ExactSpelling=true)]
    public extern static Int32 DrawThemeBackground(IntPtr hTheme, IntPtr hdc, int iPartId,
       int iStateId, ref RECT pRect, ref RECT pClipRect);

    [DllImport("uxtheme.dll", ExactSpelling=true, CharSet=CharSet.Unicode)]
    public static extern IntPtr OpenThemeData(IntPtr hWnd, String classList);

    [DllImport("uxtheme.dll", ExactSpelling=true)]
    public extern static Int32 CloseThemeData(IntPtr hTheme);

    public int SM_CYHSCROLL = 3;
    public int SM_CYVSCROLL = 20;

    public int SBP_ARROWBTN = 1;

    public int ABS_UPNORMAL = 1;
    public int ABS_UPHOT = 2;
    public int ABS_UPHOVER = 17;

    public enum ARROWBTNSTATES {
        ABS_UPNORMAL = 1,
        ABS_UPHOT = 2,
        ABS_UPPRESSED = 3,
        ABS_UPDISABLED = 4,
        ABS_DOWNNORMAL = 5,
        ABS_DOWNHOT = 6,
        ABS_DOWNPRESSED = 7,
        ABS_DOWNDISABLED = 8,
        ABS_LEFTNORMAL = 9,
        ABS_LEFTHOT = 10,
        ABS_LEFTPRESSED = 11,
        ABS_LEFTDISABLED = 12,
        ABS_RIGHTNORMAL = 13,
        ABS_RIGHTHOT = 14,
        ABS_RIGHTPRESSED = 15,
        ABS_RIGHTDISABLED = 16,
        ABS_UPHOVER = 17,
        ABS_DOWNHOVER = 18,
        ABS_LEFTHOVER = 19,
        ABS_RIGHTHOVER = 20,
    };

    public enum SCROLLBARSTYLESTATES {
        SCRBS_NORMAL = 1,
        SCRBS_HOT = 2,
        SCRBS_PRESSED = 3,
        SCRBS_DISABLED = 4,
        SCRBS_HOVER = 5,
    };

    public enum SCROLLBARPARTS {
        SBP_ARROWBTN = 1,
        SBP_THUMBBTNHORZ = 2,
        SBP_THUMBBTNVERT = 3,
        SBP_LOWERTRACKHORZ = 4,
        SBP_UPPERTRACKHORZ = 5,
        SBP_LOWERTRACKVERT = 6,
        SBP_UPPERTRACKVERT = 7,
        SBP_GRIPPERHORZ = 8,
        SBP_GRIPPERVERT = 9,
        SBP_SIZEBOX = 10,
    };
}

Here are form source files and two test PNG images for resources:
scrollbar-with-zoom-example.zip

Check MSDN for additional info about this API and PINVOKE.NET site for function signatures.

EDIT

More better solution is to use VisualStyleRenderer class. Sorry for first complicate example. I did not know about that class before. So my DrawCustomScrollButton function should be replaced:

public void DrawCustomScrollButton (Graphics aG, Int32 aX, Int32 aY, Int32 aWidth, Int32 aHeight,
    Image aImage, Int32 aState)
{
    Rectangle R = new Rectangle(aX, aY, aX + aWidth, aY + aHeight);

    VisualStyleRenderer Renderer = new VisualStyleRenderer
    (
        VisualStyleElement.ScrollBar.ThumbButtonHorizontal.Normal
    );

    Renderer.DrawBackground(aG, R);

    if (aImage != null)
    {
        aG.DrawImage(aImage,
            aX + ((ScrollBarHeight - aImage.Width   ) / 2),
            aY + ((ScrollBarHeight - aImage.Height  ) / 2));
    }
}

EDIT 2

Considering your comments, I made new try to recreate this custom control. Main idea was to use standart ScrollBar and put zoom markers above it (two Panel controls). It looks easy at first sight. But to combine these components together was more difficult than I thought.

The main problem is that difficult to alter behavior of system ScrollBar control. I found out that it does not allow to handle some events in windows message queue that I wanted to override. For example MouseUp event and some other.

In the end, I think the only right way is to recreate own copy of ScrollBar control from scratch in which will not have these constraints. Because of that, initially I went the wrong way and unfortunately did not solve your task.

Anyway here my current results (full solution):
scrollbar-with-zoom-3.zip

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文