Windows资源
Windows资源
Unit01图标资源、光标资源、字符串资源
01图标资源
- 添加资源:注意图标的大小,一个图标文件中,可以有多个不同大小的图标
- 加载
HICON LoadIcon(HINSTANCE hInstance,//handle to application instanceLPCTSTR 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函数返回0break;}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 instanceLPCTSTR 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函数返回0break;}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函数返回0break;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 moduleUINT uID,//字符串IDLPTSTR lpBuffer, //存放字符串BUFFint 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函数返回0break;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 moduleLPCTSTR 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|||低字节:1SendMessage(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函数返回0break;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函数返回0break;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函数返回0break;}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函数返回0break;}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函数返回0break;}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函数返回0break;}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函数返回0break;}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函数返回0break;}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函数返回0break;}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 instanceLPCTSTR 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 DCint nXOriginDest, // x-coord of destination upper-left cornerint nYOriginDest, // y-coord of destination upper-left cornerint nWidthDest, // width of destination rectangleint nHeightDest, // height of destination rectangleHDC hdcSrc, // handle to source DCint nXOriginSrc, // x-coord of source upper-left cornerint nYOriginSrc, // y-coord of source upper-left cornerint nWidthSrc, // width of source rectangleint nHeightSrc, // height of source rectangleDWORD 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);//释放内存DCDeleteDC(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函数返回0break;}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);//释放内存DCDeleteDC(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函数返回0break;}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函数返回0break;}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 DCCOLORREF crColor // text color
);COLORREF SetBkColor(HDC hdc, // handle to DCCOLORREF crColor // background color value
);int SetBkMode(HDC hdc, // handle to DCint 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函数返回0break;}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函数返回0break;}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;
}