提高控制框速度(C++-CLI WinForms) 我在C++中做了一个控制,允许用户在不同位置的不规则框中选择一个位置,其中一些被阻塞,其中一些填充,具有以下特点:
可以在不相同的多行中创建多个列,因此第一行可以有3列,第二行可以有1列,第三行可以有5列 每个位置具有不同的状态:已阻止、已填充、已空、已选择,因此可以同时具有其中一些状态:已阻止和已空、已阻止和已填充、已空和已选择 用户可以选择一个或多个位置 它有工具提示文本和每个填充或空白位置的不同背景图像 用于添加/删除行/列的上下文菜单 行和列标题,数字/字母数字,升序/降序 控件的结构是Container->nRows x RowClass和RowClass->nCols x ColumnClass。每列都包含一个TableLayoutPanel,因此我可以模拟卡住和凸起的效果 在网上查看不同的主题,我发现一些想法和我为速度所做的改进基本上是使用SendMessage进行SuspendDrawing,在绘制行和列之前创建并调整所有行和列的大小,双缓冲每个控件,并向容器添加BeginEdit/EndEdit方法,该容器在创建行和列以及每个RowClass时暂停绘图并阻止行和列的大小调整 对于相对较小的框,比如说20行x20列,它的效果并不差,但是当它有40行x30列1.200 TableLayoutPanel时,即使是在速度较快的计算机中,它的速度也会非常慢 我还尝试使用一个TableLayoutPanel,每个RowClass需要多少列,但问题是如何绘制边框,以便分别选择每个列、每个单元格的工具提示和背景图像 所以,问题是:我可以尝试改进吗 我一直在想,像魔兽或类似的战略游戏,它们在屏幕上有很好的速度,有成千上万的图形和计算,但我不是一个专业的程序员,所以我不知道这可能是技术,如果它是正确的方式 也许它可能是一个有一行图像的图像,或者与一类或一类不同的图像,但我不知道 可能这是一个设计问题,所以,关于如何使用这些规范创建快速控件的任何想法都将是非常好的 无论如何,谢谢你阅读我的问题,任何评论都会很好!提高控制框速度(C++-CLI WinForms) 我在C++中做了一个控制,允许用户在不同位置的不规则框中选择一个位置,其中一些被阻塞,其中一些填充,具有以下特点:,c++-cli,performance,tablelayoutpanel,C++ Cli,Performance,Tablelayoutpanel,可以在不相同的多行中创建多个列,因此第一行可以有3列,第二行可以有1列,第三行可以有5列 每个位置具有不同的状态:已阻止、已填充、已空、已选择,因此可以同时具有其中一些状态:已阻止和已空、已阻止和已填充、已空和已选择 用户可以选择一个或多个位置 它有工具提示文本和每个填充或空白位置的不同背景图像 用于添加/删除行/列的上下文菜单 行和列标题,数字/字母数字,升序/降序 控件的结构是Container->nRows x RowClass和RowClass->nCols x ColumnClass。
Miguel视频游戏至少在GPU上卸载了图形表示,而GPU正是为此而构建的。我不认为方框的表示是瓶颈,而是达到瓶颈的计算/步骤。 发布你的代码/代码片段,或者解释你对算法的使用,因为当输入增加时,一个糟糕的算法会使你的程序变得非常慢——看看计算复杂性,这是由算法课程带来的。
没有明确的解决方案,您必须放弃TLP。控件是一个过于昂贵的对象,任何具有超过一百个控件的形式都将陷入泥潭
首先看一下支持网格显示的内置控件类型。ListView with View=不可编辑网格的详细信息,可编辑网格的详细信息为DataGridView。如果这不符合你的要求,那么你必须自己做。您需要实现的关键是OnPaint方法来绘制控件的视觉外观,OnMouseDown或OnClick用于执行命中测试和实现行为。这是代码的一部分,在进行一些计算时,整个代码非常庞大 在ControlClass中:
void BeginEdit(int nFilas) {
if (!_editando) {
if (_muestraBarraProgreso) {
this->BarraProgreso->Value = 0;
this->BarraProgreso->Visible = true;
}
_editando = true;
_lastEdit = nFilas;
this->Cursor = Cursors::WaitCursor;
this->Refresh();
SendMessageClass::SuspendDrawing();
}
};
/// <summary>Provoca se realicen los cambios visuales no realizados desde que se
/// llamó a BeginEdit, como this->Controls.Add(...), Ajustar los tamaños de los controles, ...</summary>
void EndEdit(void) {
if (_editando) {
int f;
_editando = false;
AjustaHeaders();
AjustaTamaños(); //Provoca el ajuste de las filas sin ajustar las columnas
//Esto lo hago para minimizar el número de AjustaTamaños()
for (f=_lastEdit; f<_nFilas; f++)
_fila[f]->EndEdit(false); //Provoca el ajuste de las columnas
this->MuestraBarraProgreso = false;
this->Cursor = Cursors::Default;
SendMessageClass::ResumeDrawing();
}
};
void AjustaTamaños(void) {
if (!_editando && _nFilas>0) {
int topOffset = 0, leftOffset = 0, bottomOffset = 0;
if (_showColumnHeaders) topOffset = this->tlpColumnHeaders->Height;
if (_showRowHeaders) leftOffset = this->tlpRowHeaders->Width;
if (_muestraEstado) bottomOffset = this->EstadoRecipiente->Height;
int hOffset = leftOffset + 2;
int vOffset = topOffset + bottomOffset + 2;
int i, j = 0, stp;
if (_varsCom->ordenFilas == TipoOrdenFilas::Descendiente) {
j = 0; stp = 1;
}
else {
j = _nFilas-1; stp = -1;
}
for (i=0; i<_nFilas; i++) {
_fila[j]->Left = hOffset;
_fila[j]->Width = this->Width - hOffset;
_fila[j]->Top = (_nFilas - 1 - i) * (this->Height - vOffset) / _nFilas + topOffset;
_fila[j]->Height = (this->Height - vOffset) / _nFilas;
j+=stp;
}
}
};
在FilaClass中:
/// <summary>Provoca que no se realicen los cambios visuales hasta que se llame EndEdit</summary>
void BeginEdit(void) {
if (!_editando) {
_editando = true;
_lastEdit = _nColumnas;
SendMessageClass::SuspendDrawing();
}
};
/// <summary>Provoca se realicen los cambios visuales no realizados desde que se
/// llamó a BeginEdit, como this->Controls.Add(...), Ajustar los tamaños de los controles, ...</summary>
void EndEdit(bool resumirDrawing) {
if (_editando) {
_editando = false;
AjustaTamaños();
for (int c=_lastEdit; c<_nColumnas;c++)
_columna[c]->EndEdit(resumirDrawing);
if (resumirDrawing) SendMessageClass::ResumeDrawing();
}
};
void AjustaTamaños(void) {
if (!_editando) {
int j, stp;
if (_varsCom->ordenColumnas == TipoOrdenColumnas::IzquierdaDerecha) {
j = 0; stp = 1;
}
else {
j = _nColumnas-1; stp = -1;
}
for (int i=0; i<_nColumnas; i++) {
_columna[j]->Width = this->Width / _nColumnas;
_columna[j]->Left = i * this->Width / _nColumnas;
_columna[j]->Top = 0;
_columna[j]->Height = this->Height;
j+=stp;
}
}
};
在ColumnClass中:
void BeginEdit(void) {
_editando = true;
SendMessageClass::SuspendDrawing();
};
void EndEdit(bool resumirDrawing) {
if (_editando) {
_editando = false;
_CambiaEstado = _estado;
if (resumirDrawing) SendMessageClass::ResumeDrawing();
}
};
internal:
/// <summary>Obtiene o establece el estado de la posición sin activar el evento ColumnaChange</summary>
property EstadoColumna _CambiaEstado {
EstadoColumna get() { return _estado; }
void set(EstadoColumna value) {
_estado = value;
if ( (_varsCom->bloquearLlenas && ((value & EstadoColumna::llena) == EstadoColumna::llena)) ||
(_varsCom->bloquearVacias && ((value & EstadoColumna::llena) != EstadoColumna::llena)) ) {
if ((_estado & EstadoColumna::seleccionada) == EstadoColumna::seleccionada)
_estado = (EstadoColumna) (_estado ^ EstadoColumna::seleccionada);
_estado = (EstadoColumna) (_estado | EstadoColumna::bloqueada);
}
else {
if ((_estado & EstadoColumna::bloqueada) == EstadoColumna::bloqueada)
_estado = (EstadoColumna) (_estado | EstadoColumna::bloqueada);
}
if (!_editando) {
ActualizaEstado();
ActualizaToolTip();
}
}
};
/// <summary>Actualiza la visualización de la posición leyendo de nuevo los parámetros</summary>
void ActualizaEstado(void) {
if (!_editando && _varsCom->estilo) {
this->ColumnaCtl->BackColor = _varsCom->estilo->GetEstilo[(int) _estado]->colorFondo;
this->ColumnaCtl->CellBorderStyle = _varsCom->estilo->GetEstilo[(int) _estado]->bordeCelda;
this->ColumnaCtl->BackgroundImageLayout = _varsCom->imageLayout;
if (this->Estado[EstadoColumna::llena])
this->ColumnaCtl->BackgroundImage = _varsCom->imagenLlena;
else if (this->Estado[EstadoColumna::vacia])
this->ColumnaCtl->BackgroundImage = _varsCom->imagenVacia;
}
};
/// <summary>Actualiza los textos del ToolTipText de la posición</summary>
void ActualizaToolTip(void) {
if (!_editando && _varsCom->etiquetas) {
String^ sTmp = "";
int __tmp__ = 0;
if (_varsCom->tipoHeaderFilas == TipoHeader::Numerica)
sTmp = _varsCom->etiquetas->Fila + ": " + _nombreFila;
else if (System::Int32::TryParse(_nombreFila, __tmp__))
sTmp = _varsCom->etiquetas->Fila + ": " + gcnew String((wchar_t) ('A' + __tmp__ - 1), 1);
else
sTmp = _varsCom->etiquetas->Fila + ": " + _nombreFila;
if (_varsCom->tipoHeaderColumnas == TipoHeader::Numerica)
sTmp += ", " + _varsCom->etiquetas->Columna + ": " + _posicion + "\n";
else
sTmp += ", " + _varsCom->etiquetas->Columna + ": " + gcnew String((wchar_t) ('A' + _posicion - 1), 1) + "\n";
if (_nombre != "") {
if ((_estado & EstadoColumna::llena) == EstadoColumna::llena)
sTmp += _varsCom->etiquetas->Posicion + ": " + _nombre + "\n";
else
sTmp += _varsCom->etiquetas->PosicionVacia + ": " + _nombre + "\n";
}
if ((_estado & EstadoColumna::llena) == EstadoColumna::llena) sTmp += "Ocupada, ";
else sTmp += "Vacía, ";
if ((_estado & EstadoColumna::seleccionada) != EstadoColumna::vacia) sTmp += "Seleccionada";
else sTmp += "Sin seleccionar";
this->ToolTip1->ShowAlways = false;
this->ToolTip1->SetToolTip(this->ColumnaCtl, sTmp);
this->ToolTip1->ShowAlways = true;
}
};
我认为这些是计算的大部分。。
有点未注释,用西班牙语,但任何帮助都会非常有用!
无论如何谢谢你我理解,WiFrm是针对.NET的,不能用于C++。只有MS的.NET语言具有访问权限,例如C++/CLI。如果是这样的话,我建议你改变你的标签,以反映你使用的实际语言,因为使用C++的人可能不知道如何帮助你。这两种语言不一样,即使MS试图说它们是一样的。谢谢,我没有考虑为单元格构建我自己的基控件,所以我会在完成后告诉你一些事情。不是单元格,那只会用一个控件替换另一个控件。TLP。是的,是的,当然。。电池的tlp…:这个想法是创造一个自己的细胞面具,或者类似的东西。。你说得很对,bc事实上我只需要TLP的一些属性,不是全部。。多做一点工作,但可以减少创作和绘图时间。好的,所以我尝试了,它确实提高了绘图速度。。我将TLP替换为8行,以模拟凸起或选定的效果。我还将ColumnClass从UserControl更改为Control。仍存在调整各公司规模的瓶颈
控制。谢谢你的评论!!嗯。。你说得对。。瓶颈的一部分在于计算。。我发布了大部分计算代码。但是在绘制控件时确实存在一个很大的瓶颈。我已经看了链接,但需要冷静地阅读,这个周末就可以了。顺便问一下,你知道我在哪里可以找到更多关于GPU编程的信息吗?这真的是硬核吗?