C++ Windows::Forms::ListView Repaint-Bug

Allgaeuer

Newbie
Registriert
Sep. 2011
Beiträge
1
Hallo,

ich hätte da eine Frage bezüglich der System::Windows::Forms::ListView. Und zwar gibt es da einen Bug den ich partout nicht gelöst bekomme:
Die Intention war es, ein ListView-Element zu erzeugen, dessen letzte Spalte sich an den vorhandenen Raum des umgebenden Panels anpasst. Dazu erst einmal folgender Code:

Form1.h:

Code:
#pragma once

#include "MDIChild.h"

namespace ListView_Test {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;

	public ref class Form1 : public System::Windows::Forms::Form
	{
	public:
		Form1(void)
		{
			InitializeComponent();

            MDIChild ^ child = gcnew MDIChild();
            child->MdiParent=this;
            child->Show();
		}

	protected:
		~Form1()
		{
			if (components)
			{
				delete components;
			}
		}

	private:
		System::ComponentModel::Container ^components;

        void InitializeComponent(void)
		{
            this->SuspendLayout();
            // 
            // Form1
            // 
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->ClientSize = System::Drawing::Size(1060, 484);
            this->IsMdiContainer = true;
            this->Name = L"Form1";
            this->Text = L"Form1";
            this->ResumeLayout(false);

        }
	};
}

MDIChild.h:

Code:
#pragma once

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;


namespace ListView_Test {

