使用现有画笔

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)的更多相关文章

  1. {Reship}{C#}{GDI+}GDI+画笔,线,区域类型

    =================================================================================== This article is ...

  2. GDI编程

    图形设备接口(GDI)是一个可执行程序,它接受Windows应用程序的绘图请求(表现为GDI函数调用),并将它们传给相应的设备驱动程序,完成特定于硬件的输出,象打印机输出和屏幕输出.GDI负责Wind ...

  3. GDI编程小结

    图形设备接口(GDI)是一个可运行程序,它接受Windows应用程序的画图请求(表现为GDI函数调用),并将它们传给对应的设备驱动程序,完毕特定于硬件的输出,象打印机输出和屏幕输出.GDI负责Wind ...

  4. VC++学习之GDI概述

    VC++学习之GDI概述 图形设备接口(GDI)是一个可执行程序,它接受Windows应用程序的绘图请求(表现为GDI函数调用),并将它们传给相应的设备驱动程序,完成特定于硬件的输出,象打印机输出和屏 ...

  5. MFC绘图相关GDI工具对象和函数介绍

    在利用MFC进行界面编程时,除了需要熟悉各种类型控件的操作外,还会经常遇到图形绘制和显示的问题,比如时频分析界面.图像处理界面等.处理这些软件界面开发问题时,不可避免地需要用到一系列GDI工具对象和相 ...

  6. c# -- 对象销毁和垃圾回收

    有些对象需要显示地销毁代码来释放资源,比如打开的文件资源,锁,操作系统句柄和非托管对象.在.NET中,这就是所谓的对象销毁,它通过IDisposal接口来实现.不再使用的对象所占用的内存管理,必须在某 ...

  7. DWM 窗体玻璃效果实现

    我一直盼望着 Windows 新版本的发布.令人感兴趣的事情莫过于浏览 MSDN® 和 SDK 文档,查找一些可以利用和依赖的最新创新,然后让朋友和同事以及您的老板(如果幸运的话)大开眼界.Windo ...

  8. MFC编程基础

    http://www.cnblogs.com/lzmfywz/archive/2012/03/15/2399403.html 一.MFC类库概述 MFC(Microsoft Foundation cl ...

  9. 【转】DWM 窗体玻璃效果实现

    我一直盼望着 Windows 新版本的发布.令人感兴趣的事情莫过于浏览 MSDN® 和 SDK 文档,查找一些可以利用和依赖的最新创新,然后让朋友和同事以及您的老板(如果幸运的话)大开眼界.Windo ...

随机推荐

  1. Java开发中的几种对象的说明(PO,VO,DTO,BO,POJO,DAO,SAO等)

    一.PO :(persistant object ),持久对象 可以看成是与数据库中的表相映射的java对象.使用Hibernate来生成PO是不错的选择. 二.VO :(value object) ...

  2. 小议:部署SharePoint 2013时,无法连接SQL Server问题

    最近在给学员培训时发现,个别学员在完毕SharePoint 2013部署时,无法连接SQL Server,两种报错情况,例如以下所看到的: :配置SharePointConnect to SQL Se ...

  3. poj 1837 Balance (0 1 背包)

    Balance Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 10326   Accepted: 6393 题意:给你n个挂 ...

  4. Apache Traffic Server 5.3.1公布

    本文来源于我在InfoQ中文站翻译的文章,原文地址是:www.infoq.com/cn/news/2015/07/traffic-server-5.3.1-release 近日,Apache软件基金会 ...

  5. Office 365 的公共网站的一些限制及解决的办法

    当前的SharePoint Online版本是基于SharePoint 2013的,但是很多功能确被阉割掉了. 下面主要列出Office 365公共网站被限制的功能,以及可绕过的解决方案: 内容类型 ...

  6. Yum重装走过的坑

    今天因为用yum方式安装mongo遇到报错,从而我选择卸载yum并重新安装. 我先选择了用rpm方式进行重装,从163的packages列表里面找到64位redhat6.5可以用的三个rpm包,安装过 ...

  7. web端log4net输出错误日志到mysql

    1.引用log4net 2.配置log4net.config文件 <?xml version="1.0" encoding="utf-8" ?> & ...

  8. luogu2746 校园网

    题目大意: 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作“接受学校”).注意即使 B 在 A 学校的分发列表中, A 也不一定在 B 学校的列表中. 你要 ...

  9. Uboot中支持lcd和hdmi显示不同的logo图片【转】

    本文转载自:http://blog.csdn.net/u010865783/article/details/54953315 在lcd为竖屏,hdmi显示横屏的情况下,如果按照默认的uboot显示框架 ...

  10. EJB是什么鸟东西?

    到底EJB是什么 到底EJB是什么?被口口相传的神神秘秘的,百度一番,总觉得没有讲清楚的,仍觉得一头雾水.百度了很久,也从网络的文章的只言片语中,渐渐有了头绪. 用通俗话说,EJB就是:"把 ...