程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> [叩響C#之門]寫給初學者:滾動條原理

[叩響C#之門]寫給初學者:滾動條原理

編輯:關於C#

17.9.4 在滾動窗口中繪圖

窗體的大小由窗體的Size屬性確定,這個大小包括了窗體的標題欄和邊框。而窗體中用於顯示客戶文 檔的區域稱為工作區(ClientRectangle),其大小用窗體的ClientSize 屬性表示(如圖17-20所示)。

在圖17-20中,窗體的大小為308×234像素,其中標題欄的寬度為30像素,邊框的寬度為4像素,所以 工作區的大小為300×200像素。

如果我們要在300×200像素的工作區內顯示一個200×150像素的矩形和一個300×100像素的橢圓,會 出現什麼情況呢?

圖17-20 在滾動窗口中繪圖 圖17-21 文檔大小超出工作區

為了敘述方便,我們把要顯示的文本、圖形等內容稱為“文檔”。因為這時文檔的總高度為250像素, 而窗口工作區的高度只有200像素,所以總有一部分無法顯示(如圖17-21所示)。如果文檔太大,工作區 不能完全顯示,就需要在窗口中添加滾動條,以便查看被擋住的部分。

怎樣才能顯示滾動條呢?這可以通過設置窗體的AutoScrollMinSize屬性實現。

this.AutoScrollMinSize = new Size(300, 250);

因為文檔的面積為300×250像素,所以我們把AutoScrollMinSize的值設置為300×250,一旦工作區面 積小於該值,窗體就會自動顯示相應的滾動條。

請新建一個名為“ScrollWindow”的項目,窗體大小設置為308×234像素(除去標題欄和邊框,工作 區的實際大小為300×200像素),然後重寫OnPaint()方法。

試一試:在滾動窗口中繪圖

public partial class Form1 : Form
{
    //構造函數
    public Form1()
    {
        InitializeComponent();
        //將窗體的背景色設置為白色
        this.BackColor = Color.White;
        //當工作區小於300×250像素時顯示滾動條
        this.AutoScrollMinSize = new Size(300, 250);
    }
    //重寫OnPaint()方法
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        Graphics g = e.Graphics;
        //繪制矩形和橢圓
        g.FillRectangle(Brushes.LightPink, 0, 0, 200, 150);
        g.FillEllipse(Brushes.LightGreen, 0, 150, 300, 100);
    }
}

運行程序,結果如圖17-22所示,出現了滾動條。

但當我們拖動滾動條時,意想不到的事情發生了。窗體並沒有繪制橢圓的下半部分,而是又把橢圓的 上半部分繪制了一遍(如圖17-23所示)。

圖17-22 出現滾動條 圖17-23拖動滾動條時又把橢圓的上半部分繪制了一遍

為什麼會出現這種情況呢?請把窗口最小化,然後恢復,我們發現窗口中的圖像變為初始模樣了(如 圖17-24所示)。

原來當重新顯示窗體時,發生Point事件,系統調用OnPaint()方法重繪窗體,下面的代碼被再次執行 。

g.FillRectangle(Brushes.LightPink, 0, 0, 200, 150);

g.FillEllipse(Brushes.LightGreen, 0, 150, 300, 100);

第一條語句要求以點(0,0)為起點,畫一個寬200像素、高150像素的矩形;第二條語句要求以點(0 ,150)為起點,畫一個寬300、高100的橢圓。

然而,Graphics對象繪制圖形時並不知道滾動條的變化情況,默認情況下它總是以“工作區左上角” 為原點繪制圖形的,即它描點時的坐標總是參照“工作區左上角”的。形象地說就是,它總是把文檔的左 上角和工作區的左上角對齊,然後把文檔貼在工作區上。於是圖17-22所示的圖像重新繪制了一遍,圖像 變為初始模樣。

當我們拖動滾動條時,也會觸發Paint事件,重新繪制工作區,但系統並不重新繪制整個工作區。當滾 動條向下拖動50像素時,系統首先把工作區中的圖像整體向上平移50像素,這時工作區下部出現一塊大小 為300×50像素的空白(如圖17-25所示),系統只需補上這塊空白區域即可。這種按需繪制的方式可以大 大提高繪圖效率。

然而這塊空白區域縱坐標范圍為150~200,在文檔中,正好是橢圓上半部分的位置,所以Graphics對象 把橢圓上半部分重新繪制了一遍,結果就出現了橢圓上半部分出現兩次的情況(如圖17-24所示)。

(拖動滾動條時圖像向上平移50像素)

圖17-24 最小化窗口再恢復,圖像變為初始模樣 圖17-25 按需繪制的方式

實際上橢圓下半部分縱坐標范圍為200~250,所以要想正確繪制出空白區域的圖形,需要把繪圖的坐標 原點向上平移50像素,而這一點可以通過坐標的平移變換實現,如圖17-25所示。

圖17-26 坐標平移

坐標平移的情況如圖17-26所示,要繪制從A點開始的區域,就要把坐標系原點由工作區的左上角A平移 到文檔的左上角O,即始終使坐標系的原點位於文檔的左上角。這種變換可以通過下面的語句實現。

g.TranslateTransform(this.AutoScrollPosition.X, this.AutoScrollPosition.Y);

屬性AutoScrollPosition表示的是滾動條的位置,滾動條移動了多少像素,坐標系就要平移多少像素 。需要注意的是,AutoScrollPosition.X和AutoScrollPosition.Y均為負數,所以坐標原點實際上是向左 上角平移的。

試一試:根據滾動條的位置調整坐標系

public partial class Form1 : Form
{
    //構造函數
    public Form1()
    {
        InitializeComponent();
        //將窗體的背景色設置為白色
        this.BackColor = Color.White;
        //當工作區小於300×250像素時顯示滾動條
        this.AutoScrollMinSize = new Size(300, 250);
    }
    //重寫OnPaint()方法
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        Graphics g = e.Graphics;
        //平移坐標系
        g.TranslateTransform(this.AutoScrollPosition.X, this.AutoScrollPosition.Y);
        //繪制矩形和橢圓
        g.FillRectangle(Brushes.LightPink, 0, 0, 200, 150);
        g.FillEllipse(Brushes.LightGreen, 0, 150, 300, 100);
    }
}

運行程序,結果如圖17-27所示,一切正常。

圖17-27 根據滾動條的位置調整坐標系的運行結果

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved