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设置指定点的颜色

COLORREF SetPixel(
    HDC hdc, //DC句柄
    int x,//X坐标
    int y,//Y坐标
    COLORREF crColor//设置的颜色
);        
返回指定点原来的颜色

示例代码: 

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)点

示例代码:

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

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

示例代码:

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.画笔的使用: 

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

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

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

(3).绘图

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

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

(5).释放画笔

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

示例代码: 

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

示例代码:

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)
HDC CreateCompatibleDC(
	HDC hdc //当前句柄,可以为NULL(使用屏幕DC)
);
返回创建的DC句柄
  •  将位图放入匹配的内存DC中,SelectObject
  • 成像(1:1) 
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

示例代码:

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).绘制简单文件

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

示例代码:

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) 

示例代码:

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

字体的使用函数:

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 //字体名称
);

 示例代码:

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 @ 2023-09-12 22:15  TechNomad  阅读(516)  评论(0)    收藏  举报