[WTL/Win32]_[初级]_[如何设置ListView的列宽不出现水平滚动条]

场景

  1. 开发WTL/Win32的程序时,经常会用到表格控件CListViewCtrl。这个控件需要设置列的宽度,当用完100%的宽度来平均分配给列宽时,一加载数据多,就会出现垂直滚动条后,水平滚动条也会同时出现的问题。怎么设置才能让水平滚动条不出现?

图1
在这里插入图片描述

说明

  1. WTL的控件CListViewCtrl实际上就是Win32listview控件的封装。当行个数超过它的可见区域时,就会默认出现垂直滚动条。这个垂直滚动条也是占用了原本ListView的客户端区域,导致ListView的客户端区域宽度减少,也就是现在的客户端宽度 = 原来的客户端区域宽度-滑块的宽度

  2. 当然也可以在行数据超过可见区域时重新计算列宽度,只是这种做法需要在合适的时候进行判断行数据是否够多导致垂直滚动条出现。一般不建议做这个冗余的判断处理。

  3. 目前推荐的做法是布局ListView时,也就是设置它的列宽时,如果没有出现垂直滚动条,那么预留滚动条的宽度不分配给列宽。 以下是获取滑块宽度的做法:

  4. 关于WTL/Win32开发请参考我的课程 使用WTL进行Windows桌面应用开发

void CView::layoutListView()
{
	CRect rect;
	listview_.GetClientRect(&rect);
	auto width = rect.Width();
	listview_.SetColumnWidth(0, width*0.2);
	listview_.SetColumnWidth(1, width*0.3);
	listview_.SetColumnWidth(2, width*0.2);

	auto last = width * 0.3;

	if (buttonIsLayoutWithThumb_.GetCheck()) {
		auto thumbWidth = GetWindowVScrollBarThumbWidth(listview_, false);
		// 如果默认没有滚动条,减去滑块宽度。
		if (!thumbWidth) { 
			thumbWidth = GetWindowVScrollBarThumbWidth(listview_, true);
			last = last - thumbWidth;
		}
	}
	
	listview_.SetColumnWidth(3, last);
}

例子

View.h

// View.h : interface of the CView class
//
/

#pragma once

#include <utility>
#include <string>
#include <vector>
#include <memory>
#include <atlmisc.h>
#include <atlctrls.h>
#include <atlctrlx.h>
#include <GdiPlus.h>

using namespace std;

enum
{
	kMyButtonId = WM_USER+1,
	kMyButtonId2,
	kMyButtonId3,
	kMyButtonId4,
	kMyListViewId
};

class Photo
{
public:
	wstring name;
	wstring createDate;
	wstring path;
	wstring format;
};

class CView : public CWindowImpl<CView>
{
public:
	DECLARE_WND_CLASS(NULL)

	BOOL PreTranslateMessage(MSG* pMsg);

	BEGIN_MSG_MAP_EX(CView)
		MSG_WM_CREATE(OnCreate)
		MSG_WM_SIZE(OnSize)
		MESSAGE_HANDLER(WM_PAINT, OnPaint)
		NOTIFY_HANDLER(kMyListViewId,NM_CLICK,OnNMClickListResult)
		NOTIFY_HANDLER(kMyListViewId,LVN_GETDISPINFO,OnGetListViewData)
		NOTIFY_HANDLER(kMyListViewId,LVN_ODCACHEHINT,OnPrepareListViewData)
		NOTIFY_HANDLER(kMyListViewId,LVN_ODFINDITEM,OnFindListViewData)
		COMMAND_RANGE_HANDLER_EX(kMyButtonId,kMyButtonId4,OnCommandIDHandlerEX)
		REFLECT_NOTIFICATIONS()
	END_MSG_MAP()

protected:
// Handler prototypes (uncomment arguments if needed):
//	LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
//	LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
//	LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
	int OnCreate(LPCREATESTRUCT lpCreateStruct);
	LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
	void UpdateLayout();
	LRESULT OnNMClickListResult(int idCtrl,LPNMHDR pnmh,BOOL &bHandled);
	LRESULT OnGetListViewData(int idCtrl,LPNMHDR pnmh,BOOL &bHandled);
	LRESULT OnPrepareListViewData(int idCtrl,LPNMHDR pnmh,BOOL &bHandled);
	LRESULT OnFindListViewData(int idCtrl,LPNMHDR pnmh,BOOL &bHandled);
	void OnCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl);
	void OnSize(UINT nType, CSize size);
	void ReloadMockData(int count);
	void ReloadListView();

