MFC第二十七天 通过动态链表实现游戏角色动态增加、WM_ERASEBKGND背景刷新的原理、RegisterClass注册窗口与框架程序开发

文章目录

  • 通过动态链表实现游戏角色动态增加
    • CMemoryDC.h
    • CFlashDlg.h
    • CFlashDlg.cpp
  • WM_ERASEBKGND背景刷新的原理
  • RegisterClass注册窗口与框架程序开发
    • CFrameRegister

通过动态链表实现游戏角色动态增加

CMemoryDC.h

	#pragma once
	#include "resource.h"

	/*内存DC类简介: 
	1、BOOL LoadBitmap(UINT nBitmapID,CDC* pDC = NULL)
	从资源中按照,按位图ID加载位图
	2、BOOL LoadFile(LPCTSTR sFile, CDC* pDC = NULL)
	从exe外部加载图片(调用LoadImage)
	3、BOOL Create(int cx, int cy, CDC* pDC = NULL)
	创建空白位图(默认是全黑)
	4、总共有4种构造函数,包含以上3种还有空构造:
	CMemoryDC(UINT nBitmapID)//从资源按照位图编号来加载
	CMemoryDC(LPCTSTR sFile, CDC* pDC = NULL)//从exe外部加载
	CMemoryDC(int cx, int cy, CDC* pDC=NULL)//指定高宽创建空白位图

	5、void MakeRgn(CRgn& r,COLORREF col)
	生成透明区域
	6、int GetWidth() const
	int GetHeight() const
	方便地获取图片高宽:
	7、
	透明显示:BitTrans和StrecthTrans
	*/
	class CMemoryDC :public CDC
	{
		CSize m_size;
	public:
		CMemoryDC();
 

		int GetWidth() const
		{
			return m_size.cx;
		}
		int GetHeight() const
		{
			return m_size.cy;
		}
 
		CSize GetSize() const
		{
			return m_size;
		}

		void BitTrans(
			int nXDest,		// 目标起点X
			int nYDest,		// 目标起点Y
			int nWidthDest,	// 目标宽度
			int nHeightDest,// 目标高度
			CDC* pDC,		// 目标DC
			int nXSrc,		// 来源起点X
			int nYSrc,		// 来源起点Y
			COLORREF crTrans// 透明色
		)
		{
			CMemoryDC dcImage(nWidthDest, nHeightDest, pDC);//临时DC
			CBitmap bmpMask;
			bmpMask.CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);            // 创建单色掩码位图
			CDC dcMask;//掩码DC 
			dcMask.CreateCompatibleDC(pDC);
			dcMask.SelectObject(bmpMask);
			//将载入位图的内存DC中的位图,拷贝到临时DC中
			dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, this, nXSrc, nYSrc, SRCCOPY);

			// 设置临时DC的透明色
			dcImage.SetBkColor(crTrans);
			//掩码DC的透明区域为白色其它区域为黑色
			dcMask.BitBlt(0, 0, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCCOPY);

			//临时DC透明区域为黑色,其它区域保持不变
			dcImage.SetBkColor(RGB(0, 0, 0));
			dcImage.SetTextColor(RGB(255, 255, 255));
			dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);

			// 目标DC透明部分保持屏幕不变,其它部分变成黑色
			pDC->SetBkColor(RGB(255, 255, 255));
			pDC->SetTextColor(RGB(0, 0, 0));
			pDC->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);
			pDC->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCPAINT);
		}
		void StretchTrans(
			int nXDest,			// 目标起点X
			int nYDest,			// 目标起点Y
			int nWidthDest,     // 目标宽度
			int nHeightDest,    // 目标高度
			CDC* pDC,			// 目标DC
			int nXSrc,			// 来源起点X
			int nYSrc,			// 来源起点Y
			int nWidthSrc,		// 来源宽度
			int nHeightSrc,		// 来源高度
			COLORREF crTrans	// 透明色
		)
		{
			CMemoryDC dcImage(nWidthDest, nHeightDest, pDC);//临时DC
			CBitmap bmpMask;
			// 创建单色掩码位图
			bmpMask.CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);
			CDC dcMask;
			dcMask.CreateCompatibleDC(pDC);
			dcMask.SelectObject(bmpMask);

			// 将载入位图的内存DC中的位图,拷贝到临时DC中
			if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc)
				dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, this, nXSrc, nYSrc, SRCCOPY);
			else
				dcImage.StretchBlt(0, 0, nWidthDest, nHeightDest,
					this, nXSrc, nYSrc, nWidthSrc, nHeightSrc, SRCCOPY);

			// 设置临时DC的透明色
			dcImage.SetBkColor(crTrans);
			//掩码DC的透明区域为白色其它区域为黑色
			dcMask.BitBlt(0, 0, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCCOPY);

			//临时DC透明区域为黑色,其它区域保持不变
			dcImage.SetBkColor(RGB(0, 0, 0));
			dcImage.SetTextColor(RGB(255, 255, 255));
			dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);

			// 目标DC透明部分保持屏幕不变,其它部分变成黑色
			pDC->SetBkColor(RGB(255, 255, 255));
			pDC->SetTextColor(RGB(0, 0, 0));
			pDC->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);
			pDC->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCPAINT);
		}

		//创建空位图
		BOOL Create(int cx, int cy, CDC* pDc = NULL)
		{
			if (!CreateCompatibleDC(NULL))
				return FALSE;
			CBitmap bmp;
			if (pDc)
			{
				if (!bmp.CreateCompatibleBitmap(pDc, cx, cy)) 
				{
					DeleteDC();
					return FALSE;
				}
			}
			else
			{
				if (!bmp.CreateCompatibleBitmap(&CClientDC(NULL), cx, cy))
				{
					DeleteDC();
					return FALSE;
				}
			}
			this->SelectObject(&bmp);
			m_size.SetSize(cx, cy);
			return TRUE;
		}
		//加载一张exe外部位图
		BOOL LoadFile(LPCTSTR sFile, CDC* pDC = NULL)
		{
			HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, sFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
			if (!hBitmap)
				return FALSE;	
			if (!CreateCompatibleDC(NULL))
			{
				DeleteObject(hBitmap);
				return FALSE;
			}
			
			SelectObject(hBitmap);

			BITMAP bm;
			GetObject(hBitmap, sizeof(bm), &bm);
			m_size.SetSize(bm.bmWidth, bm.bmHeight);
			DeleteObject(hBitmap);
			return TRUE;
		}

		//加载一张资源位图
		BOOL LoadBitmap(UINT nBitmapID, CDC* pDC = NULL)
		{
			if (!CreateCompatibleDC(NULL))
				return FALSE;
			CBitmap bmp;
			if (!bmp.LoadBitmap(nBitmapID))
			{
				DeleteDC();
				return FALSE;
			}
			SelectObject(&bmp);

			BITMAP bm;
			bmp.GetBitmap(&bm);
			m_size.SetSize(bm.bmWidth, bm.bmHeight);
			return TRUE;
		}
		CMemoryDC(UINT nBitmapID)
		{
			LoadBitmap(nBitmapID);
		}
		CMemoryDC(LPCTSTR sFile,CDC* pDC = NULL)
		{
			LoadFile(sFile, pDC);
		}
		CMemoryDC(int cx,int cy,CDC* pDC=NULL)
		{
			Create(cx, cy, pDC);
		}
		void MakeRgn(CRgn& r, COLORREF col)
		{
			r.CreateRectRgn(0, 0, 0, 0);
			int i = -1, cx = m_size.cx;
			int j = -1, cy = m_size.cy;
			while (++j<cy)
			{
				i = -1;
				while (++i<cx)
				{
					if (GetPixel(i, j) != col)
					{
						CRgn r1;
						r1.CreateRectRgn(i, j, i + 1, j + 1); //1*1像素
						r.CombineRgn(&r, &r1, RGN_OR);
					}
				}
			}

		}
	};

