因為在.Net裡WinForm中提供了ScrollableControl,因而我們可以通過設置AutoScroll屬性來自動的顯示滾動條並通過它來滾動畫面,但是在實際的應用中,我們有時可能會覺得這個被系統提供的控件“並不好用”。這種情況往往表現在對滾動條位置不滿意的時候,或是不想使用從ScrollableControl繼承的控件的時候,或是其它的原因。這個時候我們就會考慮在程序中直接使用VScrollBar入HScrollBar控件。可是用過這兩個控件的程序員都知道,對這兩個控件的使用其實並不容易,除非你是個很厲害的家伙。
我並不是個很厲害的家伙,但我也確有個自己做法,效果,我認為是不錯的,當然你可能有更好的做法。
為了調整滾動條的大小位置,我在程序裡定義了兩個變量,並給了其初始值:
private int m_VBarWidth;
private int m_HBarHeight;
//
this.m_VBarWidth = SystemInformation.VerticalScrollBarWidth;
this.m_HBarHeight = SystemInformation.HorizontalScrollBarHeight;
接下來,我在程序裡添加滾動條,代碼放到構造函數裡了:
this.SuspendLayout();
this.m_VBar = new VScrollBar();
this.m_HBar = new HScrollBar();
this.setScrllBars();
this.m_VBar.Scroll += new ScrollEventHandler(this.VBar_Scroll);
this.m_HBar.Scroll += new ScrollEventHandler(this.HBar_Scroll);
this.Controls.Add(this.m_VBar);
this.Controls.Add(this.m_HBar);
this.ResumeLayout(true);
裡面有一個函數setScrllBars();接下來會說到,只說這些代碼的意圖是向當前窗體或控件裡添加了兩個滾動條並對其有些設置而已。
實際上所有的代碼我是寫到一個從Control繼承下來的類,這裡提到的所有代碼幾乎都在這個類裡完成。
我們不防設置一個虛擬的顯示大小,比如300×200的大小,我們在控件裡通過滾動條就滾動這一個大小的區域,這裡我們會想,如果控件的可見區域大於這個300×200的大小,滾動條是沒有必要顯示出來的,如果控件可見區域要是小於這個區域了,滾動條要可見了,有一個問題要說了,有一個可能的情況就是比如本來水平的不可見,但是因為垂直的可見了使得控件的“可見區減小了”,這個情況可能引起水平滾動條的可見,同樣,水平滾動條也可能把一個本不不可見的垂直的滾動條“擠”的顯示出來。我曾試著用代碼來協調這個情況,但是直到現在我才找到一個較“合理”的做法,這個將在我說代碼裡有處理。
下一個問題就是我們知道在兩個滾動條都顯示的時候在控件的右下角有一個空白區域,這也是個協調的難點。我曾試著對滾動條設置了兩次來達到這個效果,但也是直到現在我才否定了這個做法,采用一次設置了。
再下一個問題就是滾動條的本身的特有屬性設置,比如LargeChange(最大滾動大小),Maximum(滾動的最大取值),當然還有Minimum,這個一般來說就是0了。從表面上我們看的清楚,不就是這三個值嗎?有什麼?其實這裡是有一個公式的。就是要設置到Maximum的值必需進行與LargeChange-1相加運算,否則是不對的。
下面的方法體就試著解決了上面提到的三個問題,且是我的控件中最主要的部分,假設控件中的兩個滾動條就像一個多行的文本編輯框一樣的情況出現兩個滾動條,因為我只是提到了對滾動條的設置,所以這個文裡也就只有這一個方法,目的當然就是記錄下,方便以後查找了:
private int m_BorderWidth;
private int m_VBarWidth;
private int m_HBarHeight;
private Size size;
private void SetControl()
...{
this.m_BorderWidth = 1;
this.m_VBarWidth = SystemInformation.VerticalScrollBarWidth;
this.m_HBarHeight = SystemInformation.HorizontalScrollBarHeight;
this.SuspendLayout();
this.m_VBar = new VScrollBar();
this.m_HBar = new HScrollBar();
this.setScrllBars();
this.m_VBar.Scroll += new ScrollEventHandler(this.VBar_Scroll);
this.m_HBar.Scroll += new ScrollEventHandler(this.HBar_Scroll);
this.Controls.Add(this.m_VBar);
this.Controls.Add(this.m_HBar);
this.ResumeLayout(true);
this.size = new Size(300, 200);
}
private void setScrllBars()
...{
//設置垂直最大滾動值
int vLarge = this.Height;
//設置水平最大滾動值
int hLarge = this.Width;
//顯示區域的高
int vValue = size.Height;
//顯示區域的寬
int hValue = size.Width;
//滾動條的最大值
int vMaxValue = 0;
int hMaxValue = 0;
//垂直滾動條的可見標志
bool vVisible = false;
//水平滾動條的可見標志
bool hVisible = false;
if (vValue > this.Height - 2 * this.m_BorderWidth)
...{
vMaxValue = vValue - (this.Height - 2 * this.m_BorderWidth);
//垂直方向上顯示區域高大於窗口高時,垂直滾動條直接可見
vVisible = true;
//垂直滾動條寬影響水平滾動條可見性
hVisible = hValue > (this.Width - this.m_VBarWidth - 2 * this.m_BorderWidth);
hMaxValue = hValue - (this.Width - this.m_VBarWidth - 2 * this.m_BorderWidth);
}
else if (hValue > this.Width - 2 * this.m_BorderWidth)
...{
hMaxValue = hValue -( this.Width - 2 * this.m_BorderWidth);
//水平方向上顯示區域寬大於窗口寬時,水平滾動條直接可見
hVisible = true;
//水平方向滾動條高影響垂直滾動條可見性
vVisible = vValue > (this.Height - this.m_HBarHeight - 2 * this.m_BorderWidth);
vMaxValue = vValue - (this.Height - this.m_HBarHeight - 2 * this.m_BorderWidth);
}
int vOffset = this.m_VBarWidth;//垂直滾動條高的差值
int hOffset = this.m_HBarHeight;//水平滾動條寬的差值
if (vVisible != hVisible)
...{
//當垂直滾動條和水平滾動條可見性不同時,要顯示的滾動條占滿位置
if (vVisible)
...{
vOffset = 0;
}
if (hVisible)
...{
hOffset = 0;
}
}
//計算垂直滾動條靠近右邊所需的矩形區域
Rectangle vRect = new Rectangle(this.Width - this.m_BorderWidth - this.m_VBarWidth, this.m_BorderWidth, this.m_VBarWidth, this.Height - 2 * this.m_BorderWidth - vOffset);
//計算水平滾動條靠近下邊所需的矩形區域
Rectangle hRect = new Rectangle(this.m_BorderWidth, this.Height - this.m_HBarHeight - this.m_BorderWidth, this.Width - 2 * this.m_BorderWidth - hOffset, this.m_HBarHeight);
//當窗口的寬不足容納垂直滾動條時,需隱藏垂直滾動條
bool tmpVHide = this.Width < (this.m_VBarWidth + 2 * this.m_BorderWidth);
//當窗口的高不足容納水平滾動條時,需隱藏水平滾動條
bool tmpHHide = this.Height < (this.m_HBarHeight + 2 * this.m_BorderWidth);
//在需要顯示每個滾動條的時候先設置其各個值
this.m_VBar.Bounds = vRect;
this.m_VBar.LargeChange = vLarge;
this.m_VBar.Maximum = vMaxValue + vLarge - 1;
this.m_VBar.Minimum = 0;
this.m_HBar.Bounds = hRect;
this.m_HBar.LargeChange = hLarge;
this.m_HBar.Maximum = hMaxValue + hLarge - 1;
this.m_HBar.Minimum = 0;
//如果窗口高不夠,則直接不顯示垂直滾動條
if (tmpVHide)
...{
vVisible = false;
}
//如果窗口寬不夠,則直接不顯示水平滾動條
if (tmpHHide)
...{
hVisible = false;
}
//顯示標志決定滾動條的可見性
this.m_VBar.Visible = vVisible;
this.m_HBar.Visible = hVisible;
}
private void VBar_Scroll(object sender, ScrollEventArgs e)
...{
Console.WriteLine(e.NewValue);
}
private void HBar_Scroll(object sender, ScrollEventArgs e)
...{
Console.WriteLine(e.NewValue);
}