Windows资源

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

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

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

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值