CFlashDlg.h

#pragma once
#include "CMemoryDC.h"
class CCFlashDlg : public CDialogEx{ 
	struct sData {
		int nIndex;
		CPoint pos, dir{ 5,5 };
	};
	CList<sData> m_list;  //使用动态链表实现 角色的动态增加
// 构造
	enum {Fly_nCount =7}; //图片总数
	CMemoryDC m_dcBack{_T("./res/back.bmp")}; //背景图片
	CMemoryDC m_dcFlys[Fly_nCount]; //蝴蝶
	CRgn m_rs[Fly_nCount]; //取出背景颜色
	void LoadPictures();
	CDC m_dc; //作一个缓冲dc
// 实现
protected:
	HICON m_hIcon;
	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnTimer(UINT_PTR nIDEvent);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
};

CFlashDlg.cpp

#include "pch.h"
#include "framework.h"
#include "CFlash.h"
#include "CFlashDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CCFlashDlg::CCFlashDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_CFLASH_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CCFlashDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CCFlashDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_TIMER()
	ON_WM_LBUTTONDOWN()
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
BOOL CCFlashDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	
	int cx = GetSystemMetrics(SM_CXSCREEN);
	int cy = GetSystemMetrics(SM_CYSCREEN);
	  
	SetWindowPos(NULL, 0, 0, cx/2, cy/2, SWP_NOZORDER);

	LoadPictures();	
	SetTimer(1, 16, NULL);
	srand((int)time(NULL));
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}
void CCFlashDlg::OnPaint()
{
	CPaintDC dc(this); // 用于绘制的设备上下文
	CRect rect;
	GetClientRect(rect);

	m_dc.SetStretchBltMode(STRETCH_HALFTONE); //拉伸图片质量的
	m_dc.StretchBlt(0, 0, rect.Width(), rect.Height(), &m_dcBack, 0, 0, m_dcBack.GetWidth(), m_dcBack.GetHeight(), SRCCOPY);
	
	CMemoryDC mdc(300,280); //创建默认的黑色
	if (mdc.GetSafeHdc())
		m_dc.BitBlt(200, 150, 300, 280, &mdc, 0, 0, SRCCOPY);
	//CRgn r;
	//r.CreateRectRgn(0, 0, 0, 0); //基址
	//r.CopyRgn(m_rs+m_nIndex);  //往那个跑先复制出来 不要破坏它 形状
	//r.OffsetRgn(m_pos); //你要输出到那个位置
	//dc.SelectObject(&r);
	auto pos = m_list.GetHeadPosition();
	int i = 0;
	while (pos)
	{
		sData& d = m_list.GetNext(pos);
		auto pDC = m_dcFlys + d.nIndex;
 
	pDC->BitTrans(d.pos.x, d.pos.y, pDC->GetWidth(), pDC->GetHeight(), &m_dc, 0, 0, 0xff00ff);

	if (++d.nIndex >= Fly_nCount)
		d.nIndex = 0 ;

	d.pos.Offset(d.dir);

	if (d.pos.x + m_dcFlys->GetWidth() > rect.right || d.pos.x < 0)
		d.dir.x *= -1;
	if (d.pos.y + m_dcFlys->GetHeight() > rect.bottom || d.pos.y < 0)
		d.dir.y *= -1;
	CString str;
	str.Format(_T("%d"), i++);
	m_dc.TextOut(d.pos.x,d.pos.y,str);
	}										//闪烁 是因为交替输出 
	dc.BitBlt(0, 0, rect.Width(), rect.Height(), &m_dc, 0, 0, SRCCOPY); //双缓冲技术 防止闪烁 采用一次性输出全部由m_dc输出  
}
void CCFlashDlg::LoadPictures()	{
	int i = -1;
	CString str;
	while (++i<_countof(m_dcFlys))	
	{
		str.Format(_T("./res/%03d.bmp"), i + 1);
		m_dcFlys[i].LoadFile(str);
		m_dcFlys[i].MakeRgn(m_rs[i],0x00ff00ff);
	}
}
void CCFlashDlg::OnTimer(UINT_PTR nIDEvent)
{
	Invalidate(TRUE); //制造了闪烁 因为前景输出 会触发再一次的交替输出
	CDialogEx::OnTimer(nIDEvent);
}
void CCFlashDlg::OnLButtonDown(UINT nFlags, CPoint point)  {
	sData d;
	d.nIndex = rand() % Fly_nCount;

	int n = rand() % 2 ? 1 : -1;
	d.dir.x = 5 * n;
	n = rand() % 2 ? 1 : -1;
	d.dir.y = 5 * n;
	d.pos = point;
	d.pos.x -= m_dcFlys->GetWidth() / 2; //中心点
	d.pos.y -= m_dcFlys->GetHeight() / 2; //中心点

	m_list.AddTail(d);
	CDialogEx::OnLButtonDown(nFlags, point);
}
void CCFlashDlg::OnSize(UINT nType, int cx, int cy)
{
	CDialogEx::OnSize(nType, cx, cy);
	m_dc.DeleteDC();
	m_dc.CreateCompatibleDC(NULL);

	CBitmap bmp;
	bmp.CreateBitmap(cx, cy, 1, 32, NULL);
	m_dc.SelectObject(&bmp);
}
BOOL CCFlashDlg::OnEraseBkgnd(CDC* pDC)
{
	return TRUE; //给夺权了
}

