Meerdere images opslaan als één

Status
Niet open voor verdere reacties.

MarnixICT

Gebruiker
Lid geworden
15 okt 2011
Berichten
182
Hallo iedereen,

Ik ben bezig om een programma te ontwikkelen om volgens X en Y coördinaten een plaatje op de juiste positie wordt weergegeven in een bovenaanzicht en zijaanzicht van een watersilo.

De bedoeling is zodra alle rondjes op de juiste posities staan, alles wordt opgeslagen als een foto (of als het beter kan iets van een PDF). De plaatjes moeten wel op de juiste posities blijven staan. Weet iemand hoe dit moet?

Ik heb wel wat kennis van VisualBasic, maar op grafisch gebied niet. Ik gebruik nu pictureboxes.
helpmij-images-opslaan.png


Maakt mij in principe niet uit hoe het word opgeslagen, als het resultaat maar een foto/pdf/excel is dat iedereen kan openen. (mocht het niet kunnen/lukken, kan ik een form maken dat het voorbeeld laat zien. Hiervan kan een alt+printscreen gemaakt worden maar ik weet niet hoe ook dat opgeslagen kan worden).

Alvast bedankt voor de tijd en moeite!


Marnix
 
Laatst bewerkt:
Ik zou even moeten zoeken, maar volgens mij kun je (kon vroeger iig) je hele canvas van je form opslaan.

Een printscreen kan als volgt:
Code:
        Dim RH As Rectangle
        RH.Size = Me.Size
        Dim plaatje As New Bitmap(RH.Width, RH.Height)
        Me.DrawToBitmap(plaatje, RH)
        ' hier kan je verder met je screenshot bijvoorbeeld naar clipboard
        'Clipboard.SetImage(plaatje)

toegang tot het canvas zou ik na moeten kijken of dat nog steeds kan.
 
Wampier,

Bedankt voor je reactie en de code die je hebt gegeven.
Als het hele canvas opgeslagen kan worden, zou dat helemaal super zijn.


Als dat niet kan, is het mogelijk om het 'plaatje' ook al op te slaan? Dat is al genoeg denk ik. Ik geef namelijk de optie om een voorbeeld te bekijken, en van dat voorbeeld wil ik dan een printscreen laten maken en opslaan als foto.

alvast bedankt,

Marnix
 
Laatst bewerkt:
je kunt:
Code:
plaatje.Save("c:\test.jpg", System.Drawing.Imaging.ImageFormat.jpeg)
toevoegen om de screenshot te saven.

je kunt ook voor het opslaan van het plaatje zoiets doen:

me.formborderstyle = FormBorderStyle.None

en na het maken van de screenshot weer terugzetten. de knoppen worden dan niet meegesaved in het plaatje.

Code:
        Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
        Dim RH As Rectangle
        RH.Size = Me.Size
        Dim plaatje As New Bitmap(RH.Width, RH.Height)
        Me.DrawToBitmap(plaatje, RH)
        plaatje.Save("c:\test.jpg", System.Drawing.Imaging.ImageFormat.jpeg)
        Me.FormBorderStyle = Windows.Forms.FormBorderStyle.Sizable

dit maakt een screenshot zonder borders, saved het naar C:\test.jpg en plaatst de border weer terug.
 
Wampier,

Ik heb de code getest, en het lijkt alsof de D-plaatjes en de hulplijnen die op het boven- en zijaanzicht staan, wegvallen. Normaal hoort er ook linksonder het bovenaanzicht een pijl te staan, maar die is ook achter de picturebox van het bovenaanzicht gevallen.
(X en Y is voor bovenaanzicht, E en H voor zijaanzicht).

test.jpg



EDIT:
Ik heb de volgende code gevonden op Stackoverflow en ik heb 'm aangepast:

