Laden...

Size vs. ClientSize bei eigenem Control

Erstellt von herbivore vor 19 Jahren Letzter Beitrag vor 15 Jahren 6.005 Views
herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren
Size vs. ClientSize bei eigenem Control

Hallo Community,

bei manchen Controls ist Size gleich ClientSize (z.B. PictureBox), bei manchen ist die ClientSize kleiner als Size, weil das Control z.B. einen Rahmen hat (z.B. TextBox). Ich möchte ein solches Control mit Rahmen schreiben, leite aber von einem Control ab, bei dem Size gleich ClientSize ist.

Was muss ich tun, damit beim Setzen von Size bzw. ClientSize, das jeweils andere die korrekte Größe bekommt?

Wenn ich das bei meinem Control die Größe ändere, sind auf Grund des geerbten Verhaltens beide Größen erstmal gleich. Die ClientSize soll aber in beiden Richtungen um 4 Pixel kleiner sein als Size. Experimente mit SetClientSizeCore und SetBoundsCore führten bisher leider nicht zum Erfolg.

Vielen Dank!

herbivore

P
939 Beiträge seit 2003
vor 19 Jahren

Ist nicht getestet, aber so müsste es eigentlich gehen.

public override Size Size {
  get { return base.Size; }
  set {
    base.Size = value;
    base.ClientSize = new Size(value.Width - 4, value.Height - 4);
  }
}

public override Size ClientSize {
  get { return base.ClientSize; }
  set {
    base.ClientSize = value;
    base.Size = new Size(value.Width + 4, value.Height + 4);
  }
}
herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo Pulpapex,

vielen Dank für den Beitrag. Leider geht es so nicht. Erstens sind Size und ClientSize in Control nicht als virtual definiert, also nix mit override und zweitens - was noch wichtiger ist - wird durch die jeweils zweite Zuweisung der Effekt der jeweils ersten aufgehoben, da das Verhalten der Oberklasse (base) meiner Klasse ja gerade eben ist, beide Größen auf denselben Wert zu setzen.

Trotzdem danke!

herbivore

P
939 Beiträge seit 2003
vor 19 Jahren

Da hast du recht mit dem override, war ein Schnellschuss.
Ich habe es mir nochmal genauer angeschaut. So wie es aussieht, können Size und ClientSize nicht unabhängig voneinander geändert werden. Der Größenunterschied ist festgelegt durch die Flags Control.CreateParams.Style und Control.CreateParams.ExStyle, die Fensterarten und Borders usw. definieren. Bei einer Änderung von Size oder ClientSize werden durch einen WinAPI-Aufruf jedes Mal beide Größen neu berechnet.

Es gibt noch die Methode

UpdateBounds(int x, int y, int width, int height, int clientWidth, int clientHeight)

Ein Aufruf zeigt aber keine Wirkung bzw. die Werte werden bei nächster Gelegenheit wieder zurückkorrigiert.

Wofür wird ClientSize in deinem Fall denn genau benötigt?

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo Pulpapex,

ich habe jetzt das Control.CreateParams.ExStyle-Flag WS_EX_CLIENTEDGE aus der Win32-Header-Datei winuser.h benutzt. Dadurch ist die ClientSize jetzt die 4 Pixel kleiner und der Rahmen, den ich um die ClientArea zeichnen wollte, wird von Windows automatisch gezeichnet. Vielen Dank für diesen entscheidenden Hinweis!

Falls jemand das gleiche Problem hat, hier mein Code:


protected override CreateParams CreateParams
{
   get {
      // Definition des Extended Window Styles aus winuser.h (Win32)
      const int WS_EX_CLIENTEDGE = 0x200;

      CreateParams cp = base.CreateParams;
      cp.ExStyle |= WS_EX_CLIENTEDGE;

      return cp;
   }
}

Wofür wird ClientSize in deinem Fall denn genau benötigt?

Naja, es soll halt ein allgemein verwendbares Control werden. Daher möchte ich, dass man durch Setzen von ClientSize die effektive Größe des Controls festlegen kann. Das Control soll also, ohne Berechnung von Rahmendicken seitens des Aufrufers, die richtige Größe bekommt.

Es gibt noch die Methode UpdateBounds.

Die hatte bei meiner Suche nach den diversen Möglichkeiten der Größenänderung glatt übersehen. Jedenfalls tut die Methode genau das, was ich im ersten Ansatz wollte. Man kann damit die ClientSize kleiner festlegen als Size. Allerdings ist damit alleine - wie du ja schon schreibst - noch nicht alles erschlagen. Man müsste also in SizeChanged die unterschiedliche Größe immer wieder neu setzen - wobei einem leider die Information fehlt, ob man von ClientSize nach Size oder umgekehrt rechnen muss. Und selbst, wenn man das wüsste, schlägt die Änderung nicht auf die zugrundeliegende Win32-Ebene durch - mit ungeklärten Auswirkungen auf dortige Koordinatenberechnungen.

Aber zu Glück sind die UpdateBounds-Überlegungen nur hypothetisch, da die Windows-Styles mein aktuelles Problem vollständig erschlagen.

Vielen Dank!

herbivore

S
54 Beiträge seit 2007
vor 15 Jahren

Hab dein Code einfach Kopiert und er geht ^^, nur versteh ich halt nur Bahnhof und er macht mir jetzt immer eine Clientsize von -4 ich will in meinem Control aber nur eine differenz von ClientSize <-> Size von 1, geht das?

sorry das ich diesen alten Thread ncohmal raushole.

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Schnueggel,

ich fürchte, das Problem liegt wirklich schon bei Win32. Scheinbar ist es doch gar nicht möglich, die ClientSize um beliebige Werte kleiner zu definieren als die Size, sondern es gibt nur bestimmte Vorgabewerte, die sich aus den Window-Styles ergeben.

So berechnet die Win32-Funktion AdjustWindowRect bzw. AdjustWindowRectEx nur aus den (extended) Windows-Styles und der ClientSize die Größe des Fenster (bzw. Controls), ohne dass man den Handle eines konkreten Fensters oder auch nur seine Fenster-Klasse angeben muss.

Mein Fazit ist: Wenn es unter den vorgegebenen Styles nichts passendes gibt, dann schaut man in die Röhre.

herbivore

S
54 Beiträge seit 2007
vor 15 Jahren

Ok schade, ich werd mich glaub auch mit 4px zufrieden geben,das ist genau die Rahmenbreite die bei XP angezeigt wird wenn man Irgendwelche Fenster vergrößert. Vielleicht kann ich es auch in diesem Sinne benutzen.

Ok, eben erst kapiert, ich glaub das ist was ich meinte.

So berechnet die Win32-Funktion AdjustWindowRect bzw. AdjustWindowRectEx...