protected:
	void layoutListView();
	static int GetWindowVScrollBarThumbWidth(HWND hwnd, bool bAutoShow);

private:
	std::wstring GetControlText(HWND hwnd,wchar_t* buf = NULL);
	CListViewCtrl listview_;
	vector<shared_ptr<Photo>> photos_;

	CFont font_normal_;
	CFont font_bold_;

	CBrushHandle brush_white_;
	CBrushHandle brush_hollow_;
	CBrush brush_red_;

	CButton buttonIsLayoutWithThumb_;

	CButton buttonReloadMockData_;
	CButton buttonReloadMockData10_;
	CButton buttonReloadListView_;
};

View.cpp

// View.cpp : implementation of the CView class
//
/

#include "stdafx.h"
#include "resource.h"
#include <utility>
#include <sstream>
#include <stdint.h>
#include <assert.h>
#include <Strsafe.h>

#include "View.h"
#include <CommCtrl.h>
#include <string>
#include <regex>

using namespace std;

BOOL CView::PreTranslateMessage(MSG* pMsg)
{
	return FALSE;
}

LRESULT CView::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
	CPaintDC dc(m_hWnd);
	CMemoryDC mdc(dc,dc.m_ps.rcPaint);

	CRect rect_client;
	GetClientRect(&rect_client);
	mdc.FillSolidRect(rect_client,RGB(255,255,255));
	//TODO: Add your drawing code here

	return 0;
}

static HFONT GetFont(int pixel,bool bold,const wchar_t* font_name)
{
	LOGFONT lf; 
	memset(&lf, 0, sizeof(LOGFONT)); // zero out structure 
	lf.lfHeight = pixel; // request a 8-pixel-height font
	if(bold)
	{
		lf.lfWeight = FW_BOLD;  
	}
	lstrcpy(lf.lfFaceName, font_name); // request a face name "Arial"
	
	HFONT font = ::CreateFontIndirect(&lf);
	return font;
}


std::wstring CView::GetControlText(HWND hwnd,wchar_t* buf)
{
	auto length = ::GetWindowTextLength(hwnd);
	bool bufNull = false;
	if(!buf){
		buf = new wchar_t[length+1]();
		bufNull = true;
	}
	
	::GetWindowText(hwnd,buf,length+1);
	std::wstring str(buf);

	if(bufNull)
		delete []buf;

	return str;
}

static std::wstring GetProductBinDir()
{
	static wchar_t szbuf[MAX_PATH];  
	GetModuleFileName(NULL,szbuf,MAX_PATH);  
    PathRemoveFileSpec(szbuf);
	int length = lstrlen(szbuf);
	szbuf[length] = L'\\';
	szbuf[length+1] = 0;
	return std::wstring(szbuf);
}

LRESULT CView::OnGetListViewData(int idCtrl,LPNMHDR pnmh,BOOL &bHandled)
{
	NMLVDISPINFO* plvdi = (NMLVDISPINFO*) pnmh;
	auto iItem = plvdi->item.iItem;
	if (-1 == iItem)
		return 0;
	
	auto count = photos_.size();
	if(!count || count <= iItem)
		return 0;

	auto photo = photos_[iItem];
	if(plvdi->item.mask & LVIF_TEXT){
		switch(plvdi->item.iSubItem)
		{
		case 0:
			StringCchCopy(plvdi->item.pszText, plvdi->item.cchTextMax, to_wstring((int64_t)iItem+1).c_str());
			break;
		case 1:
			StringCchCopy(plvdi->item.pszText, plvdi->item.cchTextMax, photo->name.c_str());
			break;
		case 2:
			StringCchCopy(plvdi->item.pszText, plvdi->item.cchTextMax, photo->format.c_str());
			break;
		case 3:
			StringCchCopy(plvdi->item.pszText, plvdi->item.cchTextMax, photo->createDate.c_str());
			break;
		}
	}
	
	return 0;
}

