如何设置Winform控件的ClientRectangle

简介:
  最近学习制作WinForm控件,自己动手写控件的时候才发现System.Windows.Forms.Control 竟然没有提供默认的border绘制。记得以前用API做控件的时候,只需要设置空间窗口的WS_BORDER 风格就可以。遍寻无方,只有自己绘制了,这里有出现一个,如果border在客户区,那么在OnPaint方法里不得不每次都要考虑Border所占用的区域,而且,如果从这个类派生的话,将无法获得准确的客户区。
      现在要解决的问题就是如何重新设置客户区的矩形区域的尺寸,查看了一下Control类的ClientRectangle属性:
public Rectangle ClientRectangle { get; }是个只读属性,看来是不能通过这个属性达到目的了。再查找Control类的文档,也没有这方面的说明,没有办法,只能用API搞定了。可以通过计算非客户区尺寸来设置客户区尺寸,Border在非客户绘制。下面就是主要的代码,就是通过重载WndProc方法,捕捉WM_NCCALCSIZE消息,实现自己的逻辑。
     
protected   override   void  WndProc( ref  Message m)
{
switch (m.Msg)
{
case (int)WinAPI_WM.WM_NCCALCSIZE:
if (m.WParam.ToInt32() == 0)
{
WinAPI_RECT rc 
= (WinAPI_RECT)m.GetLParam(typeof(WinAPI_RECT));
rc.Left 
+= 1;
rc.Top 
+= 1
rc.Right 
-= 1
rc.Bottom 
-= 1;
Marshal.StructureToPtr(rc, m.LParam, 
true);
m.Result 
= IntPtr.Zero;
}

else
{
WinAPI_NCCALCSIZE_PARAMS csp;
csp 
= (WinAPI_NCCALCSIZE_PARAMS)m.GetLParam(typeof(WinAPI_NCCALCSIZE_PARAMS));
csp.rgrc0.Top 
+= 1
csp.rgrc0.Bottom 
-= 1;
csp.rgrc0.Left 
+= 1
csp.rgrc0.Right 
-= 1;

Marshal.StructureToPtr(csp, m.LParam, 
true);
//Return zero to preserve client rectangle
m.Result = IntPtr.Zero;
}

break;
case (int)WinAPI_WM.WM_NCPAINT:
{
m.WParam 
= NCPaint(m.WParam);
break;
}

}


base.WndProc(ref m);
}


public  IntPtr NCPaint(IntPtr region)
{
IntPtr hDC 
= GetWindowDC(this.Handle);
if (hDC != IntPtr.Zero)
{
Graphics grTemp 
= Graphics.FromHdc(hDC);

int ScrollBarWidth = SystemInformation.VerticalScrollBarWidth;
int ScrollBarHeight = SystemInformation.HorizontalScrollBarHeight;

WINDOWINFO wi 
= new WINDOWINFO();
wi.cbSize 
= (uint)Marshal.SizeOf(wi);

//得到当前控件的窗口信息
GetWindowInfo(Handle, ref wi);

wi.rcClient.Right
--;
wi.rcClient.Bottom
--;


//获得当前控件的区域
Region UpdateRegion = new Region(new Rectangle(wi.rcWindow.Top,wi.rcWindow.Left,wi.rcWindow.Right-wi.rcWindow.Left,wi.rcWindow.Bottom-wi.rcWindow.Top));

//获得客户区以外的区域
UpdateRegion.Exclude(new Rectangle(wi.rcClient.Top, wi.rcClient.Left, wi.rcClient.Right - wi.rcClient.Left, wi.rcClient.Bottom - wi.rcClient.Top));

if (IsHScrollVisible && IsVScrollVisible)
{
UpdateRegion.Exclude(Rectangle.FromLTRB
(wi.rcClient.Right 
+ 1, wi.rcClient.Bottom + 1,
wi.rcWindow.Right, wi.rcWindow.Bottom));
}


//得到当前区域的句柄
IntPtr hRgn = UpdateRegion.GetHrgn(grTemp);

//For Painting we need to zero offset the Rectangles.
Rectangle WindowRect = new Rectangle(wi.rcWindow.Top, wi.rcWindow.Left, wi.rcWindow.Right - wi.rcWindow.Left, wi.rcWindow.Bottom - wi.rcWindow.Top);

Point offset 
= Point.Empty - (Size)WindowRect.Location;

WindowRect.Offset(offset);

Rectangle ClientRect 
= WindowRect;

ClientRect.Inflate(
-1-1);

//Fill the BorderArea
Region PaintRegion = new Region(WindowRect);
PaintRegion.Exclude(ClientRect);
grTemp.FillRegion(SystemBrushes.Control, PaintRegion);

//Fill the Area between the scrollbars
if (IsHScrollVisible && IsVScrollVisible)
{
Rectangle ScrollRect 
= new Rectangle(ClientRect.Right - ScrollBarWidth,
ClientRect.Bottom 
- ScrollBarHeight, ScrollBarWidth + 2, ScrollBarHeight + 2);
ScrollRect.Offset(
-1-1);
grTemp.FillRectangle(SystemBrushes.Control, ScrollRect);
}


//Adjust ClientRect for Drawing Border.
ClientRect.Inflate(22);
ClientRect.Width
--;
ClientRect.Height
--;

//Draw Outer Raised Border
ControlPaint.DrawBorder3D(grTemp, WindowRect, Border3DStyle.Raised,
Border3DSide.Bottom 
| Border3DSide.Left | Border3DSide.Right | Border3DSide.Top);

//Draw Inner Sunken Border
ControlPaint.DrawBorder3D(grTemp, ClientRect, Border3DStyle.Sunken,
Border3DSide.Bottom 
| Border3DSide.Left | Border3DSide.Right | Border3DSide.Top);

ReleaseDC(Handle, hDC);

grTemp.Dispose();

return hRgn;

}


RefreshScrollBar();
return region;
}





