CTreeCtrl自绘
CSWTreeCtrl.h)
#pragma once#define _OWNER_DRAWN_TREE // 自绘CTreeCtrl,可支持背景图片显示功能class CSWTreeCtrl : public CTreeCtrl
{DECLARE_DYNAMIC(CSWTreeCtrl)// 成员私有结构定义// 构造/析构函数
public:CSWTreeCtrl();virtual ~CSWTreeCtrl();// 私有成员变量
private:// 私有成员函数
private:void CommonConstruct(); // 初始化// 受保护成员变量
protected:int m_nFirstColumnWidth; // 第一列宽度int m_nOffsetX; // 相对于父窗体X偏移量LVBKIMAGE m_bkImage; // 背景图片CImageList m_imgBtns; // 数控件展开的+/-图标符号// 受保护成员函数
protected:BOOL CheckHit(CPoint point);
#ifdef _OWNER_DRAWN_TREELRESULT CustomDrawNotify(LPNMTVCUSTOMDRAW lpNMTVCustomDraw);void OwnerDrawBackground(CDC* pDC);
#endif //_OWNER_DRAWN_TREE// 虚函数
protected:// 消息函数
protected:DECLARE_MESSAGE_MAP()afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);afx_msg void OnMouseMove(UINT nFlags, CPoint point);afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);afx_msg void OnPaint();afx_msg void OnTimer(UINT_PTR nIDEvent);afx_msg BOOL OnEraseBkgnd(CDC* pDC);
#ifdef _OWNER_DRAWN_TREEafx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar);
#endif //_OWNER_DRAWN_TREE// 共有成员变量
public:// 共有成员函数
public:// 获取背景图片BOOL GetBkImage(LVBKIMAGE* plvbkImage) const;// 设置背景图片BOOL SetBkImage(LVBKIMAGE* plvbkImage);#ifdef _OWNER_DRAWN_TREE// 设置树控件+/-按钮图标void SetTreeBtnBitmap(CBitmap* pBitmap, COLORREF clrMask = RGB(255, 0, 255));
#endif //_OWNER_DRAWN_TREE// 静态成员变量
public:// 静态成员函数
public:};
实现
#include "stdafx.h"
#include <shlwapi.h>
#include "CSWTreeCtrl.h"// IE 5.0 or higher required
#ifndef TVS_NOHSCROLL
#error CSWTreeCtrl requires IE 5.0 or higher; _WIN32_IE should be greater than 0x500.
#endif// 绘画树控件横向节点连接虚线
static void _DotHLine(HDC hdc, LONG x, LONG y, LONG w, COLORREF cr)
{for (; w > 0; w -= 2, x += 2)SetPixel(hdc, x, y, cr);
}// 绘画树控件竖向节点连接虚线
static void _DotVLine(HDC hdc, LONG x, LONG y, LONG w, COLORREF cr)
{for (; w > 0; w -= 2, y += 2)SetPixel(hdc, x, y, cr);
}IMPLEMENT_DYNAMIC(CSWTreeCtrl, CTreeCtrl)
CSWTreeCtrl::CSWTreeCtrl()
{CommonConstruct();
}CSWTreeCtrl::~CSWTreeCtrl()
{
}BEGIN_MESSAGE_MAP(CSWTreeCtrl, CTreeCtrl)ON_WM_MOUSEMOVE()ON_WM_LBUTTONDOWN()ON_WM_LBUTTONDBLCLK()ON_WM_PAINT()ON_WM_ERASEBKGND()ON_WM_VSCROLL()ON_WM_MOUSEWHEEL()ON_WM_KEYDOWN()
END_MESSAGE_MAP()void CSWTreeCtrl::CommonConstruct()
{
#ifdef _OWNER_DRAWN_TREE m_bkImage.hbm = NULL;m_bkImage.xOffsetPercent = 0;m_bkImage.yOffsetPercent = 0;
#endif //_OWNER_DRAWN_TREE
}#ifdef _OWNER_DRAWN_TREE
// 设置树控件+/-按钮图标
void CSWTreeCtrl::SetTreeBtnBitmap(CBitmap* pBitmap, COLORREF clrMask)
{ASSERT(pBitmap);if (pBitmap && pBitmap->GetSafeHandle()){m_imgBtns.Add(pBitmap, clrMask);BITMAP bmp;pBitmap->GetBitmap(&bmp);if (m_imgBtns.GetSafeHandle())m_imgBtns.DeleteImageList();m_imgBtns.Create(bmp.bmWidth / 2, bmp.bmHeight, ILC_COLOR32 | ILC_MASK, 2, 1);}
}
#endif //_OWNER_DRAWN_TREEBOOL CSWTreeCtrl::GetBkImage(LVBKIMAGE* plvbkImage) const
{memcpy(plvbkImage, &m_bkImage, sizeof(LVBKIMAGE));return TRUE;
}BOOL CSWTreeCtrl::SetBkImage(LVBKIMAGE* plvbkImage)
{memcpy(&m_bkImage, plvbkImage, sizeof(LVBKIMAGE));Invalidate();return TRUE;
}void CSWTreeCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{Invalidate();CTreeCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}void CSWTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{if (CheckHit(point)){HTREEITEM hItem = HitTest(point);if (hItem){
#ifdef _OWNER_DRAWN_TREECRect rcItem, rcClient;GetClientRect(&rcClient);GetItemRect(hItem, &rcItem, FALSE);if (rcItem.bottom > rcClient.bottom){Invalidate();EnsureVisible(hItem);SelectItem(hItem);return;}
#endif //_OWNER_DRAWN_TREESelectItem(hItem);}CTreeCtrl::OnLButtonDown(nFlags, point);}else{SetFocus();}
}void CSWTreeCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{if (CheckHit(point)){HTREEITEM hItem = HitTest(point);if (hItem){
#ifdef _OWNER_DRAWN_TREECRect rcItem, rcClient;GetClientRect(&rcClient);GetItemRect(hItem, &rcItem, FALSE);if (rcItem.bottom > rcClient.bottom){Invalidate();CTreeCtrl::OnLButtonDown(nFlags, point);return;}
#endif //_OWNER_DRAWN_TREESelectItem(hItem);}CTreeCtrl::OnLButtonDblClk(nFlags, point);}else{SetFocus();}
}void CSWTreeCtrl::OnMouseMove(UINT nFlags, CPoint point)
{if (CheckHit(point)){CTreeCtrl::OnMouseMove(nFlags, point);}
}#ifdef _OWNER_DRAWN_TREE
LRESULT CSWTreeCtrl::CustomDrawNotify(LPNMTVCUSTOMDRAW lpNMTVCustomDraw)
{lpNMTVCustomDraw->nmcd.hdr.hwndFrom = GetSafeHwnd();lpNMTVCustomDraw->nmcd.hdr.code = NM_CUSTOMDRAW;lpNMTVCustomDraw->nmcd.hdr.idFrom = GetWindowLong(m_hWnd, GWL_ID);return GetParent()->SendMessage(WM_NOTIFY, (WPARAM)0, (LPARAM)lpNMTVCustomDraw);
}void CSWTreeCtrl::OwnerDrawBackground(CDC* pDC)
{NMTVCUSTOMDRAW stuNMTVCustomDraw;DWORD dwFlags;DWORD dwRet;CRect rcClient;GetClientRect(&rcClient);memset(&stuNMTVCustomDraw, 0, sizeof(NMTVCUSTOMDRAW));stuNMTVCustomDraw.nmcd.dwDrawStage = CDDS_PREPAINT;stuNMTVCustomDraw.nmcd.hdc = pDC->m_hDC;stuNMTVCustomDraw.nmcd.rc = rcClient;dwFlags = (DWORD)CustomDrawNotify(&stuNMTVCustomDraw); // CDDS_PREPAINT// 填充背景色COLORREF crBkgnd = IsWindowEnabled() ? pDC->GetBkColor() : GetSysColor(COLOR_BTNFACE);pDC->FillSolidRect(rcClient, crBkgnd);if (m_bkImage.hbm && IsWindowEnabled()){// 画背景图片int xOffset = m_nOffsetX;int yOffset = rcClient.left;int yHeight = rcClient.Height();SCROLLINFO srlInfo;if (GetScrollInfo(SB_VERT, &srlInfo, SIF_POS | SIF_RANGE)){yOffset = -srlInfo.nPos;yHeight = max(srlInfo.nMax + 1, rcClient.Height());}CDC dcMem;dcMem.CreateCompatibleDC(pDC);BITMAP bmp;::GetObject(m_bkImage.hbm, sizeof(BITMAP), &bmp);CBitmap* pOldBitmap =dcMem.SelectObject(CBitmap::FromHandle(m_bkImage.hbm));// copy the background bitmap from temporary DC to painting DCfloat x = (float)m_bkImage.xOffsetPercent / 100 * (float)rcClient.Width();float y = (float)m_bkImage.yOffsetPercent / 100 * (float)rcClient.Height();pDC->BitBlt(/*xOffset*/+(int)x,/*yOffset+*/(int)y,bmp.bmWidth, bmp.bmHeight, &dcMem, 0, 0, SRCCOPY);dcMem.SelectObject(pOldBitmap);}if (dwFlags&CDRF_NOTIFYPOSTERASE){stuNMTVCustomDraw.nmcd.dwDrawStage = CDDS_POSTERASE;dwRet = (DWORD)CustomDrawNotify(&stuNMTVCustomDraw); // CDDS_POSTERASE}CFont* pOldFont = pDC->SelectObject(GetFont());CImageList* pstateList = GetImageList(TVSIL_STATE);CImageList* pimgList = GetImageList(TVSIL_NORMAL);CSize szIcon, szStateImg;if (pimgList){IMAGEINFO ii;if (pimgList->GetImageInfo(0, &ii))szIcon = CSize(ii.rcImage.right - ii.rcImage.left, ii.rcImage.bottom - ii.rcImage.top);}if (pstateList){IMAGEINFO ii;if (pstateList->GetImageInfo(0, &ii))szStateImg = CSize(ii.rcImage.right - ii.rcImage.left, ii.rcImage.bottom - ii.rcImage.top);}// 开始画树节点HTREEITEM hItem = GetFirstVisibleItem();while (hItem){int nOldBkMode = pDC->SetBkMode(TRANSPARENT);DWORD dwStyle = GetStyle();DWORD dwState = GetItemState(hItem, 0xFFFF);BOOL bEnabled = IsWindowEnabled();BOOL bSelected = dwState & TVIS_SELECTED;BOOL bHasFocus = (GetFocus() && GetFocus()->m_hWnd == m_hWnd) ? TRUE : FALSE;// 更新NMCUSTOMDRAW结果内容stuNMTVCustomDraw.nmcd.dwItemSpec = (DWORD_PTR)hItem;if (bEnabled){if (bHasFocus){stuNMTVCustomDraw.clrTextBk = bSelected ? GetSysColor(COLOR_HIGHLIGHT) : crBkgnd;stuNMTVCustomDraw.clrText = ::GetSysColor(bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT);stuNMTVCustomDraw.nmcd.uItemState = dwState | (bSelected ? CDIS_FOCUS : 0);}else{if (GetStyle()&TVS_SHOWSELALWAYS){stuNMTVCustomDraw.clrTextBk = bSelected ? GetSysColor(COLOR_INACTIVEBORDER) : crBkgnd;stuNMTVCustomDraw.clrText = ::GetSysColor(COLOR_MENUTEXT);}else{stuNMTVCustomDraw.clrTextBk = crBkgnd;stuNMTVCustomDraw.clrText = ::GetSysColor(COLOR_MENUTEXT);}}}else{stuNMTVCustomDraw.clrTextBk = bSelected ? GetSysColor(COLOR_BTNSHADOW) : crBkgnd;stuNMTVCustomDraw.clrText = ::GetSysColor(COLOR_GRAYTEXT);}GetItemRect(hItem, &stuNMTVCustomDraw.nmcd.rc, 0);CRgn rgn;rgn.CreateRectRgn(stuNMTVCustomDraw.nmcd.rc.left, stuNMTVCustomDraw.nmcd.rc.top, stuNMTVCustomDraw.nmcd.rc.left + m_nFirstColumnWidth, stuNMTVCustomDraw.nmcd.rc.bottom);pDC->SelectClipRgn(&rgn);dwRet = CDRF_DODEFAULT;if (dwFlags&CDRF_NOTIFYITEMDRAW){stuNMTVCustomDraw.nmcd.dwDrawStage = CDDS_ITEMPREPAINT;dwRet = (DWORD)CustomDrawNotify(&stuNMTVCustomDraw); // CDDS_ITEMPREPAINT}if (!(dwFlags&CDRF_SKIPDEFAULT)){// 画树节点图标和+/-按钮CRect rcItem;int nImage, nSelImage;GetItemRect(hItem, &rcItem, TRUE);GetItemImage(hItem, nImage, nSelImage);int x = rcItem.left - 3;int yCenterItem = rcItem.top + (rcItem.bottom - rcItem.top) / 2;if (pimgList){int nImageIndex = dwState & TVIS_SELECTED ? nImage : nSelImage;x -= szIcon.cx + 1;pimgList->Draw(pDC, nImageIndex, CPoint(x, yCenterItem - szIcon.cy / 2), ILD_TRANSPARENT);}if (GetStyle()&TVS_CHECKBOXES && pstateList != NULL){DWORD dwStateImg = GetItemState(hItem, TVIS_STATEIMAGEMASK) >> 12;x -= szStateImg.cx;pstateList->Draw(pDC, dwStateImg, CPoint(x, yCenterItem - szStateImg.cy / 2), ILD_TRANSPARENT);}if (dwStyle&TVS_HASLINES){CPen pen;pen.CreatePen(PS_DOT, 1, GetLineColor());CPen* pOldPen = pDC->SelectObject(&pen);HTREEITEM hItemParent = GetParentItem(hItem);if (hItemParent != NULL || dwStyle & TVS_LINESATROOT){_DotHLine(pDC->m_hDC, x - szIcon.cx / 2 - 2, yCenterItem, szIcon.cx / 2 + 2, RGB(128, 128, 128));}if (hItemParent != NULL || dwStyle & TVS_LINESATROOT && GetPrevSiblingItem(hItem) != NULL){_DotVLine(pDC->m_hDC, x - szIcon.cx / 2 - 2, rcItem.top,yCenterItem - rcItem.top, RGB(128, 128, 128));}if (GetNextSiblingItem(hItem) != NULL){_DotVLine(pDC->m_hDC, x - szIcon.cx / 2 - 2, yCenterItem,rcItem.bottom - yCenterItem, RGB(128, 128, 128));}int x1 = x - szIcon.cx / 2 - 2;while (hItemParent != NULL){x1 -= szIcon.cx + 3;if (GetNextSiblingItem(hItemParent) != NULL){_DotVLine(pDC->m_hDC, x1, rcItem.top, rcItem.Height(), RGB(128, 128, 128));}hItemParent = GetParentItem(hItemParent);}pDC->SelectObject(pOldPen);}if (dwStyle&TVS_HASBUTTONS && ItemHasChildren(hItem)){// 画+/-符号按钮int nImg = GetItemState(hItem, TVIF_STATE) & TVIS_EXPANDED ? 1 : 0;m_imgBtns.Draw(pDC, nImg, CPoint(x - szIcon.cx / 2 - 6, yCenterItem - 4), ILD_TRANSPARENT);}}pDC->SelectClipRgn(NULL);if (dwRet&CDRF_NOTIFYPOSTPAINT){stuNMTVCustomDraw.nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT;dwRet = (DWORD)CustomDrawNotify(&stuNMTVCustomDraw); // CDDS_ITEMPOSTPAINT}pDC->SetBkMode(nOldBkMode);hItem = GetNextVisibleItem(hItem);};pDC->SelectObject(pOldFont);
}BOOL CSWTreeCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{Invalidate();return CTreeCtrl::OnMouseWheel(nFlags, zDelta, pt);
}void CSWTreeCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar)
{Invalidate();CTreeCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}
#endif //_OWNER_DRAWN_TREEvoid CSWTreeCtrl::OnPaint()
{CRect rcClient;GetClientRect(&rcClient);CPaintDC dc(this);CDC dcMem;CBitmap bmpMem;dcMem.CreateCompatibleDC(&dc);if (bmpMem.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height())){CBitmap* pOldBmp = dcMem.SelectObject(&bmpMem);
#ifdef _OWNER_DRAWN_TREE // if owner-drawnOwnerDrawBackground(&dcMem); // use our code
#else // else use standard codeCWnd::DefWindowProc(WM_PAINT, (WPARAM)dcMem.m_hDC, 0);
#endif //_OWNER_DRAWN_TREEdc.BitBlt(0, 0, rcClient.right, rcClient.bottom, &dcMem, 0, 0, SRCCOPY);dcMem.SelectObject(pOldBmp);bmpMem.DeleteObject();}dcMem.DeleteDC();
}BOOL CSWTreeCtrl::OnEraseBkgnd(CDC* pDC)
{return TRUE;
}BOOL CSWTreeCtrl::CheckHit(CPoint point)
{UINT fFlags;HTREEITEM hItem = HitTest(point, &fFlags);CRect rcItem, rcClient;GetClientRect(rcClient);GetItemRect(hItem, &rcItem, TRUE);if (fFlags & TVHT_ONITEMICON ||fFlags & TVHT_ONITEMBUTTON ||fFlags & TVHT_ONITEMSTATEICON)return TRUE;if (GetStyle()&TVS_FULLROWSELECT){rcItem.right = rcClient.right;if (rcItem.PtInRect(point))return TRUE;return FALSE;}if (fFlags & TVHT_ONITEMLABEL){rcItem.right = m_nFirstColumnWidth;if (!rcItem.PtInRect(point))return FALSE;CString strSub;AfxExtractSubString(strSub, GetItemText(hItem), 0, '\t');CDC* pDC = GetDC();pDC->SelectObject(GetFont());rcItem.right = rcItem.left + pDC->GetTextExtent(strSub).cx + 6;ReleaseDC(pDC);if (!rcItem.PtInRect(point))return FALSE;return TRUE;}return FALSE;
}
根据节点关联数据值,采用递归算法查找指定节点。
HTREEITEM findTreeItem(CTreeCtrl& treeCtrl, HTREEITEM hItem, DWORD dwData) {if (treeCtrl.GetItemData(hItem) == dwData)return hItem;if (treeCtrl.ItemHasChildren(hItem)) {HTREEITEM hChild = treeCtrl.GetChildItem(hItem);HTREEITEM hFindItem = findTreeItem(treeCtrl, hChild, dwData);if (hFindItem != NULL)return hFindItem;}HTREEITEM hNext = treeCtrl.GetNextSiblingItem(hItem);if (hNext) {HTREEITEM hFindItem = findTreeItem(treeCtrl, hNext, dwData);if (hFindItem != NULL)return hFindItem;elsereturn NULL;}else {return NULL;}
};
相关文章:
CTreeCtrl自绘
CSWTreeCtrl.h) #pragma once#define _OWNER_DRAWN_TREE // 自绘CTreeCtrl,可支持背景图片显示功能class CSWTreeCtrl : public CTreeCtrl {DECLARE_DYNAMIC(CSWTreeCtrl)// 成员私有结构定义// 构造/析构函数 public:CSWTreeCtrl();virtual ~CSWTreeC…...
目标检测YOLO实战应用案例100讲-基于深度学习的可见光遥感图像目标检测
目录 前言 遥感图像目标的特点 基于深度学习的目标检测技术 2.1引言 2.2卷积神经网络...

MySQL数据库——存储引擎(2)-存储引擎特点(InnoDB、MyISAM、Memory)、存储引擎选择
目录 存储引擎特点 InnoDB 介绍 特点 文件 逻辑存储结构 MyISAM 介绍 特点 文件 Memory 介绍 特点 文件 区别及特点 存储引擎选择 存储引擎特点 上面我们介绍了什么是存储引擎,以及如何在建表时如何指定存储引擎,接下来我们就来介绍比较…...
【Vue】构建vue项目的几种方法以及区别
【Vue】构建vue项目的几种方法以及区别 1.通过vue-cli进行创建2.直接通过npm进行创建3.基于vite创建vue项目4.总结 构建vue项目时请确保已经安装node和npm 1.通过vue-cli进行创建 要用vue脚手架vue-cli创建vue项目首先我们需要全局安装一下vue-cli,安装命令如下&a…...
动态封装对象,属性来自json
需求: 如何动态的获取一个对象的字段,假如一个对象里面有name,age,sex三个字段,我想取name的值,这个name是存在一个json中,json的格式如下[{"key":"name"},{"key":"age…...

【LeetCode-中等题】90. 子集 II
文章目录 组合并集问题汇总:题目方法一:递归加回溯(去重版) 组合并集问题汇总: 1、子集非去重版本 2、组合非去重版本 3、组合去重版本 题目 本题nums数组存在重复元素,所以本题会涉及一个去重操作&#…...

Docker如何安装seafile
SQLite 方式 要在 Docker 中安装 Seafile,您可以按照以下步骤进行操作: 安装 Docker:确保您的系统上已经安装了 Docker。您可以根据您的操作系统类型,在官方网站上找到适合您系统的 Docker 版本并进行安装。 下载 Seafile 镜像&…...

注册法国商标的步骤和时间
注册法国商标的步骤如下: 1、商标查询:在提交申请之前,建议进行商标查询,以确保商标在法国市场上具有独特性和显著性。 2、提交申请:通过法国知识产权局的在线平台提交商标申请。申请时,需要提供以下文件…...

一起学数据结构(6)——栈和队列
上篇文章中,对栈的概念及特点进行了解释,并且给出了栈实现的具体代码。本篇文章将给出队列的基本概念及特点。并给出相应的代码。 1. 队列的概念及结构: 在给出队列的概念之前,先给出上篇文章中提到的栈的概念:一种只…...

【数据结构】二叉树的顺序结构-堆
【数据结构】二叉树的顺序结构-堆 普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间…...

2024年java面试--mysql(2)
系列文章目录 2024年java面试(一)–spring篇2024年java面试(二)–spring篇2024年java面试(三)–spring篇2024年java面试(四)–spring篇2024年java面试–集合篇2024年java面试–redi…...
IllegalArgumentException
Caused by: java.lang.IllegalArgumentException:Invalid pulsar service : persistent 参数非法异常 这个异常是由于使用了无效的 Pulsar 服务类型导致的。Pulsar 支持不同的服务类型,例如 persistent、non-persistent 等。 当你在配置 Pulsar 相关的参数时&…...

Git 概述命令、idea中的使用
目录 Git概述 Git代码托管服务 Git常用命令 Git 全局设置 获取 Git 仓库 编辑Git 工作区中文件的状态 本地仓库操作 远程仓库操作 编辑分支操作 标签操作 在IDEA中使用Git 1.获取Git仓库 .gitignore 表示忽略 2.本地仓库操作 3.远程仓库操作 4.分支操作 Git是…...

单片机之硬件记录
一、概念 VBAT 当使用电池或其他电源连接到VBAT脚上时,当VDD断电时,可以保存备份寄存器的内容和维持RTC的功能。如果应用中没有使用外部电池,VBAT引脚应接到VDD引脚上。 VCC:Ccircuit 表示电路的意思,即接入电路的电压&#x…...
QQ文件传输协议研究
引言 我们都知道,现在越来越多的应用采取了 HTTPS or TLS 传输协议,对于一般的协议,我们可以使用中间人技术对流量进行劫持转发,从而破解密文,这边可以参见我的另外一篇文章基于加密邮件协议的中间人攻防实战, 而对于 HTTPS 应用即使是我们采取中间人技术,也很难让浏览器…...

Qt/C++音视频开发51-推流到各种流媒体服务程序
一、前言 最近将推流程序完善了很多功能,尤其是增加了对多种流媒体服务程序的支持,目前支持mediamtx、LiveQing、EasyDarwin、nginx-rtmp、ZLMediaKit、srs、ABLMediaServer等,其中经过大量的对比测试,个人比较建议使用mediamtx和ZLMediaKit,因为这两者支持的格式众多,不…...

LeetCode 35. 搜索插入位置
题目链接 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 题目解析 该题我们可以采用二分查找的方式,我们可以把数组分为,小于target的一边儿和大于等于target的一边儿。 当midleft(right-left)下标所对应的数大于等于targ…...

7年经验之谈 —— Web测试是什么,有何特点?
Web测试是指对Web应用程序进行验证和评估的过程,以确保其功能、性能和安全性符合预期。 Web测试具体包括以下几个方面的内容: 功能测试:验证Web应用程序是否按照需求规格说明书中定义的功能正常工作。功能测试包括输入验证、表单提交、页面…...

【数据结构】前言概况 - 树
🚩纸上得来终觉浅, 绝知此事要躬行。 🌟主页:June-Frost 🚀专栏:数据结构 🔥该文章针对树形结构作出前言,以保证可以对树初步认知。 目录: 🌍前言:dz…...

MySQL——事务
一、事务的开始与结束 一个数据库事务由一条或多条sql语句构成,它们形成一个逻辑的工作单元。这些sql语句要么全部执行成功,要么全部执行失败。 1.1.事物的开始 1.对于DDL(create,alter,drop)和DCL&…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...