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 ...
随机推荐
- 2015 Changchun Regional
弱没机会去长春,但拿了题来做了,加上请教各路大牛,理论AC了一发,但没实现~(感谢各路有形无形的大牛的指导) A题~Too Rich 给你1,5,10,20,50,100,200,500,1000,2 ...
- 2015 编程之美初赛第一场 AC题
题目1 : 彩色的树 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定一棵n个节点的树,节点编号为1, 2, …, n.树中有n - 1条边,任意两个节点间恰好有一条路 ...
- 快速傅立叶变换&HDU 1402
参考http://www.cnblogs.com/v-July-v/archive/2011/08/13/2214132.html <算导> 那么,更快速的多项式乘法就依赖于能否把一个系数 ...
- SUSE Linux Enterprise Serve 12 试用体验
SUSE Linux Enterprise Serve 12 试用体验 大家都知道德国出产的奔驰.宝马.等车型以精美.可靠.耐用而著称.而相同出自德国人之手的Suse Linux .即使是被收购也是一 ...
- SharePoint 2013 关闭 customErrors
在SharePoint 2013上做开发时,如果不把customErrors 关掉,那调试起来那真叫一个费劲.在2013里,关闭customErrors 和2010一样,只要把文件路径改成15目录下即 ...
- HDU 5538/ 2015长春区域 L.House Building 水题
题意:求给出图的表面积,不包括底面 #include<bits/stdc++.h> using namespace std ; typedef long long ll; #define ...
- 《TCP/IP具体解释》读书笔记(21章)-TCP的超时与重传
TCP提供可靠的运输层. 它使用的方法之中的一个就是确认从还有一端收到的数据.但数据和确认都有可能会丢失.TCP通过在发送时设置一个定时器来解决这样的问题.假设当定时器溢出时还没有收到确认,它就重传该 ...
- 用Arduino+OSC建立一个iPad铁路王国巡视机
翻译自:http://blog.mydream.com.hk/howto/build-up-a-ipad-plarail-patrol-with-arduino-osc 简单介绍 这个教程告诉你怎样建 ...
- hdu 2222(AC自动机模版题)
Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- poj 2288 Islands and Bridges ——状压DP
题目:http://poj.org/problem?id=2288 状压挺明显的: 一开始写了(记忆化)搜索,但一直T: #include<iostream> #include<cs ...