在这里插入图片描述


WM_ERASEBKGND背景刷新的原理

WM_ERASEBKGND是一种消息类型,它是在窗口需要重绘背景时发送给窗口的。背景刷新的原理是在窗口绘制之前,系统首先向窗口发送WM_ERASEBKGND消息,窗口可以在处理此消息时进行背景擦除操作,即清除原有的背景后。系统会发送WM_PAINT消息,窗口可以在处理此消息时进行绘制操作,即绘制新的背景。

具体的背景刷新流程如下:

  1. 当窗口需要重绘背景时,系统发送WM_ERASEBKGND消息给窗口。
  2. 窗口接收到WM_ERASEBKGND消息后,可以执行背景擦除操作,清除原有的背景。常见的擦除操作包括用背景色填充窗口区域、绘制背景图片等。
  3. 完成背景擦除后,窗口可以返回非零值,表示背景已经擦除完毕。
  4. 系统接收到非零返回值后,发送WM_PAINT消息给窗口。
  5. 窗口接收到WM_PAINT消息后,可以执行绘制操作,即绘制新的背景。
  6. 绘制完成后,窗口可以调用ValidateRect或InvalidateRect函数,通知系统该区域已经被绘制完成,系统不再发送WM_PAINT消息。

通过以上流程,窗口可以在接收到WM_ERASEBKGND和WM_PAINT消息时分别进行背景擦除和绘制操作,实现背景的刷新。
在这里插入图片描述

