How to get mousedown (or click) event to fire on a picturebox in a worker thread

JBDayrelton 20 Reputation points
2023-09-19T16:48:35.8666667+00:00

VB.net VS20022 Windows 10

In my base UI form I create a new form which has a picturebox in a container (this is a general-purpose form for drawing and all other controls on it are disabled and not displayed)

The 2nd form overlays the bottom portion of the 1st form with the 1st form's controls at the top. (thus the 2nd form covers most of the 1st form)

In the worker, I access files and create a bitmap for each and draw their data on their respective bitmaps. At the top of each bitmap are the filenames of all the files in designated areas across the top.

Each bitmap is displayed in the picturebox as drawing on its bitmap is completed. (thus the last bitmap displayed has the names of all the files across its top - as do all the other bitmaps as they were updated when new files processed)

In the background worker I can access the mouse position in the picturebox with PointToClient(Cursor.Position) and display the coordinates thru invokerequired to a label in 1st form as I pan across the picturebox.

What I cannot do is detect a mousedown (or click) in the picturebox on the 2nd form (these events are defined in the 2nd form's design and code)

I thus want to get the event for mousedown or click to fire so I can obtain the coordinates in the event sub (thus I can identify if the user selected a file to be display and load the corresponding bitmap in the picturebox.

Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,884 questions
VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,714 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Jiachen Li-MSFT 31,011 Reputation points Microsoft Vendor
    2023-09-20T07:02:19.5366667+00:00

    Hi @JBDayrelton ,

    In a Windows Forms application, you cannot directly handle UI events like MouseDown inside a BackgroundWorker, as UI events are supposed to be handled on the UI thread. You can refer to the following code:

    Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown
        If e.Button = MouseButtons.Left Then
            BackgroundWorker1.RunWorkerAsync()
        End If
    End Sub
    
    Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        ' Perform background work here.
        ' You can access e.Argument to get any data you passed from the UI thread.
    End Sub
    
    

    If you need to pass data from the UI thread to the background worker, you can do so by setting the e.Argument property in the MouseDown event handler before calling RunWorkerAsync().

    Keep in mind that if your background work involves updating the UI, you should use the ProgressChanged event and the ReportProgress method to communicate between the background thread and the UI thread for updating the UI in a thread-safe manner. This ensures that you don't encounter cross-threading issues.

    Best Regards.

    Jiachen Li


    If the answer is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  2. JBDayrelton 20 Reputation points
    2023-09-26T22:26:08.1533333+00:00

    Here is how I solved it with no cross-threading issues. I have 3 forms layered: backmost is the main form, the UI; the next is a general-purpose drawing/printing form updating in a background worker; the topmost is a transparent form aligned with the picturebox in the drawing from.

    While this may appear to be a complex solution, it meets all the requirements of the application. The two key aspects are the drawing form communicating to the UI via invokerequired logic, and the transparent form communicating the occurrence of a mouse click to the UI via a set property. (This methodology can be applied generally where you need to capture clicks on a form in a background worker as the mouse clicks will not fire in the worker.)

    The Mouse position in the picturebox on the drawing form is captured with PointToClient(Cursor.Position) in a tight loop while looking for data files to occur in a directory. The mouse position is thus continuously sent to a UI form label via invokerequied to update a label's text with the mouse coordinates - label used for visual confirmation.

    A click event is received by the transparent and a message "MouseClick" is sent via a set property on the UI form which is essentially and interrupt. As the UI knows the position of the mouse, code inside the set can determine which form area has been selected; and, since the UI knows the mouse coordinates reported by the drawing form, it knows where the mouse click occurred in the picturebox; and lastly, if the click occurred in one of the 'file name' areas, its corresponding bitmap is displayed in the picturebox via a set property in the drawing form.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.