本文转自纶巾客博客园博客,原文链接:http://www.cnblogs.com/guanjinke/archive/2006/11/29/576961.html,如需转载请自行联系原作者
目录
相关文章
|
网络协议
tcp端口转发工具v2.0.2版本发布
tcp端口转发工具v2.0.2版本发布
534 0
|
4月前
|
缓存 弹性计算 数据挖掘
阿里云服务器经济型e与通用算力型u1实例怎么选?二则性能及适用场景区别参考
在当今数字化时代,云服务器已成为众多个人开发者、学生、小微企业以及中小企业开展业务、搭建网站、运行应用程序等不可或缺的基础设施。阿里云推出了多种类型的云服务器实例,以满足不同用户的需求。其中,经济型e实例和通用算力型u1实例备受关注。经济型e实例ECS云服务器2核2G3M带宽新购和续费同价99元1年,通用算力型u1实例2核4G5M带宽新购和续费同价199元1年(限企业用户)、4核8G云服务器955元1年。本文将为大家介绍阿里云服务器中的经济型e实例和通用算力型u1实例的特点、区别以及新手选择参考。
|
设计模式 开发框架 前端开发
在DevExpress中使用BandedGridView表格实现多行表头的处理
在DevExpress中使用BandedGridView表格实现多行表头的处理
|
存储 消息中间件 API
FreeRTOS入门教程(堆和栈)
FreeRTOS入门教程(堆和栈)
564 0
|
Web App开发 安全 前端开发
『Fiddler数据抓包功攻略』| 如何使用Fiddler进行数据抓包与分析?
『Fiddler数据抓包功攻略』| 如何使用Fiddler进行数据抓包与分析?
789 0
|
数据可视化 BI C#
C#程序采用AOT发布,真的可以避免被反编译?
C#程序采用AOT发布,真的可以避免被反编译?
1621 0
|
C# 虚拟化 开发者
WPF技术之ListBox控件
WPF ListBox控件是一种用于显示和选择多个项的常用控件。它可以展示任意类型的数据,并允许用户通过鼠标或键盘进行选择操作
1466 0
|
C#
WPF获取某控件的位置,也就是偏移量
原文:WPF获取某控件的位置,也就是偏移量 此段示例在MSDN中可见。XAML代码如下:   1、如果只需要获取相对于其父级的偏移量,则可以使用以下方法: // Return the offset vector for the TextBlock object.
1596 0
|
前端开发 安全 API
深入了解CORS数据劫持漏洞
1.1. CORS介绍 CORS(跨源资源共享)是一种用于在Web应用程序中处理跨域请求的机制。当一个Web应用程序在浏览器中向不同的域(源)发起跨域请求时,浏览器会执行同源策略,限制了跨域请求的默认行为。同源策略要求Web应用程序只能访问与其本身源(协议、域名和端口)相同的资源。 然而,在某些情况下,我们希望允许来自其他源的跨域请求,例如使用AJAX进行跨域数据访问或在前端应用程序中嵌
281 0
|
NoSQL 网络协议 安全
Linux内核0-使用QEMU和GDB调试Linux内核
Linux内核0-使用QEMU和GDB调试Linux内核