首页 > 系统相关 >使用Windows API进行GDI窗口绘图

使用Windows API进行GDI窗口绘图

时间:2024-05-28 10:55:34浏览次数:24  
标签:画刷 画笔 Windows int HDC API 绘图 GDI 设备

1.概述
在Windows上绘图方式,跟美术大师绘图差不多。美术绘画,首先要具备以下工具:画板,画布,画笔,画刷。同样,Windows上也有相关的概念。绘图设备DeviceContext(DC),位图Bitmap,画笔Pen,画刷brush。他们一一对应。

2.画板
在Windows中被称作设备上下文(Device Context,DC),我习惯称之为绘图设备。但是Windows的“画板”与美术大师手中的“画板”不一样,Windows中的“画板”实质上是一个工具的集合体,将画布、画笔、画刷、绘画方式全部综合管理起来,然后,所有的绘画操作都将在这上面进行。

1)系统绘图设备。系统有默认的绘图,我们可以直接使用它进行一系列的绘图操作。

获取系统绘图设备:

HDC GetDC(
 
HWND hWnd // 窗口句柄。即指定获得那个窗口的绘图设备。
 
);

如:

HDC hDC = GetDC(g_hWnd);
 
Rectangle(hDC,0,0,100,100);//绘制矩形
 
....

 

使用完毕后要归还给窗口:

int ReleaseDC(
 
HWND hWnd, // handle to window
 
HDC hDC // handle to DC
 
);

 

2)创建画板。通常我们不直接使用系统画板,因为系统画板直接和显示器关联,在上面一边画,就会一边显示到窗口,由于在绘制的时候,中间有时间差(我们可能经过若干次绘制,才绘制完一个地图),而游戏程序需要反复的擦除、重绘,所以常常会造成画面剧烈闪烁。为了解决这个问题,我们会创建一个辅助画板,在幕后绘制完毕后,一次性的将它显示到屏幕上,因为显示的时间非常快,所以就看不到闪烁。

创建辅助绘图设备:

HDC CreateCompatibleDC(
 
HDC hdc // 指向一个已经存在的DC,如果该值传入0,则系统会创建一个存贮DC。
 
);

 

存贮DC(辅助绘图设备),在创建完毕后,它的大小只有一个像素,我们没办法直接往他上面直接绘图,我们还需要往它上面贴一张画布。

使用完毕后记得要释放资源:

BOOL DeleteDC(
 
HDC hdc // handle to DC
 
);

例:

HDC memDC = CreateCompatibleDC(0); //创建辅助绘图设备
 
SelectObject(memDC,hBitmap); //将画布贴到绘图设备上
 
Rectangle(memDC,x1,y1,x2,y2); //绘制矩形
 
HDC hDC = GetDC(g_hWnd); //获得系统绘图设备
 
copy memDC to hDC //复制到系统设备上显示
 
ReleaseDC(g_hWnd,hDC); //归还系统绘图设备
 
DeleteDC(memDC); //释放辅助绘图设备

3.画布

画布其实就是位图。位图的作用非常强大,在此我只介绍它的普通用法——充当画布。其他作用,后面再介绍。

创建掩码位图(画布):

HBITMAP CreateCompatibleBitmap(
 
HDC hdc, //指向绘图设备,最好是系统的绘图设备
 
int nWidth, // 位图宽度
 
int nHeight // 位图高度
 
);

释放资源:

BOOL DeleteObject(
 
HGDIOBJ hObject // handle to graphic object
 
);

4.画笔

画笔就不用解释了,Windows的画笔和美术大师的差不多。

创建画笔:

HPEN CreatePen(
 
int fnPenStyle, // 画笔风格。直线:PS_SOLID,点线:PS_DOT
 
int nWidth, // 画笔宽度。决定了画出来的线条粗细
 
COLORREF crColor // 画笔颜色
 
);

释放资源:

BOOL DeleteObject(
 
HGDIOBJ hObject // handle to graphic object
 
);

 

颜色:可由红绿蓝三种颜色按程度混合起来构成。

