Win32编程之绘图编程(四)

一、绘图基础

  • 绘图设备DC(Device Context),绘图上下文/绘图描述表
  • HDC:DC句柄,表示绘图设备
  • GDI:Windows graphics device interface(Win32提供的绘图API)
  • 颜色的使用:COLORREF:实际DWORD;例如:COLORREF nColor = 0;
  • 赋值使用RGB宏:例如:nColor = RGB(0,0, 255)
  • 获取RGB值:GetRValue/GetGValue/GetBValue;例如:BYTE nRed = GetRValue(nColor)

计算机使用红、绿、蓝:

  R:0~255

  G:0~255

  B:0~255

每一个颜色是3个字节24位,保存范围:0~2^24-1

二、基本图形绘制

(1).SetPixel设置指定点的颜色

1
2
3
4
5
6
COLORREF SetPixel(
    HDC hdc, //DC句柄
    int x,//X坐标
    int y,//Y坐标
    COLORREF crColor//设置的颜色
);        <br>返回指定点原来的颜色

示例代码: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void OnDrawPoint(HDC hdc) {
    for (int i = 0; i < 256; i++) {
        for (int j = 0; j < 256; j++) {
            SetPixel(hdc, i, j, RGB(i, j, 0));
        }
    }
}
 
void OnPaint(HWND hWnd) {
    PAINTSTRUCT ps = { 0 };
    HDC hdc = BeginPaint(hWnd, &ps);
    OnDrawPoint(hdc);
    EndPaint(hWnd, &ps);
}
 
//窗口处理函数(自定义,处理消息)
LRESULT CALLBACK WindProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) {
    switch (msgID) {
    case WM_PAINT: {
        OnPaint(hWnd);
        break;
    }
    default:
        break;
    }
 
    return DefWindowProc(hWnd, msgID, wParam, lParam);
}

(2).线的使用(直接,弧线)  

  • MoveToEx:指名窗口当前点
  • LineTo:从窗口当前点到指定点绘制一条直线
  • 当前点:上一次绘图时最后一点,初始为(0,0)点

示例代码:

1
2
3
4
5
6
void OnDrawLine(HDC hdc) {
    //改变窗口当前点坐标
    MoveToEx(hdc, 100, 100, NULL);
    LineTo(hdc, 300, 300);
    LineTo(hdc, 0, 300);
}

(3).封闭图形:能够用画刷填充的图形(Rectangle/Ellipse)

示例代码:

1
2
3
4
5
6
7
void OnDrawRect(HDC hdc) {
    Rectangle(hdc, 100, 100, 300, 300);
}
 
void OnDrawEll(HDC hdc) {
    Ellipse(hdc, 100, 100, 300, 300);
}

三、GDI绘图对象

1.画笔使用流程

(1)、创建画笔

  A.画笔的作用:线的颜色、线型、线粗

  B.画笔的使用: 

1
2
3
4
5
6
HPEN CreatePen(
    int fnPenStyle;//画笔的样式
    int nWidth;//画笔的粗细
    COLORREF crColor//画笔的颜色
);
创建成功后返回画笔句柄<br>PS_SOILD:实心线,可以支持多个像素宽,其他线型只能是一个像素宽

(2).将画笔应用到DC中 

1
2
3
4
5
6
HGDIOBJ SelectObject(
    HDC hdc;//绘图设备句柄
    HGDIOBJ hgdiobj//GDI绘图对象句柄,画笔句柄
);
返回原来的GDI绘图对象句柄
注意保存原来DC当中的画笔

(3).绘图

(4).取出DC中当中的画笔

将原来的画笔,使用SelectObject函数,放入到设备DC中,就会将我们创建的画笔取出

(5).释放画笔

1
2
3
4
BOOL DeleteObject(
    HGDIOBJ hObject //GDI绘图对象句柄,画笔句柄
);
只能删除不被DC使用的画笔,所以在释放前,必须将画笔从DC中取出

示例代码: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void OnDrawEll(HDC hdc) {
    Ellipse(hdc, 100, 100, 300, 300);
}
 
void OnPaint(HWND hWnd) {
    PAINTSTRUCT ps = { 0 };
    HDC hdc = BeginPaint(hWnd, &ps);
     
    HPEN hPen = CreatePen(PS_SOLID, 10, RGB(255, 0, 0));
    HGDIOBJ nOldPen = SelectObject(hdc, hPen);
    OnDrawEll(hdc);//绘制圆形
    SelectObject(hdc, nOldPen);
    DeleteObject(hPen);
 
    EndPaint(hWnd, &ps);
}
 
