天天看點

winform适應不同的分辨率_[C#](純Winform)讓UI适應不同分辨率

winform适應不同的分辨率_[C#](純Winform)讓UI适應不同分辨率

摘要:[C#](純Winform)讓UI适應不同分辨率

這是一項非常大的困擾,是以我把我找來的知識全部做個整理。

特别是針對Winform的部分,若是WPF建議使用ViewBox并且設定适合的模式。

大緻的概念是這樣:

Step 1: 将你的UI先固定大小,但實際操作還是依個人以及美工的複雜度(圖檔越複雜就要小心所謂的作用範圍問題,以免圖檔重疊等等),像有的時候Label需要用AutoSize=true,有的則是false。

Step2:用程式取得現在的分辨率(顯示器)

Step3:依照公式:你的UI大小除以現在的分辨率,來做UI的調整。

調整時要記得不隻是大小改變,位置也要改變!

若是在容器裡就用for抓每個元件,若容器裡還有容器,則用遞歸的方式做處理。

範例以容器為Panel為例:string sHeight = SystemInformation.PrimaryMonitorSize.Height.ToString();

string sWidth = SystemInformation.PrimaryMonitorSize.Width.ToString();

double sw = Convert.ToDouble(sWidth);

double sh = Convert.ToDouble(sHeight);

double sizeX = sw / 1024;

double sizeY = sh / 768;

foreach (Control p in panel1.Controls)

{

p.Top = Convert.ToInt32(Convert.ToDouble(p.Top) * sizeX);

p.Left = Convert.ToInt32(Convert.ToDouble(p.Left) * sizeY);

if (p is Label || p is TextBox || p is ComboBox)

{

p.Font = new Font(p.Font.FontFamily, p.Font.SizeInPoints * Convert.ToSingle(sizeX) * Convert.ToSingle(sizeY));

if (!(p is Label))

p.Width = Convert.ToInt32(Convert.ToDouble(p.Width) * sizeX);

}

else

{

p.Width = Convert.ToInt32(Convert.ToDouble(p.Width) * sizeX);

p.Height = Convert.ToInt32(Convert.ToDouble(p.Height) * sizeY);

}

}

panel1即是容器,而p則是裡面的元件,假設原本設計的分辨率是1024x768。

但如果容器裡還有容器,比方另一個panel,

原本的寫法是這樣:string sHeight = SystemInformation.PrimaryMonitorSize.Height.ToString();

string sWidth = SystemInformation.PrimaryMonitorSize.Width.ToString();

double sw = Convert.ToDouble(sWidth);

double sh = Convert.ToDouble(sHeight);

double sizeX = sw / 1024;

double sizeY = sh / 768;

foreach (Control p in panel1.Controls)

{

p.Top = Convert.ToInt32(Convert.ToDouble(p.Top) * sizeX);

p.Left = Convert.ToInt32(Convert.ToDouble(p.Left) * sizeY);

if (p is Label || p is TextBox || p is ComboBox)

{

p.Font = new Font(p.Font.FontFamily, p.Font.SizeInPoints * Convert.ToSingle(sizeX) * Convert.ToSingle(sizeY));

if (!(p is Label))

p.Width = Convert.ToInt32(Convert.ToDouble(p.Width) * sizeX);

}

else

{

if (p is Panel)

{

foreach (Control c in p.Controls)

{

c.Top = Convert.ToInt32(Convert.ToDouble(c.Top) * sizeX);

c.Left = Convert.ToInt32(Convert.ToDouble(c.Left) * sizeY);

if (c is Label || c is TextBox || c is ComboBox)

{

c.Font = new Font(c.Font.FontFamily, c.Font.SizeInPoints * Convert.ToSingle(sizeX) * Convert.ToSingle(sizeY));

if (!(c is Label))

c.Width = Convert.ToInt32(Convert.ToDouble(c.Width) * sizeX);

}

else

{

c.Width = Convert.ToInt32(Convert.ToDouble(c.Width) * sizeX);

c.Height = Convert.ToInt32(Convert.ToDouble(c.Height) * sizeY);

}

}

}

p.Width = Convert.ToInt32(Convert.ToDouble(p.Width) * sizeX);

p.Height = Convert.ToInt32(Convert.ToDouble(p.Height) * sizeY);

}

}

是以概念就是若碰到容器則要以容器本身再做一次同樣的事,是以就是:double sw = Convert.ToDouble(SystemInformation.PrimaryMonitorSize.Width);

double sh = Convert.ToDouble(SystemInformation.PrimaryMonitorSize.Height);

double sizeX = sw / 1024;

double sizeY = sh / 768;

private void chResolution(Panel p,sizeX,sizeY)

{

if (p.Name == "panel1" || p.Name == "panel2" || p.Name == "panel3")

{

p.Top = Convert.ToInt32(Convert.ToDouble(p.Top) * sizeX);

p.Left = Convert.ToInt32(Convert.ToDouble(p.Left) * sizeY);

p.Width = Convert.ToInt32(Convert.ToDouble(p.Width) * sizeX);

p.Height = Convert.ToInt32(Convert.ToDouble(p.Height) * sizeY);

}

foreach (Control c in p.Controls)

{

c.Top = Convert.ToInt32(Convert.ToDouble(c.Top) * sizeX);

c.Left = Convert.ToInt32(Convert.ToDouble(c.Left) * sizeY);

if (c is Label || c is TextBox || c is ComboBox)

{

c.Font = new Font(c.Font.FontFamily, c.Font.SizeInPoints * Convert.ToSingle(sizeX) * Convert.ToSingle(sizeY));

if (!(c is Label))

c.Width = Convert.ToInt32(Convert.ToDouble(c.Width) * sizeX);

}

else

{

if (c is Panel) chResolution(c as Panel);

c.Width = Convert.ToInt32(Convert.ToDouble(c.Width) * sizeX);

c.Height = Convert.ToInt32(Convert.ToDouble(c.Height) * sizeY);

}

}

}

中間遇到control是Panel時調用自己。

中間的is Label那些是為了調整Label等元件的字型,

因為這些元件,如果你改變大小(Width, Height),隻是改變作用範圍,字的大小不變。

目前這樣的作法差不多能解決我的困擾了,

若是再遇到比較困難的處理會繼續研究,也一并更新文章。

Edit:

實際操作後,修改了遞歸的版本程式。

panel1~panel3是最大的panel(就是一開始在winform裡的),若是從winform的角度抓取panel,則不用if (p.Name == "panel1" || p.Name == "panel2" || p.Name == "panel3")的部分。因為先在winform的角度将所有的control修改大小了(即是使用基本公式)

若是取從form取得Control則是用:

http://stackoverflow.com/questions/653284/get-available-controls-from-a-form-using-c-sharp