Forum: PC-Programmierung C# listView Spaltenbreite ändert sich


von He (Gast)


Lesenswert?

Hi,

ich benutzte in einer C# Winforms Anwendung mehrere listView Elemente.
Nun ist es so dass, wenn ich Zuhause das Tool ausführe die Spalten in 
dem listView Element sich verkleinern. Auf dem anderen Monitor sind die 
Spalten in dem listView Element korrekt. Gibt es eine Möglichkeit dass 
dies automatisch angepasst werden kann?

von Name (Gast)


Lesenswert?


von He (Gast)


Lesenswert?

Danke für den Link. Dies hat mir nicht geholfen.

Die breite der einzelnen Spalten in der listView sind auch bereits ohne 
Ausführung des Tools schon falsch dargestellt. Wenn ich den Monitor in 
der Firma benutzte ist alles ok.

von He (Gast)


Angehängte Dateien:

Lesenswert?

Siehe Screenshot

von He (Gast)


Lesenswert?

Wie gesagt auf dem Monitor in der Firma werden die drei Spalten so 
dargestellt dass keine 4 Spalte zu sehen ist.

von He (Gast)


Lesenswert?

Hab nach wie vor keine Lösung gefunden.
Für jegliche Hilfe bin ich sehr dankbar :-)

von Patrick C. (pcrom)


Lesenswert?

Versuch mal wie es aussieht wenn du zuhause eine andere 
Bildschirmaufloesung einstellst

Patrick aus die Niederlaende

von Schlaumaier (Gast)


Lesenswert?

Ich habe das Problem in VB SO gelöst.

Ich frage die Größe des Listview ab. Also die Breite.

Dann weise ich JEDER Spalte eine neue Breite zu im %-Verhältnis der 
Breite während der Entwicklung. Je nach Anzeige verändere ich auch die 
Schriftart dementsprechend.

Mache ich übrigens mit JEDEN Objekt in ähnlicher Form.

Dazu lese ich VOR der Anzeige der Form alle Werte der einzelnen Objekte 
aus, und setze den Faktor auf 1. Sobald ein Resize-Ereignis auftritt 
lese ich die neue Größe der Form und passe alle Objekte an. Aus 
Sicherheitsgründen blockiere ich aber die Größe auf ein Minimum von 640 
x 480.

Du kannst mit dieser Methode JEDES Objekt anpassen.

Die selbe Technik benutze ich übrigens auch bei meinen Android-Apps. ;)

Unter VB muss ich aber den AUTOSCALEMODE der Form auf NONE setzen. 
Ansonsten versucht VB den selbst anzupassen.

Hier nähere Infos zu der Einstellung.
https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.autoscalemode?view=windowsdesktop-6.0

von Schlaumaier (Gast)


Lesenswert?

Nachtrag:

Ich mag keine Listview. Ich finden Datagridview (ungebunden) viel 
schöner. Und viel einfacher zu füttern bzw. auszulesen.

Besonders weil sie viel mehr Einstellungen im Design haben.

von He (Gast)


Lesenswert?

Ok ich hab nun mal Zuhause die Bildschirmauflösung geändert. Da wird nun 
die listView korrekt angezeigt.

von Schlaumaier (Gast)


Lesenswert?

He schrieb:
> Ok ich hab nun mal Zuhause die Bildschirmauflösung geändert. Da wird nun
> die listView korrekt angezeigt.

Ist aber nicht die richtige Lösung.

Wenn du willst zeige ich es dir in VB. Das müstest du dann nur in VC 
umwandeln. Ich kann die Syntax von VC nicht.

von He (Gast)


Lesenswert?

Hi,

ich bedanke mich schon im Vorfeld für dein Beispiel in VB.

von Schlaumaier (Gast)


Lesenswert?

OK.

Musst in den Form-Eigenschaften aber AUTOSCALEMODE = NONE setzen

Public Class hp

  Private Structure ControlPositionType  ' legt die Structure fest
    Dim m_Left As Single
    Dim m_Top As Single
    Dim m_Width As Single
    Dim m_Height As Single
    Dim m_Font_hoch As Single
    Dim m_font_fett As Boolean
  End Structure

  Private m_Con_pos(5, 100) As ControlPositionType

  Private global_form_breit = 1280 ' Größe der Entwicklungsgröße
  Private global_form_hoch = 700
   Private form_geladen As String

Private Sub hp_Load(sender As System.Object, e As System.EventArgs) 
Handles MyBase.Load

  call pos_sichern ()   '
  form_geladen = "ja"
end sub


Sub pos_sichern ()  ' liest die Werte ein die bei der Erstellung 
verwendet wurden.
 i = 1
    x = 1
    Dim ctl As Control
    For Each ctl In Me.Controls  ' liest die Position + Schrift aller 
Objekte auf der HAUPT-FORM EIN
      m_Con_pos(x, i).m_Top = ctl.Top
      m_Con_pos(x, i).m_Left = ctl.Left
      m_Con_pos(x, i).m_Height = ctl.Height
      m_Con_pos(x, i).m_Width = ctl.Width
      m_Con_pos(x, i).m_Font_hoch = ctl.Font.Size
      m_Con_pos(x, i).m_font_fett = ctl.Font.Bold
      i = i + 1
    Next
end sub

Private Sub hp_Resize(sender As Object, e As System.EventArgs) Handles 
Me.Resize   ' wird automatisch aufgerufen wenn die Form sich ändert.

 If Me.Height < 480 Then Me.Height = 480  ' blockiert bei 480x640
    If Me.Width < 640 Then Me.Width = 640
    faktor_x = Me.Width / global_form_breit  ' berechnet den 
Skalierfaktor
    faktor_y = Me.Height / global_form_hoch
    If faktor_x > faktor_y Then
      faktor_font = 11 * faktor_y
      faktor_font_2 = faktor_y
    Else
      faktor_font = 11 * faktor_x
      faktor_font_2 = faktor_x
    End If


    If Me.WindowState = FormWindowState.Minimized Then Exit Sub

    Dim ctl As Control
    If form_geladen = "ja" Then
      i = 1 : ix = 1
      For Each ctl In Me.Controls
        ctl.Left = m_Con_pos(ix, i).m_Left * faktor_x
        ctl.Top = m_Con_pos(ix, i).m_Top * faktor_y
        ctl.Width = m_Con_pos(ix, i).m_Width * faktor_x
        ctl.Height = m_Con_pos(ix, i).m_Height * faktor_y
        'Dim g As Integer = Label1.Font.Size
        'Label1.Font = New Font(Label1.Font.FontFamily, g + 2)
        If m_Con_pos(ix, i).m_font_fett = True Then
          ctl.Font = New Font("Arial", Int(m_Con_pos(ix, i).m_Font_hoch 
* faktor_font_2), FontStyle.Bold)
        Else
          ctl.Font = New Font("Arial", Int(m_Con_pos(ix, i).m_Font_hoch 
* faktor_font_2), FontStyle.Regular)
        End If
        i = i + 1
      Next

' das hier nur wenn du ein Datagridview Hier Name = gg mit 7 Sichtbaren 
Zeilen hast.

      gg.Columns(0).Width = 5 * faktor_x ' da setze ich immer ein Index 
rein
      gg.Columns(1).Width = 60 * faktor_x ' nr
      gg.Columns(2).Width = 350 * faktor_x ' kennung
      gg.Columns(3).Width = 120 * faktor_x
      gg.Columns(4).Width = 100 * faktor_x
      gg.Columns(6).Width = 120 * faktor_x
      gg.Columns(7).Width = 90 * faktor_x


' falls du ein Kalender-Objekt hasst
  kalender.Font = New Font("Arial", Int(20 * faktor_font_2), 
FontStyle.Regular) ' 20 = Font-größe bei Erstellung

end sub

End Class

'**********************************************************************

Es geht im Prinzip um folgendes.
Die Auflösung der Erstellung eingeben beim Start.
Die Position und Größe der Font sichern.
Beim ändern der Auflösung anhand der neuen Formgröße ALLE Objekte neu 
zeichnen.

Bei Android mache ich das ähnlich, nur führe ich da das Resize-Ereignis 
als SUB von Hand aus, da Android das nicht kenne.

Vorteil des ganzen. Die Form verändert sich nie wirklich. Selbst bei 
nicht gleicher Skalierung z.b. Neu Höhe 130 % der alten. Breite 80% der 
alten Breite bleibt die Form sauber erhalten.

von He (Gast)


Lesenswert?

Vielen Dank. Werde ich Morgen mal deine Implemntierung genauer 
anschauen.

von Schlaumaier (Gast)


Lesenswert?

OK, bei fragen , frag ruhig.

ist aber Visual-BASIC Code. Musst aber nur, wie ich denke, viele 
geschweifte Klammern und Semikolons verteilen ;)

von Dirk K. (merciless)


Lesenswert?

Vergiss den Quatsch mit dem Berechnen der Control-Größen, dafür gibt es
1
System.Windows.Forms.TableLayoutPanel
2
System.Windows.Forms.FlowLayoutPanel
die erledigen das automatisch (die 80er Jahre sind vorbei).

Bezüglich der Spaltenbreiten: Schau dir mal
1
// passt die Größe der Spalten an den Spalteninhalt an
2
myListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
bzw.
1
// passt die Größe der Spalten an den Spaltenheader an
2
myListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
an. Erst den ListView füllen und danach die entsprechende Methode 
aufrufen.

merciless

von Schlaumaier (Gast)


Lesenswert?

Dirk K. schrieb:
> die erledigen das automatisch (die 80er Jahre sind vorbei).

Die 80er Jahre waren nicht schlecht. Und die waren sicherer als das neue 
Zeug. Ich habe ähnliche Techniken in VB auch drin. Das Problem ist 
dabei, das wenn man die Form verändert, Objekte verschwinden oder sich 
überlagern.
Schriften nicht angepasst werden u.s.w.

Selbst in den Office-Paket bekommt MS das nicht sauber hin. Ich will 
aber in meiner Software eine Komplett-Skalierung der Form. Was bedeutet, 
sobald der Bildschirm mehr als 640*480 Pixel hat, passt die Form IMMER 
sauber verteilt auf den Bildschirm. Die Bildschirmauflösung ist dabei 
völlig egal.

Ich habe diese Techniken von dir ausprobiert. Und in mein VB klappt das 
nur "ein bisschen". Meine Routine passt auf JEDEN Gerät. Wie gesagt, 
sogar auf Android-Teilen.

von He (Gast)


Lesenswert?

Danke Dirk, allerdings funktioniert das bei mir nicht so wie es soll.
Bin jetzt echt etwas planlos wie ich das angehen soll.

von Schlaumaier (Gast)


Lesenswert?

He schrieb:
> Danke Dirk, allerdings funktioniert das bei mir nicht so wie es soll.

War zu erwarten. ;)

Wie geschrieben, VB kennt das auch. Aber mir hat das Ergebnis auch nicht 
gefallen. Deshalb steuere ich alles von Hand.

Ist zwar bedeutet aufwendiger vom Code her, aber dafür habe ich ALLES im 
Griff.

Selbst das 125% Problem.

Das Problem ist aus der ehemaligen Hilfe für Sehbehinderte entstanden. 
Damals bei Win 3.1 o.s. gab es nicht wirklich Behindertenhilfe. Also hat 
man einfach eine Einstellung gehabt im OS die den Bildschirm 
hoch-skaliert, bei Systemschriften hat das leidlich funktioniert. Bei 
den anderen Schriften gar nicht. Ich habe damals ein 19" Monitor 
bekommen und habe auf 125% gestellt. Resultat: Die einfachen Programme 
waren total verzerrt, besonders die mit Steuerelementen wie 
Gitter,Listfelder etc.

Damals habe ich angefangen diese Routine oben zu entwickeln. Gewisse 
Werte sind zwar inzwischen aus den System geholt die ich in alten 
Versionen via Einstellungen festlegen hab lassen, aber grundsätzlich ist 
es immer die selbe.

Sie funktioniert deshalb in ähnlicher Form auch auf anderen OS weil sie 
sich NICHT vom nicht sauber kompatiblen Anpassungen beeinflusst lässt, 
sondern die Eigenschaften des Objektes direkt einstellt.