//窗口处理函数(自定义,处理消息)
LRESULT CALLBACK WindProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) {
    switch (msgID) {
    case WM_PAINT: {
        OnPaint(hWnd);
        break;
    }
    default:
        break;
    }
 
    return DefWindowProc(hWnd, msgID, wParam, lParam);
}

2.画刷的使用流程

(1).画刷相关

画刷:封闭图像的填充的颜色、图案;HBRUSH:画刷句柄

(2).画刷的使用

  • 创建画刷:CreateSolidBrush:创建实现画刷;CreateHatchBrush:创建纹理画刷
  • 将画刷应用到DC中,selectObject
  • 绘图
  • 将画刷从DC中取出:SelectObject
  • 删除画刷:DeleteObject

(3).透明画刷

可以使用GetStockObject函数获取系统维护的画刷、画笔等,如果不使用画刷填充,需要使用NULL_BRUSH参数,获取不填充的画刷,GetStokObject返回的画刷不需要DeleteObject

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void OnPaint(HWND hWnd) {
    PAINTSTRUCT ps = { 0 };
    HDC hdc = BeginPaint(hWnd, &ps);
     
    HPEN hPen = CreatePen(PS_DASH, 1, RGB(255, 0, 0));
    HGDIOBJ nOldPen = SelectObject(hdc, hPen);
 
    //HBRUSH hBrush = CreateSolidBrush(RGB(0, 255, 0));
    //HBRUSH hBrush = CreateHatchBrush(HS_CROSS, RGB(0, 255, 0));
    HGDIOBJ hBrush = GetStockObject(NULL_BRUSH);
    HGDIOBJ nOldBrush = SelectObject(hdc, hBrush);
 
    OnDrawEll(hdc);//绘制圆形
     
    SelectObject(hdc, nOldBrush);
    DeleteObject(hBrush);
     
    SelectObject(hdc, nOldPen);
    //DeleteObject(hPen);
 
    EndPaint(hWnd, &ps);
}

四、位图绘制

(1).位图相关

  • 光栅图形:激励图像中每一点的颜色信息
  • 矢量图形:记录图像算法、绘图指令等
  • HBITMAP:位图句柄

(2).位图使用

  • 在资源中添加位图资源
  • 从资源中加载位图
  • 创建一个与当前DC相匹配的DC(内存DC)
1
2
3
4
HDC CreateCompatibleDC(
    HDC hdc //当前句柄,可以为NULL(使用屏幕DC)
);
返回创建的DC句柄
  •  将位图放入匹配的内存DC中,SelectObject
  • 成像(1:1) 
1
2
3
4
5
6
7
8
9
10
11
BOOL BitBlt(
    HDC hdc, //目的DC(窗口DC)
    int x, //目的的左上X坐标
    int y, //目的的左上Y坐标
    int cx, //目的宽度
    int cy, //目的的高度
    HDC hdcSrc, //源DC(内存DC)
    int x1, //源左上X坐标
    int y1, //源左上Y坐标
    DWORD rop //成像方法 SRCCOPY
);
  • 取出位图:SelectObject
  • 释放位图:DeleteObject
  • 释放匹配的DC:DeleteDC

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void OnDrawBmp(HDC hdc) {
    //添加位图资源
    HBITMAP hBmp = LoadBitmap(g_hIns, (LPCWSTR)IDB_BITMAP1);
    //创建一个内存DC,并构建一个虚拟区域,并且内存DC在虚拟区域中绘图
    HDC hMemdc = CreateCompatibleDC(hdc);
    //将位图数据送给内存DC,内存DC在虚拟区域中将位图绘制出来
    HGDIOBJ nOldBmp = SelectObject(hMemdc, hBmp);
    //将虚拟区域中绘制好的图形成像到窗口中
    BitBlt(hdc, 100, 100, 48, 48, hMemdc, 0, 0, SRCCOPY);
    //缩放成像
    StretchBlt(hdc, 200, 200, 24, 24, hMemdc, 0, 0, 48, 48, SRCCOPY);
    SelectObject(hMemdc, nOldBmp);
    DeleteObject(hBmp);
    DeleteDC(hMemdc);
}
 
void OnPaint(HWND hWnd) {
    PAINTSTRUCT ps = { 0 };
    HDC hdc = BeginPaint(hWnd, &ps);
    OnDrawBmp(hdc);
    EndPaint(hWnd, &ps);
}

五、文本绘制

(1).绘制简单文件

