GDI 画笔(9)
使用现有画笔
Windows 提供三种备用画笔(Stock Pen):BLACK_PEN(黑色画笔)、WHITE_PEN(白色画笔)、NULL_PEN(不绘制任何图形的画笔)。
调用 GetStockObject 函数可以获取备用画笔的句柄(HPEN),调用 SelectObject 函数可以将指定的画笔选入设备环境,并返回之前选入设备环境的画笔句柄:
// 定义画笔句柄
HPEN hPen, hPrevPen; // 获取备用画笔的句柄
hPen = GetStockObject(WHITE_PEN); // 将画笔选入设备环境,函数返回之前选入设备环境的画笔的句柄
hPrevPen = SelectObject(hdc, hPen);
GDI 对象使用规则
- 最终应当删除所有由用户创建的 GDI 对象
- 当 GDI 对象被选入一个有效的设备环境时,不可删除它
- 不可删除备用对象(Stock Object)
创建画笔
调用 CreatePen 函数可以创建一个画笔,画笔句柄将作为返回值返回:
HPEN CreatePen(
int fnPenStyle, // 画笔样式(决定绘制的是实线、虚线或点线)
int nWidth, // 画笔宽度(为 0 时,将设为 1 个像素。虚线或点线只能为 1 个像素,否则将被设为实线)
COLORREF crColor // 画笔颜色(COLORREF 值,可以通过 RGB 宏指定)
);
调用 CreatePenIndirect 函数可以根据 LOGPEN(逻辑画笔)结构来建立一个画笔,画笔句柄将作为返回值返回:
LOGPEN 结构:
typedef struct tagLOGPEN {
UINT lopnStyle; // 画笔样式
POINT lopnWidth; // 画笔宽度(Windows 仅使用 x 字段)
COLORREF lopnColor; // 画笔颜色
} LOGPEN, *PLOGPEN;
CreatePenIndirect 函数:
HPEN CreatePenIndirect(
CONST LOGPEN *lplgpn // LOGPEN 结构的地址
);
选择画笔
调用 SelectObject 函数,可以将刚刚创建的画笔选入设备环境,并返回之前选入设备环境的画笔句柄:
HGDIOBJ SelectObject(
HDC hdc, // 设备环境句柄
HGDIOBJ hgdiobj // GDI 对象句柄(这里指画笔句柄)
);
删除画笔
调用 DeleteObject 函数,可以将使用完的画笔删除:
BOOL DeleteObject(
HGDIOBJ hObject // GDI 对象句柄(这里指画笔句柄)
);
注:不要删除已被选入设备环境的当前画笔
获取创建的画笔
调用 GetObject 函数可以从指定画笔句柄中,得到关于此画笔的 LOGPEN 结构的各个字段的值:
GetObject(hPen, sizeof(LOGPEN), (LPVOID)&logpen);
调用 GetCurrentObject 函数可以获取当前被选入设备环境的画笔句柄:
hPen = GetCurentObject(hdc, OBJ_PEN);
填充空隙
空隙的颜色由设备环境的背景模式和背景颜色所决定,默认的背景模式是 OPAQUE(不透明),即用背景颜色(默认为白色)填充。
调用 SetBkColor 函数可以改变 Windows 填充空隙的背景颜色:
COLORREF SetBkColor(
HDC hdc, // 设备环境句柄
COLORREF crColor // 背景颜色值(COLORREF)
);
调用 GetBkColor 函数可以得到 Windows 填充空隙的背景颜色,函数将它作为返回值返回:
COLORREF GetBkColor(
HDC hdc // 设备环境句柄
);
调用 SetBkMode 函数可以设置背景模式,设置成 TRANSPARENT 可以阻止 Windows 填充空隙:
int SetBkMode(
HDC hdc, // 设备环境句柄
int iBkMode // 背景模式,可选 QPAQUE(不透明)和 TRANSPARENT(透明)两种模式
);
绘图模式
二元光栅操作(ROP2,raster operation 2):Windows 绘制直线时,将画笔的像素颜色和目标显示表面的像素颜色按位进行布尔运算
默认情况下,绘图模式是 R2_COPYPEN,像素的简单复制。
- R2_NOTCOPYPEN 像素复制为画笔颜色的反色
- R2_BLACK 总是绘制为黑色
- R2_WHITE 总是绘制为白色
- R2_NOP 不操作
- R2_NOT 将目标颜色取反,来获取绘制颜色
调用 SetROP2 函数可以设置一种新的绘图模式:
int SetROP2(
HDC hdc, // 设备环境句柄
int fnDrawMode // 绘图模式(以 R2 为前缀的标志)
);
调用 GetROP2 函数可以获取当前的绘图模式,作为返回值返回:
int GetROP2(
HDC hdc // 设备环境句柄
);
PENDEMO 示例程序
#include <windows.h>
#include <math.h> #define NUMS 1000
#define TWOPI 6.283185307179586476925286766559 LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc;
PAINTSTRUCT ps;
static LOGPEN logpen;
static HPEN hRedPen;
static HPEN hBluePen;
static int cxClient, cyClient;
POINT apt[NUMS];
int i; switch (message) { case WM_CREATE: logpen.lopnColor = RGB(255, 0, 0);
logpen.lopnStyle = PS_DASH;
logpen.lopnWidth.x = 1;
hRedPen = CreatePenIndirect(&logpen); logpen.lopnColor = RGB(0, 0, 255);
logpen.lopnStyle = PS_INSIDEFRAME;
logpen.lopnWidth.x = 3;
hBluePen = CreatePenIndirect(&logpen); return 0; case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam); return 0; case WM_PAINT:
hdc = BeginPaint(hwnd, &ps); SelectObject(hdc, hRedPen);
MoveToEx(hdc, 0, cyClient / 2, NULL);
LineTo(hdc, cxClient, cyClient / 2); SelectObject(hdc, hBluePen);
for (i = 0; i < NUMS; i++) {
apt[i].x = i * cxClient / NUMS;
apt[i].y = (int)(( 1 - sin(TWOPI * i / NUMS)) * cyClient / 2);
} SetTextAlign(hdc, TA_TOP | TA_RIGHT);
TextOut(hdc, cxClient - 12, 12, TEXT("y = sin x"), 12);
TextOut(hdc, cxClient / 2 - 12, cyClient / 2 + 12, TEXT("( π, 0 )"), 9);
TextOut(hdc, cxClient - 12, cyClient / 2 + 12, TEXT("( 2 π, 0 )"), 11); SetTextAlign(hdc, TA_TOP | TA_LEFT);
TextOut(hdc, 12, cyClient / 2 + 12, TEXT("( 0, 0 )"), 9); PolyBezier(hdc, apt, NUMS); EndPaint(hwnd, &ps);
return 0; case WM_DESTROY:
DeleteObject(hRedPen);
DeleteObject(hBluePen);
PostQuitMessage(0);
return 0;
} return DefWindowProc(hwnd, message, wParam, lParam);
} int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { LPCTSTR lpszClassName = TEXT("PenDemo");
LPCTSTR lpszWindowName = TEXT("Pen Demo Program"); WNDCLASS wndclass;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = WindowProc;
wndclass.lpszClassName = lpszClassName;
wndclass.lpszMenuName = NULL;
wndclass.style = CS_HREDRAW | CS_VREDRAW; if (!RegisterClass(&wndclass)) {
MessageBox(NULL, TEXT("This program requires Windows NT!"), lpszWindowName, MB_ICONERROR);
return 0;
} HWND hwnd = CreateWindow(
lpszClassName,
lpszWindowName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
); ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd); MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} return msg.wParam;
}
GDI 画笔(9)的更多相关文章
- {Reship}{C#}{GDI+}GDI+画笔,线,区域类型
=================================================================================== This article is ...
- GDI编程
图形设备接口(GDI)是一个可执行程序,它接受Windows应用程序的绘图请求(表现为GDI函数调用),并将它们传给相应的设备驱动程序,完成特定于硬件的输出,象打印机输出和屏幕输出.GDI负责Wind ...
- GDI编程小结
图形设备接口(GDI)是一个可运行程序,它接受Windows应用程序的画图请求(表现为GDI函数调用),并将它们传给对应的设备驱动程序,完毕特定于硬件的输出,象打印机输出和屏幕输出.GDI负责Wind ...
- VC++学习之GDI概述
VC++学习之GDI概述 图形设备接口(GDI)是一个可执行程序,它接受Windows应用程序的绘图请求(表现为GDI函数调用),并将它们传给相应的设备驱动程序,完成特定于硬件的输出,象打印机输出和屏 ...
- MFC绘图相关GDI工具对象和函数介绍
在利用MFC进行界面编程时,除了需要熟悉各种类型控件的操作外,还会经常遇到图形绘制和显示的问题,比如时频分析界面.图像处理界面等.处理这些软件界面开发问题时,不可避免地需要用到一系列GDI工具对象和相 ...
- c# -- 对象销毁和垃圾回收
有些对象需要显示地销毁代码来释放资源,比如打开的文件资源,锁,操作系统句柄和非托管对象.在.NET中,这就是所谓的对象销毁,它通过IDisposal接口来实现.不再使用的对象所占用的内存管理,必须在某 ...
- DWM 窗体玻璃效果实现
我一直盼望着 Windows 新版本的发布.令人感兴趣的事情莫过于浏览 MSDN® 和 SDK 文档,查找一些可以利用和依赖的最新创新,然后让朋友和同事以及您的老板(如果幸运的话)大开眼界.Windo ...
- MFC编程基础
http://www.cnblogs.com/lzmfywz/archive/2012/03/15/2399403.html 一.MFC类库概述 MFC(Microsoft Foundation cl ...
- 【转】DWM 窗体玻璃效果实现
我一直盼望着 Windows 新版本的发布.令人感兴趣的事情莫过于浏览 MSDN® 和 SDK 文档,查找一些可以利用和依赖的最新创新,然后让朋友和同事以及您的老板(如果幸运的话)大开眼界.Windo ...
随机推荐
- Workflow:实现一个简单的审批流程
1. 创建一个空白的项目,在其中创建Host – Windows Console Application,Client – Windows forms Application和DataExchange ...
- HDU 4598
这道题其实不需要考虑具体数值,但可以肯定的是,相连边的两端点必定有一正一负,至于谁正谁负,并不重要,这是可以思考的,很明显的一个二分图性质,如果不满足此条件,是不可能满足题目第二个条件的.所以首先对题 ...
- 零基础学python-4.2 其它内建类型
这一章节我们来聊聊其它内建类型 1.类型type 在python2.2的时候,type是通过字符串实现的,再后来才把类型和类统一 我们再次使用上一章节的图片来说明一些问题 我们通过对照上面的图片.在p ...
- ORACLE错误1033出现和ORA-00600错误解决的方法
非法关机以后.Oracle数据常常出现这个错误: EXP-00056:ORACLE错误1033出现 ORA-01033:ORACLE initialization or shutdown in pro ...
- Codeforces Round #277 (Div. 2)A. Calculating Function 水
A. Calculating Function For a positive integer n let's define a function f: f(n) = - 1 + 2 - 3 + ...
- write data to xml
public class Student { public int Id { get; set; } public string FirstName { get; set; } public stri ...
- 深度学习必备:随机梯度下降(SGD)优化算法及可视化
补充在前:实际上在我使用LSTM为流量基线建模时候,发现有效的激活函数是elu.relu.linear.prelu.leaky_relu.softplus,对应的梯度算法是adam.mom.rmspr ...
- [python 基础]python装饰器(一)添加functools获取原函数信息以及functools.partial分析
python装饰器学习的时候有两点需要注意一下 1,被装饰器装饰的函数取其func.__name__和func.func_doc的时候得到的不是被修饰函数的相关信息而是装饰器wrapper函数的doc ...
- 3-4 第三天 Generator生成器
Generator是ES6里面的新增规范,ES6其实就是ES2015.ES5.ES6.ES7这些术语大家上网一查就都明白了.JavaScript是一个范程,就是我们说的JS.ES就是ECMA Scri ...
- 前端面试准备之JavaScript
1.数据类型. JavaScript中有5种简单数据类型(也称为基本数据类型):Undefined.Null.Boolean.Number和String.还有1种复杂数据类型——Object,Obje ...