RegisterClass注册窗口与框架程序开发

classname注册窗口类型名:有3种方式注册
a)原始API:ATOM RegisterClass(const WNDCLASS *lpWndClass); 注册窗口类型
b)MFC封装之后叫做AfxRegisterClass,类似于AfxMessageBox封装了MessageBox(API)
c)MFC再次封装了一个真正的简易注册函数叫做:AfxRegisterWndClass
返回值是自动生成字符串,字符串的内容包括三要素的句柄sprintf生成的文字

注册的内容主要包括:背景颜色,图标,光标,另外还有的类型包含有菜单

typedef struct tagWNDCLASS {
  UINT      style;
  WNDPROC   lpfnWndProc;
  int       cbClsExtra;
  int       cbWndExtra;
  HINSTANCE hInstance;
  HICON     hIcon;
  HCURSOR   hCursor;
  HBRUSH    hbrBackground;
  LPCTSTR   lpszMenuName;
  LPCTSTR   lpszClassName;
} WNDCLASS, *PWNDCLASS;
typedef struct tagWNDCLASSEX {
  UINT      cbSize;
  UINT      style;
  WNDPROC   lpfnWndProc;
  int       cbClsExtra;
  int       cbWndExtra;
  HINSTANCE hInstance;
  HICON     hIcon;
  HCURSOR   hCursor;
  HBRUSH    hbrBackground;
  LPCTSTR   lpszMenuName;
  LPCTSTR   lpszClassName;
  HICON     hIconSm;
} WNDCLASSEX, *PWNDCLASSEX;
LPCTSTR  AfxRegisterWndClass( 
   UINT nClassStyle, 
   HCURSOR hCursor = 0, 
   HBRUSH hbrBackground = 0, 
   HICON hIcon = 0  
);
AfxRegisterClass比API就是多了GetClassInfo探测一下是否已注册过了。
BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass)	{
	WNDCLASS wndcls;
	if (GetClassInfo(lpWndClass->hInstance, lpWndClass->lpszClassName,
		&wndcls))
	{
		return TRUE;	// class already registered
	}
	if (!RegisterClass(lpWndClass))
	{
		TRACE(traceAppMsg, 0, _T("Can't register window class named %Ts\n"),
			lpWndClass->lpszClassName);
		return FALSE;
	}

注册的背景色的原理:
a)RegisterClass指定的背景色,依靠什么输出的呢?
b)WM_ERASEBKGND消息,是默认的背景输出管理消息。
c)WM_ERASEBKGND消息对比WM_PAINT,是微软设计的前景和背景管理消息。
d)他当年设计的原理是想要背景覆盖前景,方便刷新。 但是这个设计可能会制造闪烁问题?
解决办法
a)Invalidate函数代入TRUE,表示先触发WM_ERASEBKGRND再触发WM_PAINT消息。
b)Invalidate函数代入FALSE,表示不触发WM_ERASEBKGRND只触发WM_PAINT消息。
c)因此,好彻底解决闪烁问题还要注意,尽量Invalidate代入FALSE;
d)另外,也尽量把WM_ERASEBKGRND消息映射函数清空,只留WM_PAINT 的输出。

inline static bool IsWindowClassRegistered(LPCTSTR sClass) //用于检测注册类名 是否会重复
{
	WNDCLASSEX wcex;
	return  (GetClassInfoEx(NULL, sClass, &wcex) != 0);
}
BOOL CLadderCtrl::OnEraseBkgnd(CDC* pDC) 
 //	RegisterClass(&wc); wc.hbrBackground = m_brBack; 背景颜色依靠这个消息输出的
{
	return CWnd::OnEraseBkgnd(pDC); //默认背景输出	
}
BOOL CLadderCtrl::Create(DWORD dwStyle, CRect rect, CWnd* pParent, int nID)
{
	if (!IsWindowClassRegistered(_T("Ladder_XQ"))) //用于判断注册类名会不会重复
	{
		WNDCLASS wc = { CS_HREDRAW | CS_VREDRAW };  //注册窗口类型名
		wc.hCursor = theApp.LoadStandardCursor(IDC_HAND);
		wc.hbrBackground = m_brBack;
		wc.lpszClassName = _T("Ladder_XQ");
		wc.lpfnWndProc = ::DefWindowProc;
		RegisterClass(&wc);
	}
	return CWnd::Create(_T("Ladder_XQ"), NULL, dwStyle, rect, pParent, nID);
}
BOOL Clvxin21Dlg::OnEraseBkgnd(CDC* pDC)
{ 
	CRect rect;
	GetClientRect(rect);
	pDC->FillSolidRect(rect, GetSysColor(COLOR_BTNFACE));
	return TRUE;
}

CFrameRegister

MFC环境下创建框架窗口的必备条件:
a)InitInstance必须return TRUE;
b)theApp.m_pMainWnd 必须指向主窗口对象地址:
c)主窗口对象必须是堆空间或者生命期足够。

#include "CApp.h"
#include "CMainFrame.h"
CApp thApp;

//CWnd* pFrame = new CWnd;
 can't use for desktop or pop-up windows (use CreateEx instead) create不允许用于创建主窗口
//pFrame->Create(NULL, _T("我的世界"), WS_VISIBLE, CRect(100, 100, 800, 600), NULL, 9999);
	
//CWnd* pFrame = new CWnd;
使用CreatEx时 首先要 make sure the default window class is registered no WNDCLASS provided - use child window default  没有的默认为子窗口创建
//pFrame->CreateEx(0, NULL, _T("我的世界"), WS_VISIBLE, CRect(100, 100, 800, 600), NULL, 9999);
BOOL CApp::InitInstance(){
	/*LPCTSTR sClass = _T("MY_WORLD");
	WNDCLASS wc{ CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS };
	wc.lpfnWndProc = ::DefWindowProc;
	wc.lpszClassName = sClass;
	wc.hCursor = LoadStandardCursor(IDC_CROSS);
	wc.hIcon = LoadStandardIcon(IDI_INFORMATION);
	wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
	RegisterClass(&wc);*/
	auto pFrame = new CMainFrame;
	BOOL b = pFrame->CreateEx(0, NULL, _T("我的世界"),
	WS_VISIBLE | WS_MAXIMIZEBOX |WS_MINIMIZEBOX| WS_SYSMENU, 100, 100, 800, 600, NULL, NULL);
	m_pMainWnd = pFrame;
	return TRUE;
}
#include "CMainFrame.h"
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	//if (!CWnd::PreCreateWindow(cs)) //给子框架用来注册的,对主框架不好使
	//	return FALSE;

	cs.lpszClass = AfxRegisterWndClass(0); 
	 //自己添加的使用的AfxRegisterWndClass 也可以继续在添加属性  预处理

	return CWnd::PreCreateWindow(cs);
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/67057.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