1
2
3
4
5
6
7
8
9
10
/*
TextOut():将文字绘制在指定坐标位置
int DrawText(
    HDC hDc,//DC句柄
    LPCTSTR lpString, //字符串
    int nCount, //字符数量
    LPRECT lpRect, //绘制文字的矩形框
    UINT uFormat //绘制方式
);
*/

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void onDrawText(HDC hdc) {
    TCHAR szText[] = TEXT("Hello Text ");
    TextOut(hdc, 100, 100, szText, _tcslen(szText));
     
    RECT rc;
    rc.left = 100;
    rc.top = 150;
    rc.right = 200;
    rc.bottom = 200;
    Rectangle(hdc, 100, 150, 200, 200);
    //DT_VCENTER /DT_BOTTOM只是用于DT_SINGLELINE, 它们和DT_WORDBREAK冲突
    DrawText(hdc, szText, _tcslen(szText), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP);
}
 
void OnPaint(HWND hWnd) {
    PAINTSTRUCT ps = { 0 };
    HDC hdc = BeginPaint(hWnd, &ps);
    onDrawText(hdc);
    EndPaint(hWnd, &ps);
}

(2).文件颜色和背景

  • 文字颜色:SetTextColor
  • 文字背景颜色:SetBkColor
  • 文字背景模式:SetBkMode(OPAQUE/TRANSPARENT) 

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void onDrawText(HDC hdc) {
    TCHAR szText[] = TEXT("Hello Text ");
    TextOut(hdc, 100, 100, szText, _tcslen(szText));
     
    RECT rc;
    rc.left = 100;
    rc.top = 150;
    rc.right = 200;
    rc.bottom = 200;
    DrawText(hdc, szText, _tcslen(szText), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP);
}
 
void OnPaint(HWND hWnd) {
    PAINTSTRUCT ps = { 0 };
    HDC hdc = BeginPaint(hWnd, &ps);
    SetTextColor(hdc, RGB(255, 0, 0));
    SetBkColor(hdc, RGB(0, 255, 0));//只适用在OPAQUE模式下
    SetBkMode(hdc, TRANSPARENT);
    onDrawText(hdc);
    EndPaint(hWnd, &ps);
}

3.字体的使用

  • 字体相关:Windows常用的字体为TrueType格式的字体文件,字体名:标识字体类型;HFONT:字体句柄
  • 应用字体到DC:SelectObject
  • 绘制文字:DrawText/TextOut
  • 取出字体:SelectObject
  • 删除字体:DeleteObject

字体的使用函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CreateFont(
        _In_ int cHeight, //字体高度
        _In_ int cWidth, //字体宽度
        _In_ int cEscapement, //字符串倾斜角度
        _In_ int cOrientation, //字符旋转角度
        _In_ int cWeight, //字体的粗细
        _In_ DWORD bItalic, //斜体
        _In_ DWORD bUnderline, //字符下划线
        _In_ DWORD bStrikeOut, //删除线
        _In_ DWORD iCharSet, //字符集
        _In_ DWORD iOutPrecision, //输出精度
        _In_ DWORD iClipPrecision, //剪切精度
        _In_ DWORD iQuality, //输出质量
        _In_ DWORD iPitchAndFamily, //匹配字体
        _In_opt_ LPCWSTR pszFaceName //字体名称
);

 示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void onDrawText(HDC hdc) {
    TCHAR szText[] = TEXT("Hello Text ");
    HFONT hFont = CreateFont(30, 0, 45, 0, 900, 1, 1, 1, GB2312_CHARSET, 0, 0, 0, 0, TEXT("黑体"));
    HGDIOBJ nOldFont = SelectObject(hdc, hFont);
 
    TextOut(hdc, 100, 100, szText, _tcslen(szText));
 
    RECT rc;
    rc.left = 100;
    rc.top = 150;
    rc.right = 200;
    rc.bottom = 200;
    DrawText(hdc, szText, _tcslen(szText), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP);
 
    SelectObject(hdc, nOldFont);
    DeleteObject(hFont);
}
 
void OnPaint(HWND hWnd) {
    PAINTSTRUCT ps = { 0 };
    HDC hdc = BeginPaint(hWnd, &ps);
    SetTextColor(hdc, RGB(255, 0, 0));
    SetBkColor(hdc, RGB(0, 255, 0));//只适用在OPAQUE模式下
    SetBkMode(hdc, TRANSPARENT);
    onDrawText(hdc);
    EndPaint(hWnd, &ps);
}

  

  

posted @   TechNomad  阅读(410)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示