How to access "My" from a thread?

JumpyNET

Centurion
Joined
Apr 4, 2005
Messages
196
I'm trying to acces "My.Computer.Clipboard" from a thread and I get an error "Object reference not set to an instance of an object.". Any ideas where I go wrong??


Here is my code (Form1 + one class). The program listens for a printscreen press in a low priority thread. And once the print screen is pressed it should save the picture to disk, but thats when I get the error.

Form1 code:
Code:
Public Class Form1





    Public Shared Snooper As New SnoopClass
    Public Shared ImageCounter As Integer = 0


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        'Start snooping for Print Screen key press
        Snooper.StartSnoopingThread()
        AddHandler Snooper.MainLoopClass.PrntScrPressed, AddressOf PrntScrnPressed

    End Sub

    Public Shared Sub PrntScrnPressed()

        'Increment image counter
        ImageCounter += 1
        'Set image name
        Dim ImgName As String = IO.Path.Combine("C:\temp", "Capt Screen " & ImageCounter & ".png")
        'Get image from clipboard
        Dim ClipImage As Image = My.Computer.Clipboard.GetImage()
        'Save image to selected path
        ClipImage.Save(ImgName, System.Drawing.Imaging.ImageFormat.Png)

    End Sub




End Class


SnoopClass code:
Code:
Imports System.Threading

Public Class SnoopClass

    Private Declare Function GetKeyState Lib "user32" (ByVal KeyCode As Integer) As Integer

    Public Class MainLoopClass

        Public Shared Event PrntScrPressed()

        Private Shared PrntScrn_mem As Boolean = False

        Public Sub MainLoop()

            While True

                If IsKeyPressedPosEdge(44, PrntScrn_mem) Then
                    RaiseEvent PrntScrPressed()
                End If

            End While

        End Sub

        Public Function IsKeyPressed(ByVal KeyCode As Integer) As Boolean
            Dim RetVal As Boolean = False

            Dim KeyStat As Integer = GetKeyState(KeyCode)
            If KeyStat < -1 Or KeyStat > 1 Then
                RetVal = True
            End If

            Return RetVal
        End Function

        Public Function IsKeyPressedPosEdge(ByVal KeyCode As Integer, ByRef MemoryBit As Integer) As Boolean
            Dim RetVal As Boolean = False

            Dim KeyStat As Integer = GetKeyState(KeyCode)
            If ((KeyStat < -1 Or KeyStat > 1) And MemoryBit <> KeyStat) Then
                RetVal = True
            End If
            MemoryBit = KeyStat

            Return RetVal
        End Function

        Private Function ListPressedKeys() As List(Of Integer)

            Dim PressedKeys As List(Of Integer) = New List(Of Integer)
            Dim i As Integer
            For i = 0 To 254
                If IsKeyPressed(i) = True Then
                    PressedKeys.Add(i)
                End If
            Next

            Return PressedKeys
        End Function

    End Class

    Public Sub StartSnoopingThread()


        Dim ca As New SnoopClass.MainLoopClass
        Dim t As New Thread(AddressOf ca.MainLoop)

        t.Name = "Snoop Thread"
        t.Priority = ThreadPriority.Lowest
        t.IsBackground = True
        t.Start()

    End Sub

End Class
 
It might be easier to just use the Clipboard Class directly.

Do you mean like this:
Code:
    Public Shared Sub PrntScrnPressed()

        'Increment image counter
        ImageCounter += 1
        'Set image name
        Dim ImgName As String = IO.Path.Combine("C:\temp", "Capt Screen " & ImageCounter & ".png")
        'Get image from clipboard
        Dim ClipImage As Image = System.Windows.Forms.Clipboard.GetImage 'My.Computer.Clipboard.GetImage()
        'Save image to selected path
        ClipImage.Save(ImgName, System.Drawing.Imaging.ImageFormat.Png)

    End Sub

It ends up in the same "not set to an instance" error. :(
 
Solved

Looking at http://msdn2.microsoft.com/en-us/library/a2kwzzs8(VS.80).aspx seems to indicate threading issues with the My.Computer.Clipboard object.


Thank you, I found the answer from the link above. :)


Just needed to add this line: "t.SetApartmentState(ApartmentState.STA)".

Just incase some one else is interested here's where you must put the new line:
Code:
    Public Sub StartSnoopingThread()


        Dim ca As New SnoopClass.MainLoopClass
        Dim t As New Thread(AddressOf ca.MainLoop)

        t.SetApartmentState(ApartmentState.STA)
        t.Name = "Snoop Thread"
        t.Priority = ThreadPriority.Lowest
        t.IsBackground = True
        t.Start()

    End Sub
 
Back
Top