LRESULT CView::OnPrepareListViewData(int idCtrl,LPNMHDR pnmh,BOOL &bHandled)
{
	return 0;
}

LRESULT CView::OnFindListViewData(int idCtrl,LPNMHDR pnmh,BOOL &bHandled)
{
    LPNMLVFINDITEM  pnmfi = (LPNMLVFINDITEM)pnmh;

	auto iItem = pnmfi->iStart;
	if (-1 == iItem)
		return -1;
	
	auto count = photos_.size();
	if(!count || count <= iItem)
		return -1;
	
	return 0;
}

LRESULT CView::OnNMClickListResult(int idCtrl,LPNMHDR pnmh,BOOL &bHandled)
{
	return 0;
}

void CView::OnCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
{
	switch(nID)
	{
		case kMyButtonId3:
		{
			buttonIsLayoutWithThumb_.SetCheck(!buttonIsLayoutWithThumb_.GetCheck());
			ReloadListView();
			layoutListView();

			break;
		}
		case kMyButtonId:
		{
			ReloadMockData(10000);
			break;
		}
		case kMyButtonId4:
		{
			ReloadMockData(10);
			break;
		}
		case kMyButtonId2:
		{
			ReloadListView();
			break;
		}
	}
}

void CView::ReloadListView()
{
	listview_.SetItemCount(0);
	photos_.clear();
}

void CView::ReloadMockData(int count)
{
	wchar_t buf[MAX_PATH] = {0};
	LVCOLUMN co;
	memset(&co,0,sizeof(co));
	co.mask = LVCF_TEXT;
	co.pszText = buf;
	co.cchTextMax = MAX_PATH;
	listview_.GetColumn(1,&co);
	std::wstring c0Text(buf);

	listview_.GetColumn(2,&co);
	std::wstring c1Text(buf);
	
	listview_.GetColumn(3,&co);
	std::wstring c2Text(buf);

	static int index = 0;
	for(int i = 0; i< count;++i,++index){
		auto photo = new Photo();
		wsprintf(buf,(c0Text+L"-%d").c_str(),index);
		photo->name = buf;

		wsprintf(buf,(c1Text+L"-%d").c_str(),index);
		photo->format = buf;

		wsprintf(buf,(c2Text+L"-%d").c_str(),index);
		photo->createDate = buf;

		photos_.push_back(move(shared_ptr<Photo>(photo)));
	}
	listview_.SetItemCount(photos_.size());
}

int CView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	font_normal_ = ::GetFont(16,false,L"Arial");
	font_bold_ = ::GetFont(16,true,L"Arial");
	
	brush_hollow_ = AtlGetStockBrush(HOLLOW_BRUSH);
	brush_white_ = AtlGetStockBrush(WHITE_BRUSH);
	brush_red_.CreateSolidBrush(RGB(255,0,0));

	// 1.创建CListViewCtrl
	listview_.Create(m_hWnd,0,NULL,WS_CHILD | WS_TABSTOP |WS_VISIBLE
		|LVS_ALIGNLEFT|LVS_REPORT|LVS_SHOWSELALWAYS|WS_BORDER|LVS_OWNERDATA,0,kMyListViewId);
	listview_.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_DOUBLEBUFFER);
	listview_.SetFont(font_normal_);
	auto header = listview_.GetHeader();
	header.SetFont(font_bold_);
	listview_.SetBkColor(RGB(255,255,255));

	listview_.InsertColumn(0,L"No.",LVCFMT_LEFT,0);
	listview_.InsertColumn(1,L"Name",LVCFMT_LEFT,0);
	listview_.InsertColumn(2,L"Format",LVCFMT_LEFT,0);
	listview_.InsertColumn(3,L"Create Date",LVCFMT_LEFT,0);

	// 2.创建按钮
	buttonIsLayoutWithThumb_.Create(m_hWnd, 0, L"布局列宽是否计算滑块宽度", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, 0, kMyButtonId3);
	buttonIsLayoutWithThumb_.SetFont(font_normal_);

	buttonReloadMockData_.Create(m_hWnd,0,L"加载新数据10000条",WS_CHILD|WS_VISIBLE,0,kMyButtonId);
	buttonReloadMockData_.SetFont(font_normal_);

	buttonReloadMockData10_.Create(m_hWnd, 0, L"加载新数据10条", WS_CHILD | WS_VISIBLE, 0, kMyButtonId4);
	buttonReloadMockData10_.SetFont(font_normal_);

	buttonReloadListView_.Create(m_hWnd,0,L"清空表格",WS_CHILD|WS_VISIBLE,0,kMyButtonId2);
	buttonReloadListView_.SetFont(font_normal_);
	
	return 0;
}

int CView::GetWindowVScrollBarThumbWidth(HWND hwnd, bool bAutoShow)
{
	SCROLLBARINFO sb = { 0 };
	sb.cbSize = sizeof(SCROLLBARINFO);
	GetScrollBarInfo(hwnd, OBJID_VSCROLL, &sb);

	if (!bAutoShow)
		return sb.dxyLineButton;

	if (sb.dxyLineButton)
		return sb.dxyLineButton;

	::ShowScrollBar(hwnd, SB_VERT, TRUE);
	sb.cbSize = sizeof(SCROLLBARINFO);
	GetScrollBarInfo(hwnd, OBJID_VSCROLL, &sb);
	::ShowScrollBar(hwnd, SB_VERT, FALSE);
	return sb.dxyLineButton;
}

void CView::layoutListView()
{
	CRect rect;
	listview_.GetClientRect(&rect);
	auto width = rect.Width();
	listview_.SetColumnWidth(0, width*0.2);
	listview_.SetColumnWidth(1, width*0.3);
	listview_.SetColumnWidth(2, width*0.2);

	auto last = width * 0.3;

	if (buttonIsLayoutWithThumb_.GetCheck()) {
		auto thumbWidth = GetWindowVScrollBarThumbWidth(listview_, false);
		if (!thumbWidth) {
			// 如果默认没有滚动条
			thumbWidth = GetWindowVScrollBarThumbWidth(listview_, true);
			last = last - thumbWidth;
		}
	}
	
	listview_.SetColumnWidth(3, last);
}

void CView::OnSize(UINT nType, CSize size)
{
	if (!size.cx)
		return;

	UpdateLayout();
}

void CView::UpdateLayout()
{
	CRect rect;
	GetClientRect(&rect);

	CClientDC dc(m_hWnd);
	dc.SelectFont(font_normal_);

	CSize sizeCheck;
	buttonIsLayoutWithThumb_.GetIdealSize(&sizeCheck);
	buttonIsLayoutWithThumb_.MoveWindow(CRect(20,2, sizeCheck.cx+20, sizeCheck.cy+2));

	CSize size_control(rect.Width() - 50,300);
	CRect rect_control = CRect(CPoint(20,20),size_control);
	listview_.MoveWindow(rect_control);
	layoutListView();

	CSize size_button;
	buttonReloadMockData_.GetIdealSize(&size_button);
	rect_control = CRect(CPoint(rect_control.left,rect_control.bottom+10),size_button);
	buttonReloadMockData_.MoveWindow(rect_control);

	CSize size_button4;
	buttonReloadMockData10_.GetIdealSize(&size_button4);
	rect_control = CRect(CPoint(rect_control.right+10, rect_control.top), size_button);
	buttonReloadMockData10_.MoveWindow(rect_control);

	CSize sizeButton2;
	buttonReloadListView_.GetIdealSize(&sizeButton2);
	rect_control = CRect(CPoint(rect_control.right+10,rect_control.top),sizeButton2);
	buttonReloadListView_.MoveWindow(rect_control);

}

图2
在这里插入图片描述
图3
在这里插入图片描述

项目下载地址

https://download.csdn.net/download/infoworld/89036594