即将发布的 Kibana 版本可运行 Node.js 18

作者&#xff1a;Thomas Watson Kibana 构建在 Node.js 框架之上。 为了确保每个 Kibana 版本的稳定性和使用寿命&#xff0c;我们始终将捆绑的 Node.js 二进制文件保持为最新的最新长期支持 (LTS) 版本。 当 Node.js 版本 18 升级到 LTS 时&#xff0c;我们开始将 Kibana 升级…

图的遍历之 深度优先搜索和广度优先搜索

深度优先搜索的图文介绍 1. 深度优先搜索介绍 图的深度优先搜索(Depth First Search)&#xff0c;和树的先序遍历比较类似。 它的思想&#xff1a;假设初始状态是图中所有顶点均未被访问&#xff0c;则从某个顶点v出发&#xff0c;首先访问该顶点&#xff0c;然后依次从它的各…

java中try-with-resources自动关闭io流

文章目录 java中try-with-resources自动关闭io流0 简要说明try-with-resources java中try-with-resources自动关闭io流 0 简要说明 在传统的输入输出流处理中&#xff0c;我们一般使用的结构如下所示&#xff0c;使用try - catch - finally结构捕获相关异常&#xff0c;最后不…

【Spring】如果你需要使用重试机制,请使用Spring官方的Spring Retry

文章目录 前言Spring Retry的基本使用第一步&#xff0c;引入Spring Retry的jar包第二步&#xff0c;构建一个RetryTemplate类第三步&#xff0c;使用RETRY_TEMPLATE注意事项 拓展方法降级操作重试策略&#xff1a;时间策略重试策略&#xff1a;指定异常策略 前言 Spring Retr…

吉利科技携手企企通,打造集团化数智供应链系统

近日&#xff0c;吉利科技集团有限公司&#xff08;以下简称“吉利科技”&#xff09;联合企企通成功召开SRM采购供应链管理项目启动会。企企通与吉利科技高层、项目负责人与团队成员出席此次启动会。 双方将携手在企业供应商全生命周期管理、采购全流程、电子招投标、采购分析…

opencv动态目标检测

文章目录 前言一、效果展示二、实现方法构造形态学操作所需的核:创建背景减除模型:形态学操作:轮廓检测: 三、代码python代码C代码 总结参考文档 前言 很久没更新文章了&#xff0c;这次因为工作场景需要检测动态目标&#xff0c;特此记录一下。 一、效果展示 二、实现方法 基…

华为运动健康,十年创新天地宽

我听一位朋友讲过这样一个故事。某天早上&#xff0c;急诊科的医生迎来了一位患者&#xff0c;患者进来后直接说&#xff1a;“大夫&#xff0c;我房颤了。” 这位医生非常诧异&#xff0c;因为心脏房颤确实非常危急&#xff0c;但很多时候并没有明显的生理体征&#xff0c;患者…

Flutter:屏幕适配

flutter_screenutil flutter_screenutil是一个用于在Flutter应用程序中进行屏幕适配的工具包。它旨在帮助开发者在不同屏幕尺寸和密度的设备上创建响应式的UI布局。 flutter_screenutil提供了一些用于处理尺寸和间距的方法&#xff0c;使得开发者可以根据设备的屏幕尺寸和密度…

基于Crow的C++的WebSocket服务器

基于Crow的C的WebSocket服务器 一、WebSocket 1.1 什么是WebSocket WebSocket 是一种持久化的通讯协议。 很多网站为了实现推送技术&#xff0c;所用的技术都是轮询&#xff0c;这种解决方案是指由浏览器每隔一段时间向服务器发出 HTTP 请求&#xff0c;然后服务器返回最新的…

React源码解析18(2)------ FilberNode,FilberRootNode结构关系

