Windows程序设计-GDI图形

GDI

图形设备接口(GDI:Graphics Device Interface)是Windows的子系统,它负责在视频显示器和打印机上显示图形。

六种GDI对象:画笔、画刷、位图、区域、字体和调色板。
除了调色盘之外,这些对象都是通过SelectObject选进设备内容的。

GDI函数分类

  • 取得(或者建立)和释放(或者清除)设备内容的函数:GetDC RealseDC BeginPaint EndPaint
  • 取得有关设备内容信息的函数:GetTextMetrics
  • 绘图函数:TextOut
  • 设定和取得设备内容参数的函数:SetTextColor SetTextAlign
  • 使用GDI对象的函数:CreatePen CreatePenIndirect ExtCreatePen

GDI基本图形

  • 直线和曲线
  • 填入区域
  • 位图
  • 文字

其它部分

  • 影像模式和变换
  • Metafile
  • 绘图区域
  • 路径
  • 剪裁
  • 调色板
  • 打印

取得设备内容

处理WM_PAINT消息

PAINTSTRUCT ps;
hdc = BeginPaint (hwnd, &ps) ;
// 其它行程序
EndPaint (hwnd, &ps) ;

在整个显示区域上绘图

hdc = GetWindowDC (hwnd) ;
// 其它行程序
ReleaseDC (hwnd, hdc) ;

在整个窗口(包括标题、菜单、状态栏、滚动条)上绘图

GetWindowDC

更通用

hdc = CreateDC (pszDriver, pszDevice, pszOutput, pData) ;
// 其它行程序
DeleteDC (hdc) ;

hdc = CreateDC (TEXT ("DISPLAY"), NULL, NULL, NULL) ; // 取得整个屏幕的

信息内容

hdc = CreateIC (TEXT ("DISPLAY"), NULL, NULL, NULL) ; // 信息内容句柄

hdcMem = CreateCompatibleDC (hdc) ; // 位图 内存设备内容
// 其它行程序
DeleteDC (hdcMem) ;

hdcMeta = CreateMetaFile (pszFilename) ; // metafile
// 其它行程序
hmf = CloseMetaFile (hdcMeta) ;

取得设备内容信息

// 参数iIndex取值为WINGDI.H表头文件中定义的29个标识符之一 如HORZRES
iValue = GetDeviceCaps (hdc, iIndex) ;

DEVCAPS1.C
Windows程序设计-GDI图形_第1张图片

