Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

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:

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:


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

Posted

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

 

Do you mean like this:

   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. :(

Posted

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:

   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

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...