30、Windows API GDI(2)

简介: 一、GDI的几个示例与概念 1、笔和话刷的基本操作 示例 画笔示例 **************************************//* 头文件 */#include /* 函数声明 */void GdiOut(HDC hdc);// WinMainint WI...

一、GDI的几个示例与概念

1、笔和话刷的基本操作

示例

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 画笔示例
 
   
**************************************/
/* 头文件 */
#include
< Windows.h >
/* 函数声明 */
void GdiOut(HDC hdc);

// WinMain
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
HDC hdc
= GetDC(NULL);
GdiOut(hdc);
ReleaseDC(NULL, hdc);
}
/* ************************************
* VOID GdiOut(HDC hdc)
* 功能 演示GDI基本功能的使用
* 参数 HDC hdc,用于显示所绘制的图像
* 无返回值
*************************************
*/
VOID GdiOut(HDC hdc)
{
HPEN hpen, hpenOld;
HBRUSH hbrush, hbrushOld;
// 初始的颜色
BYTE bRed = 0 ;
BYTE bGreen
= 0 ;
BYTE bBlue
= 0 ;
// 笔的颜色 正黑
COLORREF cPen = RGB(bRed, bGreen, bBlue);
// 从COLORREF类型拆解颜色,设置笔刷的颜色,这里为紫偏蓝
COLORREF cBrush = RGB( 233 , GetGValue(cPen), 255 );
// 创建笔
hpen = CreatePen(PS_SOLID, 10 , cPen);
// 创建笔刷
hbrush = CreateSolidBrush(cBrush);
// 为DC选择笔和笔刷
hpenOld = (HPEN)SelectObject(hdc, hpen);
hbrushOld
= (HBRUSH)SelectObject(hdc, hbrush);
// 绘制线条
LineTo(hdc, 500 , 500 );
// 使用初始的笔
SelectObject(hdc,hpenOld);
// 绘制矩形
Rectangle( hdc, 200 , 200 , 500 , 500 );
// 释放资源
DeleteObject(hpen);
SelectObject(hdc, hbrushOld);
DeleteObject(hbrush);
}
2 DC 的操作

GetDC

CreateDC 除了GetDC函数外CreateDC也可以获取DC的句柄。

ReleaseDC ReleaseDC的作用是释放DC,使其他应用程序可以使用。

DeleteDC DeleteDC的功能是释放DC的相关系统资源。

3、颜色的表示

COLORREF类型和RGB

GDI中使用红、绿、蓝三原色的组合来表示颜色。使用38位的数据组合来表示颜色,称作RGB字节,可以表示0x1000000种颜色。RGBQUAD数据结构用于表示RGB颜色,也可以使用COLORREF数据类型来表示,COLORREFDWORD大小相同,RGB宏可以将颜色表示为COLORREFGetRValueGetGValueGetBValue3个宏可以将COLORREF拆解为三原色的字节。

DC中可用的颜色信息

使用NUMCOLORS参数,调用GetDeviceCaps API函数即可获得指定DC的颜色数量。再使用EnumObjects函数就可以列举指定DC的所有颜色的表示。

4、字体操作

示例

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 字体示例
 
   
**************************************/
/* 头文件 */
#include
< Windows.h >
/* ************************************
* HFONT ChooseNewFont()
* 功能 选择字体
*
* 返回值 返回字体句柄
*************************************
*/
HFONT ChooseNewFont()
{
CHOOSEFONT cf;
LOGFONT lf;
HFONT hfont;

// CHOOSEFONT 结构
cf.lStructSize = sizeof (CHOOSEFONT);
cf.hwndOwner
= (HWND)NULL;
cf.hDC
= (HDC)NULL;
cf.lpLogFont
= & lf;
cf.iPointSize
= 0 ;
cf.Flags
= CF_SCREENFONTS;
cf.rgbColors
= RGB( 0 , 0 , 0 );
cf.lCustData
= 0L ;
cf.lpfnHook
= (LPCFHOOKPROC)NULL;
cf.lpTemplateName
= (LPSTR)NULL;
cf.hInstance
= (HINSTANCE) NULL;
cf.lpszStyle
= (LPSTR)NULL;
cf.nFontType
= SCREEN_FONTTYPE;
cf.nSizeMin
= 0 ;
cf.nSizeMax
= 0 ;

// 选择字体对话框
ChooseFont( & cf);
// 得到HFONT 返回
hfont = CreateFontIndirect(cf.lpLogFont);
return (hfont);
}
/* ************************************
* WinMain
* 功能 选择字体,并将文字显示在界面上
*
*************************************
*/
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
HDC hdc
= GetDC(NULL);

int XIncrement = 10 ;
int YStart = 50 ;
TEXTMETRIC tm;
HFONT hfntDefault, hfntChoose;
SIZE sz;
UINT uAlignPrev;
LPSTR lpszString1
= " 字符串一 " ;
LPSTR lpszString2
= " 字符串二 " ;
LPSTR lpszString3
= " 字符串三 " ;
DWORD dwStrLen1
= lstrlen(lpszString1);
DWORD dwStrLen2
= lstrlen(lpszString2);
DWORD dwStrLen3
= lstrlen(lpszString3);

// 选择字体
hfntChoose = ChooseNewFont();
// 设置颜色
SetBkColor(hdc,RGB( 255 , 255 , 255 ));
SetTextColor(hdc,RGB(
255 , 0 , 0 ));
SetBkMode(hdc,TRANSPARENT);

// 输出字符串一
TextOut(hdc, XIncrement, YStart, lpszString1, dwStrLen1);

// 为字符串二设置输出位置
GetTextExtentPoint32(hdc, lpszString1, dwStrLen1, & sz);
XIncrement
+= sz.cx;
GetTextMetrics(hdc,
& tm);
XIncrement
-= tm.tmOverhang;
// 改变字体
hfntDefault = (HFONT)SelectObject(hdc, hfntChoose);
// 输出字符串二
TextOut(hdc, XIncrement, YStart, lpszString2, dwStrLen2);
// 设置字符串三的输出位置
GetTextExtentPoint32(hdc, lpszString1, dwStrLen1, & sz);
XIncrement
= 10 ;
YStart
+= sz.cy;
GetTextMetrics(hdc,
& tm);
XIncrement
-= tm.tmOverhang;
// 设置为默认字体
SelectObject(hdc, hfntDefault);
// 输出字符串三
uAlignPrev = SetTextAlign(hdc, TA_UPDATECP);
MoveToEx(hdc, XIncrement, YStart, (LPPOINT)NULL);
TextOut(hdc,
0 , 0 , lpszString3, dwStrLen3);
SetTextAlign(hdc, uAlignPrev);
// Clear
DeleteObject(hfntChoose);
SetBkMode(hdc, OPAQUE);
DeleteDC( hdc );
return 0 ;
}

遍历字体

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 遍历字体
 
   
**************************************/
/* 头文件 */
#include
< Windows.h >
#include
< stdio.h >
/* 函数声明 */
BOOL CALLBACK EnumFamCallBack(LPLOGFONT , LPNEWTEXTMETRIC , DWORD , LPVOID ) ;
DWORD ListFont(HWND hwnd);
// main
int main()
{
// 桌面DC
ListFont(NULL);
}
/* ************************************
* DWORD ListFont(HWND hwnd)
* 功能 列举指定窗口的DC的所具有的字体
*************************************
*/
DWORD ListFont(HWND hwnd)
{
// 获得DC
HDC hdc = GetDC(hwnd);
// 用于计数
int aFontCount[] = { 0 , 0 , 0 };
// 调用EnumFontFamilies,开始列举,

EnumFontFamilies(hdc, (
LPCTSTR) NULL,
// 列举所有类型
(FONTENUMPROC) EnumFamCallBack, // 回调函数为EnumFamCallBack
(LPARAM) aFontCount); // 传递给EnumFamCallBack的参数

// 显示统计信息
printf( " Number of raster fonts: %d\n " ,aFontCount[ 0 ]);
printf(
" Number of vector fonts: %d\n " ,aFontCount[ 1 ]);
printf(
" Number of TrueType fonts: %d\n " ,aFontCount[ 2 ]);
// 返回
return 0 ;
}

/* ************************************
* EnumFamCallBack
* 功能 字体列举回调函数次
* 每列举一个字体会被调用一次
* 参数 lplf,字体的LOGFONT结构
* lpntm,字符的尺度属性
* FontType,字体类型
* lParam,通过EnumFontFamilies输入给本函数的参数,这里用于计数
*************************************
*/
BOOL CALLBACK EnumFamCallBack(
LPLOGFONT lplf,
LPNEWTEXTMETRIC lpntm,
DWORD FontType,
LPVOID aFontCount)
{
// 获得参数
PINT aiFontCount = (PINT) aFontCount;
// 判断字体类型,输出类型信息,并根据类型进行计数
if (FontType & RASTER_FONTTYPE)
{
printf(
" RASTER TYPE \t " );
aiFontCount[
0 ] ++ ;
}
else if (FontType & TRUETYPE_FONTTYPE)
{
printf(
" TRUETYPE \t " );
aiFontCount[
2 ] ++ ;
}
else
{
printf(
" VECTOR TYPE \t " );
aiFontCount[
1 ] ++ ;
}
// 显示字体信息
printf( " %s\tItalic = %d\n " ,lplf -> lfFaceName,lplf -> lfItalic);
// 返回
if (aiFontCount[ 0 ] || aiFontCount[ 1 ] || aiFontCount[ 2 ])
return TRUE;
else
return FALSE;
}

EnumFontFamilies函数是实现列举DC中已经安装的字体的API函数;EnumFontFamilies函数指定了一个回调函数,每列举一个字体,回调函数就会被调用一次,字体的LOGFONT结构、字体的类型会作为参数输出给回调函数。

5、绘制线条

在绘制线条前需将线条所使用的画笔对象选择入DC。画笔对象决定了所绘制线条的颜色、宽度、样式。

示例鼠标跟踪

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif绘制线条
 
   
**************************************/
/* 头文件 */
#include
< windows.h >
/* 预定义 */
#define MAXGUIDESEGMENTS 1000
#define MyAlloc(dwSize) HeapAlloc(GetProcessHeap(),0,dwSize)
#define MyFree(lpMem) HeapFree(GetProcessHeap(),0,lpMem);
/* 函数声明 */
BOOL GetGuideLine(HWND, LPPOINT
* , LPDWORD);
BOOL ShowGuide(HDC, LPPOINT, DWORD);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
DWORD GetLastErrorBox(HWND hWnd, LPSTR lpTitle);
/* 全局变量 */
HINSTANCE hInst;
LPSTR szAppName
= " Curves " ;
LPSTR szTitle
= " Curves Application " ;

/* ************************************
* WinMain
* 功能 创建窗口
*************************************
*/
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASS wc;

hInst
= hInstance;
// 注册窗口类
wc.style = CS_OWNDC;
wc.lpfnWndProc
= (WNDPROC)WndProc;
wc.cbClsExtra
= 0 ;
wc.cbWndExtra
= 0 ;
wc.hInstance
= hInstance;
wc.hIcon
= NULL;
wc.hCursor
= LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground
= (HBRUSH)(COLOR_WINDOW + 1 );
wc.lpszMenuName
= NULL;
wc.lpszClassName
= szAppName;

if ( ! RegisterClass( & wc))
{
GetLastErrorBox(NULL,
" Error in RegisterClass " );
return (FALSE);
}
// 创建窗口
hWnd = CreateWindow(
szAppName,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
0 , CW_USEDEFAULT, 0 ,
NULL,
NULL,
hInstance,
NULL
);

if ( ! hWnd)
{
GetLastErrorBox(hWnd,
" Error in CreateWindow " );
return (FALSE);
}
// 显示更新
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// 消息循环
while (GetMessage( & msg, NULL, 0 , 0 ))
{
TranslateMessage(
& msg);
DispatchMessage(
& msg);
}

return ( int )(msg.wParam);

UNREFERENCED_PARAMETER(lpCmdLine);
}

/* ************************************
* WndProc
* 功能 窗口消息处理函数
*************************************
*/
LRESULT CALLBACK WndProc(
HWND hWnd,
UINT message,
WPARAM uParam,
LPARAM lParam)
{
static BOOL bOn = TRUE;
static LPPOINT lpBlue = NULL;
static LPPOINT lpRed = NULL;
static DWORD dwBlue = 0 ;
static DWORD dwRed = 0 ;
static BOOL bOutlineOnly = FALSE;
static BOOL bShowGuides = TRUE;
static HPEN hpenBlue, hpenRed;

switch (message)
{
case WM_CREATE:
{
// 获取DC
HDC hDC = GetDC(hWnd);
// 创建笔对象
hpenBlue = CreatePen(PS_SOLID, 1 , RGB( 0 , 0 , 255 ));
hpenRed
= CreatePen(PS_SOLID, 1 , RGB( 255 , 0 , 0 ));
}
GetLastErrorBox(hWnd,
" Error in WM_CREATE " );
break ;

case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC
= BeginPaint(hWnd, & ps);
RECT rect;
// 将客户区绘制为白色
GetClientRect(hWnd, & rect);
PatBlt(hDC,
0 , 0 , rect.right, rect.bottom, WHITENESS);
// 即存在红线,又存在蓝线
if (dwBlue && dwRed)
{
// 显示蓝线
if (dwBlue && bShowGuides)
{
SelectObject(hDC, hpenBlue);
ShowGuide(hDC, lpBlue, dwBlue);
SelectObject(hDC, GetStockObject(BLACK_PEN));
}
// 显示红线
if (dwRed && bShowGuides)
{
SelectObject(hDC, hpenRed);
ShowGuide(hDC, lpRed, dwRed);
SelectObject(hDC, GetStockObject(BLACK_PEN));
}
}
EndPaint(hWnd,
& ps);
}
break ;

case WM_LBUTTONDOWN:
{
HDC hDC
= GetDC(hWnd);
RECT rect;

if (bOn) // 消除并画蓝线
{
// 将客户区填充为白色
GetClientRect(hWnd, & rect);
PatBlt(hDC,
0 , 0 , rect.right, rect.bottom, WHITENESS);

// 释放资源
if (lpBlue)
MyFree(lpBlue);
if (lpRed)
MyFree(lpRed);
dwRed
= 0 ;
dwBlue
= 0 ;

// 开始跟踪鼠标移动,绘制蓝线
SelectObject(hDC, hpenBlue);
GetGuideLine(hWnd,
& lpBlue, & dwBlue);
}
else // 画红线
{
// 开始跟踪鼠标移动,绘制红线
SelectObject(hDC, hpenRed);
GetGuideLine(hWnd,
& lpRed, & dwRed);
}
// 鼠标左键放开,恢复笔对象
SelectObject(hDC, GetStockObject(BLACK_PEN));
// 取反,在红色和蓝色间交替
bOn = ! bOn;
}
GetLastErrorBox(hWnd,
" Error in WM_LBUTTONDOWN " );
break ;

case WM_DESTROY:
// 释放资源,退出
if (lpBlue) MyFree(lpBlue);
if (lpRed) MyFree(lpRed);
PostQuitMessage(
0 );
break ;

default :
return (DefWindowProc(hWnd, message, uParam, lParam));
}
return ( 0 );
}
/* ************************************
* BOOL GetGuideLine(HWND hWnd, LPPOINT *lpPoint, LPDWORD lpdwNumPts)
* 功能 跟踪鼠标,绘制鼠标轨迹
* 参数 hWnd,窗口
* lpPoint,用于保存点的数组,向调用函数返回
* lpdwNumPts,返回的数组的大小
*************************************
*/
BOOL GetGuideLine(HWND hWnd, LPPOINT
* lpPoint, LPDWORD lpdwNumPts)
{
MSG msg;
HDC hDC
= GetDC(hWnd);
BOOL bFirstTime
= TRUE;
DWORD dwPos
= 0 ;
RECT rect;

SetCapture(hWnd);
// 设置鼠标捕获器
GetClientRect(hWnd, & rect);
// 为点数组分配空间
* lpPoint = (LPPOINT)MyAlloc(MAXGUIDESEGMENTS * sizeof (POINT));

for (;;)
{
// 过滤所有鼠标消息
WaitMessage();
if (PeekMessage( & msg,NULL,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE))
{
// 判断是否在客户区中
if ((LOWORD(msg.lParam) < rect.right) && (HIWORD(msg.lParam) <

rect.bottom))
{
// 是否第一次收到消息
if (bFirstTime)
{
bFirstTime
= FALSE;
// 如果是第一次将笔的起点移动到鼠标点击的位置
MoveToEx(hDC, LOWORD(msg.lParam), HIWORD(msg.lParam),

NULL);
}
// 是否达到了最大点数
if (dwPos < MAXGUIDESEGMENTS)
{
// 鼠标的移动会产生鼠标消息,每收到一次消息保存一个点


(
* lpPoint)[dwPos].x = LOWORD(msg.lParam);
(
* lpPoint)[dwPos].y = HIWORD(msg.lParam);
// 绘制到鼠标所在的点
LineTo(hDC, ( * lpPoint)[dwPos].x, ( * lpPoint)

[dwPos].y);
dwPos
++ ;
}
}
if (msg.message == WM_LBUTTONUP)
break ;
}
else
continue ;
}

* lpdwNumPts = dwPos;
ReleaseDC(hWnd, hDC);
ReleaseCapture();
DeleteDC( hDC );

return TRUE;
}

/* ************************************
* BOOL ShowGuide(HDC hDC, LPPOINT lpPoints, DWORD dwNumPts)
* 功能 根据保存的点的数组重绘曲线
* 参数 hWnd,窗口
* lpPoint,保存的点的数组,
* dwNumPts,数组的大小
*************************************
*/
BOOL ShowGuide(HDC hDC, LPPOINT lpPoints, DWORD dwNumPts)
{
Polyline(hDC, lpPoints, dwNumPts);
return TRUE;
}

// 显示错误信息
DWORD GetLastErrorBox(HWND hWnd, LPSTR lpTitle)
{
LPVOID lpv;
DWORD dwRv;

if (GetLastError() == 0 ) return 0 ;

dwRv
= FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(LPSTR)
& lpv,
0 ,
NULL);

MessageBox(hWnd, (LPCSTR)lpv, lpTitle, MB_OK);

if (dwRv)
LocalFree(lpv);

SetLastError(
0 );
return dwRv;
}

二、相关API

1、定义图形对象:

CreatePen

CreateSolidBrushCreateHatchBrushCreatePatternBrush系列

2、图形对象的选择

SeleteObject

DC中每一类图形对象有一个“当前”图形对象(一个DC中同一时刻只能有一个画笔对象,也只能有一个画刷对象)。

3、绘制图形和线条

LineTo

MoveToEx

4、选择、设置字体

CreateFont,CreateFontIndirect

ChooseFont

    填充LOGFONT结构

用于创建字体的LOGFONT结构成员较多,各成员的意义也不十分明确,在使用LOGFONT表示一个字体时,填充比较复杂。但是在程序设计时,一般可由程序来完成填充。有两种方法可供选用:一是使用ChooseFont API函数弹出选择字体选择对话由用户选择,ChooseFont函数会返回用户选择的字体所对应的LOGFONT结构。二是遍历系统中已经安装的字体,遍历程序会返回每一个字体所对应的LOGFONT结构,在得到LOGFONT结构后,直接调用CreateFontIndirect API函数就可以得到字体的句柄HFONT

5、设置颜色

SetTextColor

6、输出文字

DrawText

TextOut

    GetTextExtentPoint32函数的功能是计算使用当前文本输出指定字符串后,输出的字符串的长和高(像素)。在使用TextOut等函数进行文字显示时,可以用于定义下次显示的文字的位置。

GetTextMetrics函数用于获取文本的尺度信息。SetTextAlign函数可以指定DC的文本输出对齐方式。

7、设置背景色

SetBkMode

8、安装删除字体

AddFontResource

RemoveFontResource

9、绘制线条[3]

直线:

LineTo

MoveToEx

绘制任意曲线

PolyBezierPolylinePolylineToPolyPolyline

SetCapture

ArcTo用于绘制椭圆弧线

参考

[1] 精通Windows API 函数、接口、编程实例

[2] http://msdn.microsoft.com/en-us/library/dd183553%28VS.85%29.aspx

[3] http://msdn.microsoft.com/en-us/library/dd162811%28VS.85%29.aspx

目录
相关文章
|
监控 编译器 API
[笔记]Windows核心编程《二十二》注入DLL和拦截API(一)
[笔记]Windows核心编程《二十二》注入DLL和拦截API
262 0
|
2月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
106 9
|
3月前
|
网络协议 API Windows
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
|
7月前
|
API Python Windows
python3应用windows api对后台程序窗口及桌面截图并保存的方法
python3应用windows api对后台程序窗口及桌面截图并保存的方法
541 1
|
编解码 应用服务中间件 开发工具
Windows平台RTMP|RTSP播放器为什么要兼容GDI绘制
先说结论,Windows平台播放渲染这块,一般来说99%以上的机器都是支持D3D的,实现GDI模式绘制,除了为了好的兼容性外,在远程连接的场景下,D3D创建不成功,需要使用GDI模式。
122 0
|
存储 缓存 API
[总结]Windows Crypto API 自动更新根证书问题原因及解决方案
[总结]Windows Crypto API 自动更新根证书问题原因及解决方案
162 0
|
API Windows
[笔记]Windows核心编程《番外篇》常用的NT API及使用示例
[笔记]Windows核心编程《番外篇》常用的NT API及使用示例
209 0
|
安全 API Windows
[笔记]Windows核心编程《二十二》注入DLL和拦截API(三)
[笔记]Windows核心编程《二十二》注入DLL和拦截API(三)
351 0
|
消息中间件 编解码 安全
[笔记]Windows核心编程《二十二》注入DLL和拦截API(二)
[笔记]Windows核心编程《二十二》注入DLL和拦截API(二)
158 0
|
API C++ Windows
Windows API Hooking 学习
Windows API Hooking 学习
下一篇
DataWorks