如COLORREF cr = RGB(255,0,255),此时cr是粉红色(红色+蓝色)。COLORREF实际上是无符号长整型的别名,RGB将红绿蓝三个数值整合成一个无符号长整型数。

COLORREF RGB(
 
BYTE byRed, //红色分量0~255,值越大表面程度越深。
 
BYTE byGreen, // 绿色分量0~255
 
BYTE byBlue // 蓝色分量0~255
 
);

5.画刷

创建画刷:

HBRUSH CreateSolidBrush(
 
COLORREF crColor // brush color value
 
);

 

释放资源:

BOOL DeleteObject(
 
HGDIOBJ hObject // handle to graphic object
 
);

 

6.绘画
画布、画笔、画刷创建好之后,要是分别使用API,将它们选入绘图设备。当然,绘图设备,有自己的默认画刷和画笔。

HGDIOBJ SelectObject(
 
HDC hdc, // 直线绘图设备
 
HGDIOBJ hgdiobj // 指向GDI对象。就是画刷、画笔、位图等。
 
);

 

返回值是旧有的相关内容。

一些常用绘图API:
1)绘制矩形。

BOOL Rectangle(
 
HDC hdc, // 绘图设备
 
int nLeftRect, // 矩形区域左上角x坐标
 
int nTopRect, // 矩形区域左上角y坐标
 
int nRightRect, //矩形区域右下角x坐标
 
int nBottomRect // 矩形区域右下角y坐标
 
);

 

2)填充区域。用画刷来填充区域,经常用来擦除整个窗口。

int FillRect(
 
HDC hDC, // 绘图设备
 
CONST RECT *lprc, // 矩形区域
 
HBRUSH hbr // 填充画刷
 
);

 

区域结构:

typedef struct _RECT {
 
LONG left; //矩形左边(左上角x坐标)
 
LONG top; //矩形顶边(左上角y坐标)
 
LONG right; //矩形右边(右下角x坐标)
 
LONG bottom; //矩形底边(右下角y坐标)
 
} RECT, *PRECT;

 

获得窗口客户区区域:

BOOL GetClientRect(
 
HWND hWnd, // handle to window
 
LPRECT lpRect // client coordinates
 
);

 

3)绘图设备之间的拷贝。

BOOL BitBlt(
 
HDC hdcDest,//目标绘图设备
 
int nXDest, // 目标区域左上角x坐标
 
int nYDest, //目标区域左上角y坐标
 
int nWidth, // 目标区域宽度
 
int nHeight,// 目标区域高度
 
HDC hdcSrc, // 源绘图设备
 
int nXSrc, // 源区域左上角x坐标
 
int nYSrc, // 源区域左上角y坐标
 
DWORD dwRop // 操作码。常用SRCCOPY(复制)。
 
);

 

可以简单的理解这个API:将源绘图设备拷贝给目标绘图设备。从幕后画布拷贝给前景画布。从幕后绘图设备拷贝给显示器。拷贝的区域,就是上面指定的。

如:BitBlt(hDC,0,0,g_nWidth,g_nHeight,memDC,0,0,SRCCOPY);


4)其他常用API

文字处理
创建字体:CreateFont,CreatePointFont,SelectObject(.,font)。
显示文本:Textout,DrawText
设置文本颜色:SetTextColor ,GetTextColor
设置背景:SetBkColor,SetBkMode(设置背景模式,TRANSPARENT为透明)

绘制
点:SetPixel,SetPixelV,GetPixel。
线:MoveToEx-LinTo。
圆:Ellipse
多边形:Polygon
弧:Arc

位图处理
从文件加载位图/图标/光标:LoadImage
从资源加载位图:LoadBitmap
获得位图信息:GetObject
绘图设备间的拷贝复制
直接模式:BitBlt
拉伸拷贝:StretchBlt
透明处理:TranparentBlt,需要加 Msimg32.lib库。
半透明处理(Alpha混合):AlpaBlend

其他
获得系统属性:GetSystemMetrics,一些很重要的信息。
获得鼠标屏幕坐标:GetCursorPos,需使用坐标转换转换为窗口坐标
坐标转换:ClientToScreen,ScreenToClient
获得键盘键状态:GetAsyncKeyState
获得整个键盘信息:GetKeyboardState

消息框:MessageBox

 

一个完整的代码示例:

#include "app.h"
 
 
 
int g_nWidth = 600;//窗口宽度
 
int g_nHeight = 480;//窗口高度
 
 
 
void init()//游戏初始化
 
{
 
}
 
 
 
void update()//逻辑更新
 
{
 
}
 
 
 
void render()//画面渲染
 
{
 
HDC hDC = GetDC(getHWnd()); //获得系统绘图设备
 
 
 
HDC memDC = CreateCompatibleDC(0); //创建辅助绘图设备
 
 
 
HBITMAP bmpBack = CreateCompatibleBitmap(hDC,g_nWidth,g_nHeight);//创建掩码位图(画布)
 
SelectObject(memDC,bmpBack); //将画布贴到绘图设备上
 
 
 
HPEN penBack = CreatePen(PS_SOLID,1,RGB(255,0,255));//创建画笔
 
SelectObject(memDC,penBack); //将画笔选到绘图设备上
 
 
 
HBRUSH brushBack = CreateSolidBrush(RGB(255,255,255));//创建画刷
 
SelectObject(memDC,brushBack); //将画刷选到绘图设备上
 
 
 
//擦除背景
 
RECT rcClient;//区域结构
 
GetClientRect(getHWnd(),&rcClient);//获得客户区域
 
HBRUSH brushTemp = (HBRUSH)GetStockObject(WHITE_BRUSH);//获得库存物体,白色画刷。
 
FillRect(memDC,&rcClient,brushTemp);//填充客户区域。
 
//
 
HBRUSH brushObj = CreateSolidBrush(RGB(0,255,0));//创建物体画刷
 
//绘制维网格,矩形画法。
 
int dw = 30;
 
int rows = g_nHeight/dw;
 
int cols = g_nWidth/dw;
 
for (int r=0; r<rows; ++ r)
 
{
 
for (int c=0; c<cols; ++c)
 
{
 
if (r == c)
 
{
 
SelectObject(memDC,brushObj);
 
}
 
else
 
{
 
SelectObject(memDC,brushBack);
 
}
 
Rectangle(memDC,c*dw,r*dw,(c+1)*dw,(r+1)*dw);
 
}
 
}
 
 
 
DeleteObject(brushObj);
 
//
 
BitBlt(hDC,0,0,g_nWidth,g_nHeight,memDC,0,0,SRCCOPY);//复制到系统设备上显示
 
DeleteObject(penBack); //释放画笔资源
 
DeleteObject(brushBack);//释放画刷资源
 
DeleteObject(bmpBack); //释放位图资源
 
DeleteDC(memDC); //释放辅助绘图设备
 
ReleaseDC(getHWnd(),hDC); //归还系统绘图设备
 
Sleep(1);
 
}
 
 
 
void clear()//资源释放
 
{
 
}
 
 
 
 
 
//主函数
 
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE , LPSTR , int )
 
{
 
if(!initApp(hInstance,L"贪吃蛇游戏",g_nWidth,g_nHeight))
 
{
 
return 0;
 
}
 
 
 
//初始化游戏
 
init();
 
 
 
//游戏循环
 
mainLoop();
 
 
 
//释放资源
 
clear();
 
 
 
return 0;
 
}

原文地址:https://blog.csdn.net/celte/article/details/10243309 

原文地址:http://blog.csdn.net/you_lan_hai/article/details/6911497

标签:画刷,画笔,Windows,int,HDC,API,绘图,GDI,设备
From: https://www.cnblogs.com/1175429393wljblog/p/18217429

相关文章

  • 测试[C#]GDI+中使用BitBlt绘制图像到窗口
    安神颗粒的哈喽###2024-5-28WindowsFormPaintFormTES_ESEB测试[C#]GDI+中使用BitBlt绘制图像到窗口```#region测试[C#]GDI+中使用BitBlt绘制图像到窗口privatevoidpbx01_Paint(objectsender,PaintEventArgse){#regionMyRegion......
  • 淘宝订单信息获取接口API,淘宝打单发货接口
    从事电商软件开发的小伙伴,在日常开发任务中,经常会遇到一个需求,就是将淘宝店铺的订单,同步到自己的内部订单管理系统OMS中,进行淘宝打单发货操作。我介绍下如何将订单同步下来,供各位参考。(注意:所有电商平台目前能同步订单的接口要么就不让申请,要么就申请门槛和维护资质的成本很高,具体......
  • ChatGPT-Next-Web一键部署搭建教学:Github开源+Vercel+API 快速部署
    ChatGPT-Next-Web一键部署搭建教学:Github开源+Vercel+API快速部署文章目录ChatGPT-Next-Web一键部署搭建教学:Github开源+Vercel+API快速部署导语:需要用到的链接汇总1、github项目直达地址2、vercel服务器直达地址3、三方API获取一、Github项目`star`+Vercel......
  • 命令启用Windows7 .NetFramework 3.5
    最近在测试某系统安装包在各个环境下的安装使用情况,在window7下使用时,安装完成iis后,发现.NetFramework3.5没有自动勾选;命令没有执行成功。通过以下命令可以在window7下打开自带的.netframework3.5.1(CMD窗口内执行)dism/online/enable-feature/featurename:NetFx3 ......
  • 如何在c#中禁用Windows键?
    如何禁用或锁定Windows按钮?     使用windowshooks比修改注册表要干净得多。此外,有时人们会设置自己的个性化扫描码图,覆盖它们并不是一件好事。要使用windows键钩函数,您需要DllImport几个winapi函数:[DllImport("kernel32.dll",CharSet=CharSet.Auto,......
  • 我见我思之hvv偷师学艺——远程文件包含 windows.ini
    注:本文仅作为技术交流使用,如有违反行为本文作者概不负责。常见告警信息价值提取:源IP大概率为代理IP,可通过情报平台进行识别此IP的历史攻击行为。源端口参考意义不大。目的IP我方资产IP(可定位疑似漏洞的具体资产范围)。目的端口我方资产IP对应端口(可辅助确认端口所在资产范......
  • WindowsCA证书服务(三)证书的基础知识
    CA证书申请流程嫖个图吧。TLS/ssl发展 1、SSL3SSL3于1995年末发布,为了弥补先前协议版本的诸多弱点,SSL3从头开始设计了一套协议,并一直沿用到了最新版本的TLS。2、TLS1.0TLS1.0于1999年1月发布,3、TLS1.1TLS1.1于2006年4月发布。4、TLS1.2TLS1.2于2008年8月发布。5、T......
  • Windows 7 任务栏开发 之 进度条(Progress Bar)
         上一篇我们完成了“覆盖图标”(OverlayIcon)的相关开发,本篇我们将对进度条特性进行研究。在使用IE下载文件时,任务栏图标会同步显示当前下载进度(如下图)。那么在应用程序中如何实现这个效果呢? 下载状态 TaskbarManager.SetProgressValue 方法      在Tas......
  • windows系统桌面壁纸切换的三种csharp办法,兼容win10及旧版,还有一个现成桌面小程序
    我自己用这些代码做的小app如下: 最新版本已经改成了服务的方式,也可以选择性添加系统的右键菜单,并且我自己使用的源码库已经开源到了nuget,大家可以直接拿来做二次开发,新版的下载地址为:https://www.zhaimaojun.cn/P/桌面壁纸管理器/开源库为(可以直接在vs的nuget包管理中搜索......
  • 镇海-APIO联合总结
    镇海考试见此处:https://www.cnblogs.com/british-union/p/liankao.html考的是湖南省队集训,除了第一天有点头昏导致体验很差之外体验非常好,剩下两次考试非常对我胃口,是mathround。THUSC的第一天遭遇了巨大失败。具体来说,第一题是非常简单的数位dp但是我不会做。这是由于我......