Windows资源
Unit01图标资源、光标资源、字符串资源
01图标资源
- 添加资源:注意图标的大小,一个图标文件中,可以有多个不同大小的图标
- 加载
HICON LoadIcon(
HINSTANCE hInstance,//handle to application instance
LPCTSTR lpIconName//name string or resource identifier
); //成功返回HICON句柄
- 设置:注册窗口类
示例代码:
#include <windows.h>
#include "resource.h"
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = LoadIcon(hIns,(char*)IDI_ICON1);
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
02光标资源
例如鼠标箭头光标其实是一张小图片
- 添加光标的资源:光标的大小默认为32x32像素,每个光标有Hotspot,是当前鼠标的热点(即鼠标的光标中包含的1000个点,但是真正点击有效的只有一个,如鼠标的尖尖)
- 加载光标
HCURSOR LoadCursor(
HINSTANCE hInstance,//handle to application instance
LPCTSTR lpCursorName//name or resource identifier
);//hInstance可以为NULL,获取系统默认的cursor
- 设置资源
- 在注册窗口时,设置光标
- 使用SetCursor设置光标(可以随时改变光标的样式)
HCURSOR SetCursor( HCURSOR hCursor);
WM_SETCURSOR
消息参数- 在移动鼠标时产生
- WPARAM:当前使用的光标句柄
- LPARAM
- LOWORD当前区域的代码(Hit-Test code)
HTCLIENT:表示在客户窗口里活动/HTCAPTION:表示在窗口在非客户窗口活动(如标题栏或者其它窗口)
- HIWORD当前鼠标消息ID
- LOWORD当前区域的代码(Hit-Test code)
示例代码1:在注册窗口时设置光标
#include <windows.h>
#include "resource.h"
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = LoadCursor(hIns, (char*)IDC_CURSOR1);
wc.hIcon = LoadIcon(hIns,(char*)IDI_ICON1);
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
示例代码2:在客户区内活动改变光标,在非客户区活动变为普通股鼠标箭头
#include <windows.h>
#include "resource.h"
HINSTANCE g_hInstance = 0;
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
case WM_SETCURSOR:
{
HCURSOR hCur = LoadCursor(g_hInstance, (char*)IDC_CURSOR2);
if(LOWORD(lParam)==HTCLIENT){
SetCursor(hCur);
return 0;
}else{
//非客户区内活动
}
}
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
g_hInstance = hIns;
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = LoadCursor(hIns, (char*)IDC_CURSOR1);
wc.hIcon = LoadIcon(hIns,(char*)IDI_ICON1);
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
03字符串资源
- 添加字符串资源:添加字符串表,在表中增加字符串
- 字符串资源的使用
int LoadString(
HINSTANCE hInstance,//handle to resource module
UINT uID,//字符串ID
LPTSTR lpBuffer, //存放字符串BUFF
int cchBufferMax//字符串BUFF长度
); //成功返回字符串长度,失败返回0
示例代码:将英文标题改成中文,再从中文改为英文
#include <windows.h>
#include "resource.h"
HINSTANCE g_hInstance = 0;
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
case WM_SETCURSOR:
{
HCURSOR hCur = LoadCursor(g_hInstance, (char*)IDC_CURSOR2);
if(LOWORD(lParam)==HTCLIENT){
SetCursor(hCur);
return 0;
}else{
//非客户区内活动
}
}
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
g_hInstance = hIns;
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = LoadCursor(hIns, (char*)IDC_CURSOR1);
wc.hIcon = LoadIcon(hIns,(char*)IDI_ICON1);
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
char szTitle[256] = {0};
LoadString(hIns,IDS_WND,szTitle,256);
HWND hWnd = CreateWindowEx(0,"Main",szTitle,WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
如果客户想还是改为英文,此时就不用再更改代码了,而是直接更改字符串资源将:窗口改为window就行
Unit02加速键资源(如复制<ctrl+c>、粘贴<ctrl+v>)
- 添加:资源添加加速键表,增加命令ID对应的加速键
- 使用
//加载加速键表
HACCEL LoadAccelerators(
HINSTANCE hInstance,//handle to module
LPCTSTR lpTableName//accelerator table name
); //返回加速键表句柄
//翻译加速键
int TranslateAccelerator(
HWND hWnd,//处理消息的窗口句柄
HACCEL hAccTable,//加速键表句柄
LPMSG lpMsg//消息
); //如果是加速键,返回非零
TranslateAccelerator
内部的执行过程,伪代码:
TranslateAccelerator(hWnd,hAccel,&nMsg){
if(nMsg.message != WM_KEYDOWN)
return 0;
//根据nMsg.wParam(键码值),获知那些按键被按下(Ctrl+M)
//拿着(Ctrl+M)到nAccel(加速键表)中去匹配查找
if(没找到)
return 0;
if(找到){
//wParam:高字节:ID_NEW|||低字节:1
SendMessage(hWnd,WM_COMMAND,ID_NEW|||1,...);
return 1;
}
}
示例代码:按Ctrl+M
实现菜单项新建
的功能弹窗
#include <windows.h>
#include "resource.h"
HINSTANCE g_hInstance = 0;
void OnCommand(HWND hWnd, WPARAM wParam){
switch(LOWORD(wParam)){
case ID_NEW:
MessageBox(hWnd,"新建菜单项被点击","Infor",MB_OK);
break;
}
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_COMMAND:
OnCommand(hWnd, wParam);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
case WM_SETCURSOR:
{
HCURSOR hCur = LoadCursor(g_hInstance, (char*)IDC_CURSOR2);
if(LOWORD(lParam)==HTCLIENT){
SetCursor(hCur);
return 0;
}else{
//非客户区内活动
}
}
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
g_hInstance = hIns;
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = LoadCursor(hIns, (char*)IDC_CURSOR1);
wc.hIcon = LoadIcon(hIns,(char*)IDI_ICON1);
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = (char*)IDR_MENU1;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
char szTitle[256] = {0};
LoadString(hIns,IDS_WND,szTitle,256);
HWND hWnd = CreateWindowEx(0,"Main",szTitle,WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//获取加速键表的句柄
HACCEL hAccel = LoadAccelerators(hIns,(char*)IDR_ACCELERATOR1);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
//TranslateAccelerator函数应该放在GetMessage和TranslateMessage之间执行
if(!TranslateAccelerator(hWnd,hAccel,&nMsg)){//当不是加速键消息时应该执行下面两句语句
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
}
return 0;
}
- 在
WM_COMMAND
中相应消息,消息参数- WPARAM:
- HIWORD为1表示加速键,为0表示菜单项
- LOWORD:为命令ID(加速键ID或者是菜单项ID)
- LPARAM:为0
- WPARAM:
示例代码:区分WM_COMMAND
消息来自加速键还是菜单项(但实际应用不会区分,这样主要是让加速键和菜单项复用消息处理代码)
#include <windows.h>
#include "resource.h"
HINSTANCE g_hInstance = 0;
void OnCommand(HWND hWnd, WPARAM wParam){
switch(LOWORD(wParam)){
case ID_NEW:
//区分消息来自加速键还是菜单项,通过WPARAM的高字节决定
if(HIWORD(wParam) == 0)
MessageBox(hWnd,"新建菜单项被点击","Infor",MB_OK);
else if(HIWORD(wParam) == 1)
MessageBox(hWnd,"Ctrl+M加速键点击","Infor",MB_OK);
break;
}
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_COMMAND:
OnCommand(hWnd, wParam);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
case WM_SETCURSOR:
{
HCURSOR hCur = LoadCursor(g_hInstance, (char*)IDC_CURSOR2);
if(LOWORD(lParam)==HTCLIENT){
SetCursor(hCur);
return 0;
}else{
//非客户区内活动
}
}
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
g_hInstance = hIns;
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = LoadCursor(hIns, (char*)IDC_CURSOR1);
wc.hIcon = LoadIcon(hIns,(char*)IDI_ICON1);
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = (char*)IDR_MENU1;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
char szTitle[256] = {0};
LoadString(hIns,IDS_WND,szTitle,256);
HWND hWnd = CreateWindowEx(0,"Main",szTitle,WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//获取加速键表的句柄
HACCEL hAccel = LoadAccelerators(hIns,(char*)IDR_ACCELERATOR1);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
//TranslateAccelerator函数应该放在GetMessage和TranslateMessage之间执行
if(!TranslateAccelerator(hWnd,hAccel,&nMsg)){//当不是加速键消息时应该执行下面两句语句
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
}
return 0;
}
Unit03绘图编程
01绘图基础
-
绘图设备DC(Device Context),也叫:绘图上下文或绘图描述表
-
HDC:DC句柄,表示绘图设备
-
GDI:全称
Windows graphics device interface
(Win32提供的绘图API) -
颜色
- 计算机使用红、绿、蓝(R、G、B取值范围都是0~255)
- 每个颜色点都是3个字节24位保存,所以范围是
0~2^24-1
=16M
- 16位:RGB分别是5,5,6位(很古老的颜色存储)
- 32位:RGB还是8,8,8位,剩余8位是绘图透明度(用于3维画图)
-
颜色的使用
COLORREF
:实际DWORD
,例如:COLORREF nColor=0
-
赋值使用RGB宏:例如
nColor=RGB(0,0,255)
; -
获取RGB值,
GetRValue/GetGValue/GetBValue
,例如BYTE nRed = GetRValue(nColor)
02基本图形绘制
SetPixel
设置指定点的颜色
COLORREF SetPixel(
HDC hdc, // handle to DC(DC句柄)
int X, // x-coordinate of pixel(X坐标)
int Y, // y-coordinate of pixel(Y 坐标)
COLORREF crColor // pixel color(设置的颜色)
);//返回点原来的颜色
示例代码1:画一个点(为了防止看不见画了多个点)
#include <windows.h>
void DrawPit(HDC hdc){
//SetPixel(hdc,100, 100,RGB(255,0,0));
for(int i=100;i<110;i++){
for(int j=100;j<110;j++){
SetPixel(hdc,i, j,RGB(255,0,0));
}
}
}
void OnPaint(HWND hWnd){
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
DrawPit(hdc);//绘制点
EndPaint(hWnd, &ps);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
- 线的使用(直线、弧线)
- MoveToEx:指名窗口当前点
- LineTo:从窗口当前到指定绘制一条线
- 当前点:上一次绘图时的最后一点,初始为(0,0)点
示例代码:
#include <windows.h>
void DrawPit(HDC hdc){
//SetPixel(hdc,100, 100,RGB(255,0,0));
for(int i=100;i<110;i++){
for(int j=100;j<110;j++){
SetPixel(hdc,i, j,RGB(255,0,0));
}
}
}
void DrawLine(HDC hdc){
MoveToEx(hdc, 100, 100, NULL);
LineTo(hdc, 300, 300);
LineTo(hdc, 0, 300);//再画一条直线
}
void OnPaint(HWND hWnd){
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
//DrawPit(hdc);//绘制点
DrawLine(hdc);//绘制直线
EndPaint(hWnd, &ps);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
- 封闭图形:能够用画刷填充的图形(Rectangle、Ellipse)
示例代码:画一个矩形
#include <windows.h>
void DrawPit(HDC hdc){
//SetPixel(hdc,100, 100,RGB(255,0,0));
for(int i=100;i<110;i++){
for(int j=100;j<110;j++){
SetPixel(hdc,i, j,RGB(255,0,0));
}
}
}
void DrawLine(HDC hdc){
MoveToEx(hdc, 100, 100, NULL);
LineTo(hdc, 300, 300);
LineTo(hdc, 0, 300);//再画一条直线
}
void DrawRect(HDC hdc){
Rectangle(hdc,100,100,300,300);
}
void OnPaint(HWND hWnd){
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
//DrawPit(hdc);//绘制点
//DrawLine(hdc);//绘制直线
DrawRect(hdc);//绘制矩形
EndPaint(hWnd, &ps);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
示例代码:画一个圆形
#include <windows.h>
void DrawPit(HDC hdc){
//SetPixel(hdc,100, 100,RGB(255,0,0));
for(int i=100;i<110;i++){
for(int j=100;j<110;j++){
SetPixel(hdc,i, j,RGB(255,0,0));
}
}
}
void DrawLine(HDC hdc){
MoveToEx(hdc, 100, 100, NULL);
LineTo(hdc, 300, 300);
LineTo(hdc, 0, 300);//再画一条直线
}
void DrawRect(HDC hdc){
//参数是左上角坐标,右下角坐标
Rectangle(hdc,100,100,300,300);
}
void DrawEll(HDC hdc){
Ellipse(hdc,100,100,300,300);
}
void OnPaint(HWND hWnd){
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
//DrawPit(hdc);//绘制点
//DrawLine(hdc);//绘制直线
//DrawRect(hdc);//绘制矩形
DrawEll(hdc);//绘制圆形
EndPaint(hWnd, &ps);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
03GDI绘图对象
01画笔
- 画笔的作用
- 线的颜色、线型、线粗
HPEN
:画笔句柄
画笔的使用
- 1.创建画笔
HPEN CreatePen(
int fnPenStyle, // pen style 画笔的样式
int nWidth, // pen width 画笔的粗细
COLORREF crColor // pen color 画笔的颜色
);//创建成功返回画笔句柄
注意
:如果fnPenStyle
的值是PS_SOLID
实心线,可以支持多个像素宽,其他线型只能是一个像素宽
- 2.将画笔应用到DC中
HGDIOBJ SelectObject(
HDC hdc, // handle to DC 绘图设备句柄
HGDIOBJ hgdiobj // handle to object GDI绘图对象句柄,画笔句柄
);//返回原来的GDI绘图对象句柄
- 3.绘图
- 4.取出DC中的画笔:使用
SelectObject
函数,放入设备DC中,就会将我们创建的画笔取出 - 5.释放画笔
BOOL DeleteObject(
HGDIOBJ hObject // handle to graphic object(GDI绘图对象句柄,画笔句柄)
);
注意
:只能删除不被DC使用的画笔,所以在释放前,必须将画笔从DC中取出
示例代码:画红色的圆
#include <windows.h>
void DrawPit(HDC hdc){
//SetPixel(hdc,100, 100,RGB(255,0,0));
for(int i=100;i<110;i++){
for(int j=100;j<110;j++){
SetPixel(hdc,i, j,RGB(255,0,0));
}
}
}
void DrawLine(HDC hdc){
MoveToEx(hdc, 100, 100, NULL);
LineTo(hdc, 300, 300);
LineTo(hdc, 0, 300);//再画一条直线
}
void DrawRect(HDC hdc){
//参数是左上角坐标,右下角坐标
Rectangle(hdc,100,100,300,300);
}
void DrawEll(HDC hdc){
Ellipse(hdc,100,100,300,300);
}
void OnPaint(HWND hWnd){
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
//1.创建画笔
HPEN hPen = CreatePen(PS_SOLID,10,RGB(255,0,0));//实线圆形, PS_DASH是虚线
//2.将画笔递给画家,并保存原来的黑白画笔
HGDIOBJ nOldPen = SelectObject(hdc, hPen);
//DrawPit(hdc);//绘制点
//DrawLine(hdc);//绘制直线
//DrawRect(hdc);//绘制矩形
//3.让画家画出相关图形
DrawEll(hdc);//绘制实线圆形
//4.画家画完了图将画笔还给系统,相当于系统那黑白的画笔换回彩色画笔
SelectObject(hdc, nOldPen);
//5.系统销毁彩色画笔,相当于释放资源
DeleteObject(hPen);
EndPaint(hWnd, &ps);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
02画刷
画刷相关
- 画刷:给封闭图形填充的颜色、图案
HBRUSH
:画刷句柄
画刷的使用
- 1.创建画刷
//创建实心画刷
HBRUSH CreateSolidBrush(
COLORREF crColor // brush color value
);
//创建纹理画刷
HBRUSH CreateHatchBrush(
int fnStyle, // hatch style
COLORREF clrref // foreground color
);
- 2.将画刷用到DC中
SelectObject
- 3.绘图
- 4.将画刷从DC中取出
SelectObject
- 5.删除画刷
DeleteObject
示例代码:画一个红边绿色实心圆
#include <windows.h>
void DrawPit(HDC hdc){
//SetPixel(hdc,100, 100,RGB(255,0,0));
for(int i=100;i<110;i++){
for(int j=100;j<110;j++){
SetPixel(hdc,i, j,RGB(255,0,0));
}
}
}
void DrawLine(HDC hdc){
MoveToEx(hdc, 100, 100, NULL);
LineTo(hdc, 300, 300);
LineTo(hdc, 0, 300);//再画一条直线
}
void DrawRect(HDC hdc){
//参数是左上角坐标,右下角坐标
Rectangle(hdc,100,100,300,300);
}
void DrawEll(HDC hdc){
Ellipse(hdc,100,100,300,300);
}
void OnPaint(HWND hWnd){
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
//1.创建画笔
HPEN hPen = CreatePen(PS_SOLID,10,RGB(255,0,0));
//2.将画笔递给画家,并保存原来的黑白画笔
HGDIOBJ nOldPen = SelectObject(hdc, hPen);
//HBRUSH hBrush = CreateHatchBrush(HS_CROSS,RGB(0,255,0));//纹理画刷,HS_CROSSS经纬线
HBRUSH hBrush = CreateSolidBrush(RGB(0,255,0));//绿色画刷
HGDIOBJ hOldBrush = SelectObject(hdc, hOldBrush);//与画家交换画刷
//DrawPit(hdc);//绘制点
//DrawLine(hdc);//绘制直线
//DrawRect(hdc);//绘制矩形
//3.让画家画出相关图形
DrawEll(hdc);//绘制圆形
SelectObject(hdc, hOldBrush);
DeleteObject(hBrush);
//4.画家画完了图将画笔还给系统,相当于系统那黑白的画笔换回彩色画笔
SelectObject(hdc, nOldPen);
//5.系统销毁彩色画笔,相当于释放资源
DeleteObject(hPen);
EndPaint(hWnd, &ps);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+3);//将背景设置为黑颜色
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
其他
- 可以使用
GetStockObject
函数获取系统维护的画刷、画笔等 - 如果不使用画刷填充,需要使用
NULL_BRUSH
参数,获取不填充的画刷(就是透明的画刷) GetStockObject
返回的画刷不需要DeleteObject
,因为这个是向系统借来的不能释放
HGDIOBJ GetStockObject(
int fnObject // stock object type
0);
示例代码:让圆的背景和背景色一样
#include <windows.h>
void DrawPit(HDC hdc){
//SetPixel(hdc,100, 100,RGB(255,0,0));
for(int i=100;i<110;i++){
for(int j=100;j<110;j++){
SetPixel(hdc,i, j,RGB(255,0,0));
}
}
}
void DrawLine(HDC hdc){
MoveToEx(hdc, 100, 100, NULL);
LineTo(hdc, 300, 300);
LineTo(hdc, 0, 300);//再画一条直线
}
void DrawRect(HDC hdc){
//参数是左上角坐标,右下角坐标
Rectangle(hdc,100,100,300,300);
}
void DrawEll(HDC hdc){
Ellipse(hdc,100,100,300,300);
}
void OnPaint(HWND hWnd){
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
//1.创建画笔
HPEN hPen = CreatePen(PS_SOLID,10,RGB(255,0,0));
//2.将画笔递给画家,并保存原来的黑白画笔
HGDIOBJ nOldPen = SelectObject(hdc, hPen);
//HBRUSH hBrush = CreateSolidBrush(RGB(0,255,0));//绿色画刷
HGDIOBJ hBrush = GetStockObject(NULL_BRUSH);
HGDIOBJ hOldBrush = SelectObject(hdc, hBrush);//与画家交换画刷
//DrawPit(hdc);//绘制点
//DrawLine(hdc);//绘制直线
//DrawRect(hdc);//绘制矩形
//3.让画家画出相关图形
DrawEll(hdc);//绘制圆形
SelectObject(hdc, hOldBrush);
//DeleteObject(hBrush);
//4.画家画完了图将画笔还给系统,相当于系统那黑白的画笔换回彩色画笔
SelectObject(hdc, nOldPen);
//5.系统销毁彩色画笔,相当于释放资源
DeleteObject(hPen);
EndPaint(hWnd, &ps);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+3);//将背景设置为黑颜色
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
Unit05位图
01位图的绘制
- 位图相关
- 光栅图形:记录图形中每一个点的颜色等信息
- 矢量图形:记录图像算法、绘图指令等
HBITMAP
:位图句柄
- 位图的使用
- 在资源中添加位图资源
- 从资源中加载位图
LoadBitMap
- 创建一个与当前DC相匹配的DC(内存DC),相当于两个同步的画家一个在窗口上画图,一个在后面的内存中画图
- 将位图放入匹配的DC中,使用
SelectObject
- 成像(1:1),使用
BitBlt
函数(就是将内存的虚拟图像画到窗口的指定位置上,类比老式的照相机交卷图像就是内存DC中的图像,窗口就是将要晒出来照片的相纸) - 取出位图
SelectObject
- 释放位图
DeleteObject
- 释放匹配的内存DC
DeleteDC
HDC CreateCompatibleDC(
HDC hdc // handle to DC 当前DC句柄,可以为NULL(使用屏幕DC)
);//返回创建好的DC句柄
HBITMAP LoadBitmap(
HINSTANCE hInstance, // handle to application instance
LPCTSTR lpBitmapName // name of bitmap resource
);
//1:1成像
BOOL BitBlt(
HDC hdcDest, // handle to destination DC(目标DC)
int nXDest, // x-coord of destination upper-left corner(目的左上X坐标)
int nYDest, // y-coord of destination upper-left corner(目的左上Y坐标)
int nWidth, // width of destination rectangle(目的宽度)
int nHeight, // height of destination rectangle(目的高度)
HDC hdcSrc, // handle to source DC(源DC,就是内存DC)
int nXSrc, // x-coordinate of source upper-left corner(源左上X坐标)
int nYSrc, // y-coordinate of source upper-left corner(源左上Y坐标)
DWORD dwRop // raster operation code(成像方法 SRCCORY原样成像)
);
//缩放成像
BOOL StretchBlt(
HDC hdcDest, // handle to destination DC
int nXOriginDest, // x-coord of destination upper-left corner
int nYOriginDest, // y-coord of destination upper-left corner
int nWidthDest, // width of destination rectangle
int nHeightDest, // height of destination rectangle
HDC hdcSrc, // handle to source DC
int nXOriginSrc, // x-coord of source upper-left corner
int nYOriginSrc, // y-coord of source upper-left corner
int nWidthSrc, // width of source rectangle
int nHeightSrc, // height of source rectangle
DWORD dwRop // raster operation code
);
//释放DC
BOOL DeleteDC(
HDC hdc // handle to DC
);
示例代码:画出位图到窗口
#include <windows.h>
#include "resource.h"
HINSTANCE g_hInstance = 0;
void DrawPit(HDC hdc){
//SetPixel(hdc,100, 100,RGB(255,0,0));
for(int i=100;i<110;i++){
for(int j=100;j<110;j++){
SetPixel(hdc,i, j,RGB(255,0,0));
}
}
}
void DrawLine(HDC hdc){
MoveToEx(hdc, 100, 100, NULL);
LineTo(hdc, 300, 300);
LineTo(hdc, 0, 300);//再画一条直线
}
void DrawRect(HDC hdc){
//参数是左上角坐标,右下角坐标
Rectangle(hdc,100,100,300,300);
}
void DrawEll(HDC hdc){
Ellipse(hdc,100,100,300,300);
}
void DrawBmp(HDC hdc){
//添加位图资源(不需要写代码,在.rc文件中编辑)
//加载位图资源,注意类型(CAHR*)
HBITMAP hBmp = LoadBitmap(g_hInstance,(CHAR*)IDB_BITMAP1);
//创建一个内存DC,并构建一个虚拟区域,并且内存DC在虚拟区域中画图
HDC hMemdc = CreateCompatibleDC(hdc);
//将位图数据传给内存DC,内存DC在虚拟区域中将位图绘制出来
HGDIOBJ nOldBmp = SelectObject(hMemdc, hBmp);
//将虚拟区域中绘制好的图像成像到窗口中
BitBlt(hdc,100,100,48,48,hMemdc,0,0,SRCCOPY);
//取出内存DC中的位图
SelectObject(hMemdc,nOldBmp);
//释放位图资源
DeleteObject(hBmp);
//释放内存DC
DeleteDC(hMemdc);
}
void OnPaint(HWND hWnd){
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
//1.创建画笔
HPEN hPen = CreatePen(PS_SOLID,10,RGB(255,0,0));
//2.将画笔递给画家,并保存原来的黑白画笔
HGDIOBJ nOldPen = SelectObject(hdc, hPen);
//HBRUSH hBrush = CreateSolidBrush(RGB(0,255,0));//绿色画刷
HGDIOBJ hBrush = GetStockObject(NULL_BRUSH);
HGDIOBJ hOldBrush = SelectObject(hdc, hBrush);//与画家交换画刷
//DrawPit(hdc);//绘制点
//DrawLine(hdc);//绘制直线
//DrawRect(hdc);//绘制矩形
//3.让画家画出相关图形
//DrawEll(hdc);//绘制圆形
//画位图
DrawBmp(hdc);
SelectObject(hdc, hOldBrush);
//DeleteObject(hBrush);
//4.画家画完了图将画笔还给系统,相当于系统那黑白的画笔换回彩色画笔
SelectObject(hdc, nOldPen);
//5.系统销毁彩色画笔,相当于释放资源
DeleteObject(hPen);
EndPaint(hWnd, &ps);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
g_hInstance = hIns;
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+3);//将背景设置为黑颜色
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
示例代码2:缩放位图
#include <windows.h>
#include "resource.h"
HINSTANCE g_hInstance = 0;
void DrawPit(HDC hdc){
//SetPixel(hdc,100, 100,RGB(255,0,0));
for(int i=100;i<110;i++){
for(int j=100;j<110;j++){
SetPixel(hdc,i, j,RGB(255,0,0));
}
}
}
void DrawLine(HDC hdc){
MoveToEx(hdc, 100, 100, NULL);
LineTo(hdc, 300, 300);
LineTo(hdc, 0, 300);//再画一条直线
}
void DrawRect(HDC hdc){
//参数是左上角坐标,右下角坐标
Rectangle(hdc,100,100,300,300);
}
void DrawEll(HDC hdc){
Ellipse(hdc,100,100,300,300);
}
void DrawBmp(HDC hdc){
//添加位图资源(不需要写代码,在.rc文件中编辑)
//加载位图资源,注意类型(CAHR*)
HBITMAP hBmp = LoadBitmap(g_hInstance,(CHAR*)IDB_BITMAP1);
//创建一个内存DC,并构建一个虚拟区域,并且内存DC在虚拟区域中画图
HDC hMemdc = CreateCompatibleDC(hdc);
//将位图数据传给内存DC,内存DC在虚拟区域中将位图绘制出来
HGDIOBJ nOldBmp = SelectObject(hMemdc, hBmp);
//将虚拟区域中绘制好的图像成像到窗口中
BitBlt(hdc,100,100,48,48,hMemdc,0,0,SRCCOPY);
//缩放成像(缩放的做法是看在窗口开辟的区域大小,比源小就缩,比源大就放)
StretchBlt(hdc,200,200,96,96,hMemdc,0,0,48,48,SRCCOPY);
//取出内存DC中的位图
SelectObject(hMemdc,nOldBmp);
//释放位图资源
DeleteObject(hBmp);
//释放内存DC
DeleteDC(hMemdc);
}
void OnPaint(HWND hWnd){
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd,&ps);
//1.创建画笔
HPEN hPen = CreatePen(PS_SOLID,10,RGB(255,0,0));
//2.将画笔递给画家,并保存原来的黑白画笔
HGDIOBJ nOldPen = SelectObject(hdc, hPen);
//HBRUSH hBrush = CreateSolidBrush(RGB(0,255,0));//绿色画刷
HGDIOBJ hBrush = GetStockObject(NULL_BRUSH);
HGDIOBJ hOldBrush = SelectObject(hdc, hBrush);//与画家交换画刷
//DrawPit(hdc);//绘制点
//DrawLine(hdc);//绘制直线
//DrawRect(hdc);//绘制矩形
//3.让画家画出相关图形
//DrawEll(hdc);//绘制圆形
//画位图
DrawBmp(hdc);
SelectObject(hdc, hOldBrush);
//DeleteObject(hBrush);
//4.画家画完了图将画笔还给系统,相当于系统那黑白的画笔换回彩色画笔
SelectObject(hdc, nOldPen);
//5.系统销毁彩色画笔,相当于释放资源
DeleteObject(hPen);
EndPaint(hWnd, &ps);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
g_hInstance = hIns;
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+3);//将背景设置为黑颜色
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
Unit06文本绘制
01绘制字符串
- 文字的绘制
TextOut
:将文字绘制在指定坐标位置DrawText
int DrawText(
HDC hDC, // handle to DC(DC句柄)
LPCTSTR lpString, // text to draw (字符串)
int nCount, // text length(字符数量)
LPRECT lpRect, // formatting dimensions(绘制文字的矩形框)
UINT uFormat // text-drawing options(绘制的方式)
);
DrawText的绘制方式(其功能比TextOut强大就体现在这个参数上)
示例代码:对比TextOut和DrawText的区别
#include <windows.h>
void OnPaint(HWND hWnd){
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd, &ps);
char szText[] = "hello txt long long LONG long long LONG";
TextOut(hdc, 100, 100, szText, strlen(szText));
RECT rc;
rc.left = 100;
rc.top = 150;
rc.right = 200;
rc.bottom = 200;
Rectangle(hdc, 100, 150, 200, 200);
//DT_CENTER/DT_BOTTOM只适用于DT_SINGLELINE和DT_WORDBREAK冲突
//DrawText(hdc, szText, strlen(szText), &rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_NOCLIP);
DrawText(hdc, szText, strlen(szText), &rc, DT_LEFT|DT_TOP|DT_WORDBREAK|DT_NOCLIP);
EndPaint(hWnd, &ps);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
- 文字颜色和背景
- 文字颜色:
SetTextColor
- 文字背景色:
SetBkColor
- 文字背景模式:
SetBkMode
(OPAQUE/TRANSPARENT)
- 文字颜色:
COLORREF SetTextColor(
HDC hdc, // handle to DC
COLORREF crColor // text color
);
COLORREF SetBkColor(
HDC hdc, // handle to DC
COLORREF crColor // background color value
);
int SetBkMode(
HDC hdc, // handle to DC
int iBkMode // background mode
);
示例代码:改变文字的颜色和背景颜色
#include <windows.h>
void OnPaint(HWND hWnd){
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd, &ps);
char szText[] = "hello txt";
SetTextColor(hdc, RGB(255, 0, 0));
SetBkColor(hdc, RGB(0,255,0));//只适用于SetBkMode的OPAQUE不透明模式下,当SetBkMode的模式是TRANSPARENT,SetBkColor函数会失效
//SetBkMode(hdc, TRANSPARENT);//设置背景颜色是透明的
TextOut(hdc, 100, 100, szText, strlen(szText));
RECT rc;
rc.left = 100;
rc.top = 150;
rc.right = 200;
rc.bottom = 200;
//Rectangle(hdc, 100, 150, 200, 200);
//DT_CENTER/DT_BOTTOM只适用于DT_SINGLELINE和DT_WORDBREAK冲突
DrawText(hdc, szText, strlen(szText), &rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_NOCLIP);
EndPaint(hWnd, &ps);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+3);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
02字体
字体相关
- Window常用的字体为
TrueType
格式的字体文件- 字体名标识字体类型
HFONT
:字体句柄
注意
:在C:\Windows\Fonts
文件夹中有本机所有的字体文件(所以想创建某种字体本机一定要有改字体的字体文件)
字体的使用
- 1.创建字体
HFONT CreateFont(
int nHeight, // height of font 字体高度
int nWidth, // average character width 字体宽度(给0让系统自适应)
int nEscapement, // angle of escapement 字符倾斜角度
int nOrientation, // base-line orientation angle 字符串旋转角度(注意字符串是否在同一水平线上,以0.1度为单位)
int fnWeight, // font weight 字体的粗细
DWORD fdwItalic, // italic attribute option 斜体(1/0)
DWORD fdwUnderline, // underline attribute option 字符下划线(1/0)
DWORD fdwStrikeOut, // strikeout attribute option 删除线(1/0)
DWORD fdwCharSet, // character set identifier 字符集(GB2312)
DWORD fdwOutputPrecision, // output precision 输出精度(0)
DWORD fdwClipPrecision, // clipping precision 剪切精度(0)
DWORD fdwQuality, // output quality 输出质量(0)
DWORD fdwPitchAndFamily, // pitch and family 匹配字体(0)
LPCTSTR lpszFace // typeface name 字体名称(看字体文件的第一行)
);
- 2.应用字体到DC,
SelectObject
- 3.绘制文字,
DrawText/TextOut
- 4.取出字体,
SelectObject
- 5.删除字体,
DeleteObject
示例代码:给字符添加一些特效
#include <windows.h>
void OnPaint(HWND hWnd){
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hWnd, &ps);
HFONT hFont = CreateFont(30,0,45,0,900,1,1,1,GB2312_CHARSET,0,0,0,0,"黑体");
HGDIOBJ nOldFont = SelectObject(hdc, hFont);
char szText[] = "hello txt";
SetTextColor(hdc, RGB(255, 0, 0));
SetBkColor(hdc, RGB(0,255,0));//只适用于SetBkMode的OPAQUE不透明模式下,当SetBkMode的模式是TRANSPARENT,SetBkColor函数会失效
//SetBkMode(hdc, TRANSPARENT);//设置背景颜色是透明的
TextOut(hdc, 100, 100, szText, strlen(szText));
RECT rc;
rc.left = 100;
rc.top = 150;
rc.right = 200;
rc.bottom = 200;
//Rectangle(hdc, 100, 150, 200, 200);
//DT_CENTER/DT_BOTTOM只适用于DT_SINGLELINE和DT_WORDBREAK冲突
DrawText(hdc, szText, strlen(szText), &rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_NOCLIP);
SelectObject(hdc, nOldFont);
DeleteObject(hFont);
EndPaint(hWnd, &ps);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
switch(msgID){
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage函数返回0
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
//注册窗口类
WNDCLASS wc = {0};
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+3);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "Main";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
//在内存创建窗口
HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0};
while(GetMessage(&nMsg,NULL,0,0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}