参考

  1. GetScrollBarInfo 函数 (winuser.h) - Win32 apps | Microsoft Learn

  2. SCROLLBARINFO (winuser.h) - Win32 apps | Microsoft Learn

  3. ShowScrollBar 函数 (winuser.h) - Win32 apps | Microsoft Learn

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

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

相关文章

Redis如何应对缓存穿透问题——Java全栈知识(9)

我们在正常使用缓存的时候的流程大概就是这样的&#xff1a; 请求访问缓存&#xff0c;缓存有数据就返回&#xff0c;缓存无数据就去数据库里面查数据写入到缓存中。 1、缓存穿透问题 但是如果由恶意请求&#xff0c;短时间内大量的访问不存在的数据&#xff0c;这时每个请求…

Matlab之求直角坐标系下两直线的交点坐标

目的&#xff1a;在直角坐标系下&#xff0c;求两个直线的交点坐标 一、函数的参数说明 输入参数&#xff1a; PointA&#xff1a;直线A上的点坐标&#xff1b; AngleA&#xff1a;直线A的倾斜角&#xff0c;单位度&#xff1b; PointB&#xff1a;直线B上的点坐标&#xf…

5个免费的3D钣金CAD软件

如果你正在设计简单的折叠钣金零件&#xff0c;则只需设计一些具有圆角半径的法兰&#xff1a;一个简单的钣金模块。 首先&#xff0c;你可以采用老式方式绘图并以 2D 方式完成所有操作。 许多传统制造商仍在使用 2D DWG 和 DXF 图纸。 因此&#xff0c;你很有可能只需快速起草…

视频声音生成字幕 pr生成视频字幕 以及字幕乱码的解决

目录 目录 1、首先把要生成字幕的视频拖入以创建序列 2、点击工具栏的 窗口 选择 文本 3、选择字幕下的 转录序列 4、选择输出的语言&#xff08;主要看视频声音说的是啥语言&#xff09; 5、音轨 选择 音频1​编辑 6、点击转录 7、等待转录文本 8、点击创建说明性字幕按…

【C语言】C语言运算符优先级详解

文章目录 &#x1f4dd;前言&#x1f309;运算符优先级简述 &#x1f320;逻辑与和逻辑或&#x1f309;赋值和逗号运算符 &#x1f320;位运算&#x1f309;条件表达式&#x1f309;位运算与算术运算结合&#x1f309;混合使用条件表达式和赋值运算符&#x1f309; 逗号运算符的…

数据结构——队列(C语言版)

前言&#xff1a; 在学习完数据结构顺序表和链表之后&#xff0c;其实我们就可以做很多事情了&#xff0c;后面的栈和队列&#xff0c;其实就是对前面的顺序表和链表的灵活运用&#xff0c;今天我们就来学习一下队列的原理和应用。 准备工作&#xff1a;本人习惯将文件放在test…

MATLAB 自定义生成直线点云(详细介绍) (47)

MATLAB 自定义生成直线点云 (详细介绍)(47) 一、算法介绍二、具体步骤二、算法实现1.代码2.效果一、算法介绍 通过这里的直线生成方法,可以生成模拟直线的点云数据,并通过调整起点、终点、数量和噪声水平等参数来探索不同类型的直线数据。这种方法可以用于测试、验证和开…

两区域二次调频风火机组,麻雀启发式算法改进simulink与matlab联合

区域1结果 区域2结果 红色曲线为优化后结果〔风火机组二次调频〕

搭建 Apple Mac M1 stm32 开发环境

近期想学习 stm32 开发,看了些书和视频,买了开发板。开发板到了后就迫不及待的的进行尝试。由于我目前使用的电脑是 Apple M1 Pro,目前用的比较多的是 windows + keil。我先是在 mac 使用虚拟机,安装 win 环境来使用,但是我分别使用了 VMware 和 parallels desktop ,keil…

知行之桥EDI系统功能介绍——系统安全性

在知行之桥EDI系统中&#xff0c;系统安全性问题主要分为两大类&#xff1a; 保证知行之桥EDI系统运行的基础通过知行之桥EDI系统保护数据 保证知行之桥EDI系统运行的基础 许多安全设置由服务器配置文件管理。使用知行之桥中包含的嵌入式 Web 服务器时&#xff0c;可以在以下…

