如何获得面板的可见边界
问题描述:
我有一个面板可能或可能不在其他面板内。我正在努力解决该小组的可见范围。我认为GetWindowRect
或GetClientRect
会做的伎俩,但没有喜悦。如何获得面板的可见边界
为了测试这个,我创建了一个带有面板和多行文本框的窗体。面板比表格大(即它伸展到表格底部以下)
所以如果我的表格是300的300.并且面板位于10,10并且是100的500 我想要一些会告诉我,可视面积是100,290(假设面板0,0的相对起点,这将是在10,10在所有。
难道这样的方法存在吗?
我曾尝试一些不同的方法,例如获得我感兴趣的面板的父母手柄并进行测试,但是我不能总是确定直接父母是确定可见性的那个人。
下面是测试应用程序的我写的测试GetWindowRect
代码或GetClientRect
:
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.将重做我的一些测试用例。我不会想到这条线会导致问题。
答
这是我最终想出了:
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;
答
您应该能够使用面板的DisplayRectangle属性来获取当前正在显示的矩形。该酒店在控制中实现,而是由ScrollableControl(System.Windows.Forms.Panel的母公司)重写
是啊,我是TREID同样,它给了我与客户矩形相同的结果。所以这仍然太大。 – AidanO 2010-08-10 14:02:07