none
Return value in DLL Class after various functions

    Question

  • Hi

    Most likely to be an easy one to the experts, bit of a head scratcher or me....

    I have a class that gets a screen shot from a rectangle (like a cookie cutter). I need it to load when I click a button. I am currently doing it like this:

    Dim GetRect as New WinRect.cCapture 'the New() method loads the form inside the class

    The issue I am having is that I need the WinRect form to load, let me capture manually and return the captured image back before my button code proceeds to the end of the method. currently, as soon as the WinRect form loads, my main code continues before I have captured the image. So, this is what I need to do:

    • Click main button to load capture method form from the WinRect class
    • manually capture and click my capture button on my capture form
    • return the captured image as a member
    • continue to the end of my main button method

    What is the best way to do this and get my method to wait until I receive the image back from the class?

    Thanks

    Nacho


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Tuesday, December 05, 2017 9:31 AM

All replies

  • Using the newer Framework (see the following) we can use the pattern below. There is a one second delay after the save to disk.

    Demo https://1drv.ms/u/s!AtGAgKKpqdWjiQCFsakm3pYwuIVv

    Imports System.Drawing.Imaging
    
    Public Class Form1
        Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim ops As New WinRect
            Dim bm As Bitmap = Nothing
    
            Await Task.Run(
                Sub()
                    bm = ops.Capture
                End Sub)
            bm.Save(IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Screenshot.png"), ImageFormat.Png)
            Await Task.Delay(1000)
            Console.WriteLine("Done")
        End Sub
    
    End Class

    Class

    Imports System.Drawing.Imaging
    Public Class WinRect
        Public Function Capture() As Bitmap
    
            'Create a new bitmap.
            Dim bmpScreenshot = New Bitmap(
                Screen.PrimaryScreen.Bounds.Width,
                Screen.PrimaryScreen.Bounds.Height,
                PixelFormat.Format32bppArgb)
    
            ' Create a graphics object from the bitmap.
            Dim gfxScreenshot = Graphics.FromImage(bmpScreenshot)
    
            ' Take the screenshot from the upper left corner to the right bottom corner.
            gfxScreenshot.CopyFromScreen(
                Screen.PrimaryScreen.Bounds.X,
                Screen.PrimaryScreen.Bounds.Y, 0, 0,
                Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy)
    
            Return bmpScreenshot
    
        End Function
    End Class

    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites






    Tuesday, December 05, 2017 10:31 AM
    Moderator
  • Some things are not clear to me. First, do you have access to the code for the WinRect form application? I assume not since that would probably make it easier but it would help to know for sure. Also, it is not clear what is doing the capturing. You say "click my capture button on my capture form" so that implies you have access to the code for the form. I am confused.

    I am not sure if the capturing is done in the same process or a different process. Is the WinRect form part of the same application?



    Sam Hobbs
    SimpleSamples.Info

    Tuesday, December 05, 2017 7:46 PM
  • Hi

    Thanks for the reply. WinRect is my Class project so i have access to all of the code. What it does:

    Loads a full screen form with a movable rectangle that i can position and resize to get a screen capture from the rectangle. When i have position the rectangle correctly, i click a capture button that gets the image from the rectangle and stores it as a binary object in a public Member.

    WinRect is a separate class within the project. ( i made it separately and added the project to my main project). It is compiled as a DLL that i reference in my main project. As its a referenced DLL, it should be using the same process. What i need to happen is something like:

    Dim GetRect As New WinRect.cCapture
    
    'pause until WinRect process has been completed or cancelled
    'Winrect will capture image and store it in the Public Member CapturedImage
    
    Try
      Call UpdateImageData(GetRect.CapturedImage)
    
    Catch ex As Exception
      Call UpdateImageData(My.Resources.DefaultImage)
    
    End Try

    Thanks

    Nacho



    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Tuesday, December 05, 2017 8:30 PM
  • Perhaps all your problems can be solved by Form.ShowDialog. You are probably using "Show" to show the form. If you use ShowDialog then the main form won't work (by design and that is what you want) while the other form is shown. Then when the other form is closed the main form will continue.


    Sam Hobbs
    SimpleSamples.Info

    Tuesday, December 05, 2017 9:17 PM
  •  Normally you would have public events that you have added or ones that already exist in your dll class library that you would raise from withing the class library when something has finished,  started,  or changed.  Those events can be subscribed to in your Form's application to notify it that something is finished, started, or changed.  You would wait for that event to be raised in your Form's class and then continue.

     If you still need access to the main form or other forms at the same time the dll form is opened,  then instead of using ShowDialog,  use the Show method and just subscribe to the dll form's Closing event when you create the new instance of it inside your main application's Form class.  Place code inside that event to retrieve the captured image from a Public Property in the dll form.

     Also,  on a side note,  you do not need to use the old VB6 Call word to call a method in modern VB.Net,  you can just write the method name to call the methods....

    Try
      UpdateImageData(GetRect.CapturedImage)
    
    Catch ex As Exception
      UpdateImageData(My.Resources.DefaultImage)
    
    End Try


    If you say it can`t be done then i`ll try it


    • Edited by IronRazerz Wednesday, December 06, 2017 11:22 PM
    Wednesday, December 06, 2017 9:33 PM
  • Hi

    Yes. I dont actually put 'Call' in my VB code. I am working also in VBA with Inventor to quick test (as inventor requires a full restart for every test usng vb.net) and i typed it without thinking....

    I have private event that i can change to a public event no problem.

    originally i wanted a separate form class that i could reference from my project and simply call the form and get the image back in a couple of lines of code. For example:

    MyPictureBox.Image = New WinRect()

    or

    Dim GetRect As New WinRect.CapRect()

    MyPictureBox.Image = GetRect.CapturedImage

    However, Even though the CapturedImage member is Public, it didnt seem to be available in intellisense... I have since copied the code & forms into my main project instead of referencing a project :(

    I would have preferred the Class to be separate allowing me to reference it and call the form but i couldnt seem to set it up correctly. (Something i will no doubt learn how to do).

    Thanks

    Nacho


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, December 06, 2017 11:18 PM
  • Hi Karen

    Thanks for the reply and sample. Am i able to add a form to the WinRect Class and use that, click a complete button and then return to the Async method to complete the process?

    Is it as simple as just adding the form and it will naturally behave this way?

    Thanks


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Thursday, December 07, 2017 7:12 PM