0

C++ でコントロールを作成して、ユーザーがさまざまな位置を持つ不規則なボックス内の位置を選択できるようにしました。一部はブロックされ、一部は塗りつぶされ、次の特性があります。

  • 複数の行に複数の列を作成できます (同じではないため、最初の行に 3 列、2 番目に 1 列、3 番目に 5 列を持つことができます)

  • 位置ごとに異なる状態: ブロック、塗りつぶし、空、選択済み (したがって、同時にいくつかの状態を保持できます: ブロック & 空、ブロック & 塗りつぶし、空 & 選択済み)

  • ユーザーは 1 つまたは複数の位置を選択できます

  • 塗りつぶされた位置または空の位置ごとにツールチップ テキストと異なる背景画像があります。

  • 行/列を追加/削除するためのコンテキスト メニュー。

  • 行と列のヘッダー、数値/英数字、昇順/降順。

コントロールの構造は、Container->(nRows x RowClass) および RowClass->(nCols x ColumnClass) です。各列には TableLayoutPanel が含まれているため、スタック効果と隆起効果をシミュレートできます。

Web でさまざまなトピックを探して、いくつかのアイデアを見つけ、速度のために行った改善は、基本的に SendMessage を使用した SuspendDrawing (ペイントする前にすべての行と列を作成およびサイズ変更するため)、各コントロールをダブル バッファリングし、BeginEdit/ を追加することです。 EndEdit メソッドを Container に追加し、SuspendDrawing を実行して、行と列の作成中に行と列のサイズ変更をブロックします (各 RowClass についても同様です)。

比較的小さなボックス、たとえば 20 行 x 20 列ではそれほど悪くはありませんが、40 行 x 30 列 (1.200 TableLayoutPanel) の場合、高速なコンピューターでも非常に遅くなります。

RowClass ごとに 1 つの TableLayoutPanel (必要な列数) も試しましたが、問題は、各列を個別に選択するために境界線を描画する方法、各セルのツールヒントと背景画像です。

それで、質問:私が試すことができる改善はありますか?

ウォークラフトなどの戦略ゲームは、画面上で数千のグラフィックスと計算が表示され、速度が速いと考えていましたが、私はプロのプログラマーではないので、どのテクノロジーが適切であるかはわかりません。仕方..

たぶん、画像が一列に並んだ画像のようなものか、クラスのクラスのクラスとは異なるものかもしれませんが、私にはわかりません...

おそらく設計上の問題なので、これらの仕様で高速なコントロールを作成する方法についてのアイデアは素晴らしいでしょう.

とにかく私の質問を読んでくれてありがとう、どんなコメントも歓迎します! ミゲル

4

3 に答える 3

0

ビデオゲームは、少なくともGPU(その目的のために構築されたもの)でグラフィック表現をオフロードします。ボックスの表現がボトルネックではなく、そこに到達するための計算/ステップだと思います。コード/コードのスニペットを投稿するか、アルゴリズムの使用法を説明してください。アルゴリズムが悪いと、入力が増えるとプログラムが非常に遅くなるためです。アルゴリズムコースによってもたらされる計算の複雑さを見てください。 http://en.wikipedia.org/wiki/Computational_complexity_theory

于 2010-12-23T18:09:55.083 に答える
0

これを完全に修正する方法はありません。TLP をあきらめる必要があります。コントロールは非常に高価なオブジェクトであり、100 個を超えるフォームは泥を吸うでしょう。

最初に、グリッドのような表示をサポートする組み込みのコントロール タイプを見てください。View = Details の ListView は、編集不可のグリッド用、DataGridView は編集可能なグリッド用です。それが請求書に合わない場合は、独自に作成する必要があります。実装する必要がある重要なものは、コントロールの視覚的な外観を描画する OnPaint() メソッドと、ヒット テストを実行して動作を実装する OnMouseDown または OnClick です。

于 2010-12-23T18:19:33.023 に答える
0

これは、いくつかの計算が行われるコードの一部です (コード全体は非常に巨大です)。

コントロールクラス::

    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;
                }
            }
        };

フィラクラスで:

    /// <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;
                }
            }
        };

ColumnaClass で:

    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;
            }
        };

私はそれらが計算のほとんどの部分だと思います..少しコメントを外して、スペイン語ですが、どんな助けも本当に役に立ちます! とにかくありがとう!

于 2010-12-24T18:19:54.737 に答える