AUTOSCALEMODE kennt 3 Einstellungen. Womit man den Faktor_x + Faktor_y 
in meiner Routine versucht zu errechnen. DPI, FONT, NONE.  ABER, der 
Faktor wird als gebunden berechnet. Was bedeutet das Verhältnis bleibt 
immer gleich. Bei mir nicht. !!!  Und allein diese Tatsache sorgt dafür 
das meine Software auch auf 16:9 / 16:10 oder anderen Varianten 1:1 
läuft, solange er min. 640 x 480 Pixel darstellen kann.

Das von meiner Software einige 10.000 Kopien installiert wurden und ich 
nur 1 x ein Problem hatte, also ist die zu Routine zu 99,999 % Sauber.

Das Problem trat übrigens auf, bei einen Monitor mit Drehschalter. Ich 
hatte (bis heute) keine Möglichkeit gefunden diese Info auszulesen, ob 
der Monitor hoch o. Quer stand. Also habe ich (hier im Code nicht 
vorhanden) eine Menü-Einstellung geschrieben, wo der User die 
Monitorausrichtung (hoch o. Quer-Format) einstellen kann, und auch ob er 
voll- o. Teilskalierung wünscht.

Der Kunde war übrigens Hoch-Zufrieden über meinen Support. ;)

von He (Gast)


Lesenswert?

Ich kann den VB Code nur schwer lesen und verstehen.
Was machst du eigentlich genau?

1: Bildschirmgröße ermitteln?
2: ALle Elemente neu skalieren (Breite und Höhe) ?

von Dirk K. (merciless)


Lesenswert?

He schrieb:
> Danke Dirk, allerdings funktioniert das bei mir nicht so wie es soll.
> Bin jetzt echt etwas planlos wie ich das angehen soll.

Und WAS funktioniert nicht? Ich habe das bei vielen Programmen hier so 
im Einsatz und da habe ich keine Probleme.

@Schlaumaier Meine Forms werden korrekt skaliert, da muss ich nichts von 
Hand rechnen.

merciless

von Schlaumaier (Gast)


Lesenswert?

He schrieb:
> Ich kann den VB Code nur schwer lesen und verstehen.
> Was machst du eigentlich genau?

Ich gebe oben als Gobale Variabel Größe der Entwicklungsumgebung an. Den 
Wert liest du einfach aus den Eigenschaftenfenster ab.

Könnte ich auch im Code unten aber so ist es schöner

Private global_form_breit = 1280 ' Größe der Entwicklungsgröße
Private global_form_hoch = 700

Private form_geladen As String <- Diese Variable blockiert das Resize 
bevor die Form geladen ist.
MUSS als letztes gesetzt werden, damit der Resize-Code nicht blockiert 
wird.

In der pos_sichern sub  sichere ich nun die Werte width,height, top + 
left, die Schriftart und ob sie fett geschrieben ist, in ein Array. Das 
sind IMMER die Werte der Entwicklungsgröße.

Sobald der User die Form verändert (Das System löst ein Resize-Ereignis 
aus).

lese ich mit  me.Width + me.height die NEUE Größe aus die die  Form nun 
hat, berechne die Skalierungsfaktor im Verhältnis zur Entwicklungsgröße 
Global_form_breit/hoch. Dann positioniere ich ALLE Elemente neu, 
aufgrund der Berechnung.

Da die Skalierung bei den Kalender-Objekt gar nicht, und bei einen 
Datagrid nur auf die äußere Form greift, positioniere ich danach so 
Sachen wie Spaltenbreite nach.

Das ist im Prinzip alles.

Und da alle Objekt-Orientierten Formen (Fenster) gleich arbeiten, kann 
man diese Technik problemlos auf C+ / Android und was weiß ich anwenden. 
Vielleicht muss man bei einigen Objekten spezielle Nachbesserungen 
machen (Spaltenbreite beim Datagridview wenn man die Fixiert hat im 
Code) aber das ist Kleinkram.

Bei Android gibt es kein Resize. Da löse ich den Code vor den 
Form-Zeichen aus.

von Schlaumaier (Gast)


Lesenswert?

Dirk K. schrieb:
> @Schlaumaier Meine Forms werden korrekt skaliert, da muss ich nichts von
> Hand rechnen.

Meine sind nicht so nett. Und es wird wohl ein Grund geben wieso MS ein 
Resize-Ereignis auslösen lässt. ;)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.