unity中手势识别开源代码——HandPoseBarracuda

HandPoseBarracuda是一个使用单目彩色摄像头工作的神经网络手/手指追踪器的概念验证实现。 基本上,HandPoseBarracuda是MediaPipe Hands管道的一个部分端口。尽管它并不是原始包的直接端口,但它使用了相同的基本设计和相同的预训练模型。 请注意,这只是一个概念验证实现。…

IDEA编辑国际化.properties文件没有Resource Bundle怎么办?

问题描述 最近在做SpringBoot国际化&#xff0c;IDEA添加了messages.properties、messages_en_US.properties、messages_zh_CN.properties国际化文件后&#xff0c;在编辑页面底部没有Resource Bundle&#xff0c;这使得我在写keyvalue的时候在每个properties文件都要拷贝一次…

Python 全栈体系【四阶】(二十)

第五章 深度学习 二、推荐系统 1. 推荐算法介绍 1.1 个性化推荐算法 人口属性 地理属性 资产属性 兴趣属性 1.2 推荐算法分支 协同过滤推荐算法基于内容的推荐算法混合推荐算法流行度推荐算法 1.3 推荐算法 为推荐系统选择正确的推荐算法是非常重要的决定。目前为止…

困难重重!如何将超导量子计算机完好无损地搬进数据中心

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨慕一 编译/排版丨浪味仙 沛贤 深度好文&#xff1a;3700字丨18分钟阅读 如何把超导量子计算机部署到数据中心&#xff1f;数据中心运营商和量子公司面临着以前没有见过的重重难关。 首…

白帽子讲Wbe安全

在安全圈子里&#xff0c;素有“白帽”、“黑帽”一说。 黑帽子是指那些造成破坏的黑客&#xff0c;而白帽子则是研究安全&#xff0c;但不造成破坏的黑客。白帽子均以建设更安全的互联网为已任。 Web 是互联网的核心&#xff0c;是未来云计算和移动互联网的最佳载体&#xff0…

漏洞扫描-让安全弱点无所遁形

随着信息技术的迅猛发展和互联网的广泛普及&#xff0c;网络安全问题日益凸显。在这个数字化的世界里&#xff0c;无论是企业还是个人&#xff0c;都面临着前所未有的安全威胁。安全漏洞&#xff0c;作为这些威胁的源头&#xff0c;常常被忽视或无法及时发现。 而漏洞扫描&…

牛客NC27 集合的所有子集(一)【中等 DFS Java,Go,PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/c333d551eb6243e0b4d92e37a06fbfc9 思路 递归实现&#xff1a;先升序排序&#xff1b;然后每个位置i为起点&#xff0c;i到最后的数&#xff0c;要么被选择&#xff0c;要么被放弃 递归实现&#xff1b;注意结果…

【MATLAB源码-第15期】基于matlab的MSK的理论误码率与实际误码率BER对比仿真,采用差分编码和IQ调制解调。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 在数字调制中&#xff0c;最小频移键控&#xff08;Minimum-Shift Keying&#xff0c;缩写&#xff1a;MSK&#xff09;是一种连续相位调制的频移键控方式&#xff0c;在1950年代末和1960年代产生。[1] 与偏移四相相移键控&a…

ppp验证实验

实际操作图 1&#xff0c;IP划分分配 [r1]interface Serial 4/0/0 [r1-Serial4/0/0]ip add 192.168.1.1 24 [r2]interface Serial 4/0/0 [r2-Serial4/0/0]ip address 192.168.1.2 24 [r2]int Mp-group 0/0/0 [r2-Mp-group0/0/0]ip add 192.168.2.1 24 [r3]int Mp-group 0/…

RelayAttention:让大型语言模型更高效地处理长提示符

一、前言 虽然大型语言模型 (LLM) 近年来取得了非常显著的进展&#xff0c;也在各种自然语言处理任务中展现出强大的能力。然而&#xff0c;LLM 的在实际的应用落地层面也面临着一些实际挑战&#xff0c;其中之一就是效率和成本问题&#xff0c;导致了在垂直行业实际落地的应用…