1. Trang chủ
  2. » Công Nghệ Thông Tin

Các giải pháp lập trình CSharp- P30 pps

10 139 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 2,61 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

.NET Framework cung cấp ba phương thức có thể thực hiện công việc này: • Phương thức Rectangle.Contains—nhận vào một điểm và trả về true nếu điểm này nằm bên trong hình chữ nhật cho trư

Trang 1

Hình 8.1 Danh sách các font đã được cài đặt

2. Th c hi n “hit testing” v i shape Th c hi n “hit testing” v i shape ự ệ ự ệ ớ ớ

Bạn cần nhận biết người dùng có nhắp vào trong một shape hay không.

Kiểm tra điểm mà người dùng đã nhắp vào bằng các phương thức như

Rectangle.ContainsRegion.IsVisible (thuộc không gian tên System.Drawing), hoặc GraphicsPath.IsVisible (thuộc không gian tên System.Drawing.Drawing2D), tùy vào kiểu của shape.

Thông thường, nếu sử dụng GDI+ để vẽ shape trên form, có thể bạn sẽ cần xác định xem khi nào người dùng nhắp vào trong một shape cho trước .NET Framework cung cấp ba phương

thức có thể thực hiện công việc này:

• Phương thức Rectangle.Contains—nhận vào một điểm và trả về true nếu điểm này nằm bên trong hình chữ nhật cho trước Trong nhiều trường hợp, bạn có thể lấy được hình chữ nhật đối với một kiểu shape khác Ví dụ, bạn có thể sử dụng Image.GetBounds

để lấy hình chữ nhật mô tả đường biên của shape Cấu trúc Rectangle là thành viên của không gian tên System.Drawing.

• Phương thức GraphicsPath.IsVisible—nhận vào một điểm và trả về true nếu điểm này nằm bên trong một vùng được định nghĩa bởi GraphicsPath khép kín Vì một

GraphicsPath có thể chứa nhiều line, shape, và figure nên cách này rất hữu ích nếu bạn muốn kiểm tra một điểm có nằm bên trong một vùng không phải hình chữ nhật hay không Lớp GraphicsPath là một thành viên của không gian tên

System.Drawing.Drawing2D.

• Phương thức Region.IsVisible—nhận vào một điểm và trả về true nếu điểm này nằm bên trong một vùng được định nghĩa bởi Region Cũng giống như GraphicsPath, Region

có thể mô tả một shape không phải hình chữ nhật Region là một thành viên của không gian tên System.Drawing.

Trang 2

Ví dụ sau đây sẽ tạo một Rectangle và một GraphicsPath Theo mặc định, hai shape này có nền màu xanh nhạt Tuy nhiên, phương thức thụ lý sự kiện Form.MouseMove sẽ kiểm tra xem con trỏ chuột có nằm trong một trong hai shape này hay không, và cập nhật màu nền thành hồng tươi nếu con trỏ ở đó.

using System;

using System.Windows.Forms;

using System.Drawing;

using System.Drawing.Drawing2D;

public class HitTesting : System.Windows.Forms.Form {

// (Bỏ qua phần mã designer.)

// Định nghĩa các shape sẽ được sử dụng

private GraphicsPath path;

private Rectangle rectangle;

// Định nghĩa các cờ để theo vết con trỏ chuột

private bool inPath = false;

private bool inRectangle = false;

// Định nghĩa các bút vẽ

Brush highlightBrush = Brushes.HotPink;

Brush defaultBrush = Brushes.LightBlue;

private void HitTesting_Load(object sender, System.EventArgs e) {

// Tạo các shape

path = new GraphicsPath();

path.AddEllipse(10, 10, 100, 60);

path.AddCurve(new Point[] {new Point(50, 50),

new Point(10,33), new Point(80,43)});

path.AddLine(50, 120, 250, 80);

path.AddLine(120, 40, 110, 50);

path.CloseFigure();

Trang 3

}

private void HitTesting_Paint(object sender,

System.Windows.Forms.PaintEventArgs e) {

Graphics g = e.Graphics;

// Vẽ shape dựa trên phần chọn hiện tại

if (inPath) {

g.FillPath(highlightBrush, path);

g.FillRectangle(defaultBrush, rectangle);

}else if (inRectangle) {

g.FillRectangle(highlightBrush, rectangle);

g.FillPath(defaultBrush, path);

}else {

g.FillPath(defaultBrush, path);

g.FillRectangle(defaultBrush, rectangle);

}

g.DrawPath(Pens.Black, path);

g.DrawRectangle(Pens.Black, rectangle);

}

private void HitTesting_MouseMove(object sender,

System.Windows.Forms.MouseEventArgs e) {

Graphics g = this.CreateGraphics();

// Thực hiện "hit testing" với hình chữ nhật

if (rectangle.Contains(e.X, e.Y)) {

if (!inRectangle) {

Trang 4

inRectangle = true;

// Đổi màu nền hình chữ nhật

g.FillRectangle(highlightBrush, rectangle); g.DrawRectangle(Pens.Black, rectangle); }

}else if (inRectangle) {

inRectangle = false;

// Phục hồi hình chữ nhật

g.FillRectangle(defaultBrush, rectangle); g.DrawRectangle(Pens.Black, rectangle);

}

// Thực hiện "hit testing" với path

if (path.IsVisible(e.X, e.Y)) {

if (!inPath) {

inPath = true;

// Đổi màu nền path

g.FillPath(highlightBrush, path);

g.DrawPath(Pens.Black, path);

}

}else if (inPath) {

inPath = false;

// Phục hồi path

g.FillPath(defaultBrush, path);

Trang 5

}

g.Dispose();

}

}

Hình 8.2 Thực hiện “hit testing” với đối tượng Rectangle và GraphicsPath

Chú ý rằng hoạt động này diễn ra trực tiếp bên trong phương thức thụ lý sự kiện MouseMove Việc vẽ chỉ được thực hiện nếu phần chọn hiện tại thay đổi Đối với một đoạn mã đơn giản, bạn có thể làm mất hiệu lực toàn bộ form mỗi khi con trỏ chuột di chuyển vào trong hoặc ra khỏi một vùng và thụ lý tất cả việc vẽ trong phương thức thụ lý sự kiện Form.Paint, nhưng

điều này dẫn đến việc phải vẽ nhiều hơn và tạo nên hiện tượng rung hình (flicker) khi toàn bộ

form được vẽ lại.

3. T o form có hình d ng tùy bi n T o form có hình d ng tùy bi n ạ ạ ạ ạ ế ế

Bạn cần tạo một form hoặc điều kiểm không phải hình chữ nhật.

Tạo một đối tượng System.Drawing.Region có hình dạng như bạn muốn, và gán

nó vào thuộc tính Form.Region hoặc Control.Region.

Để tạo một form hoặc điều kiểm không phải hình chữ nhật, trước hết bạn cần định nghĩa hình dạng mình muốn Cách tiếp cận dễ nhất là sử dụng đối tượng

System.Drawing.Drawing2D.GraphicsPath, nó có thể điều tiết bất kỳ sự kết hợp nào của các hình ellipse, chữ nhật, và cung khép kín Bạn có thể thêm các shape vào một đối tượng

GraphicsPath bằng các phương thức như AddEllipse, AddRectangle, và AddClosedCurve Một khi đã hoàn tất việc định nghĩa hình dạng như mong muốn, bạn có thể tạo một đối tượng

Region từ GraphicsPath này—chỉ cần trình ra GraphicsPath trong phương thức khởi dựng của

Trang 6

lớp Region Cuối cùng, bạn có thể gán Region vào thuộc tính Form.Region hoặc

Control.Region.

Ví dụ dưới đây trình bày cách tạo một form có hình dáng bất thường (xem hình 8.3) bằng hai cung tròn (hai cung này được chuyển thành một figure khép kín bằng phương thức

GraphicsPath.CloseAllFigures).

Hình 8.3 Form không phải hình chữ nhật

using System;

using System.Windows.Forms;

using System.Drawing;

using System.Drawing.Drawing2D;

public class IrregularForm : System.Windows.Forms.Form {

private System.Windows.Forms.Button cmdClose;

private System.Windows.Forms.Label label1;

// (Bỏ qua phần mã designer.)

private void IrregularForm_Load(object sender, System.EventArgs e) {

GraphicsPath path = new GraphicsPath();

Point[] pointsA = new Point[] {new Point(0, 0),

new Point(40, 60), new Point(this.Width - 100, 10)};

path.AddCurve(pointsA);

Trang 7

{new Point(this.Width - 40, this.Height - 60),

new Point(this.Width, this.Height),

new Point(10, this.Height)};

path.AddCurve(pointsB);

path.CloseAllFigures();

this.Region = new Region(path);

}

private void cmdClose_Click(object sender, System.EventArgs e) {

this.Close();

}

}

Đối với ví dụ tạo điều kiểm không phải hình chữ nhật, bạn hãy tham khảo mục 8.4.

4. T o đi u ki m có hình d ng tùy bi n T o đi u ki m có hình d ng tùy bi n ạ ề ạ ề ể ể ạ ạ ế ế

Bạn cần tạo một shape mà người dùng có thể thao tác với nó trên form như kéo

rê, thay đổi kích thước

Tạo một điều kiểm tùy biến, và chép đè painting logic để vẽ shape Gán shape

của bạn vào thuộc tính Control.Region Kế đó, bạn có thể sử dụng Region này để thực hiện “hit testing”.

Nếu muốn tạo một giao diện người dùng phức tạp kết hợp nhiều phần tử được vẽ tùy biến, bạn cần có phương cách để theo vết các phần tử này và cho phép người dùng tương tác với chúng

Cách tiếp cận dễ nhất trong NET là tạo một điều kiểm chuyên biệt bằng cách dẫn xuất một

lớp từ System.Windows.Forms.Control Kế đó, bạn có thể tùy biến phương cách mà điều kiểm này được vẽ dựa theo tập các sự kiện cơ bản của nó.

Điều kiểm được trình bày dưới đây mô tả một hình ellipse đơn giản trên form Tất cả các điều kiểm đều được liên hợp với một vùng chữ nhật trên form, do đó điều kiểm EllipseShape sẽ tạo một ellipse lắp đầy các đường biên này (được cấp thông qua thuộc tính

Control.ClientRectangle) Một khi shape đã được tạo, thuộc tính Control.Region được thiết lập dựa theo biên trên ellipse Điều này bảo đảm các sự kiện như MouseMove, MouseDown,

Click sẽ xảy ra chỉ khi chuột ở trên ellipse, chứ không phải toàn bộ hình chữ nhật.

Dưới đây là phần mã đầy đủ của lớp EllipseShape:

using System;

using System.Windows.Forms;

using System.Drawing;

Trang 8

using System.Drawing.Drawing2D;

public class EllipseShape : System.Windows.Forms.Control {

private GraphicsPath path = null;

private void RefreshPath() {

// Tạo GraphicsPath cho shape và áp dụng nó vào

// điều kiểm bằng cách thiết lập thuộc tính Region

path = new GraphicsPath();

path.AddEllipse(this.ClientRectangle);

this.Region = new Region(path);

}

protected override void OnResize(System.EventArgs e) {

base.OnResize(e);

RefreshPath();

this.Invalidate();

}

protected override void OnPaint

(System.Windows.Forms.PaintEventArgs e) {

base.OnPaint(e);

if (path != null) {

e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

e.Graphics.FillPath(new SolidBrush(this.BackColor), path);

e.Graphics.DrawPath(new Pen(this.ForeColor, 4), path);

}

}

}

Bạn có thể định nghĩa điều kiểm EllipseShape trong một Class Library Assembly độc lập để

nó có thể được thêm vào hộp công cụ của Microsoft Visual Studio NET và được sử dụng lúc

Trang 9

thử nghiệm đơn giản Ví dụ dưới đây tạo hai ellipse và cho phép người dùng kéo rê cả hai vòng quanh form bằng cách giữ chuột xuống và di chuyển con trỏ.

Hình 8.4 Kéo rê các điều kiểm có hình dạng tùy biến trên form

public class SpriteTest : System.Windows.Forms.Form {

// (Bỏ qua phần mã designer.)

// Các cờ dùng để theo vết chuột khi chế độ kéo rê được kích hoạt

private bool isDraggingA = false;

private bool isDraggingB = false;

// Các điều kiểm có hình dạng ellipse

private EllipseShape ellipseA, ellipseB;

private void SpriteTest_Load(object sender, System.EventArgs e) {

// Tạo và cấu hình cả hai ellipse

ellipseA = new EllipseShape();

ellipseA.Width = ellipseA.Height = 100;

ellipseA.Top = ellipseA.Left = 30;

ellipseA.BackColor = Color.Red;

this.Controls.Add(ellipseA);

ellipseB = new EllipseShape();

ellipseB.Width = ellipseB.Height = 100;

ellipseB.Top = ellipseB.Left = 130;

Trang 10

ellipseB.BackColor = Color.Azure;

this.Controls.Add(ellipseB);

// Gắn cả hai ellipse vào cùng tập các phương thức

// thụ lý sự kiện

ellipseA.MouseDown += new MouseEventHandler(Ellipse_MouseDown); ellipseA.MouseUp += new MouseEventHandler(Ellipse_MouseUp); ellipseA.MouseMove += new MouseEventHandler(Ellipse_MouseMove);

ellipseB.MouseDown += new MouseEventHandler(Ellipse_MouseDown); ellipseB.MouseUp += new MouseEventHandler(Ellipse_MouseUp); ellipseB.MouseMove += new MouseEventHandler(Ellipse_MouseMove); }

private void Ellipse_MouseDown(object sender, MouseEventArgs e) {

// Thu lấy ellipse gây ra sự kiện này

Control control = (Control)sender;

if (e.Button == MouseButtons.Left) {

control.Tag = new Point(e.X, e.Y);

if (control == ellipseA) {

isDraggingA = true;

}else {

isDraggingB = true;

}

}

}

private void Ellipse_MouseUp(object sender, MouseEventArgs e) {

isDraggingA = false;

isDraggingB = false;

Ngày đăng: 08/07/2014, 17:20

HÌNH ẢNH LIÊN QUAN

Hình 8.1 Danh sách các font đã được cài đặt - Các giải pháp lập trình CSharp- P30 pps
Hình 8.1 Danh sách các font đã được cài đặt (Trang 1)
Hình 8.2 Thực hiện “hit testing” với đối tượng Rectangle và GraphicsPath - Các giải pháp lập trình CSharp- P30 pps
Hình 8.2 Thực hiện “hit testing” với đối tượng Rectangle và GraphicsPath (Trang 5)
Hình 8.3 Form không phải hình chữ nhật - Các giải pháp lập trình CSharp- P30 pps
Hình 8.3 Form không phải hình chữ nhật (Trang 6)
Hình 8.4 Kéo rê các điều kiểm có hình dạng tùy biến trên form - Các giải pháp lập trình CSharp- P30 pps
Hình 8.4 Kéo rê các điều kiểm có hình dạng tùy biến trên form (Trang 9)