摘要 在上一篇&#xff0c;我们实现了通过JSX转换为ReactElement的方法&#xff0c;也看到了转换后React元素的结构。但是这个React元素&#xff0c;并不能很清楚的表达组件之间的关系&#xff0c;以及属性的处理。 所以在React内部&#xff0c;会将所有的React元素转换为Fil…

idea集成svn

一、注意 安装svn客户端的时候一定要勾选&#xff0c;否则在idea上集成svn的时候会找不到 svn.exe 而报错。 如果当初安装时忘记勾选&#xff0c;重新运行安装包&#xff0c;选择modify&#xff0c;勾选command line client tools项中的内容。 二、配置idea集成svn 三、检出(c…

电影票接单售票小程序搭建--java开源+后台管理系统

要搭建一个电影票接单售票小程序和后台管理系统&#xff0c;可以采取以下步骤&#xff08;以下步骤不分先后&#xff09;&#xff1a; 设计系统架构首先需要设计系统的整体架构&#xff0c;确定系统的技术选型、功能模块和业务流程等。可以考虑使用微服务架构&#xff0c;将系…

Jmeter添加cookie的两种方式

jmeter中添加cookie可以通过配置HTTP Cookie Manager&#xff0c;也可以通过HTTP Header Manager&#xff0c;因为cookie是放在头文件里发送的。 实例&#xff1a;博客园点击添加新随笔 https://i.cnblogs.com/EditPosts.aspx?opt1 如果未登录&#xff0c;跳转登录页&#xf…

MongoDB SQL

Microsoft Windows [版本 6.1.7601] 版权所有 (c) 2009 Microsoft Corporation。保留所有权利。C:\Users\Administrator>cd C:\MongoDB\Server\3.4\binC:\MongoDB\Server\3.4\bin> C:\MongoDB\Server\3.4\bin> C:\MongoDB\Server\3.4\bin>net start MongoDB 请求的…

ArcGIS、ENVI、InVEST、FRAGSTATS技术教程

专题一 空间数据获取与制图 1.1 软件安装与应用讲解 1.2 空间数据介绍 1.3海量空间数据下载 1.4 ArcGIS软件快速入门 1.5 Geodatabase地理数据库 专题二 ArcGIS专题地图制作 2.1专题地图制作规范 2.2 空间数据的准备与处理 2.3 空间数据可视化&#xff1a;地图符号与注…

FPGA应用学习笔记--时钟域的控制 亚稳态的解决

时钟域就是同一个时钟的区域&#xff0c;体现在laways语句边缘触发语句中&#xff0c;设计规模增大就会导致时钟不同步&#xff0c;有时差&#xff0c;就要设计多时钟域。 会经过与门的延时产生的新时钟域&#xff0c;这种其实不推荐使用&#xff0c;但在ascl里面很常见 在处理…

开发工具Eclipse的使用

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Eclipse使用的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Eclipse是什么 二.使用Eclipse的…

openGauss学习笔记-35 openGauss 高级数据管理-ALTER TABLE语句

文章目录 openGauss学习笔记-35 openGauss 高级数据管理-ALTER TABLE语句35.1 语法格式35.2 参数说明35.3 示例 openGauss学习笔记-35 openGauss 高级数据管理-ALTER TABLE语句 修改表&#xff0c;包括修改表的定义、重命名表、重命名表中指定的列、重命名表的约束、设置表的所…

激活函数总结(四):Hard系列激活函数补充(HardSigmoid、HardTanh、Hardswish)

激活函数总结&#xff08;四&#xff09;&#xff1a;Hard系列激活函数补充 1 引言2 激活函数2.1 HardSigmoid激活函数2.2 HardTanh激活函数2.3 Hardswish激活函数 3. 总结 1 引言 在前面的文章中已经介绍了过去大家较为常见的激活函数 (Sigmoid、Tanh、ReLU、Leaky ReLU、PRe…

Vue中使用qrcode说明

1.安装 npm i qrcode1.5.3 2.导入 import QRCode from qrcode 3.转换 说明&#xff1a;拿到服务器传来的字符串&#xff0c;转换成base64&#xff0c;然后通过img标签展示。 // 字符串转成二维码 let result await this.$API.reqPayInfo(this.orderId); 总结&#xff1a;