Code:
        Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None

        Dim bmpScreenShot As Bitmap
        Dim gfxScreenshot As Graphics

        bmpScreenShot = New Bitmap(Me.Bounds.Width, Me.Bounds.Height)
        gfxScreenshot = Graphics.FromImage(bmpScreenShot)

        gfxScreenshot.CopyFromScreen(Me.Bounds.X, Me.Bounds.Y, 0, 0, Me.Bounds.Size, CopyPixelOperation.SourceCopy)
        bmpScreenShot.Save("c:\test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg)

        Me.FormBorderStyle = Windows.Forms.FormBorderStyle.FixedSingle

en het werkt!

test2.jpg


Nadeel hiervan is dat het er gebruik word gemaakt van de printscreen functie. Elk beeldscherm is weer anders en het venster is redelijk groot. Het venster past bijvoorbeeld niet op beeldschermen met een resolutie van 1024*786. Ook moet het venster actief zijn en er moeten geen andere vensters voor staan (TopMost gebruiken).

Mocht er toch een oplossing zijn om een canvas te gebruiken zou dat nog beter zijn. Bedankt voor de hulp tot zover en mocht je er wel achter komen hoe het met een canvas kan werken zie ik het wel in dit topic.
 
Laatst bewerkt:
Heb er speciaal met een leraar programmeren naar gekeken en het blijkt dus dat het opslaan van die bitmap een veel voorkomende bug is bij VStudio. De Z-volgorde wordt bij het opslaan van een bitmap omgedraaid. Om dit te voorkomen moet de bitmap worden opgeslagen met een omgekeerde Z-volgorde.
Deze code is op het internet verschenen om het probleem op te lossen:

Code:
Const WM_PRINT As Integer = &H317
    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Select Case m.Msg
            Case WM_PRINT
                Me.SuspendLayout()
                Try
                    Me.ReverseControlsCollection(Me)
                Catch ex As Exception
                    'dont throw an error on the control order failing
                    'If the order fails, the second call (below) will set the indexes back
                End Try
                MyBase.WndProc(m)
                Try
                    Me.ReverseControlsCollection(Me)
                Catch ex As Exception
                    'dont throw an error on the control order failing
                End Try
                Me.ResumeLayout(False)
                Return
        End Select
        MyBase.WndProc(m)
    End Sub

    Sub ReverseControlsCollection(ByVal pControl As Control)
        If pControl.Controls.Count > 0 Then
            For Each lControl As Control In pControl.Controls
                ReverseControlsCollection(lControl)
            Next
        End If
        Dim max As Integer = pControl.Controls.Count - 1
        For i As Integer = max To 1 Step -1
            pControl.Controls.SetChildIndex(pControl.Controls(max), max - i)
        Next
    End Sub

    Private Function GetFormImage(ByVal include_borders As Boolean) As Bitmap
        ' Make the bitmap.
        Dim wid As Integer = Me.Width
        Dim hgt As Integer = Me.Height
        Dim bm As New Bitmap(wid, hgt)

        ' Draw the form onto the bitmap.
        Me.DrawToBitmap(bm, New Rectangle(0, 0, wid, hgt))

        ' If we want the borders, return the bitmap.
        If include_borders Then Return bm

        ' Make a smaller bitmap without borders.
        wid = Me.ClientSize.Width
        hgt = Me.ClientSize.Height
        Dim bm2 As New Bitmap(wid, hgt)

        ' Get the offset from the window's corner to its client
        ' area's corner.
        Dim pt As New Point(0, 0)
        pt = PointToScreen(pt)
        Dim dx As Integer = pt.X - Me.Left
        Dim dy As Integer = pt.Y - Me.Top

        ' Copy the part of the original bitmap that we want
        ' into the bitmap.
        Dim gr As Graphics = Graphics.FromImage(bm2)
        gr.DrawImage(bm, 0, 0, New Rectangle(dx, dy, wid, hgt), GraphicsUnit.Pixel)
        Return bm2
    End Function

Mochten meer mensen hier problemen mee hebben: Plak de bovenstaande code gewoon ergens binnen de class van het form.
Plaats een "opslaan" button om de bitmap op te slaan:

Code:
Private Sub Save_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Save_Button.Click
        'Save_Button.Visible = False als de knop niet in de bitmap voor mag komen.
        Try
            Dim uitvoer_image As Bitmap = GetFormImage(False)
            uitvoer_image.Save(SaveFileDialog1.FileName, System.Drawing.Imaging.ImageFormat.Jpeg)
        Catch ex As Exception
            MsgBox("Er is een fout opgetreden: " & ex.Message, MsgBoxStyle.Critical, "Fout")
        End Try
        'Save_Button.Visible = True
End Sub

Of maak er een publieke functie van, zodat het canvas kan worden opgeslagen, zodat het van andere forms kan worden aangeroepen:

Code:
Public Function opslaan()
        Try
            Dim uitvoer_image As Bitmap = GetFormImage(False)
            uitvoer_image.Save(SaveFileDialog1.FileName, System.Drawing.Imaging.ImageFormat.Jpeg)
        Catch ex As Exception
            MsgBox("Er is een fout opgetreden: " & ex.Message, MsgBoxStyle.Critical, "Fout")
            Return False
        End Try
        Return True
    End Function
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan