none
[VB2005] Frage zu Panel, Size <--> ClientSize RRS feed

  • Frage

  • Hi Leute.

    Eine kurze aber doch recht grundsätzliche Frage zu Frames: Angenommen ich habe ein Frame von 100x100 Pixeln (entspricht vll. einem Client-Size von 90x90, wegen Abzügen durch Scrollbars und so), will aber in diesem einen scrollbaren Inhalt von 500x500 anzeigen. Nun überschreib ich die OnPaint und male dort ein 500x500 großes Bild. Aber wie sag ich dem Control (Panel), dass sein eigentlicher Inhalt nicht 100x100 ist, sondern 500x500?

    Weil ich bekomme ja so erstmal keine Scrollbars. Und Size ist ja Teil von Bounds, sprich dem Außenrechteck, also dem des Controls, nicht seines (virtuellen) Inhaltes. Und ClientRectangle isses auch nicht (das ist doch der Ausschnitt innerhalb des Controls, also ca. 90x90). Ich frage mich, "wessen Size" ich dann manipulieren muss, damit das blöde Ding endlich die Scrollbars anzeigt bzw. richtig einstellt, so dass ich auch wirklich auf 500x500 rumscrollen kann.

    Kann mir da einer helfen?

    Als Krücke hab ich anfangs ein kleines eingebettetes Control eingefügt (irgend ne Picturebox oder so, Größe 1x1), das einfach auf 500x500 positioniert war. Dann klappte es und ich bekam Scrollbars angezeigt. Aber das wäre doch ein schlechter Witz, wenn es nur so gehen würde. :-)

    LG, Dennis.

    Freitag, 9. Dezember 2011 13:51

Antworten

  • Hallo,

    wenn Du AutoScroll aktivierst, bestimmt sich die Größe über die AutoScrollMinSize.

    Als Beispiel mal ein Control, das ich für ein Testprojekt gebastelt hatte, um Bitmaps anzuzeigen und optional die Anzeige zu skalieren:

    Imports System.ComponentModel
    Imports System.Drawing
    Imports System.Drawing.Drawing2D
    Imports System.Windows.Forms
    
    Namespace ElmarBoye.Samples.Forms
        Public Class BitmapPanel
            Inherits System.Windows.Forms.Panel
            Private _bitmap As Bitmap
            Private _zoom As Single
    
            Public Sub New()
                MyBase.SetStyle(ControlStyles.ResizeRedraw, True)
                MyBase.SetStyle(ControlStyles.UserPaint Or ControlStyles.AllPaintingInWmPaint, True)
                MyBase.AutoScroll = True
    
                Me._zoom = 1F
            End Sub
    
    
            <DefaultValue(1F)> _
            Public Property Zoom() As Single
                Get
                    Return Me._zoom
                End Get
                Set
                    If Me._zoom <> value Then
                        Me._zoom = value
                        Me.ZoomBitmap()
                    End If
                End Set
            End Property
    
            <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
            Public Property Bitmap() As Bitmap
                Get
                    Return Me._bitmap
                End Get
                Set
                    If Me._bitmap IsNot value Then
                        Me._bitmap = value
                        Me._zoom = 1F
                        Me.ZoomBitmap()
                    End If
                End Set
            End Property
    
            Private Sub ZoomBitmap()
                If Me.Bitmap IsNot Nothing Then
                    MyBase.AutoScrollMinSize = New Size( _
                        CInt(Math.Truncate(Me.Bitmap.Width * Me.Zoom)), _
                        CInt(Math.Truncate(Me.Bitmap.Height * Me.Zoom)))
                Else
                    MyBase.AutoScrollMinSize = Size.Empty
                End If
                Me.Invalidate()
            End Sub
    
            Protected Overrides Sub OnPaint(e As PaintEventArgs)
                MyBase.OnPaint(e)
    
                If Me.Bitmap IsNot Nothing Then
                    e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic
    
                    Dim bounds As New Rectangle( _
                        CInt(Math.Truncate(Math.Floor(-MyBase.AutoScrollPosition.X / Me.Zoom))), _ CInt(Math.Truncate(Math.Floor(-MyBase.AutoScrollPosition.Y / Me.Zoom))), _ CInt(Math.Truncate(Math.Ceiling(MyBase.DisplayRectangle.Width / Me.Zoom))), _ CInt(Math.Truncate(Math.Ceiling(MyBase.DisplayRectangle.Height / Me.Zoom))))
    
                    e.Graphics.DrawImage(Me.Bitmap, _
                        New Rectangle(Point.Empty, MyBase.DisplayRectangle.Size), _
                        bounds, _
                        GraphicsUnit.Pixel)
                End If
            End Sub
    
            Protected Overrides Sub OnDoubleClick(e As EventArgs)
                MyBase.OnDoubleClick(e)
                If Not MyBase.DesignMode AndAlso Me.Bitmap IsNot Nothing Then
                    If Me.Zoom <> 1F Then
                        MyBase.AutoScrollMinSize = Me.Bitmap.Size
                        Me.Zoom = 1F
                    Else
                        Dim panelScale As Double = CDbl(Me.Width) / CDbl(Me.Height)
                        Dim bitmapScale As Double = CDbl(Me.Bitmap.Width) / CDbl(Me.Bitmap.Height)
                        Dim zoom As Double = If((bitmapScale >= panelScale), _
                            CDbl(MyBase.Width) / CDbl(Me.Width), _
                            CDbl(MyBase.Height) / CDbl(Me.Bitmap.Height))
    
                        Me.Zoom = CSng(zoom)
                    End If
                End If
            End Sub
        End Class
    End Namespace
    
    

    Evtl. kannst Du Du Dir daraus einiges abgucken.

    Gruß Elmar

    Samstag, 10. Dezember 2011 19:24
    Beantworter

