Avatar billede Slettet bruger
14. november 2003 - 17:24 Der er 21 kommentarer og
2 løsninger

resize vindue/form til skærmstørrelse?

Hej X-perter! :-)

Jeg er i gang med at programmere et brugerinterface i Visual Basic.

Min projektvejleder efterspørger mulighed for, at når programmet startes, at det for det første altid kører i maksimeret vindue og for det andet, kan køres på flere forskellige skærmstørrelser (f.eks. 15", 17", 19" osv.)

At sikre sig at det kører maksimeret er meget nemt:

Form properites -> Windowstate -> 2 - Maximized

Problemet er at indholdet af formen.
Frames, listboxe, checkboxe, knapper osv. automatisk skal tilpasse sig (størrelseforhold og indbyrdes afstand) i forhold til skærmstørrelsen...

I MSDN-help har jeg læst om resize event, som skulle muliggøre dette - kodeeksemplet viser kun hvordan det gøres for en enkelt textboks....

Hvad gør man når der er mange forskellige "objekter" på formen?

Spørg hvis det ikke er forståeligt! :-)
Avatar billede driis Nybegynder
14. november 2003 - 17:28 #1
Du er nødt til at gøre det manuelt for hvert enkelt objekt på formen, der er ikke nogen nem måde.
Avatar billede heavybreezer Nybegynder
14. november 2003 - 17:58 #2
Driss har ret. Du skal gøre det manuelt for hvert enkelt objekt i din form.
Et eksempel kunne være:

Private Sub Form_Resize()
Command1.Left = Me.Width / 2
Command1.Top = Me.Top / 2
End Sub
Avatar billede martin_moth Mester
14. november 2003 - 19:36 #3
Jeg har lavet et program, hvor alle usercontrols resized afhængigt af formens aktuelle størrelse - og så har jeg en nedre grænse for hvor lille formen kan blive.

Det er bare at sætte alle kontrollers størrelse op som en funktion af formens størelse, og smide det hele i formens resize-event. Og så meget arbejde er der nu ikke i det...
Avatar billede kantoraza Nybegynder
14. november 2003 - 22:21 #4
Et andet udgangspunkt kunne simpelthen være at skifte skærmopløsningen!?

Link: http://pscode.com/vb/scripts/ShowCode.asp?txtCodeId=3840&lngWId=1

www.visonic.1go.dk/Index.html
Avatar billede sjh Nybegynder
15. november 2003 - 09:37 #5
Ja hvis det skal gøres automatisk så er den her nok den eneste mulighed.
http://www.vb-helper.com/howto_resize_controls_to_fit.html

Men ellers som driss og heavybreezer siger gør det manuelt...

Private Sub Form_Resize()
Dim fWidth  As Integer 'Form width
Dim fHeight As Integer 'Form height

  'Brug ScaleWidth/ScaleHeight og ikke Width/Height ellers kommer det ikke til at passe.
  fWidth = Me.ScaleWidth
  fHeight = Me.ScaleHeight

  With Command1 'Center CommandButton
      .Left = (fWidth / 2) - (.Width / 2)
      .Top = (fHeight / 2) - (.Height / 2)
  End With
End Sub
Avatar billede Slettet bruger
15. november 2003 - 16:08 #6
-> martin_moth
Kan jeg få dig til at smide et lille eksempel på hvordan du har gjort?

Min form er opdelt i 4 frames.
Hver frame er underopdelt i andre frames som indeholder knapper, listbox, combobox og labels...

->kantoraza

Hvis det kan lade sig gøre på en fornuftig måde som martin_moth skriver, vil jeg ikke til at rode med skærmopløsning

->sjh

Det er et genialt eksempel som du linker til!
Jeg kan bare ikke få det til at virke hmm...
Testede i første omgang eksemplet i et nyt projekt. Smed lige et par knapper, listboxe, frames m.m.
Og det fungerede fint!

