【问题标题】:How to get the visible bounds of a panel如何获取面板的可见边界
【发布时间】:2010-08-10 13:44:06
【问题描述】:

我有一个面板,它可能在也可能不在其他面板中。我正在尝试确定该面板的可见边界。我认为GetWindowRectGetClientRect 可以解决问题,但没有乐趣。

为了测试这一点,我创建了一个带有面板和多行文本框的表单。面板比表单大(即它延伸到表单底部以下)

所以如果我的表格是 300 x 300。面板位于 10,10 并且是 100 x 500 我想要一些可以告诉我可见区域为 100、290 的东西(假设面板的 0,0 相对起点为 10,10。

有这样的方法吗?

我尝试了几种不同的方法,例如获取我感兴趣的面板的父句柄并对其进行测试,但我不能始终确定直接父句柄会决定可见性。

这是我为测试GetWindowRectGetClientRect 而编写的测试应用程序代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace clientRectTest
{
public partial class Form1 : Form
{
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public Int32 left;
        public Int32 top;
        public Int32 right;
        public Int32 bottom;

        public static RECT FromRectangle(Rectangle rectangle)
        {
            RECT win32rect = new RECT();
            win32rect.top = rectangle.Top;
            win32rect.bottom = rectangle.Bottom;
            win32rect.left = rectangle.Left;
            win32rect.right = rectangle.Right;
            return win32rect;
        }
    }

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
    [DllImport("user32.dll")]
    public static extern IntPtr GetWindowDC(IntPtr hWnd);


    public Form1()
    {
        InitializeComponent();
        this.AutoScrollMinSize = new Size(250, 500);

    }


    protected override void OnMouseClick(MouseEventArgs e)
    {
        NewLine("Click Location: " + e.Location.ToString());
        base.OnMouseClick(e);
    }

    protected override void OnResize(EventArgs e)
    {
        this.textBox1.Text = "Panel Size" + this.panel1.Size.ToString();

        NewLine( "Form Size" + this.Size.ToString());
        //  NewLine("Panel PARENT Client Rectangle: " + getPanelClientRectangle(this.panel1.Parent.Handle));


        NewLine("Panel Client Rectangle: " + getPanelClientRectangle(this.panel1.Handle));
        NewLine("Panel Window Rectangle: " + getPanelWindowRectangle(this.panel1.Handle));
        NewLine("Panel Window Bounts: " + this.panel1.Bounds.ToString());


        NewLine("Panel DC Client Rectangle: " + getPanelDCClientRectangle(this.panel1.Handle));
        NewLine("Panel DC Window Rectangle: " + getPanelDCWindowRectangle(this.panel1.Handle));

        NewLine("Panel Location: " + this.panel1.Location.ToString());


        base.OnResize(e);
    }

    private string getPanelDCClientRectangle(IntPtr handle)
    {
        string cr = string.Empty;

        RECT r1 = new RECT();
        IntPtr dc = GetWindowDC(handle);
        GetClientRect(dc, out r1);

        cr = r1.left.ToString() + ", " + r1.top.ToString() + ", " + r1.right.ToString()
         + ", " + r1.bottom.ToString();
        Point thisLocation = this.Location;

        return cr;
    }

    private string getPanelDCWindowRectangle(IntPtr handle)
    {
        string cr = string.Empty;

        RECT r1 = new RECT();
        IntPtr dc = GetWindowDC(handle);
        GetWindowRect(dc, out r1);

        cr = r1.left.ToString() + ", " + r1.top.ToString() + ", " + r1.right.ToString()
         + ", " + r1.bottom.ToString();
        Point thisLocation = this.Location;

        return cr;
    }

    private string getPanelWindowRectangle(IntPtr handle)
    {
        string cr = string.Empty;

        RECT r1 = new RECT();

        GetWindowRect(handle, out r1);

        cr = r1.left.ToString() + ", " + r1.top.ToString() + ", " + r1.right.ToString()
         + ", " + r1.bottom.ToString();
        Point thisLocation = this.Location;

        return cr;
    }

    private string getPanelClientRectangle(IntPtr handle)
    {
        string cr = string.Empty;

        RECT r1 = new RECT();

        GetClientRect(handle, out r1);

        cr = r1.left.ToString() + ", " + r1.top.ToString() + ", " + r1.right.ToString()
         + ", " + r1.bottom.ToString();
        Point thisLocation = this.Location;

        return cr;
    }

    private void NewLine(string p)
    {
        this.textBox1.Text += Environment.NewLine + p;
    }
}
}

编辑:找到更多信息:

我觉得行this.AutoScrollMinSize = new Size(250, 500); 搞砸了我的结果。这似乎使面板 500 即使它没有显示 500。将重做我的一些测试用例。我没想到这条线会引起问题。

【问题讨论】:

    标签: c# panel bounds


    【解决方案1】:

    您应该能够使用面板的 DisplayRectangle 属性来获取当前正在显示的矩形。此属性在 Control 中实现,但被 ScrollableControl(System.Windows.Forms.Panel 的父级)覆盖

    【讨论】:

    • 是的,我也这样做了,它给了我与客户端矩形相同的结果。所以这还是太大了。
    【解决方案2】:

    这是我最后想到的:

    WinSDK.RECT parentRect = new WinSDK.RECT();
                WinSDK.RECT intersectRect = new WinSDK.RECT();
    
                Rectangle parentRectangle = new Rectangle();
                Rectangle intersectRectangle = new Rectangle();
    
                // Get the current Handle.
                IntPtr currentHandle = this.Handle;
    
                // Get next Parent Handle.
                IntPtr parentHandle = WinSDK.GetParent(this.Handle);
    
                // Get the Rect for the current Window.
                WinSDK.GetWindowRect(this.Handle, out intersectRect);
    
                // Load Current Window Rect into a System.Drawing.Rectangle
                intersectRectangle = new Rectangle(intersectRect.left, intersectRect.top, intersectRect.right - intersectRect.left, intersectRect.bottom - intersectRect.top );
    
                // Itterate through all parent windows and get the overlap of the visible areas to find out what's actually visible.
                while (parentHandle != IntPtr.Zero)
                {
                    // Get the Rect for the Parent Window.
                    WinSDK.GetWindowRect(parentHandle, out parentRect);
                    parentRectangle = new Rectangle(parentRect.left, parentRect.top, parentRect.right - parentRect.left, parentRect.bottom - parentRect.top);
    
                    // Get the intersect between the current and parent window.
                    intersectRectangle.Intersect(parentRectangle);
    
                    // Set up for next loop.
                    currentHandle = parentHandle;
                    parentHandle = WinSDK.GetParent(currentHandle);
                }
    
                return intersectRectangle;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-26
      • 1970-01-01
      • 2019-08-06
      • 1970-01-01
      • 2016-04-06
      • 2023-04-06
      • 1970-01-01
      相关资源
      最近更新 更多