(九)C# Winform自定义控件-树
proginn468312
共 6011字,需浏览 13分钟
· 2020-08-10
准备工作
对原始树控件treeview进行扩展以更改样式
先了解一下我们需要哪些功能,控件ain可以更改整好颜色,行高,选中效果,分割线等
开始
添加组件,命名TreeViewEx 继承TreeView
先看下属性
private const int WS_VSCROLL = 2097152;
private const int GWL_STYLE = -16;
private Dictionary<string, string> _lstTips = new Dictionary<string, string>();
private Font _tipFont = new Font("Arial Unicode MS", 12f);
private Image _tipImage = Resources.tips;
private bool _isShowTip = false;
private bool _isShowByCustomModel = true;
private int _nodeHeight = 50;
private Image _nodeDownPic = Resources.list_add;
private Image _nodeUpPic = Resources.list_subtract;
private Color _nodeBackgroundColor = Color.FromArgb(61, 60, 66);
private Color _nodeForeColor = Color.White;
private bool _nodeIsShowSplitLine = false;
private Color _nodeSplitLineColor = Color.FromArgb(54, 53, 58);
private Color m_nodeSelectedColor = Color.FromArgb(255, 121, 74);
private Color m_nodeSelectedForeColor = Color.White;
private bool _parentNodeCanSelect = true;
private SizeF treeFontSize = SizeF.Empty;
private bool blnHasVBar = false;
public Dictionary<string, string> LstTips
{
get
{
return this._lstTips;
}
set
{
this._lstTips = value;
}
}
[Category("自定义属性"), Description("角标文字字体")]
public Font TipFont
{
get
{
return this._tipFont;
}
set
{
this._tipFont = value;
}
}
[Category("自定义属性"), Description("是否显示角标")]
public Image TipImage
{
get
{
return this._tipImage;
}
set
{
this._tipImage = value;
}
}
[Category("自定义属性"), Description("是否显示角标")]
public bool IsShowTip
{
get
{
return this._isShowTip;
}
set
{
this._isShowTip = value;
}
}
[Category("自定义属性"), Description("使用自定义模式")]
public bool IsShowByCustomModel
{
get
{
return this._isShowByCustomModel;
}
set
{
this._isShowByCustomModel = value;
}
}
[Category("自定义属性"), Description("节点高度(IsShowByCustomModel=true时生效)")]
public int NodeHeight
{
get
{
return this._nodeHeight;
}
set
{
this._nodeHeight = value;
base.ItemHeight = value;
}
}
[Category("自定义属性"), Description("下翻图标(IsShowByCustomModel=true时生效)")]
public Image NodeDownPic
{
get
{
return this._nodeDownPic;
}
set
{
this._nodeDownPic = value;
}
}
[Category("自定义属性"), Description("上翻图标(IsShowByCustomModel=true时生效)")]
public Image NodeUpPic
{
get
{
return this._nodeUpPic;
}
set
{
this._nodeUpPic = value;
}
}
[Category("自定义属性"), Description("节点背景颜色(IsShowByCustomModel=true时生效)")]
public Color NodeBackgroundColor
{
get
{
return this._nodeBackgroundColor;
}
set
{
this._nodeBackgroundColor = value;
}
}
[Category("自定义属性"), Description("节点字体颜色(IsShowByCustomModel=true时生效)")]
public Color NodeForeColor
{
get
{
return this._nodeForeColor;
}
set
{
this._nodeForeColor = value;
}
}
[Category("自定义属性"), Description("节点是否显示分割线(IsShowByCustomModel=true时生效)")]
public bool NodeIsShowSplitLine
{
get
{
return this._nodeIsShowSplitLine;
}
set
{
this._nodeIsShowSplitLine = value;
}
}
[Category("自定义属性"), Description("节点分割线颜色(IsShowByCustomModel=true时生效)")]
public Color NodeSplitLineColor
{
get
{
return this._nodeSplitLineColor;
}
set
{
this._nodeSplitLineColor = value;
}
}
[Category("自定义属性"), Description("选中节点背景颜色(IsShowByCustomModel=true时生效)")]
public Color NodeSelectedColor
{
get
{
return this.m_nodeSelectedColor;
}
set
{
this.m_nodeSelectedColor = value;
}
}
[Category("自定义属性"), Description("选中节点字体颜色(IsShowByCustomModel=true时生效)")]
public Color NodeSelectedForeColor
{
get
{
return this.m_nodeSelectedForeColor;
}
set
{
this.m_nodeSelectedForeColor = value;
}
}
[Category("自定义属性"), Description("父节点是否可选中")]
public bool ParentNodeCanSelect
{
get
{
return this._parentNodeCanSelect;
}
set
{
this._parentNodeCanSelect = value;
}
}
样式的更改主要通过节点的重绘,我们使用DrawNode事件来完成
base.DrawNode += new DrawTreeNodeEventHandler(this.treeview_DrawNode);
private void treeview_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
try
{
if (e.Node == null || !this._isShowByCustomModel || (e.Node.Bounds.Width <= 0 && e.Node.Bounds.Height <= 0 && e.Node.Bounds.X <= 0 && e.Node.Bounds.Y <= 0))
{
e.DrawDefault = true;
}
else
{
if (base.Nodes.IndexOf(e.Node) == 0)
{
this.blnHasVBar = this.IsVerticalScrollBarVisible();
}
Font font = e.Node.NodeFont;
if (font == null)
{
font = ((TreeView)sender).Font;
}
if (this.treeFontSize == SizeF.Empty)
{
this.treeFontSize = this.GetFontSize(font, e.Graphics);
}
bool flag = false;
int num = 0;
if (base.ImageList != null && base.ImageList.Images.Count > 0 && e.Node.ImageIndex >= 0 && e.Node.ImageIndex < base.ImageList.Images.Count)
{
flag = true;
num = (e.Bounds.Height - base.ImageList.ImageSize.Height) / 2;
}
if ((e.State == TreeNodeStates.Selected || e.State == TreeNodeStates.Focused || e.State == (TreeNodeStates.Focused | TreeNodeStates.Selected)) && (this._parentNodeCanSelect || e.Node.Nodes.Count <= 0))
{
e.Graphics.FillRectangle(new SolidBrush(this.m_nodeSelectedColor), new Rectangle(new Point(0, e.Node.Bounds.Y), new Size(base.Width, e.Node.Bounds.Height)));
e.Graphics.DrawString(e.Node.Text, font, new SolidBrush(this.m_nodeSelectedForeColor), (float)e.Bounds.X, (float)e.Bounds.Y + ((float)this._nodeHeight - this.treeFontSize.Height) / 2f);
}
else
{
e.Graphics.FillRectangle(new SolidBrush(this._nodeBackgroundColor), new Rectangle(new Point(0, e.Node.Bounds.Y), new Size(base.Width, e.Node.Bounds.Height)));
e.Graphics.DrawString(e.Node.Text, font, new SolidBrush(this._nodeForeColor), (float)e.Bounds.X, (float)e.Bounds.Y + ((float)this._nodeHeight - this.treeFontSize.Height) / 2f);
}
if (flag)
{
int num2 = e.Bounds.X - num - base.ImageList.ImageSize.Width;
if (num2 < 0)
{
num2 = 3;
}
e.Graphics.DrawImage(base.ImageList.Images[e.Node.ImageIndex], new Rectangle(new Point(num2, e.Bounds.Y + num), base.ImageList.ImageSize));
}
if (this._nodeIsShowSplitLine)
{
e.Graphics.DrawLine(new Pen(this._nodeSplitLineColor, 1f), new Point(0, e.Bounds.Y + this._nodeHeight - 1), new Point(base.Width, e.Bounds.Y + this._nodeHeight - 1));
}
bool flag2 = false;
if (e.Node.Nodes.Count > 0)
{
if (e.Node.IsExpanded && this._nodeUpPic != null)
{
e.Graphics.DrawImage(this._nodeUpPic, new Rectangle(base.Width - (this.blnHasVBar ? 50 : 30), e.Bounds.Y + (this._nodeHeight - 20) / 2, 20, 20));
}
else if (this._nodeDownPic != null)
{
e.Graphics.DrawImage(this._nodeDownPic, new Rectangle(base.Width - (this.blnHasVBar ? 50 : 30), e.Bounds.Y + (this._nodeHeight - 20) / 2, 20, 20));
}
flag2 = true;
}
if (this._isShowTip && this._lstTips.ContainsKey(e.Node.Name) && !string.IsNullOrWhiteSpace(this._lstTips[e.Node.Name]))
{
int num3 = base.Width - (this.blnHasVBar ? 50 : 30) - (flag2 ? 20 : 0);
int num4 = e.Bounds.Y + (this._nodeHeight - 20) / 2;
e.Graphics.DrawImage(this._tipImage, new Rectangle(num3, num4, 20, 20));
SizeF sizeF = e.Graphics.MeasureString(this._lstTips[e.Node.Name], this._tipFont, 100, StringFormat.GenericTypographic);
e.Graphics.DrawString(this._lstTips[e.Node.Name], this._tipFont, new SolidBrush(Color.White), (float)(num3 + 10) - sizeF.Width / 2f - 3f, (float)(num4 + 10) - sizeF.Height / 2f);
}
}
}
catch (Exception ex)
{
throw ex;
}
}
private SizeF GetFontSize(Font font, Graphics g = null)
{
SizeF result;
try
{
bool flag = false;
if (g == null)
{
g = base.CreateGraphics();
flag = true;
}
SizeF sizeF = g.MeasureString("a", font, 100, StringFormat.GenericTypographic);
if (flag)
{
g.Dispose();
}
result = sizeF;
}
catch (Exception ex)
{
throw ex;
}
return result;
}
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern int GetWindowLong(IntPtr hwnd, int nIndex);
private bool IsVerticalScrollBarVisible()
{
return base.IsHandleCreated && (TreeViewEx.GetWindowLong(base.Handle, -16) & 2097152) != 0;
}
我们还需要对选中节点时做一些处理
private void TreeViewEx_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
try
{
if (e.Node != null)
{
if (e.Node.Nodes.Count > 0)
{
if (e.Node.IsExpanded)
{
e.Node.Collapse();
}
else
{
e.Node.Expand();
}
}
if (base.SelectedNode != null)
{
if (base.SelectedNode == e.Node && e.Node.IsExpanded)
{
if (!this._parentNodeCanSelect)
{
if (e.Node.Nodes.Count > 0)
{
base.SelectedNode = e.Node.Nodes[0];
}
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
选中后也需要根据属性做相应的操作
private void TreeViewEx_AfterSelect(object sender, TreeViewEventArgs e)
{
try
{
if (e.Node != null)
{
if (!this._parentNodeCanSelect)
{
if (e.Node.Nodes.Count > 0)
{
e.Node.Expand();
base.SelectedNode = e.Node.Nodes[0];
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
主要的东西就这些了,我们看下完成的代码吧
// 版权所有 黄正辉 交流群:568015492 QQ:623128629
// 文件名称:TreeViewEx.cs
// 创建日期:2019-08-15 16:00:55
// 功能描述:TreeView
// 项目地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using HZH_Controls.Properties;
namespace HZH_Controls.Controls
{
public partial class TreeViewEx : TreeView
{
private const int WS_VSCROLL = 2097152;
private const int GWL_STYLE = -16;
private Dictionary<string, string> _lstTips = new Dictionary<string, string>();
private Font _tipFont = new Font("Arial Unicode MS", 12f);
private Image _tipImage = Resources.tips;
private bool _isShowTip = false;
private bool _isShowByCustomModel = true;
private int _nodeHeight = 50;
private Image _nodeDownPic = Resources.list_add;
private Image _nodeUpPic = Resources.list_subtract;
private Color _nodeBackgroundColor = Color.FromArgb(61, 60, 66);
private Color _nodeForeColor = Color.White;
private bool _nodeIsShowSplitLine = false;
private Color _nodeSplitLineColor = Color.FromArgb(54, 53, 58);
private Color m_nodeSelectedColor = Color.FromArgb(255, 121, 74);
private Color m_nodeSelectedForeColor = Color.White;
private bool _parentNodeCanSelect = true;
private SizeF treeFontSize = SizeF.Empty;
private bool blnHasVBar = false;
public Dictionary<string, string> LstTips
{
get
{
return this._lstTips;
}
set
{
this._lstTips = value;
}
}
[Category("自定义属性"), Description("角标文字字体")]
public Font TipFont
{
get
{
return this._tipFont;
}
set
{
this._tipFont = value;
}
}
[Category("自定义属性"), Description("是否显示角标")]
public Image TipImage
{
get
{
return this._tipImage;
}
set
{
this._tipImage = value;
}
}
[Category("自定义属性"), Description("是否显示角标")]
public bool IsShowTip
{
get
{
return this._isShowTip;
}
set
{
this._isShowTip = value;
}
}
[Category("自定义属性"), Description("使用自定义模式")]
public bool IsShowByCustomModel
{
get
{
return this._isShowByCustomModel;
}
set
{
this._isShowByCustomModel = value;
}
}
[Category("自定义属性"), Description("节点高度(IsShowByCustomModel=true时生效)")]
public int NodeHeight
{
get
{
return this._nodeHeight;
}
set
{
this._nodeHeight = value;
base.ItemHeight = value;
}
}
[Category("自定义属性"), Description("下翻图标(IsShowByCustomModel=true时生效)")]
public Image NodeDownPic
{
get
{
return this._nodeDownPic;
}
set
{
this._nodeDownPic = value;
}
}
[Category("自定义属性"), Description("上翻图标(IsShowByCustomModel=true时生效)")]
public Image NodeUpPic
{
get
{
return this._nodeUpPic;
}
set
{
this._nodeUpPic = value;
}
}
[Category("自定义属性"), Description("节点背景颜色(IsShowByCustomModel=true时生效)")]
public Color NodeBackgroundColor
{
get
{
return this._nodeBackgroundColor;
}
set
{
this._nodeBackgroundColor = value;
}
}
[Category("自定义属性"), Description("节点字体颜色(IsShowByCustomModel=true时生效)")]
public Color NodeForeColor
{
get
{
return this._nodeForeColor;
}
set
{
this._nodeForeColor = value;
}
}
[Category("自定义属性"), Description("节点是否显示分割线(IsShowByCustomModel=true时生效)")]
public bool NodeIsShowSplitLine
{
get
{
return this._nodeIsShowSplitLine;
}
set
{
this._nodeIsShowSplitLine = value;
}
}
[Category("自定义属性"), Description("节点分割线颜色(IsShowByCustomModel=true时生效)")]
public Color NodeSplitLineColor
{
get
{
return this._nodeSplitLineColor;
}
set
{
this._nodeSplitLineColor = value;
}
}
[Category("自定义属性"), Description("选中节点背景颜色(IsShowByCustomModel=true时生效)")]
public Color NodeSelectedColor
{
get
{
return this.m_nodeSelectedColor;
}
set
{
this.m_nodeSelectedColor = value;
}
}
[Category("自定义属性"), Description("选中节点字体颜色(IsShowByCustomModel=true时生效)")]
public Color NodeSelectedForeColor
{
get
{
return this.m_nodeSelectedForeColor;
}
set
{
this.m_nodeSelectedForeColor = value;
}
}
[Category("自定义属性"), Description("父节点是否可选中")]
public bool ParentNodeCanSelect
{
get
{
return this._parentNodeCanSelect;
}
set
{
this._parentNodeCanSelect = value;
}
}
public TreeViewEx()
{
base.HideSelection = false;
base.DrawMode = TreeViewDrawMode.OwnerDrawAll;
base.DrawNode += new DrawTreeNodeEventHandler(this.treeview_DrawNode);
base.NodeMouseClick += new TreeNodeMouseClickEventHandler(this.TreeViewEx_NodeMouseClick);
base.SizeChanged += new EventHandler(this.TreeViewEx_SizeChanged);
base.AfterSelect += new TreeViewEventHandler(this.TreeViewEx_AfterSelect);
base.FullRowSelect = true;
base.ShowLines = false;
base.ShowPlusMinus = false;
base.ShowRootLines = false;
this.BackColor = Color.FromArgb(61, 60, 66);
DoubleBuffered = true;
}
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0014) // 禁掉清除背景消息WM_ERASEBKGND
return;
base.WndProc(ref m);
}
private void TreeViewEx_AfterSelect(object sender, TreeViewEventArgs e)
{
try
{
if (e.Node != null)
{
if (!this._parentNodeCanSelect)
{
if (e.Node.Nodes.Count > 0)
{
e.Node.Expand();
base.SelectedNode = e.Node.Nodes[0];
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
private void TreeViewEx_SizeChanged(object sender, EventArgs e)
{
this.Refresh();
}
private void TreeViewEx_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
try
{
if (e.Node != null)
{
if (e.Node.Nodes.Count > 0)
{
if (e.Node.IsExpanded)
{
e.Node.Collapse();
}
else
{
e.Node.Expand();
}
}
if (base.SelectedNode != null)
{
if (base.SelectedNode == e.Node && e.Node.IsExpanded)
{
if (!this._parentNodeCanSelect)
{
if (e.Node.Nodes.Count > 0)
{
base.SelectedNode = e.Node.Nodes[0];
}
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
private void treeview_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
try
{
if (e.Node == null || !this._isShowByCustomModel || (e.Node.Bounds.Width <= 0 && e.Node.Bounds.Height <= 0 && e.Node.Bounds.X <= 0 && e.Node.Bounds.Y <= 0))
{
e.DrawDefault = true;
}
else
{
if (base.Nodes.IndexOf(e.Node) == 0)
{
this.blnHasVBar = this.IsVerticalScrollBarVisible();
}
Font font = e.Node.NodeFont;
if (font == null)
{
font = ((TreeView)sender).Font;
}
if (this.treeFontSize == SizeF.Empty)
{
this.treeFontSize = this.GetFontSize(font, e.Graphics);
}
bool flag = false;
int num = 0;
if (base.ImageList != null && base.ImageList.Images.Count > 0 && e.Node.ImageIndex >= 0 && e.Node.ImageIndex < base.ImageList.Images.Count)
{
flag = true;
num = (e.Bounds.Height - base.ImageList.ImageSize.Height) / 2;
}
if ((e.State == TreeNodeStates.Selected || e.State == TreeNodeStates.Focused || e.State == (TreeNodeStates.Focused | TreeNodeStates.Selected)) && (this._parentNodeCanSelect || e.Node.Nodes.Count <= 0))
{
e.Graphics.FillRectangle(new SolidBrush(this.m_nodeSelectedColor), new Rectangle(new Point(0, e.Node.Bounds.Y), new Size(base.Width, e.Node.Bounds.Height)));
e.Graphics.DrawString(e.Node.Text, font, new SolidBrush(this.m_nodeSelectedForeColor), (float)e.Bounds.X, (float)e.Bounds.Y + ((float)this._nodeHeight - this.treeFontSize.Height) / 2f);
}
else
{
e.Graphics.FillRectangle(new SolidBrush(this._nodeBackgroundColor), new Rectangle(new Point(0, e.Node.Bounds.Y), new Size(base.Width, e.Node.Bounds.Height)));
e.Graphics.DrawString(e.Node.Text, font, new SolidBrush(this._nodeForeColor), (float)e.Bounds.X, (float)e.Bounds.Y + ((float)this._nodeHeight - this.treeFontSize.Height) / 2f);
}
if (flag)
{
int num2 = e.Bounds.X - num - base.ImageList.ImageSize.Width;
if (num2 < 0)
{
num2 = 3;
}
e.Graphics.DrawImage(base.ImageList.Images[e.Node.ImageIndex], new Rectangle(new Point(num2, e.Bounds.Y + num), base.ImageList.ImageSize));
}
if (this._nodeIsShowSplitLine)
{
e.Graphics.DrawLine(new Pen(this._nodeSplitLineColor, 1f), new Point(0, e.Bounds.Y + this._nodeHeight - 1), new Point(base.Width, e.Bounds.Y + this._nodeHeight - 1));
}
bool flag2 = false;
if (e.Node.Nodes.Count > 0)
{
if (e.Node.IsExpanded && this._nodeUpPic != null)
{
e.Graphics.DrawImage(this._nodeUpPic, new Rectangle(base.Width - (this.blnHasVBar ? 50 : 30), e.Bounds.Y + (this._nodeHeight - 20) / 2, 20, 20));
}
else if (this._nodeDownPic != null)
{
e.Graphics.DrawImage(this._nodeDownPic, new Rectangle(base.Width - (this.blnHasVBar ? 50 : 30), e.Bounds.Y + (this._nodeHeight - 20) / 2, 20, 20));
}
flag2 = true;
}
if (this._isShowTip && this._lstTips.ContainsKey(e.Node.Name) && !string.IsNullOrWhiteSpace(this._lstTips[e.Node.Name]))
{
int num3 = base.Width - (this.blnHasVBar ? 50 : 30) - (flag2 ? 20 : 0);
int num4 = e.Bounds.Y + (this._nodeHeight - 20) / 2;
e.Graphics.DrawImage(this._tipImage, new Rectangle(num3, num4, 20, 20));
SizeF sizeF = e.Graphics.MeasureString(this._lstTips[e.Node.Name], this._tipFont, 100, StringFormat.GenericTypographic);
e.Graphics.DrawString(this._lstTips[e.Node.Name], this._tipFont, new SolidBrush(Color.White), (float)(num3 + 10) - sizeF.Width / 2f - 3f, (float)(num4 + 10) - sizeF.Height / 2f);
}
}
}
catch (Exception ex)
{
throw ex;
}
}
private SizeF GetFontSize(Font font, Graphics g = null)
{
SizeF result;
try
{
bool flag = false;
if (g == null)
{
g = base.CreateGraphics();
flag = true;
}
SizeF sizeF = g.MeasureString("a", font, 100, StringFormat.GenericTypographic);
if (flag)
{
g.Dispose();
}
result = sizeF;
}
catch (Exception ex)
{
throw ex;
}
return result;
}
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern int GetWindowLong(IntPtr hwnd, int nIndex);
private bool IsVerticalScrollBarVisible()
{
return base.IsHandleCreated && (TreeViewEx.GetWindowLong(base.Handle, -16) & 2097152) != 0;
}
}
}
用处及效果
用处:觉得原始的treeview太难看了,想换一种好看点的风格
效果:
调用示例
for (int i = 0; i < 3; i++)
{
TreeNode tn = new TreeNode(" 父节点" + i);
for (int j = 0; j < 3; j++)
{
tn.Nodes.Add(" 子节点" + j);
}
this.treeViewEx1.Nodes.Add(tn);
}
最后的话
如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星星吧,另本站转载地址:https://dotnet9.com/5316.html。
作者:冰封一夏 出处:http://www.hzhcontrols.com/doc.html 本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明, 且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
评论
轻松学习C#:百度行驶证C++离线SDK接入详解
效果 先看最终效果SDK 拿到完整包如图,687M解压后看看内容发现有个readme.txt,那就先看看内容1:用vs2015打开sln工程,最好用vs2015 comunity版本,可微软官网下载。2:sdk的doc目录有pdf接口文档。3:工程总入口main.cpp、请参考示例实现您的功能。4:
DotNet NB
9
C#中using的使用的几种场景
using在C#中随处可见,比如引入命名空间,这是也是每个C#的cs页面必须存在的,除了引入命名空间还有几种用法,下面将介绍这几种的使用。1、用于引入命名空间 这是最常见最基本的用法, 这样可以在程序中直
dotNET全栈开发
10
C# 优雅的处理 TCP 数据
前言Tcp是一个面向连接的流数据传输协议,用人话说就是传输是一个已经建立好连接的管道,数据都在管道里像流水一样流淌到对端。那么数据必然存在几个问题,比如数据如何持续的读取,数据包的边界等。Nagle's算法Nagle 算法的核心思想是,在一个 TCP 连接上,最多只能有一个未被确认的小数据包(小于
dotNET全栈开发
10
视九科技确认出席「长江论道」,引领大屏智能技术革新
5月23-24日,长江论道诚邀您的参与主办单位流媒体网协办单位湖北长江云新媒体集团举办时间2024年5月23-24日举办地点武汉富力威斯汀酒店视九科技公司介绍LUNDAO上海视九信息科技有限公司是一家聚焦大屏领域核心技术深层研发的企业,也是论道重要的合作伙伴。此次「长江论道」,视九科技将进行主题演讲
流媒体网
0
mica-mqtt 2.2.12 发布,简化 MqttClientTemplate 构造,方便自定义
一、简介mica-mqtt 基于 java aio 实现的简单、低延迟、高性能 的 mqtt 物联网开源组件。mica-mqtt 更加易于集成到已有服务和二次开发,降低自研物联网平台开发成本。二、功能支持 MQTT v3.1、v3.1.1 以及 v5.0 协议。支持 websocket mqtt 子
JAVA架构日记
0
C#中HttpClient的演进与避坑指南
引子 在互联网时代,与网络通信相关的功能已成为不可或缺的一部分。C# 中的 HttpClient 类是一个强大的工具,用于执行 HTTP 请求和处理响应。虽然HttpClient 类简单易用,但在实际应用中,仍然存在一些需要注意...
llovebo
0
你的SaaS生意,是“摇钱树”模式、还是“卖树”模式?
如果单从损益表上看,SaaS公司都显得有些“吃亏”。因为按照通常的会计规则,很多SaaS企业在损益表上都表现为“亏损”。而实际上这些SaaS公司,不但不是烂公司,可能还是个好公司,甚至可能还是一门“摇钱树”式的好生意。...
ToBeSaaS
0
并行化优化KD树算法:使用C#实现高效的最近邻搜索
本文信息 中文名:《并行化优化KD树算法:使用C#实现高效的最近邻搜索》 英文名:"Parallelized Optimization of KD-Tree Algorithm: Implementing Efficient Nearest Neighbor Search in C#" 摘要 本文介绍了如何使...
程序设计实验室
0