Windows编程,画笔画刷的介绍
画笔,可以用以下代码新建一个画笔对象:
HPEN hpen = CreatePen(PS_SOLID, 1, RGB(255,0,0));
可以看到,画笔的CreatePen()有三个参数(parameter),第一个参数表示画笔类型,第二个参数表示画笔宽度(注意以pixel为单位),第三个参数是画笔颜色。
除了上述的方法之外,还可以通过这两种方法获得画笔对象:
GetStockObject(WHITE_PEN),CreatePenIndirect(CONST LOGPEN*lplgpn)。
这三种方式的返回值都是HPEN,而他们的区别就是,Stock Pen,系统库存的pen的颜色,比如WHITE_PEN, BLACK_PEN, NULL_PEN,这些样式都可以直接从GetStockObject()函数中获得。
为了使我们要画的图形的线是我们设置好的画笔类型画出的线,就要在代码中使用SelectObject()函数,来具体调用画笔。
由于每次画笔的产生都要分配存储空间,故在使用完之后(程序结束后),使用DeleteObject()函数删除画笔对象。
那么,画笔类型有多少种呢?下面附上画笔的基本类型:
PS_DOT //点状线
PS_DASHDOT // 线段加点
PS_DASHDOTDOT//线段加点再加点
PS_DASH //线段
PS_SOLID //直线
PS_NULL //无
想要使用不同类型的画笔,只需更改第一个参数即可
画刷,可以用以下代码新建一个画刷:
hBrush = CreateSolidBrush (crColor) ;//单色填充
hBrush = CreateHatchBrush (iHatchStyle,crColor) ; //阴影填涂
CreatePatternBrush
CreateDIBPatternBrushPt
hBrush = CreateBrushIndirect(&logbrush) ; //逻辑画刷
Windows提供了五种函数用于构建 画刷对象。
当然,同画笔一样,画刷也可以用GetStockObject()函数来获得windows自身所存的画刷类型(NULL_BRUSH 等)。
而画刷的类型如下:
//HS_VERTICAL, /* ||||| 垂直 */
// HS_HORIZONTAL, /* ----- 水平 */
// HS_BDIAGONAL /* 左斜线 */
// HS_FDIAGONAL /* \\\\ 右斜线 */
// HS_CROSS, /* +++++ 正十字 */
// HS_DIAGCROSS /* xxxxx 斜十字 */
同样,为了使我们要画的图形的用上我们所设置的画刷类型,就要在代码中使用SelectObject()函数,来具体调用画刷。
由于每次画刷的产生都要分配存储空间,故在使用完之后(程序结束后),使用DeleteObject()函数删除画刷对象。
初步了解画笔和画刷后,让我们开始尝试绘制几何图形
几何图形的绘制
首先我们得明确在windows中提供的绘制几何图形的各类函数:
直角矩形:Rectangle()
具体:
WINGDIAPI BOOL WINAPI Rectangle(In HDC hdc, In int left, In int top, In int right, In int bottom);
椭圆 :Ellipse ()
具体:
WINGDIAPI BOOL WINAPI Ellipse( In HDC hdc, In int left, In int top, In int right, In int bottom);
圆角矩形:RoundRect()
具体:
WINGDIAPI BOOL WINAPI RoundRect(In HDC hdc, In int left, In int top, In int right, In int bottom, In int width, In int height);
椭圆周上的弧,两端以弦连接:Chord ()
具体:
WINGDIAPI BOOL WINAPI Chord( In HDC hdc, In int x1, In int y1, In int x2, In int y2, In int x3, In int y3, In int x4, In int y4);
椭圆上的饼图:Pie ()
具体:
WINGDIAPI BOOL WINAPI Pie(In HDC hdc, In int left, In int top, In int right, In int bottom, In int xr1, In int yr1, In int xr2, In int yr2);
多边形:Polygon ()
具体:
WINGDIAPI BOOL WINAPI Polygon(In HDC hdc, In_reads(cpt) CONST POINT *apt, In int cpt);
多个多边形:PolyPolygon()
具体:
WINGDIAPI BOOL WINAPI PolyPolygon(In HDC hdc, In CONST POINT *apt, In_reads(csz) CONST INT *asz, In int csz);
便于更好的理解和运用,我会逐个分析各个几何图形函数中参数的意义。
Rectangle()
它有5个参数,第一个参数(剩下的各个函数的第一个参数也都相同)是指设备描述表句柄,即在WM_PAINT中定义的一个HDC类的句柄,为了使函数能正常作用,必须将设备描述表句柄信息提供给函数。,这个函数剩余的四个参数的功能非常简单,就如定义所简写,表示两个点,矩形的左上角端点的横纵坐标和矩形的右下角端点的横纵坐标。
Ellipse()
几乎和矩形一样,注意,windows中的构建椭圆(圆形),是通过先建立矩形确定范围,再画出椭圆,所以后四个参数也是先构建的矩形的左上角端点坐标和右下角端点坐标。
RoundRect()
圆角矩形,比起普通的矩形函数多了最后两个参数,这两个参数也是 int类型,具体功能是改变圆角矩形圆角的弯曲程度,数值设置的较高,则弯曲程度越强。
Pie(),
饼图,它有八个int类型的参数,前四个也是表示先构建的矩形左上角端点和右下角端点。后四个,注意,是由圆心衍生的两条半径的端点的坐标。或者说是坐标点 与 圆心 相连的线,在运行后会保留线在圆内的部分,从而实现饼图。
Polygon()
其中,第二个参数 是一个 POINT 结构的数组,第三个参数 是点的个数。如果数组中最后一个点与第一个点不同,则 Windows 会再加一条线连接最后一个点与第一个点。(在 Polyline 函数中不会这么做。)
PolyPolygon()
最后一个参数是绘制的多边形的个数。对每个多边形,第二个参数数值给出了多边形顶点的个数。数组中含有全部多边形的所有顶点。
了解上述基础知识后,以下是一个使用visual studio 2017 编写的 实现 基本几何图形绘制 和 画笔画刷类型应用的程序;
//WindowsProject3.cpp: 定义应用程序的入口点。
//
#include "stdafx.h"
#include "WindowsProject3.h"
#define MAX_LOADSTRING 100
// 全局变量:
HINSTANCE hInst; // 当前实例
WCHAR szTitle[MAX_LOADSTRING] = TEXT("2_1"); // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 在此放置代码。
// 初始化全局字符串
//LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_WINDOWSPROJECT3, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT3));
MSG msg;
// 主消息循环:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// 函数: MyRegisterClass()
//
// 目的: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT3));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT3);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// 函数: InitInstance(HINSTANCE, int)
//
// 目的: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 将实例句柄存储在全局变量中
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
/* case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;*/
case WM_PAINT:
{
//hBru[i] = CreateHatchBrush(sBru[i], RGB(255, 0, 0))
HBRUSH hBrush;//添加画刷
//HBRUSH hBrush2;//添加画刷
HPEN hPen;
static HPEN hPen2;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
//hBrush2 = (HBRUSH)GetStockObject(NULL_BRUSH);//空心,画刷取空
//SelectObject(hdc, hBrush2);
hPen = CreatePen(PS_DASH, 1, RGB(255, 0, 0));//red
SelectObject(hdc, hPen);
//SelectObject(hdc, hBrush);
Ellipse(hdc, 0, 150,150,0);
hPen = CreatePen(PS_DASHDOT, 1, RGB(0, 255, 0));//green
SelectObject(hdc, hPen);
hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);//空心,画刷取空
SelectObject(hdc, hBrush);
Ellipse(hdc, 50, 0, 200, 150);
hPen = CreatePen(PS_DOT, 1, RGB(0, 255, 255));//blue
SelectObject(hdc, hPen);
//hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);//空心,画刷取空
//SelectObject(hdc, hBrush);
Ellipse(hdc, 50, 50, 200, 200);
hPen = CreatePen(PS_DASHDOTDOT, 1, RGB(0, 0, 255));// blue
SelectObject(hdc, hPen);
Ellipse(hdc, 0, 50, 150, 200);
//
//以上圆圈绘制完毕
//
//开始饼图绘制
//
//
//hBrush = CreateHatchBrush(HS_VERTICAL, RGB(255, 255, 255));
hPen2 = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));//red
SelectObject(hdc, hPen2);
hBrush = CreateSolidBrush(RGB(0, 255, 255));//设置画刷,纯色填充 蓝
SelectObject(hdc, hBrush);
Pie(hdc, 50, 300, 250, 500, 100, 300, 80, 500);
hBrush = CreateSolidBrush(RGB(255, 0, 0)); //红
SelectObject(hdc, hBrush);
Pie(hdc, 50, 300, 250, 500, 80, 500, 250, 400);
hBrush = CreateSolidBrush(RGB(255, 255, 0));//
SelectObject(hdc, hBrush);
Pie(hdc, 50, 300, 250, 500, 250, 400, 100, 300);
//以上饼图的绘制结束
//
//
//
//开始绘制正方形
//下排正方形的绘制
//
//
//
hPen2 = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));//red
SelectObject(hdc, hPen2);
//第一排圆角正方形
//
//
hBrush = CreateSolidBrush(RGB(0, 0, 0));//1
SelectObject(hdc, hBrush);
RoundRect(hdc, 600, 0, 700, 100, 30, 30);
hBrush = CreateSolidBrush(RGB(50, 50, 50));//2
SelectObject(hdc, hBrush);
RoundRect(hdc, 700, 0, 800, 100, 30, 30);
hBrush = CreateSolidBrush(RGB(130, 130, 130));//3
SelectObject(hdc, hBrush);
RoundRect(hdc, 800, 0, 900, 100, 30, 30);
hBrush = CreateSolidBrush(RGB(255, 255, 255));//4
SelectObject(hdc, hBrush);
RoundRect(hdc, 600, 100, 700, 200, 30, 30);
hBrush = CreateSolidBrush(RGB(180, 180, 180));//5
SelectObject(hdc, hBrush);
RoundRect(hdc, 700, 100, 800, 200, 30, 30);
hBrush = CreateSolidBrush(RGB(255, 255, 255));//6
SelectObject(hdc, hBrush);
RoundRect(hdc, 800, 100, 900, 200, 30, 30);
Pie();
Rectangle();
Ellipse();
Chord();
RoundRect();
Polygon();
PolyPolygon();
//HS_VERTICAL, /* ||||| 垂直 */
// HS_HORIZONTAL, /* ----- 水平 */
// HS_BDIAGONAL /* 左斜线 */
// HS_FDIAGONAL /* \\\\ 右斜线 */
// HS_CROSS, /* +++++ 正十字 */
// HS_DIAGCROSS /* xxxxx 斜十字 */
//hBrush = CreateHatchBrush(HS_VERTICAL, RGB(220, 220, 220));//黄
//SelectObject(hdc, hBrush);
//
//第二排正方形
//
hBrush = CreateHatchBrush(HS_BDIAGONAL, RGB(200, 200, 200));//1
SelectObject(hdc, hBrush);
Rectangle(hdc, 600, 200, 700, 300);
hBrush = CreateHatchBrush(HS_DIAGCROSS, RGB(200, 200, 200));//2
SelectObject(hdc, hBrush);
Rectangle(hdc, 700, 200, 800, 300);
hBrush = CreateHatchBrush(HS_FDIAGONAL, RGB(200, 200, 200));//3
SelectObject(hdc, hBrush);
Rectangle(hdc, 800, 200, 900, 300);
//
hBrush = CreateHatchBrush(HS_CROSS, RGB(200, 200, 200));//4
SelectObject(hdc, hBrush);
Rectangle(hdc, 600, 300, 700, 400);
hBrush = CreateHatchBrush(HS_HORIZONTAL, RGB(200, 200, 200));//5
SelectObject(hdc, hBrush);
Rectangle(hdc, 700, 300, 800, 400);
hBrush = CreateHatchBrush(HS_VERTICAL, RGB(200, 200, 200));//6
SelectObject(hdc, hBrush);
Rectangle(hdc, 800, 300, 900, 400);
//最后delete 画刷
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “关于”框的消息处理程序。
/*
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}*/
该程序我保留了部分默认初始化好的代码,运行结果如下图所示;