	public ref class MDIChild : public System::Windows::Forms::Form
	{
	public:
		MDIChild(void)
		{
			InitializeComponent();
		}

	protected:
		~MDIChild()
		{
			if (components)
			{
				delete components;
			}
		}

    private: System::Windows::Forms::ListView^  listView1;
    private: System::Windows::Forms::ColumnHeader^  columnHeader1;
    private: System::Windows::Forms::ColumnHeader^  columnHeader2;
    private: System::Windows::Forms::ColumnHeader^  columnHeader3;
    private: System::Windows::Forms::ColumnHeader^  columnHeader4;
    private: System::Windows::Forms::ColumnHeader^  columnHeader5;
    private: System::Windows::Forms::ColumnHeader^  columnHeader6;
    private: System::Windows::Forms::ColumnHeader^  columnHeader7;
    private: System::Windows::Forms::ColumnHeader^  columnHeader8;

		System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code

		void InitializeComponent(void)
		{
            System::Windows::Forms::ListViewItem^  listViewItem1 = (gcnew System::Windows::Forms::ListViewItem(gcnew cli::array< System::String^  >(9) {L"1", 
                L"a", L"b", L"c", L"d", L"e", L"f", L"g", L"h"}, -1));
            System::Windows::Forms::ListViewItem^  listViewItem2 = (gcnew System::Windows::Forms::ListViewItem(gcnew cli::array< System::String^  >(9) {L"2", 
                L"b", L"c", L"d", L"e", L"f", L"g", L"h", L"i"}, -1));
            System::Windows::Forms::ListViewItem^  listViewItem3 = (gcnew System::Windows::Forms::ListViewItem(gcnew cli::array< System::String^  >(9) {L"3", 
                L"c", L"d", L"e", L"f", L"g", L"h", L"i", L"j"}, -1));
            System::Windows::Forms::ListViewItem^  listViewItem4 = (gcnew System::Windows::Forms::ListViewItem(gcnew cli::array< System::String^  >(9) {L"4", 
                L"d", L"e", L"f", L"g", L"h", L"i", L"j", L"k"}, -1));
            System::Windows::Forms::ListViewItem^  listViewItem5 = (gcnew System::Windows::Forms::ListViewItem(gcnew cli::array< System::String^  >(9) {L"5", 
                L"e", L"f", L"g", L"h", L"i", L"j", L"k", L"l"}, -1));
            System::Windows::Forms::ListViewItem^  listViewItem6 = (gcnew System::Windows::Forms::ListViewItem(gcnew cli::array< System::String^  >(9) {L"6", 
                L"f", L"g", L"h", L"i", L"j", L"k", L"l", L"m"}, -1));
            System::Windows::Forms::ListViewItem^  listViewItem7 = (gcnew System::Windows::Forms::ListViewItem(gcnew cli::array< System::String^  >(9) {L"7", 
                L"g", L"h", L"i", L"j", L"k", L"l", L"m", L"n"}, -1));
            System::Windows::Forms::ListViewItem^  listViewItem8 = (gcnew System::Windows::Forms::ListViewItem(gcnew cli::array< System::String^  >(9) {L"8", 
                L"h", L"i", L"j", L"k", L"l", L"m", L"n", L"o"}, -1));
            System::Windows::Forms::ListViewItem^  listViewItem9 = (gcnew System::Windows::Forms::ListViewItem(gcnew cli::array< System::String^  >(9) {L"9", 
                L"i", L"j", L"k", L"l", L"m", L"n", L"o", L"p"}, -1));
            System::Windows::Forms::ListViewItem^  listViewItem10 = (gcnew System::Windows::Forms::ListViewItem(gcnew cli::array< System::String^  >(9) {L"0", 
                L"j", L"k", L"l", L"m", L"n", L"o", L"p", L"q"}, -1));
            this->listView1 = (gcnew System::Windows::Forms::ListView());
            this->columnHeader1 = (gcnew System::Windows::Forms::ColumnHeader());
            this->columnHeader2 = (gcnew System::Windows::Forms::ColumnHeader());
            this->columnHeader3 = (gcnew System::Windows::Forms::ColumnHeader());
            this->columnHeader4 = (gcnew System::Windows::Forms::ColumnHeader());
            this->columnHeader5 = (gcnew System::Windows::Forms::ColumnHeader());
            this->columnHeader6 = (gcnew System::Windows::Forms::ColumnHeader());
            this->columnHeader7 = (gcnew System::Windows::Forms::ColumnHeader());
            this->columnHeader8 = (gcnew System::Windows::Forms::ColumnHeader());
            this->SuspendLayout();
            // 
            // listView1
            // 
            this->listView1->Anchor = static_cast<System::Windows::Forms::AnchorStyles>((((System::Windows::Forms::AnchorStyles::Top | System::Windows::Forms::AnchorStyles::Bottom) 
                | System::Windows::Forms::AnchorStyles::Left) 
                | System::Windows::Forms::AnchorStyles::Right));
            this->listView1->Columns->AddRange(gcnew cli::array< System::Windows::Forms::ColumnHeader^  >(8) {this->columnHeader1, this->columnHeader2, 
                this->columnHeader3, this->columnHeader4, this->columnHeader5, this->columnHeader6, this->columnHeader7, this->columnHeader8});
            this->listView1->FullRowSelect = true;
            this->listView1->HeaderStyle = System::Windows::Forms::ColumnHeaderStyle::Nonclickable;
            this->listView1->Items->AddRange(gcnew cli::array< System::Windows::Forms::ListViewItem^  >(10) {listViewItem1, listViewItem2, 
                listViewItem3, listViewItem4, listViewItem5, listViewItem6, listViewItem7, listViewItem8, listViewItem9, listViewItem10});
            this->listView1->Location = System::Drawing::Point(6, 15);
            this->listView1->Name = L"listView1";
            this->listView1->Size = System::Drawing::Size(710, 110);
            this->listView1->TabIndex = 2;
            this->listView1->UseCompatibleStateImageBehavior = false;
            this->listView1->View = System::Windows::Forms::View::Details;
            this->listView1->SizeChanged += gcnew System::EventHandler(this, &MDIChild::ResizeListView);
            // 
            // columnHeader1
            // 
            this->columnHeader1->Text = L"Main";
            // 
            // columnHeader2
            // 
            this->columnHeader2->Text = L"Sub1";
            // 
            // columnHeader3
            // 
            this->columnHeader3->Text = L"Sub2";
            // 
            // columnHeader4
            // 
            this->columnHeader4->Text = L"Sub3";
            // 
            // columnHeader5
            // 
            this->columnHeader5->Text = L"Sub4";
            // 
            // columnHeader6
            // 
            this->columnHeader6->Text = L"Sub5";
            // 
            // columnHeader7
            // 
            this->columnHeader7->Text = L"Sub6";
            // 
            // columnHeader8
            // 
            this->columnHeader8->Text = L"Sub7";
            this->columnHeader8->Width = 55;
            // 
            // MDIChild
            // 
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->ClientSize = System::Drawing::Size(721, 139);
            this->Controls->Add(this->listView1);
            this->Name = L"MDIChild";
            this->Text = L"MDIChild";
            this->ResumeLayout(false);

        }
#pragma endregion

        void ResizeListView(System::Object ^ sender, System::EventArgs ^ e)
        {
            try
            {
                ListView ^ list = listView1;

                int nSize = 3;
                int nLastIndex = 7;
                int nLastColumnSize;

                nSize += list->Columns[0]->Width;
                nSize += list->Columns[1]->Width;
                nSize += list->Columns[2]->Width;
                nSize += list->Columns[3]->Width;
                nSize += list->Columns[4]->Width;
                nSize += list->Columns[5]->Width;
                nSize += list->Columns[6]->Width;

                nLastColumnSize = 200;

                nSize = list->ClientRectangle.Width - nSize - 19;

                if (nSize > nLastColumnSize)
                {
                    nLastColumnSize = nSize;
                }

                list->Columns[nLastIndex]->Width = nLastColumnSize;
            }
            catch(...)
            {
                ;
            }
        }
	};
}