Alle Antworten

  • Hallo,

    wenn Du AutoScroll aktivierst, bestimmt sich die Größe über die AutoScrollMinSize.

    Als Beispiel mal ein Control, das ich für ein Testprojekt gebastelt hatte, um Bitmaps anzuzeigen und optional die Anzeige zu skalieren:

    Imports System.ComponentModel
    Imports System.Drawing
    Imports System.Drawing.Drawing2D
    Imports System.Windows.Forms
    
    Namespace ElmarBoye.Samples.Forms
        Public Class BitmapPanel
            Inherits System.Windows.Forms.Panel
            Private _bitmap As Bitmap
            Private _zoom As Single
    
            Public Sub New()
                MyBase.SetStyle(ControlStyles.ResizeRedraw, True)
                MyBase.SetStyle(ControlStyles.UserPaint Or ControlStyles.AllPaintingInWmPaint, True)
                MyBase.AutoScroll = True
    
                Me._zoom = 1F
            End Sub
    
    
            <DefaultValue(1F)> _
            Public Property Zoom() As Single
                Get
                    Return Me._zoom
                End Get
                Set
                    If Me._zoom <> value Then
                        Me._zoom = value
                        Me.ZoomBitmap()
                    End If
                End Set
            End Property
    
            <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
            Public Property Bitmap() As Bitmap
                Get
                    Return Me._bitmap
                End Get
                Set
                    If Me._bitmap IsNot value Then
                        Me._bitmap = value
                        Me._zoom = 1F
                        Me.ZoomBitmap()
                    End If
                End Set
            End Property
    
            Private Sub ZoomBitmap()
                If Me.Bitmap IsNot Nothing Then
                    MyBase.AutoScrollMinSize = New Size( _
                        CInt(Math.Truncate(Me.Bitmap.Width * Me.Zoom)), _
                        CInt(Math.Truncate(Me.Bitmap.Height * Me.Zoom)))
                Else
                    MyBase.AutoScrollMinSize = Size.Empty
                End If
                Me.Invalidate()
            End Sub
    
            Protected Overrides Sub OnPaint(e As PaintEventArgs)
                MyBase.OnPaint(e)
    
                If Me.Bitmap IsNot Nothing Then
                    e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic
    
                    Dim bounds As New Rectangle( _
                        CInt(Math.Truncate(Math.Floor(-MyBase.AutoScrollPosition.X / Me.Zoom))), _ CInt(Math.Truncate(Math.Floor(-MyBase.AutoScrollPosition.Y / Me.Zoom))), _ CInt(Math.Truncate(Math.Ceiling(MyBase.DisplayRectangle.Width / Me.Zoom))), _ CInt(Math.Truncate(Math.Ceiling(MyBase.DisplayRectangle.Height / Me.Zoom))))
    
                    e.Graphics.DrawImage(Me.Bitmap, _
                        New Rectangle(Point.Empty, MyBase.DisplayRectangle.Size), _
                        bounds, _
                        GraphicsUnit.Pixel)
                End If
            End Sub
    
            Protected Overrides Sub OnDoubleClick(e As EventArgs)
                MyBase.OnDoubleClick(e)
                If Not MyBase.DesignMode AndAlso Me.Bitmap IsNot Nothing Then
                    If Me.Zoom <> 1F Then
                        MyBase.AutoScrollMinSize = Me.Bitmap.Size
                        Me.Zoom = 1F
                    Else
                        Dim panelScale As Double = CDbl(Me.Width) / CDbl(Me.Height)
                        Dim bitmapScale As Double = CDbl(Me.Bitmap.Width) / CDbl(Me.Bitmap.Height)
                        Dim zoom As Double = If((bitmapScale >= panelScale), _
                            CDbl(MyBase.Width) / CDbl(Me.Width), _
                            CDbl(MyBase.Height) / CDbl(Me.Bitmap.Height))
    
                        Me.Zoom = CSng(zoom)
                    End If
                End If
            End Sub
        End Class
    End Namespace
    
    

    Evtl. kannst Du Du Dir daraus einiges abgucken.

    Gruß Elmar

    Samstag, 10. Dezember 2011 19:24
    Beantworter
  • Hi Elmar,

    das probiere ich mal aus, ob das nur mit Autosize und ohne "Hilfscontrols" klappt. Danke dir.

    Ich gehe aber mal davon aus, dass dann die linke obere Ecke immer (0,0) ist und AutoScrollMinSize halt die maximale Ausdehnung des be'scroll'ten Bereichs. Oder kann man da auch ein anderes Eckoffset verwenden als (0,0)? Im Zweifelsfall muss ich dann immer umrechnen auf Fensterkoordinaten, denke ich.

    LG, Dennis.

    Freitag, 16. Dezember 2011 10:18
  • Hallo Dennis,

    die "linke, obere Ecke" bezieht sich auf das Steuerelement.
    Will man einen anderen Ausschnitt zeigen, so muss man wie gezeigt, den Ausschnitt an jene Position verschieben.

    Gruß Elmar

    Freitag, 16. Dezember 2011 12:36
    Beantworter
  • Hallo Dennis Becker,

    Ich gehe davon aus, dass die Antwort Dir weitergeholfen hat.
    Solltest Du noch "Rückfragen" dazu haben, so gib uns bitte Bescheid.

    Grüße,
    Robert


    Robert Breitenhofer, MICROSOFT  Twitter Facebook
    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Mittwoch, 21. Dezember 2011 16:29
    Moderator