Graphic Device Interface (GDI)

GDI là giao diện làm việc đồ họa. GDI được sử dụng để tương tác với các thiết bị đồ họa như màn hình, máy in hoặc file. GDI cho phép người lập trình hiển thị dữ liệu lên màn hình hoặc máy in mà không cần quan tâm tới đặc tính kĩ thuật của thiết bị (màn hình, máy in,…). Theo quan điểm người lập trình, GDI là 1 thư viện các API function làm việc với đồ họa. GDI bao gồm các vecto đồ họa 2D, Fonts và Image. Để băt đầu vẽ đồ họa, chúng ta phải lấy được đối tượng “ngữ cảnh thiết bị” (device context).

Pixel

#include "windows.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void DrawPixels(HWND hwnd);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    WNDCLASSW wc = {0};

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpszClassName = L"Pixels";
    wc.hInstance = hInstance;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc = WndProc;
    wc.hCursor = LoadCursor(0, IDC_ARROW);

    RegisterClassW(&wc);
    CreateWindowW(wc.lpszClassName, L"Pixels", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 150, NULL, NULL, hInstance, NULL);

    while( GetMessage(&msg, NULL, 0, 0)) 
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_PAINT:
        DrawPixels(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

void DrawPixels(HWND hwnd)
{
    PAINTSTRUCT ps;
    RECT r;

    HDC hdc = BeginPaint(hwnd, &ps);
    GetClientRect(hwnd, &r);
    for (int i=0; i<1000; i++) 
    {
        int x = (rand() % r.right - r.left);
        int y = (rand() % r.bottom - r.top);
        SetPixel(hdc, x, y, RGB(255, 0, 0));
    }
    EndPaint(hwnd, &ps);
}

Giải thích:
Hàm SetPixel() là hàm để vẽ 1 pixel lên cửa sổ ứng dụng.
Trong ví dụ này, chúng ta sử dung hàm SetPixel() để vẽ 1000 pixel màu đỏ lên cửa sổ ứng dụng.

wc.style = CS_HREDRAW | CS_VREDRAW;

Với 2 cờ CS_HREDRAW và CS_VREDRAW, cửa sổ sẽ được vẽ lại khi thay đổi kích thước

case WM_PAINT:
    DrawPixels(hwnd);
    break;

Việc vẽ pixel được thực hiện trong message WM_PAINT. Chương trình sẽ gọi DrawPixels() để vẽ 1000 pixel.

HDC hdc = BeginPaint(hwnd, &ps);

Hàm BeginPaint() chuẩn bị vùng cửa sổ để vẽ pixel. Hàm này sẽ điền thông tin vào struct PAINTSTRUCT. Và hàm trả về handle tới device context(thiết bị ngữ cảnh) của ứng dụng.

GetClientRect(hwnd, &r);

Hàm GetClientRect() kích thước (tọa độ) vùng cửa sổ cần vẽ pixel. Thông tin về tọa độ cửa sổ được lưu trong struct RECT r.

for (int i=0; i<1000; i++)
{
    int x = (rand() % r.right - r.left);
    int y = (rand() % r.bottom - r.top);
    SetPixel(hdc, x, y, RGB(255, 0, 0));
}

Hàm SetPixel vẽ pixel đỏ (RGB(255, 0, 0)) lên cửa sổ.

EndPaint(hwnd, &ps);

Khi vẽ xong, chúng ta gọi hàm EndPaint() để giải phóng bộ nhớ chứa thiết bị ngữ cảnh (device context) mà hàm BeginPaint() đã lấy.

Kết quả:

Pixels

 

Rectangle

Để vẽ hình chữ nhật, chúng ta sử dụng hàm Rectangle().

BOOL Rectangle(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);

Tham số:

 hdc: handle trỏ tới device context
 nLeftRect, nTopRect: tọa độ x, y góc trái phía trên hình chữ nhật
 nRightRect, nBottomRect: tọa độ x, y góc phải phía dưới hình chữ nhật

Trả về:

 - Hàm trả về 0 (false), nếu xảy ra lỗi
 - Hàm trả về khác 0 (true), nếu thành công
<pre>#include "windows.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    WNDCLASSW wc = {0};

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpszClassName = L"Rectangle";
    wc.hInstance = hInstance;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc = WndProc;
    wc.hCursor = LoadCursor(0, IDC_ARROW);

    RegisterClassW(&wc);
    CreateWindowW(wc.lpszClassName, L"Rectangle", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 200, NULL, NULL, hInstance, NULL);

    while( GetMessage(&msg, NULL, 0, 0)) 
    {
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;

    switch(msg)
    {
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        Rectangle(hdc, 50, 50, 200, 100);
        EndPaint(hwnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

Kết quả:

Rectangle

 

Pen

– Pen là 1 đối tượng đồ họa. Nó được dùng để vẽ line, đường cung, đường bao hình cn, elip, đa giác và các hình khác.
– Hàm CreatePen() tạo 1 logical pen với style, width và colour.

 

#include "windows.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void DrawLines(HWND);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 PWSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    WNDCLASSW wc = {0};

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpszClassName = L"Pens";
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
    wc.lpfnWndProc = WndProc;
    wc.hCursor = LoadCursor(0, IDC_ARROW);

    RegisterClassW(&wc);
    CreateWindowW(wc.lpszClassName, L"Pens",
 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
 100, 100, 250, 180, NULL, NULL, hInstance, NULL);

    while( GetMessage(&msg, NULL, 0, 0)) 
    {
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
 WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_PAINT:
        DrawLines(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

void DrawLines(HWND hwnd) 
{
    PAINTSTRUCT ps;

    HDC hdc = BeginPaint(hwnd, &ps);
    HPEN hPen1 = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
    HPEN hPen2 = CreatePen(PS_DASH, 1, RGB(0, 0, 0));
    HPEN hPen3 = CreatePen(PS_DOT, 1, RGB(0, 0, 0));
    HPEN hPen4 = CreatePen(PS_DASHDOT, 1, RGB(0, 0, 0));
    HPEN hPen5 = CreatePen(PS_DASHDOTDOT, 1, RGB(0, 0, 0));

    SelectObject(hdc, hPen1);
    MoveToEx(hdc, 50, 30, NULL);
    LineTo(hdc, 200, 30);

    SelectObject(hdc, hPen2);
    MoveToEx(hdc, 50, 50, NULL);
    LineTo(hdc, 200, 50);

    SelectObject(hdc, hPen2);
    MoveToEx(hdc, 50, 70, NULL);
    LineTo(hdc, 200, 70);

    SelectObject(hdc, hPen3);
    MoveToEx(hdc, 50, 90, NULL);
    LineTo(hdc, 200, 90);

    SelectObject(hdc, hPen4);
    MoveToEx(hdc, 50, 110, NULL);
    LineTo(hdc, 200, 110);

    DeleteObject(hPen1);
    DeleteObject(hPen2);
    DeleteObject(hPen3);
    DeleteObject(hPen4);
    DeleteObject(hPen5);

    EndPaint(hwnd, &ps); 
}

Giải thích:
Trong ví dụ này, chúng ta vẽ 5 line khác nhau bằng việc sử dụng 5 style pen khác nhau.
Việc vẽ line được thực hiện trong message WM_PAINT, hàm DrawLines() được gọi để vẽ line.

HPEN hPen1 = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));

Hàm CreatePen() dùng để tạo logical pen
PS_SOLID là hằng số, viết tắt của solid pen
1: độ rộng
RGB(0, 0, 0): chúng ta sử dụng macro RGB() để tạo màu cho pen.

SelectObject(hdc, hPen1);

Để kích hoạt (active) pen, chúng ta sử dụng SelectObject().

MoveToEx(hdc, 50, 30, NULL);
LineTo(hdc, 200, 30);

Để vẽ line, chúng ta sử dụng hàm MoveToEx() và LineTo().

DeleteObject(hPen1);
DeleteObject(hPen2);
DeleteObject(hPen3);
DeleteObject(hPen4);
DeleteObject(hPen5);

Cuối cùng, chúng ta giải phóng các đối tượng HPEN.

Kết quả:

Pen

 

Solid brush

Brush là 1 đối tượng đồ họa cơ bản. Nó được dùng để vẽ background của các hình như: hình chữ nhật. elip hoặc đa giác. Brush có thể là màu cứng (solid color), các nét gạch (hatch color),…

#include "windows.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void DrawRectangles(HWND);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 PWSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    WNDCLASSW wc = {0};

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpszClassName = L"Brush";
    wc.hInstance = hInstance;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc = WndProc;
    wc.hCursor = LoadCursor(0, IDC_ARROW);

    RegisterClassW(&wc);
    CreateWindowW(wc.lpszClassName, L"Solid Brush",
 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
 100, 100, 220, 240, NULL, NULL, hInstance, NULL);

    while (GetMessage(&msg, NULL, 0, 0)) 
    {
        DispatchMessage(&msg);
    }
    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg,
 WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_PAINT:
        DrawRectangles(hwnd); 
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

void DrawRectangles(HWND hwnd)
{
    PAINTSTRUCT ps;

    HDC hdc = BeginPaint(hwnd, &ps);

    HBRUSH hBrush1 = CreateSolidBrush(RGB(121, 90, 0));
    HBRUSH hBrush2 = CreateSolidBrush(RGB(240, 63, 19));
    HBRUSH hBrush3 = CreateSolidBrush(RGB(240, 210, 18));
    HBRUSH hBrush4 = CreateSolidBrush(RGB(9, 189, 21));

    Rectangle(hdc, 30, 30, 100, 100);
    SelectObject(hdc, hBrush2);
    Rectangle(hdc, 110, 30, 180, 100);
    SelectObject(hdc, hBrush3);
    Rectangle(hdc, 30, 110, 100, 180);
    SelectObject(hdc, hBrush4);
    Rectangle(hdc, 110, 110, 180, 180);

    DeleteObject(hBrush1);
    DeleteObject(hBrush2);
    DeleteObject(hBrush3);
    DeleteObject(hBrush4);

    EndPaint(hwnd, &ps);
}

Giải thích:
Trong ví dụ này, chúng ta fill 4 màu solid.

HBRUSH hBrush1 = CreateSolidBrush(RGB(121, 90, 0));

Hàm CreateSolidBrush() dùng để tạo 1 solid color.

SelectObject(hdc, hBrush2);

Hàm SelectObject() lựa chọn đối tượng brush vào device context.


Kết quả:

Solid Brush

 

Hatch brush

Hatch brush là 1 đối tượng đồ họa cơ bản. Nó bao gồm 6 kiểu hatch brush khác nhau. Ví dụ này sẽ show toàn bộ 6 kiểu hatch brush.

#include "windows.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void DrawRectangles(HWND hwnd);


int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 PWSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    WNDCLASSW wc = {0};

    wc.style = CS_VREDRAW | CS_HREDRAW;
    wc.lpszClassName = L"Brush";
    wc.hInstance = hInstance;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc = WndProc;
    wc.hCursor = LoadCursor(0, IDC_ARROW);

    RegisterClassW(&wc);
    CreateWindowW(wc.lpszClassName, L"Hatch brushes",
 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
 100, 100, 300, 220, NULL, NULL, hInstance, NULL);

    while( GetMessage(&msg, NULL, 0, 0)) {
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
 WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_PAINT:
        DrawRectangles(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0); 
        return 0;
    }
    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

void DrawRectangles(HWND hwnd)
{
    PAINTSTRUCT ps;

    HDC hdc = BeginPaint(hwnd, &ps);
    HPEN hPen = CreatePen(PS_NULL, 1, RGB(0, 0, 0));
    HGDIOBJ holdPen = SelectObject(hdc, hPen);

    HBRUSH hBrush1 = CreateHatchBrush(HS_BDIAGONAL, RGB(0, 0, 0));
    HBRUSH hBrush2 = CreateHatchBrush(HS_FDIAGONAL, RGB(0, 0, 0));
    HBRUSH hBrush3 = CreateHatchBrush(HS_CROSS, RGB(0, 0, 0));
    HBRUSH hBrush4 = CreateHatchBrush(HS_HORIZONTAL, RGB(0, 0, 0));
    HBRUSH hBrush5 = CreateHatchBrush(HS_DIAGCROSS, RGB(0, 0, 0));
    HBRUSH hBrush6 = CreateHatchBrush(HS_VERTICAL, RGB(0, 0, 0));

    HGDIOBJ holdBrush = SelectObject(hdc, hBrush1);

    DWORD col = GetSysColor(COLOR_BTNFACE);
    SetBkColor(hdc, col);

    Rectangle(hdc, 30, 30, 100, 80);
    SelectObject(hdc, hBrush2);
    Rectangle(hdc, 110, 30, 180, 80);
    SelectObject(hdc, hBrush3);
    Rectangle(hdc, 190, 30, 260, 80);
    SelectObject(hdc, hBrush4);
    Rectangle(hdc, 30, 110, 100, 160);
    SelectObject(hdc, hBrush5);
    Rectangle(hdc, 110, 110, 180, 160);
    SelectObject(hdc, hBrush6);
    Rectangle(hdc, 190, 110, 260, 160);

    SelectObject(hdc, holdPen);
    SelectObject(hdc, holdBrush);

    DeleteObject(hPen);
    DeleteObject(hBrush1);
    DeleteObject(hBrush2);
    DeleteObject(hBrush3);
    DeleteObject(hBrush4);
    DeleteObject(hBrush5);
    DeleteObject(hBrush6);

    EndPaint(hwnd, &ps);
}

Giải thích:
Trong ví dụ này, cũng tương tự ví dụ trước. Chúng ta sử dụng hàm CreateHatchBrush() để tạo brush.

HBRUSH hBrush1 = CreateHatchBrush(HS_BDIAGONAL, RGB(0, 0, 0));

Hàm này tạo brush kiểu đường chéo (diagonal brush).

HBRUSH holdBrush = SelectObject(hdc, hBrush1);

Brush được lựa chọn vào device context mà hdc trỏ tới. Hàm trả về handle tới old brush.

DeleteObject(hBrush1);

Đối tượng brush được giải phóng.

Kết quả:

Hatch brushes

 

Shape

 

#include "windows.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 PWSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    WNDCLASSW wc = {0};

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpszClassName = L"Shapes";
    wc.hInstance = hInstance;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc = WndProc;
    wc.hCursor = LoadCursor(0, IDC_ARROW);

    RegisterClassW(&wc);
    CreateWindowW(wc.lpszClassName, L"Shapes",
 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
 100, 100, 390, 230, NULL, NULL, hInstance, NULL);

    while( GetMessage(&msg, NULL, 0, 0)) 
    {
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
 WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    const POINT polygon[10] = { 30, 145, 85, 165, 105, 110, 65, 125, 30, 105 };
    const POINT bezier[4] = {280, 160, 320, 160, 325, 110, 350, 110};

    switch(msg)
    {
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        Ellipse(hdc, 30, 30, 120, 90);
        RoundRect(hdc, 150, 30, 240, 90, 15, 20);
        Chord(hdc, 270, 30, 360, 90, 270, 45, 360, 45);
        Polygon(hdc, polygon, 5);
        Rectangle(hdc, 150, 110, 230, 160);
        PolyBezier(hdc, bezier, 4);
        EndPaint(hwnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

Giải thích:
Trong ví dụ này, chúng ta sẽ vẽ 1 elip, hình chữ nhật, dây cung, đa giác, đường cong.


Ellipse(hdc, 30, 30, 120, 90);

Hàm Ellipse() vẽ hình ellip. Các thông số của hàm là tọa độ x,y của góc trái trên và góc phải dưới của hình chữ nhât bao lấy elip. Elip này được vẽ bên trong hình chữ nhật.


RoundRect(hdc, 150, 30, 240, 90, 15, 20);

Hàm RoundRect() dùng để vẽ hình chữ nhật bo tròn 4 góc.


Chord(hdc, 270, 30, 360, 90, 270, 45, 360, 45);

Hàm Chord() dùng để vẽ hình dây cung.


Polygon(hdc, polygon, 5);

Hàm Polygon() dùng để vẽ đa giác. Tham số polygon là mảng struct POINT gồm tọa độ của các đỉnh, 5 là số đỉnh của đa giác.


Rectangle(hdc, 150, 110, 230, 160);

Hàm Rectangle() dùng để vẽ hình chữ nhật. (150,110) là tọa độ của góc trái trên của hình chữ nhật, (230,160) là tọa độ góc phải dưới của hình chữ nhật.


PolyBezier(hdc, bezier, 4);

Hàm PolyBezier() dùng để vẽ. Tham số bezier là 1 mảng struct POINT chỉ ra các điểm trên đường cong. Tham số cuối cùng là điểm trong mảng.

Kết quả:

Shapes

 

Text

Hàm TextOutW() vẽ text lên vị trí chỉ định trên cửa sổ với các đặc tính: font, background color, text color,..

 

#include "windows.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 PWSTR lpCmdLine, int nCmdShow)
{
    MSG msg ;
    WNDCLASSW wc = {0};

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpszClassName = L"Text";
    wc.hInstance = hInstance;
    wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
    wc.lpfnWndProc = WndProc;
    wc.hCursor = LoadCursor(0, IDC_ARROW);

    RegisterClassW(&wc);
    CreateWindowW(wc.lpszClassName, L"GDI-Text",
 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
 100, 100, 390, 350, NULL, NULL, hInstance, NULL);

    while( GetMessage(&msg, NULL, 0, 0)) {
        DispatchMessage(&msg);
    }
    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
 WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;

    DWORD color;
    HFONT hFont, holdFont;

    static wchar_t ver1[] = L"Hello everybody,";
    static wchar_t ver2[] = L"This is forum for developer";
    static wchar_t ver3[] = L"Sharing everything";

    switch(msg)
    {
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        color = GetSysColor(COLOR_BTNFACE);
        SetBkColor(hdc, color);
        hFont = CreateFontW(15, 0, 0, 0, FW_MEDIUM, 0, 0, 0, 0, 0, 0, 0, 0, L"Georgia");
        holdFont = (HFONT)SelectObject(hdc, hFont);

        TextOutW(hdc, 50, 20, ver1, lstrlenW(ver1));
        TextOutW(hdc, 50, 40, ver2, lstrlenW(ver2));
        TextOutW(hdc, 50, 60, ver3, lstrlenW(ver3));

        SelectObject(hdc, holdFont);
        DeleteObject(hFont);

        EndPaint(hwnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

Giải thích:

color = GetSysColor(COLOR_BTNFACE);
SetBkColor(hdc, color);

Với chế độ mặc định, khi chúng ta ghi text lên vị trí của cửa sổ thì màu background là màu trắng. Chúng ta có thể thay đổi màu nền bằng hàm SetBkColor(). Ở đây, chúng ta đặt màu xám cho background. Hàm GetSysColor() lấy màu hệ thống (được sử dụng cho button, tiêu đề,..)

hFont = CreateFontW(15, 0, 0, 0, FW_MEDIUM, 0, 0, 0, 0, 0, 0, 0, 0, L"Georgia");
holdFont = SelectObject(hdc, hFont);

Hàm CreateFontW() để tạo font cho text. Hàm này có 14 tham số, nhưng chúng ta chỉ không cần chỉ định hết tất cả các tham số, chỉ quan tâm tới một vài tham số như: font size, font weight, fontface(kiểu chữ)).

TextOutW(hdc, 50, 20, verse1, lstrlenW(verse1));

Cuối cùng, chúng ta vẽ text lên cửa sổ bằng hàm TextOutW().

Kết quả:

Text

2 Comments on Graphic Device Interface (GDI)

Leave a Reply