Når jeg smider eksemplet ind i mit eget projekt får jeg følgende fejl:

Run-time error '393'
'Left' property cannot be read at run time

Debuggeren peger på følgende linie:

Private Sub SaveSizes()
Dim i As Integer
Dim ctl As Control

    ' Save the controls' positions and sizes.
    ReDim m_ControlPositions(1 To Controls.Count)
    i = 1
    For Each ctl In Controls
        With m_ControlPositions(i)
            If TypeOf ctl Is Line Then
--------------->.Left = ctl.X1<-------------------
                .Top = ctl.Y1
                .Width = ctl.X2 - ctl.X1
                .Height = ctl.Y2 - ctl.Y1
            Else
                .Left = ctl.Left
                .Top = ctl.Top
                .Width = ctl.Width
                .Height = ctl.Height
                On Error Resume Next
                .FontSize = ctl.Font.Size
                On Error GoTo 0
            End If
        End With
        i = i + 1
    Next ctl

    ' Save the form's size.
    m_FormWid = ScaleWidth
    m_FormHgt = ScaleHeight
End Sub

Jeg kalder proceduren 'SaveSizes' i Form_Load
og proceduren 'ResizeControls' i Form_Resize
som der foreskrives eksemplet, men får alligevel ovenstående fejl?
Avatar billede martin_moth Mester
15. november 2003 - 20:04 #7
Jeg gør præcis som f.eks. skitseret i det svar du fik 14/11-2003 17:58:01. Det er så ganske simpelt - udtryk alle dine kontrollers bredde/højde/placering som funktion af formens størrelse, som vist
Avatar billede Slettet bruger
16. november 2003 - 16:26 #8
->martin_moth

Ok helt i orden...

->sjh

