Tài trợ bài viết này và giới thiệu dịch vụ, sản phẩm, thương hiệu, nhu cầu tuyển dụng của doanh nghiệp đến với cộng đồng.
La Kiến Vinh Lập trình đồ họa trên Win32 API C++. Cung cấp project mẫu trong việc khởi tạo, và ví dụ cụ thể về một số cách thức vẽ hình trên Win32 với GDI+. Nếu bạn là lập trình viên, thì nên thử nghiệm mảng kiến thức Win32 API và nếu bạn đã lập trình với Win32 API thì bạn nên biết thêm về GDI+.
Nội dung bài viết

Giới thiệu

Bài viết này bao gồm 1 project mẫu về GDI+ trên ứng dụng Win32 API. Bao gồm việc khởi tạo GDI+ và thao tác vẽ đơn giản sử dụng GDI+. Nếu bạn là lập trình viên, thì nên thử nghiệm mảng kiến thức Win32 API và nếu bạn đã lập trình với Win32 API thì bạn nên biết thêm về GDI+.

Tiền đề bài viết

Khi phát triển ứng dụng Rulek, tôi đã sử dụng GDI+ cho project đó để vẽ các thành phần đơn giản, việc tổng hợp ra một bài viết hoàn chỉnh về GDI+ này sẽ giúp các bạn có thể xem xét việc khởi tạo GDI+ và sử dụng hiệu quả. Các hệ thống đồ họa liên quan phần cứng GPU ngày càng phát triển như OpenGL và Direct3D, và các ứng dụng này phụ thuộc vào hệ thống phần cứng và tương tác trực tiếp với phần cứng, đặt giả thiết ta cần làm các ứng dụng nhỏ trên Windows và mong muốn cung cấp cho nhiều người sử dụng (việc bắt buộc người sử dụng phải có card đồ họa trong khi ứng dụng dạng nhỏ sẽ giới hạn rất lớn cho việc phân phát ứng dụng, .NET cũng là điều tương tự). Việc càng sử dụng các công nghệ cao sẽ càng tăng rủi ro ứng dụng kém thích nghi trên các hệ thống khác nhau. Tôi chọn GDI+ cho các ứng dụng không đòi hỏi GPU này nhằm tăng lượng người sử dụng và tránh làm rối thêm cho tổ chức ứng dụng.

Đối tượng hướng đến

Để hiểu mã nguồn này bạn cần biết thêm về kiến thức Win32 API. Tuy nhiên, tôi đã viết sẵn các hàm và đối tượng để bạn không cần phải quan tâm vấn đề Win32 này. Tuy nhiên nếu bạn băn khoăn về Win32 API, bạn có thể tìm hiểu thêm tại Lập Trình Win32 API - Phần 1: Tổng Quan.

Project mẫu - VS2013, VS2015

Download Project mẫu

Download project mẫu ở cuối bài, trước khi theo dõi bài viết này.

Giải thích mã nguồn

Do tránh việc hạn chế nhiều bạn đọc chưa biết về OOP (lập trình hướng đối tượng) nên tôi tổ chức chương trình theo hướng thủ tục.

Trong mã nguồn này bạn có thể tập trung vào các file chính như sau:

  • STDIO_GDIPlus.cpp - Dành cho việc khởi tạo project và có thể hiểu như đầu vào (Entry Point) của chương trình Win32 API vì nó chứa đầu vào của chương trình và các cài đặt cần thiết.
  • GlobalVars.h - Chứa các biến toàn cục liên quan tới GDI+.
  • STDIO_Application.h và STDIO_Application.cpp - Chứa tất cả các hàm liên quan đến việc khởi tạo và hủy các tài nguyên của GDI+.

STDIO_GDIPlus.cpp

Ta có thể không cần quan tâm (vì việc khảo sát file này liên quan đến vấn đề Win32 API), hoặc bạn có thể khảo sát lướt qua xem các hàm trong STDIO_Application được gọi ở những đâu.

GlobalVars.h

extern Gdiplus::GdiplusStartupInput	STDIO_gdiplusStartupInput;
extern ULONG_PTR					STDIO_gdiplusToken;

extern Gdiplus::Graphics*			STDIO_graphic;

STDIO_gdiplusStartupInput và STDIO_gdiplusToken là 2 biến dành cho việc khởi tạo tài nguyên và token nắm giữ chìa khóa để hủy GDI+ khi sử dụng xong (bạn sẽ thấy bên dưới có hàm STDIO_GDIP_Destroy() có gọi hàm Gdiplus::GdiplusShutdown và truyền token (chìa khóa) này vào để giải phóng toàn bộ tài nguyên của GDI+. Hiện tại ta sẽ không khảo sát kỹ 2 biến này, tạm để mặc định).

Chứa đối tượng Graphics (là đối tượng chứa toàn bộ các phương thức vẽ quan trọng cho GDI+). Nếu đối tượng này khởi tạo không thành công, xem như ta không thể vẽ được.

STDIO_Application.h

Để sử dụng GDI+ ta cần thư viện gdiplus.h và 1 static library gdiplus.lib, cần lưu ý là toàn bộ thành phần liên quan GDI+ nằm trong namespace Gdiplus, bạn có thể thêm dòng using namespace Gdiplus nếu như muốn bỏ qua việc phải gõ Gdiplus:: trước các kiểu dữ liệu hoặc thành phần thuộc GDI+. Trong project này tôi không khai báo using namespace Gdiplus nên ở mỗi kiểu dữ liệu hoặc thành phần liên quan GDI+ tôi phải thêm Gdiplus:: vào trước kiểu dữ liệu hoặc thành phần này

#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")

Hàm khởi tạo GDI+ và khởi tạo đối tượng đồ họa Graphic STDIO_Application.cpp

void STDIO_GDIP_Init()
{
	GdiplusStartup(&STDIO_gdiplusToken, &STDIO_gdiplusStartupInput, NULL);
	
	STDIO_graphic = new Gdiplus::Graphics(GetDC(STDIO_AppHandle));
}

Hàm hủy khi không dùng GDI+ nữa

void STDIO_GDIP_Destroy()
{
	delete STDIO_graphic;
	Gdiplus::GdiplusShutdown(STDIO_gdiplusToken);
}

Hàm vẽ chính, bạn muốn thêm thành phần vẽ thì thêm vào hàm này, đây là hàm chính tôi viết ra để các bạn có thể thao tác vẽ sẽ tập trung thêm codes vào hàm này. Bạn có thể không cần quan tâm các hàm khác ngoài việc thao tác vẽ trong hàm này, tuy nhiên, nếu muốn thật sự hiểu biết về GDI+ thì nên tìm hiểu kỹ từng phần như tôi đã nêu ở trên.

void STDIO_GDIP_AppRun()

Kết quả

ss_1

Download demo hoàn chỉnh

Một số lưu ý về bài viết

  • Bài viết là 1 trải nghiệm với GDI+, trong bài viết lẫn demo để giữ cho các bạn mới tiếp cận tránh khó hiểu tôi không xây dựng kiến trúc phức tạp mà chỉ đơn thuần sử dụng phương pháp hướng thủ tục, không sử dụng class.
  • Không dùng các kỹ thuật tối ưu hóa phương pháp vẽ do đó nếu sử dụng để hoàn tất 1 đề tài về đồ họa cần cập nhật vẽ liên tục sẽ thấy demo giật.
THẢO LUẬN
ĐÓNG