/*------------------------------------------------------------------------
DEVCAPS1.C -- Device Capabilities Display Program No. 1
(c) Charles Petzold, 1998
----------------------------------------------------------------------*/
#include 
#define NUMLINES ((int) (sizeof devcaps / sizeof devcaps [0]))
struct
{
    int iIndex;
    TCHAR *szLabel;
    TCHAR *szDesc;
}
devcaps[] =
{
    HORZSIZE, TEXT("HORZSIZE"),TEXT("Width in millimeters:"),
    VERTSIZE, TEXT("VERTSIZE"),TEXT("Height in millimeters:"),
    HORZRES, TEXT("HORZRES"), TEXT("Width in pixels:"),
    VERTRES, TEXT("VERTRES"), TEXT("Height in raster lines:"),
    BITSPIXEL, TEXT("BITSPIXEL"),TEXT("Color bits per pixel:"),
    PLANES, TEXT("PLANES"), TEXT("Number of color planes:"),
    NUMBRUSHES, TEXT("NUMBRUSHES"), TEXT("Number of device brushes:"),
    NUMPENS, TEXT("NUMPENS"), TEXT("Number of device pens:"),
    NUMMARKERS, TEXT("NUMMARKERS"), TEXT("Number of device markers:"),
    NUMFONTS, TEXT("NUMFONTS"), TEXT("Number of device fonts:"),
    NUMCOLORS, TEXT("NUMCOLORS"), TEXT("Number of device colors:"),
    PDEVICESIZE, TEXT("PDEVICESIZE"),TEXT("Size of device structure:"),
    ASPECTX, TEXT("ASPECTX"), TEXT("Relative width of pixel:"),
    ASPECTY, TEXT("ASPECTY"), TEXT("Relative height of pixel:"),
    ASPECTXY, TEXT("ASPECTXY"), TEXT("Relative diagonal of pixel:"),
    LOGPIXELSX, TEXT("LOGPIXELSX"), TEXT("Horizontal dots per inch:"),
    LOGPIXELSY, TEXT("LOGPIXELSY"), TEXT("Vertical dots per inch:"),
    SIZEPALETTE, TEXT("SIZEPALETTE"),TEXT("Number of palette entries:"),
    NUMRESERVED, TEXT("NUMRESERVED"),TEXT("Reserved palette entries:"),
    COLORRES, TEXT("COLORRES"), TEXT("Actual color resolution:")
};
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("DevCaps1");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
            szAppName, MB_ICONERROR);
        return 0;
    }
    hwnd = CreateWindow(szAppName, TEXT("Device Capabilities"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static int cxChar, cxCaps, cyChar;
    TCHAR szBuffer[10];
    HDC hdc;
    int i;
    PAINTSTRUCT ps;
    TEXTMETRIC tm;
    switch (message)
    {
    case WM_CREATE:
        hdc = GetDC(hwnd);
        GetTextMetrics(hdc, &tm);
        cxChar = tm.tmAveCharWidth;
        cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;
        cyChar = tm.tmHeight + tm.tmExternalLeading;
        ReleaseDC(hwnd, hdc);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        for (i = 0; i < NUMLINES; i++)
        {
            TextOut(hdc, 0, cyChar * i,
                devcaps[i].szLabel,
                lstrlen(devcaps[i].szLabel));
            TextOut(hdc, 14 * cxCaps, cyChar * i,
                devcaps[i].szDesc,
                lstrlen(devcaps[i].szDesc));
            SetTextAlign(hdc, TA_RIGHT | TA_TOP);
            TextOut(hdc, 14 * cxCaps + 35 * cxChar, cyChar*i, szBuffer,
                wsprintf(szBuffer, TEXT("%5d"),
                    GetDeviceCaps(hdc, devcaps[i].iIndex)));
            SetTextAlign(hdc, TA_LEFT | TA_TOP);
        }
        EndPaint(hwnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

画线正弦三角函数

Windows程序设计-GDI图形_第2张图片

#include 
#include 
#define NUM 1000
#define TWOPI (2 * 3.14159)
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("SineWave");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("Program requires Windows NT!"),
            szAppName, MB_ICONERROR);
        return 0;
    }
    hwnd = CreateWindow(szAppName, TEXT("Sine Wave Using Polyline"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam,
    LPARAM lParam)
{
    static int cxClient, cyClient;
    HDC hdc;
    int i;
    PAINTSTRUCT ps;
    POINT apt[NUM];
    switch (message)
    {
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        MoveToEx(hdc, 0, cyClient / 2, NULL);
        LineTo(hdc, cxClient, cyClient / 2);
        for (i = 0; i < NUM; i++)
        {
            apt[i].x = i * cxClient / NUM;
            apt[i].y = (int)(cyClient / 2 * (1 - sin(TWOPI * i / NUM)));
        }
        Polyline(hdc, apt, NUM);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

画图形

Windows程序设计-GDI图形_第3张图片

#include 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("LineDemo");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("Program requires Windows NT!"),
            szAppName, MB_ICONERROR);
        return 0;
    }
    hwnd = CreateWindow(szAppName, TEXT("Line Demonstration"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static int cxClient, cyClient;
    HDC hdc;
    PAINTSTRUCT ps;
    switch (message)
    {
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        Rectangle(hdc, cxClient / 8, cyClient / 8,
            7 * cxClient / 8, 7 * cyClient / 8);
        MoveToEx(hdc, 0, 0, NULL);
        LineTo(hdc, cxClient, cyClient);
        MoveToEx(hdc, 0, cyClient, NULL);
        LineTo(hdc, cxClient, 0);
        Ellipse(hdc, cxClient / 8, cyClient / 8,
            7 * cxClient / 8, 7 * cyClient / 8);
        RoundRect(hdc, cxClient / 4, cyClient / 4,
            3 * cxClient / 4, 3 * cyClient / 4,
            cxClient / 4, cyClient / 4);
        EndPaint(hwnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

填入方式

Windows程序设计-GDI图形_第4张图片
ALTWIND.C

/*-------------------------------------------------------------------
ALTWIND.C -- Alternate and Winding Fill Modes
(c) Charles Petzold, 1998
-------------------------------------------------------------------*/
#include 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("AltWind");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("Program requires Windows NT!"),
            szAppName, MB_ICONERROR);
        return 0;
    }
    hwnd = CreateWindow(szAppName, TEXT("Alternate and Winding Fill Modes"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam,
    LPARAM lParam)
{
    static POINT aptFigure[10] = { 10,70, 50,70, 50,10, 90,10, 90,50,
        30,50, 30,90, 70,90, 70,30, 10,30 };
    static int cxClient, cyClient;
    HDC hdc;
    int i;
    PAINTSTRUCT ps;
    POINT apt[10];
    switch (message)
    {
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        SelectObject(hdc, GetStockObject(GRAY_BRUSH));
        for (i = 0; i < 10; i++)
        {
            apt[i].x = cxClient * aptFigure[i].x / 200;
            apt[i].y = cyClient * aptFigure[i].y / 100;
        }
        SetPolyFillMode(hdc, ALTERNATE);
        Polygon(hdc, apt, 10);
        for (i = 0; i < 10; i++)
        {
            apt[i].x += cxClient / 2;
        }
        SetPolyFillMode(hdc, WINDING);
        Polygon(hdc, apt, 10);
        EndPaint(hwnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

映射模式

Windows程序设计-GDI图形_第5张图片

/*------------------------------------------------------------
WHATSIZE.C -- What Size is the Window?
(c) Charles Petzold, 1998
----------------------------------------------------------*/
#include 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("WhatSize");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
            szAppName, MB_ICONERROR);
        return 0;
    }
    hwnd = CreateWindow(szAppName, TEXT("What Size is the Window?"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
void Show(HWND hwnd, HDC hdc, int xText, int yText, int iMapMode,
    TCHAR * szMapMode)
{
    TCHAR szBuffer[60];
    RECT rect;
    SaveDC(hdc);
    SetMapMode(hdc, iMapMode);
    GetClientRect(hwnd, &rect);
    DPtoLP(hdc, (PPOINT)&rect, 2);
    RestoreDC(hdc, -1);
    TextOut(hdc, xText, yText, szBuffer, wsprintf(szBuffer, TEXT("%-20s %7d %7d %7d %7d"),
        szMapMode,
        rect.left, rect.right, rect.top, rect.bottom));
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam,
    LPARAM lParam)
{
    static TCHAR szHeading[] =
        TEXT("Mapping Mode Left Right Top Bottom");
    static TCHAR szUndLine[] =
        TEXT("------------ ---- ----- --- ------");
    static int cxChar, cyChar;
    HDC hdc;
    PAINTSTRUCT ps;
    TEXTMETRIC tm;
    switch (message)
    {
    case WM_CREATE:
        hdc = GetDC(hwnd);
        SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
        GetTextMetrics(hdc, &tm);
        cxChar = tm.tmAveCharWidth;
        cyChar = tm.tmHeight + tm.tmExternalLeading;
        ReleaseDC(hwnd, hdc);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
        SetMapMode(hdc, MM_ANISOTROPIC);
        SetWindowExtEx(hdc, 1, 1, NULL);
        SetViewportExtEx(hdc, cxChar, cyChar, NULL);
        TextOut(hdc, 1, 1, szHeading, lstrlen(szHeading));
        TextOut(hdc, 1, 2, szUndLine, lstrlen(szUndLine));
        Show(hwnd, hdc, 1, 3, MM_TEXT, TEXT("TEXT (pixels)"));
        Show(hwnd, hdc, 1, 4, MM_LOMETRIC, TEXT("LOMETRIC (.1mm)")) ;
            Show(hwnd, hdc, 1, 5, MM_HIMETRIC, TEXT("HIMETRIC (.01mm)")) ;
                Show(hwnd, hdc, 1, 6, MM_LOENGLISH, TEXT("LOENGLISH (.01in)")) ;
                    Show(hwnd, hdc, 1, 7, MM_HIENGLISH, TEXT("HIENGLISH (.001in)")) ;
                        Show(hwnd, hdc, 1, 8, MM_TWIPS, TEXT("TWIPS (1/1440 in)"));
        EndPaint(hwnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

使用PeekMessage实现随机矩形

/*----------------------------------------------------------------------
RANDRECT.C -- Displays Random Rectangles
(c) Charles Petzold, 1998
-----------------------------------------------------------------------*/
#include 
#include // for the rand function
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void DrawRectangle(HWND);
int cxClient, cyClient;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("RandRect");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
            szAppName, MB_ICONERROR);
        return 0;
    }
    hwnd = CreateWindow(szAppName, TEXT("Random Rectangles"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    while (TRUE)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
                break;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
            DrawRectangle(hwnd);
    }
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam,
    LPARAM lParam)
{
    switch (iMsg)
    {
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
void DrawRectangle(HWND hwnd)
{
    HBRUSH hBrush;
    HDC hdc;
    RECT rect;
    if (cxClient == 0 || cyClient == 0)
        return;
    SetRect(&rect, rand() % cxClient, rand() % cyClient,
        rand() % cxClient, rand() % cyClient);
    hBrush = CreateSolidBrush(
        RGB(rand() % 256, rand() % 256, rand() % 256));
    hdc = GetDC(hwnd);
    FillRect(hdc, &rect, hBrush);
    ReleaseDC(hwnd, hdc);
    DeleteObject(hBrush);
}

Windows程序设计-GDI图形_第6张图片

剪裁区域

/*--------------------------------------------------------------------------
CLOVER.C -- Clover Drawing Program Using Regions
(c) Charles Petzold, 1998
----------------------------------------------------------------------*/
#include 
#include 
#define TWO_PI (2.0 * 3.14159)
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("Clover");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
            szAppName, MB_ICONERROR);
        return 0;
    }
    hwnd = CreateWindow(szAppName, TEXT("Draw a Clover"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam,
    LPARAM lParam)
{
    static HRGN hRgnClip;
    static int cxClient, cyClient;
    double fAngle, fRadius;
    HCURSOR hCursor;
    HDC hdc;
    HRGN hRgnTemp[6];
    int i;
    PAINTSTRUCT ps;
    switch (iMsg)
    {
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
        ShowCursor(TRUE);
        if (hRgnClip)
            DeleteObject(hRgnClip);
        hRgnTemp[0] = CreateEllipticRgn(0, cyClient / 3,
            cxClient / 2, 2 * cyClient / 3);
        hRgnTemp[1] = CreateEllipticRgn(cxClient / 2, cyClient / 3,
            cxClient, 2 * cyClient / 3);
        hRgnTemp[2] = CreateEllipticRgn(cxClient / 3, 0,
            2 * cxClient / 3, cyClient / 2);
        hRgnTemp[3] = CreateEllipticRgn(cxClient / 3, cyClient / 2,
            2 * cxClient / 3, cyClient);
        hRgnTemp[4] = CreateRectRgn(0, 0, 1, 1);
        hRgnTemp[5] = CreateRectRgn(0, 0, 1, 1);
        hRgnClip = CreateRectRgn(0, 0, 1, 1);
        CombineRgn(hRgnTemp[4], hRgnTemp[0], hRgnTemp[1], RGN_OR);
        CombineRgn(hRgnTemp[5], hRgnTemp[2], hRgnTemp[3], RGN_OR);
        CombineRgn(hRgnClip, hRgnTemp[4], hRgnTemp[5],
            RGN_XOR);
        for (i = 0; i < 6; i++)
            DeleteObject(hRgnTemp[i]);
        SetCursor(hCursor);
        ShowCursor(FALSE);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        SetViewportOrgEx(hdc, cxClient / 2, cyClient / 2, NULL);
        SelectClipRgn(hdc, hRgnClip);
        fRadius = _hypot(cxClient / 2.0, cyClient / 2.0);
        for (fAngle = 0.0; fAngle < TWO_PI; fAngle += TWO_PI / 360)
        {
            MoveToEx(hdc, 0, 0, NULL);
            LineTo(hdc, (int)(fRadius * cos(fAngle) + 0.5),
                (int)(-fRadius * sin(fAngle) + 0.5));
        }
        EndPaint(hwnd, &ps);
        return 0;
    case WM_DESTROY:
        DeleteObject(hRgnClip);
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

效果:
Windows程序设计-GDI图形_第7张图片

使用GDI对象的原则:

  • 最后要删除自己建立的所有GDI对象。
  • 当GDI对象正在一个有效的设备内容中使用时,不要删除它。
  • 不要删除现有对象。

你可能感兴趣的:(windows,c)