Har fundet ud af hvorfor det kodeeksempel du henviser til ikke virker i mit projekt.
Hvis man eksempelvis har en timer-control inkluderet i sit program forsøger den at "resize" denne også - og det kan åbenbart ikke lade sig gøre...
Nu er det ikke lige en timer-control jeg har i mit projekt -  men derimod en ´
IO-control som muliggør kommunikation med COM-portene, og den kan jeg ikke undvære :-(

Kan jeg tage højde for det i min kode - altså at ekskludere en control fra at blive resizet?
Avatar billede martin_moth Mester
16. november 2003 - 16:33 #9
Du tjekker på typen inden du sorterer. Det er også vist i koden

If TypeOf ctl Is Blablabla Then
Avatar billede martin_moth Mester
16. november 2003 - 16:33 #10
Vrøvl - inden du resizer, ikke "sorterer"
Avatar billede Slettet bruger
16. november 2003 - 17:05 #11
->martin_moth

Jeg smider lige hele koden ind, så jeg kan fortælle hvor det går galt...
Ganske rigtigt som du siger, kan jeg tjekke på typen inden jeg sorterer (foregår i sub'en resize - se markering i koden)

Men jeg får allerede fejlen når formen ”loades” og hvor sub’en SaveSizes kaldes (fejlen opstår i linien – se tråd 15/11-2003 16:08:09)
Jeg har så forsøgt at tjekke på typen i sub’en SaveSizes ved at indsætte følgende kode

    If TypeOf ctl Is Timer Then
        .Left = 10
        .Top = 10
    End If

men det kan naturligvis ikke lade sig gøre, da man ikke kan kalde .Left og .Top på en timercontrol?? Jeg skal på en eller anden måde bare skippe resizing af timercontrollen..

Har du en idé til, hvordan jeg løser problemet?


Private Type ControlPositionType
    Left As Single
    Top As Single
    Width As Single
    Height As Single
    FontSize As Single
End Type

Private m_ControlPositions() As ControlPositionType
Private m_FormWid As Single
Private m_FormHgt As Single

' Save the form's and controls' dimensions.
Private Sub SaveSizes()
Dim i As Integer
Dim ctl As Control

    ' Save the controls' positions and sizes.
    ReDim m_ControlPositions(1 To Controls.Count)
    i = 1
   
    If TypeOf ctl Is Timer Then
   
       
    End If
   
    For Each ctl In Controls
        With m_ControlPositions(i)
            If TypeOf ctl Is Line Then
                .Left = ctl.X1
                .Top = ctl.Y1
                .Width = ctl.X2 - ctl.X1
                .Height = ctl.Y2 - ctl.Y1
            Else
                .Left = ctl.Left
                .Top = ctl.Top
                .Width = ctl.Width
                .Height = ctl.Height
                On Error Resume Next
                .FontSize = ctl.Font.Size
                On Error GoTo 0
            End If
        End With
        i = i + 1
    Next ctl

    ' Save the form's size.
    m_FormWid = ScaleWidth
    m_FormHgt = ScaleHeight
End Sub

' Arrange the controls for the new size.
Private Sub ResizeControls()
Dim i As Integer
Dim ctl As Control
Dim x_scale As Single
Dim y_scale As Single

    ' Don't bother if we are minimized.
    If WindowState = vbMinimized Then Exit Sub

    ' Get the form's current scale factors.
    x_scale = ScaleWidth / m_FormWid
    y_scale = ScaleHeight / m_FormHgt

    ' Position the controls.
    i = 1
    For Each ctl In Controls
        With m_ControlPositions(i)
            If TypeOf ctl Is Line Then
                ctl.X1 = x_scale * .Left
                ctl.Y1 = y_scale * .Top
                ctl.X2 = ctl.X1 + x_scale * .Width
                ctl.Y2 = ctl.Y1 + y_scale * .Height
            Else
                ctl.Left = x_scale * .Left
                ctl.Top = y_scale * .Top
                ctl.Width = x_scale * .Width
            --->If Not (TypeOf ctl Is ComboBox) Then<---
                    ' Cannot change height of ComboBoxes.
                    ctl.Height = y_scale * .Height
                End If
                On Error Resume Next
                ctl.Font.Size = y_scale * .FontSize
                On Error GoTo 0
            End If
        End With
        i = i + 1
    Next ctl
End Sub

Private Sub Form_Load()
    SaveSizes
End Sub

Private Sub form_Resize()
    ResizeControls
End Sub
Avatar billede martin_moth Mester
16. november 2003 - 17:57 #12
Nu har jeg ikek lige lkæst din kode igennem. Men hvorfor sætter du .width og .Height på din timer når du VED at de giver fejl. Tjek om den aktuelle kontrol er en timer - er den det, springer du den over, og sætter IKKE .width og .Heigth for kontrollen...
Avatar billede Slettet bruger
16. november 2003 - 19:34 #13
->martin_moth.

Ja det kan jeg jo selvfølgelig godt se er tåbeligt :-)
Det var mest for at illustrere at jeg godt kan tjekke om den akutelle kontrol er en Timer-control.
Men hvordan springer jeg den over??
Avatar billede sjh Nybegynder
16. november 2003 - 20:46 #14
du kan bruge: ElseIf Not TypeOf ctl Is Timer Then

    For Each ctl In Controls
        With m_ControlPositions(i)
            If TypeOf ctl Is Line Then
                .Left = ctl.X1
                .Top = ctl.Y1
                .Width = ctl.X2 - ctl.X1
                .Height = ctl.Y2 - ctl.Y1
            ElseIf Not TypeOf ctl Is UserControl Or _
                  Not TypeOf ctl Is Timer Then
                .Left = ctl.Left
                .Top = ctl.Top
                .Width = ctl.Width
                .Height = ctl.Height
                On Error Resume Next
                .FontSize = ctl.Font.Size
                On Error GoTo 0
            End If
        End With
        i = i + 1
    Next ctl
Avatar billede Slettet bruger
16. november 2003 - 21:18 #15
->sjh

Har "pastet" din kode over i eksemplet som du linkede til.
Har derefter indsat en timer-control i mit projekt..
Når programmet køres får jeg igen fejlen

Run-time error '393'
'Left' property cannot be read at run time

Debuggeren peger på følgende linje
ElseIf Not TypeOf ctl Is UserControl Or _
                  Not TypeOf ctl Is Timer Then
            ------>.Left = ctl.Left<----

Ser ud som om den stadig forsøger at sætte en left-property på timer-controllen..
Har du nogen forslag?
Avatar billede sjh Nybegynder
16. november 2003 - 21:27 #16
så brug (On Error Resume Next)

Private Sub SaveSizes()
Dim i As Integer
Dim ctl As Control

  On Error Resume Next
.........
...........
.............
Avatar billede Slettet bruger
16. november 2003 - 21:43 #17
->sjh

Efter at have indsat

On Error Resume Next

Fik jeg en ny fejl:
Denne gang i ResizeControls()
Samme fejl som før

Run-time error '393'
'Left' property cannot be read at run time

Debuggeren pegede på denne linje:

Else
            --->ctl.Left = x_scale * .Left<---
                ctl.Top = y_scale * .Top

Jeg satte igen: On Error Resume Next ind i koden

Her (i ResizeControls)

Dim x_scale As Single
Dim y_scale As Single
-->On Error Resume Next<--

Og nu virker det!

Jeg ved ikke om det er den helt "rigtige" måde at løse sådant et problem på, men det virker ihvertfald..

->martin_moth

Jeg synes du fortjener del i pointene så smid lige et svar hvis du er interesseret.. ellers går pointene til sjh :-)
Avatar billede Slettet bruger
16. november 2003 - 21:58 #18
Sådan noget tis!!
Hvis jeg tilføjer endnu en timer-control til formen, så brokker den sig igen

