C#实现窗体控件随窗体大小改变(包括字体大小)

private float X;
private float Y;
private void setTag(Control cons)
foreach (Control con in cons.Controls)
{
    con.Tag = con.Width +":" + con.Height + ":" + con.Left + ":" + con.Top + ":" + con.Font.Size;
    if (con.Controls.Count > 0)
    setTag(con);
}
}
private void setControls(float newx, float newy, Control cons)
{
	 foreach (Control con in cons .Controls )
{
string[] mytag = con.Tag.ToString().Split(new char[] { ':' });
float a = Convert.ToSingle(mytag[0]) * newx;
con.Width = (int)a;
a=Convert.ToSingle(mytag[1]) * newy;
con.Height = (int)(a);
a=Convert.ToSingle(mytag[2]) * newx;
con.Left = (int)(a);
a=Convert.ToSingle(mytag[3]) * newy;
con.Top = (int)(a);
Single currentSize = Convert.ToSingle (mytag[4]) * Math.Min(newx,newy);
con .Font =new Font (con.Font .Name ,currentSize,con.Font .Style ,con.Font .Unit );
if(con.Controls .Count >0)
{
	 setControls (newx ,newy ,con );
}
}
}
void Form1_Resize(object sender, EventArgs e)
{
    float newx = (this.Width )/ X;
    float newy = this.Height / Y;
    setControls(newx, newy, this);
    this.Text = this.Width.ToString() +" "+ this.Height.ToString();
}

在Form_Load里面添加:
this.Resize += new EventHandler(Form1_Resize);
//X = this.Width;
//Y = this.Height;
setTag (this);
Form1_Resize(new object(),new EventArgs());//x,y可在实例化时赋值,最后这句是新加的,在MDI时有用​
当控件比较多时,每次改变窗体大小都会有明显的闪烁​
为什么会闪烁?
因为窗体控件状态转换时,windows需要负责"擦除"其背景,重新绘制,在一台性能并不优良的终端上(很大可能程度上客户端电脑都不是那么强劲吧) ,这个过程不是一时半会就能完成的,尤其对于很多个子控件的情况,因此就…​
查询一些资料提到的解决方法有:​
1.双缓冲​
SetStyle(ControlStyles.DoubleBuffer, true); ​
效果不是很明显​
2.由于底层重绘每次会清除画布,然后再全部重新绘制,这才是导致闪烁最主要的原因。于是重载消息发送函数操作,禁掉这条消息。代码如下:

protected override void WndProc(ref Message m)
{
    if (m.Msg == 0x0014) // 禁掉清除背景消息
    return;
    base.WndProc(ref m);
}​

但是这样效果依然不明显​
继续研究,看到网上有人写过解决类似问题方法,其原理是参考ListView控件中的两个函数

internal void BeginUpdateInternal()
{
    if (this.IsHandleCreated)
    {
	    if (this.updateCount == 0)
	    {
	   		 this.SendMessage(11, 0, 0);
	    }
   		this.updateCount = (short) (this.updateCount + 1);
    }
}​​

this.SendMessage(11, 0, 0)表示它给自身Send了一个code为11的windows消息,
在windows消息定义中可以看到 WM_SETREDRAW = 0x0B (0x0B也就是11),这行代码的意思是告诉windows对ListView控件停止重绘界面,直到显式要求重新绘制为止.

internal bool EndUpdateInternal(bool invalidate)
{
	    if (this.updateCount <= 0)
	    {
	    	return false;
	    }
	    this.updateCount = (short) (this.updateCount - 1);
	    if (this.updateCount == 0)
	    {
		    this.SendMessage(11, -1, 0);
		    if (invalidate)
		    {
		    	this.Invalidate();
		    }
	    }
	    return true;
}

同样有一行代码: this.SendMessage(11, –1, 0); 11还是同一个意思,此时告知windows可以重绘ListView控件了​
按照这种思路​在Resize函数中增加发送消息​

[DllImport("user32")]
private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, IntPtr lParam);
private const int WM_SETREDRAW = 0xB;​
private void Form2_Resize(object sender, EventArgs e)
{
    SendMessage(this.Handle, WM_SETREDRAW, 0, IntPtr.Zero);
    float newx = (this.Width) / X;
    float newy = this.Height / Y;
    setControls(newx, newy, this);
    SendMessage(this.Handle, WM_SETREDRAW, 1, IntPtr.Zero);
    this.Invalidate(true);
}​

问题得到解决
转自:http://blog.sina.com.cn/s/blog_1499e59430102vh28.html

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
C#中,实现窗体控件自适应窗体布局可以通过使用WinForms的布局管理器来完成。布局管理器可以自动调整控件大小和位置,以适应窗体大小变化。下面是一些常用的布局管理器和方法: 1. **TableLayoutPanel**:这是一种非常灵活的布局方式,可以根据行和列来组织控件。每个单元格中可以放置一个控件,并且可以设置每个单元格的大小比例,这样当窗体大小改变时,表格中的控件会根据设置的比例重新分配空间。 2. **FlowLayoutPanel**:这个布局容器会按顺序排列控件,当容器的大小改变时,控件会流动到下一行或列。可以设置FlowLayoutPanel的FlowDirection属性来控制控件的流动方向。 3. **Anchor和Dock属性**:对于单个控件,可以通过设置Anchor属性使控件相对于窗体的边缘固定,这样当窗体改变大小时,控件会保持与指定边缘的距离不变。而Dock属性允许控件“停靠”在窗体或容器的边缘,控件会随着窗体大小的变化而伸缩。 4. **自定义布局逻辑**:在某些情况下,可能需要编写自定义代码来处理控件的布局。这可以通过监听窗体的Resize事件来实现,在事件处理器中编写代码,根据窗体的新大小重新设置控件的位置和大小。 以下是一个简单的示例代码,展示如何使用TableLayoutPanel来实现控件自适应窗体布局: ```csharp // 创建TableLayoutPanel实例 TableLayoutPanel table = new TableLayoutPanel(); // 设置行列数量 table.ColumnCount = 2; table.RowCount = 2; // 设置每个单元格的大小权重 table.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F)); table.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F)); table.RowStyles.Add(new RowStyle(SizeType.Percent, 50F)); table.RowStyles.Add(new RowStyle(SizeType.Percent, 50F)); // 添加控件到TableLayoutPanel table.Controls.Add(new Button(), 0, 0); table.Controls.Add(new TextBox(), 1, 0); table.Controls.Add(new Label(), 0, 1); table.Controls.Add(new ListBox(), 1, 1); // 将TableLayoutPanel添加到窗体 this.Controls.Add(table); // 设置TableLayoutPanel的Dock属性,使其填满窗体 table.Dock = DockStyle.Fill; ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值