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&…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
数据库——redis
一、Redis 介绍 1. 概述 Redis(Remote Dictionary Server)是一个开源的、高性能的内存键值数据库系统,具有以下核心特点: 内存存储架构:数据主要存储在内存中,提供微秒级的读写响应 多数据结构支持&…...
初级程序员入门指南
初级程序员入门指南 在数字化浪潮中,编程已然成为极具价值的技能。对于渴望踏入程序员行列的新手而言,明晰入门路径与必备知识是开启征程的关键。本文将为初级程序员提供全面的入门指引。 一、明确学习方向 (一)编程语言抉择 编…...
