> 文章列表 > Windows资源

Windows资源

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

示例代码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

示例代码:区分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
    • 释放匹配的内存DCDeleteDC
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;
}

在这里插入图片描述