[叩響C#之門]寫給初學者:捲軸原理

來源:互聯網
上載者:User
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 文檔大小超出工作區

作者:梁斌玉 摘自《叩響C#之門》,寫了將近五年時間,七月初出版出版
BeginnerClassroom@163.com
http://www.cnblogs.com/BeginnerClassroom

為了敘述方便,我們把要顯示的文本、圖形等內容稱為“文檔”。因為這時文檔的總高度為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 根據捲軸的位置調整座標系的運行結果

作者:梁斌玉 摘自《叩響C#之門》,寫了將近五年時間,七月初出版出版
BeginnerClassroom@163.com
http://www.cnblogs.com/BeginnerClassroom

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.