Wie man sieht dient ein äußeres Panel(Form1) als MDI Container für das Innere(MDIChild) welches das ListView enthält.
Wenn nun aber ein ListView Element angezeigt wird, dessen Inhalt so viele Zeilen umfasst, das der vertikale Scrollbalken erscheint, entsteht ein drastischer Darstellungsfehler beim Maximieren. Allerdings nur wenn das Fenster vor dem Maximieren ganz nach unten gescrollt wurde. Vermutlich entsteht er durch das Setzen der Groesse der letzten Header-Spalte, waehrend das ListView neu gezeichnet wird.

Reproduktion:
1.Den oben geposteten Code ausführen.
2.Den vertikalen Scrollbalken des "MDIChild"-Fensters ganz nach unten ziehen.
3.(optional) Das Form1 maximieren.
4.Das MDIChild-Fenster maximieren.

Symptomatik:
Zunächst werden überhaupt keine Zeilen mehr angezeigt. Versucht man nun mit einem Markierungsrechteck einige Zeilen zu markieren, fällt auf, dass diese erst angezeigt werden, nachdem man mit der Maus über sie fährt, allerdings an der falschen Stelle. Sie scheinen um genau die Höhe des nicht-maximierten Panels nach unten verschoben zu sein. Auch nach Drücken des Verkleinern-Buttons, bleiben die Zeilen zunächst verschwunden, bis man einmal mit dem Scrollbalken ganz nach unten scrollt.
Zusaetzlich ist beim wieder verkleinern noch ein horizontaler Scrollbalken vorhanden, der dann im Vergleich zum ListView zu breit ist. Wird mit diesem an die rechte Seite gescrollt, verkleinert sich der Scrollbalken auf die korrekte Breite.

Kann mir jemand bei diesem Problem helfen? -Im Anhang ist noch ein Screenshot der das Problem aufzeigt.

Mit freundlichen Grüßen

Michael
 

Anhänge

  • ListViewBug.png
    ListViewBug.png
    54,7 KB · Aufrufe: 282
Hi,

ich hatte das Problem auch mal, allerdings nutze ich die MFC.
Habe es dann so gelöst.

1. Resizeereignis des Listview abfangen und an die Parentklasse weiter leiten
2. Reference zum ListCtrl holen
3. Anzahl der ColumnHeader herausfinden
4. Breite vom letztem Column von Windows selber festlegen lassen mit "LVSCW_AUTOSIZE_USEHEADER"
5. Breite dann nochmal abfragen
6. und mit 5 Pixel weniger neu setzen

kann dir als Ansatz hoffentlich helfen anbei noch der Code
PHP:
void	CToolListView::OnSize				( UINT nType, int cx, int cy )
{


	if ( this->m_OnSizing ) return ;
	this->m_OnSizing = true;

	CListView::OnSize(nType, cx, cy);

	CListCtrl& ctlList = GetListCtrl();
	
	// Resize the Last ColumHeader
	int		tCount = ctlList.GetHeaderCtrl()->GetItemCount();
	int		tSize;

	if( tCount > 0 ) 	
	{
		ctlList.SetColumnWidth(tCount -1 , LVSCW_AUTOSIZE_USEHEADER); 
		tSize = ctlList.GetColumnWidth( tCount -1 );

		ctlList.SetColumnWidth(tCount -1 , (tSize - 5) ); 
	}

	this->m_OnSizing = false;
}

mfg
 
Zurück
Oben