Fejlen denne gang hedder:

Run-time error '382'
'Left' property cannot be read at run time

Bemærk anden fejlkode denne gang 382 i stedet for 393
Avatar billede Slettet bruger
16. november 2003 - 22:02 #19
Ok... dette problem er også løst..

i ResizeControls indsættes denne linje

ElseIf Not TypeOf ctl Is Timer Then

i stedet for denne linje

  ctl.Y2 = ctl.Y1 + y_scale * .Height
-->Else<--
  ctl.Left = x_scale * .Left
Avatar billede martin_moth Mester
17. november 2003 - 16:29 #20
Din lærer ser sikekrt gerne at du forstår hvad du laver.
Derfor synes jeg du skulle resize alle dine kontroller "manuelt" under formens resize-event - så ved du hvad der sker...
Avatar billede Slettet bruger
17. november 2003 - 16:52 #21
->martin_moth

Jeg kan ikke udtale mig om, hvad min lærer gerne ser og ikke ser...
Jeg har endnu ikke besluttet om, koden som sjh har henvist til skal indgå i det endelige projekt...
Desuden synes jeg det er noget bøvl, at skulle sidde og resize samtlige kontroller manuelt.
Har allerede forsøgt med dit princip - men inden jeg får placeret den første frame inklusive knapper m.m. skal jeg køre programmet en masse gang for at se det stemmer visuelt, og det er det simpelthen ikke værd.

Med mindre du har mere at tilføje (eventuelt et svar for at få del i pointene) så lukker jeg spørgsmålet..
Avatar billede martin_moth Mester
17. november 2003 - 16:56 #22
Ikke mere at tilføje :o)
Avatar billede Slettet bruger
17. november 2003 - 16:58 #23
Ok - så lukker jeg spørgsmålet..

STOR tak til alle som har gidet beskæftige sig med mit spørgsmål

->sjh
Jeg har forøget point-antallet lidt...
samtidig tillader jeg, at give mig selv lidt point for at løse nogle af problemerne selv..
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester