1. 程式人生 > >C# 在滾動視窗中繪圖(滾動條原理) 轉載

C# 在滾動視窗中繪圖(滾動條原理) 轉載

窗體的大小由窗體的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 根據滾動條的位置調整座標系的執行結果

相關推薦

C# 在滾動視窗繪圖滾動原理 轉載

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

c#禁止視窗關閉方法重寫關閉事件

  (1)直接設定 視窗樣式中的ControlBox選為False就可以去掉右上角的叉 (2)重寫關閉事件        privatevoid Form1_FormClosing(object sender, FormClosingEventArgs e)       

C++virtual虛函數的用法

this char 基類 變化 代碼 程序 但是 cnblogs else 轉載:http://blog.csdn.net/foreverhuylee/article/details/34107615 在面向對象的C++語言中,虛函數(virtual function)是一

C++virtual虛函數的用法詳解

sla margin tar 實現 store ocs rfs hud iuc int128除法怎麽實現? 怎麽求十億個64位整數的平均數? C語言是否正在走下坡路 看幾遍了 老是1error, 求大神幫忙!!! 狗lKst頻1e甘邪攪http://jz.docin

.NET/C# 使視窗永不啟用No Activate 永不獲得焦點

原文 .NET/C# 使視窗永不啟用(No Activate 永不獲得焦點) 有些視窗天生就是為了輔助其它程式而使用的,典型的如“輸入法視窗”。這些視窗不希望搶奪其它視窗的焦點。 有 Win32 方法來解決這樣的問題,WS_EX_NOACTIVATE 便是關鍵。 具體來說,是給視窗樣式中額

【資源分享】Half-Life英版

*----------------------------------------------下載區----------------------------------------------* 下載地址:https://pan.baidu.com/s/1pFb8YZ4hdmHsla5ldQDqcg 提

在Eclipse進行C/C++開發的配置方法20140721最新版

Eclipse 是一個開放原始碼的、基於Java的可擴充套件開發平臺。就其本身而言,它只是一個框架和一組服務,用於通過外掛元件構建開發環境。——語出百度百科。簡單的說Eclipse 是免費的開源的Jav

C# throw 丟擲異常 的用法

throw 用來丟擲異常,可自己編寫程式碼,丟擲所需要的異常。 程式碼如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespa

QML繪圖1、Canvas 2、QPainter與QML結合

#include "alpainteditem.h" ALPaintedItem::ALPaintedItem(QQuickItem *parent)     : QQuickPaintedItem(parent),     m_brushColor(QColor(0, 0, 0 ,255)),     m_

Android視窗座標體系分二種、獲取座標的方法

Android座標系 在Android中,將螢幕最左上角的頂點作為Android座標系的原點,從這個點向右是X軸正方向,從這個點向下是Y軸正方向。 系統提供了getLocationOnScreen(intlocation[])獲取Android座標系中點

電子書 C#高級編程第9版.pdf

work 並發編程 桌面應用 href 驅動開發 靈活 交互 c# 電子 《C#高級編程(第9版):C# 5.0 & .NET 4.5.1 》由.NET專家的夢幻組合編寫,包含開發人員使用C#所需的所有內容。C#是編寫.NET應用程序的一種語言,本書適合於希望提高編

C++ 何時使用動態分配即使用newkeyword?何時使用指針?

指向 delet 問題 con 擁有 才會 屬性 想要 自己 動態分配 在你的問題裏。你用了兩種方式創建對象。這兩種方式基本的不同在於對象的存儲時間。當運行Object myObject;這句代碼時。它作為自己主動變量被創建,這意味著當對象出了作用域時也會自己主動銷毀。

C#調用Java方法詳細實例

art dem 關系 進行 網上 auto mar ctr 環境 閱讀目錄 C#調用c++ C#調用JAVA方法 C#可以直接引用C++的DLL和轉換JAVA寫好的程序。最近由於工作原因接觸這方面比較多,根據實際需求,我們通過一個具體例子把一個JAVA方法轉換成可以

C++11 Lambda表達式匿名函數

class 訪問 namespace 表達式 span sin clas style col http://www.cnblogs.com/RainyBear/p/5733399.html 匿名函數,好屌的樣子。 Lambda表達式的引入標誌,在‘[]’裏面可以填入‘=’

設計模式C++學習筆記之十三Decorator裝飾模式

com img c++ 進行 done 設計 out set 筆記 裝飾模式,動態地給一個對象添加一些額外的職責。就增加功能來說,Decorator模式相比生成子類更為靈活。 13.1.解釋 main(),老爸 ISchoolReport,成績單接口 CFourthGrad

C#文件讀寫txt 簡單方式

換行 line string txt 不換行 返回 true text empty 1.文件寫入 // 路徑,寫入內容 System.IO.File.WriteAllText(@".\File.txt", string.Empty); 可更換相應的方法 2.文件讀入 /

c++ 循環簡單說for)(讀書體會

left p s margin face href pxn gin 讀書 blank Y宜oab樸祭Q蔚06詞ghttp://www.facebolw.com/space/2103436/following Z煤94o販40鑰qg魄http://www.facebolw.

1014 C語言程序設計教程第三版課後習題6.4

content += 教程 print ons ont c語言程序設計 lld cnblogs 題目描述 求Sn=1!+2!+3!+4!+5!+…+n!之值,其中n是一個數字。 輸入 n 輸出 和 樣例輸入 5 樣例輸出 153 1 #include "stdio.h"

1013: C語言程序設計教程第三版課後習題6.3

其中a是一個數字 blog += color turn sam c語言程序 [] c語言 題目描述 求Sn=a+aa+aaa+…+aa…aaa(有n個a)之值,其中a是一個數字。 例如:2+22+222+2222+22222(n=5),n由鍵盤輸入。 輸入 a 輸出 和 樣

1024: C語言程序設計教程第三版課後習題7.3

c語言程序 print clas 程序 scanf col class pri printf 題目描述 求一個3×3矩陣對角線元素之和。 輸入 矩陣 輸出 主對角線 副對角線 元素和 樣例輸入 1 2 3 1 1 1 3 2 1 樣例輸出 3 7 1 #include