[vb2005] Clipboard verandering afvangen

Pagina: 1
Acties:

  • steffex
  • Registratie: Augustus 2003
  • Laatst online: 12-08-2025
Ik ben in vb2005express bezig met een programmatje dat urls opslaat die op het clipboard staan. Nu wil ik dit programma in de systemtray laten draaien, zodat hij telkens de urls opslaat.

Nu zit ik echter met 1 probleem. Hoe detecteer ik een verandering van het clipboard? Ik heb al een functie die bij een druk op de knop naar het clipboard kijkt en als er een url staat, deze dan opslaat in een collection. Ik wil dat proces dus telkens laten doen, zodra er iets nieuws op het clipboard komt te staan.

Ik zoek al een week naar een oplossing, maar dat heeft tot nu toe geen resultaat. Hopelijk weet van onze Tweakers het :)

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Gebruik een timer om je clipboard te pollen :?
En anders even Googlen ? Vergeet Google groups niet ;)

[ Voor 88% gewijzigd door RobIII op 03-10-2006 16:31 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • steffex
  • Registratie: Augustus 2003
  • Laatst online: 12-08-2025
lijkt me niet echt een handige oplossing, zo kun je heel wat informatie mislopen... :/

  • mulder
  • Registratie: Augustus 2001
  • Nu online

mulder

ik spuug op het trottoir

Als je zoekt op 'monitor clipboard windows api' krijg je genoeg links op bv google. Bv over SetClipboardViewer

oogjes open, snaveltjes dicht


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
stef-o.nl schreef op dinsdag 03 oktober 2006 @ 16:30:
lijkt me niet echt een handige oplossing, zo kun je heel wat informatie mislopen... :/
Hangt natuurlijk van je poll interval af. En anders kun je de links die ik gaf wel eens even bekijken (dat heb je wel heel vlug gedaan anders) want daar staan voldoende suggesties in (waaronder die van Don Facundo, eerste hit van mijn google suggestie)
In Detail
The code for implementing the Clipboard Change Notification is fairly short. As it is necessary to respond to a messages sent to a Window, the best starting point is the .NET Framework NativeWindow class, as described in the article Subclassing in .NET. This provides all the code we need to subclass a Window procedure and start receiving messages, so next the API calls for the Clipboard viewer can to be implemented. There are three API calls you need:

SetClipboardViewer - Adds a window to the clipboard viewer chain.
ChangeClipboardChain - Allows the window to be removed from the clipboard viewer chain.
SendMessage - To pass on any clipboard change notifications to the next window in the chain.
Je kunt aldaar de code downloaden en er je lering uit trekken en aan de hand daarvan gewoon je eigen code schrijven of het domweg gewoon gebruiken.

[ Voor 64% gewijzigd door RobIII op 03-10-2006 16:44 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • steffex
  • Registratie: Augustus 2003
  • Laatst online: 12-08-2025
Bedankt RobIII,

Heb het nu werkend!
Die reactie had ik gepost voordat jij je links erbij had geplaatst, vandaar dat het netzo leek alsof ik heel snel was :P

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
stef-o.nl schreef op dinsdag 03 oktober 2006 @ 22:26:
Bedankt RobIII,

Heb het nu werkend!
Die reactie had ik gepost voordat jij je links erbij had geplaatst, vandaar dat het netzo leek alsof ik heel snel was :P
Niet zo zeer voor mij alswel voor alle (toekomstige) GoT-ters; kun je (een stuk van) je oplossing alhier posten? Zo vullen we onze eigen "Knowledgebase" ook fijn met kennis en kan ik de volgende topicstarter die ooit zoiets probeert te bereiken fijn naar dit topic verwijzen (en op slot knallen :+ ) in plaats van naar vbaccelerator.com te hoeven verwijzen ;)
Zie ook even ons beleidsstukje daarover ;)

[ Voor 9% gewijzigd door RobIII op 03-10-2006 22:35 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • steffex
  • Registratie: Augustus 2003
  • Laatst online: 12-08-2025
Ok, zal hier even de oplossing posten. Vergeet niet, dit is voor vb2005!

Maak een nieuwe class aan met de naam ClipboardChangeNotifier en gooi onderstaande code erin.
Visual Basic .NET: ClipboardChangeNotifier.vb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
' Requires unmanaged code
'<Assembly: System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.RequestMinimum, System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode = True)> 
' Requires all clipboard access
'<Assembly: System.Security.Permissions.UIPermissionAttribute(System.Security.Permissions.SecurityAction.RequestMinimum, Clipboard = UIPermissionClipboard.AllClipboard)> 

Namespace vbAccelerator.Components.Win32
    ''' <summary>
    ''' Provides a way to receive notifications of changes to the 
    ''' content of the clipboard using the Windows API.  
    ''' </summary>
    ''' <remarks>
    ''' To be a part of the change notification you need to register a 
    ''' window in the Clipboard Viewer Chain.  This provides
    ''' notification messages to the window whenever the 
    ''' clipboard changes, and also messages associated with managing
    ''' the chain.  This class manages the detail of keeping the
    ''' chain intact and ensuring that the application is removed
    ''' from the chain at the right point.
    ''' 
    ''' Use the <see cref="System.Windows.Forms.NativeWindow.AssignHandle"/> method 
    ''' to connect this class up to a form to begin receiving notifications.
    ''' Note that a Form can change its <see cref="System.Windows.Forms.Form.Handle"/> 
    ''' under certain circumstances; for example, if you change the 
    ''' <see cref="System.Windows.Forms.Form.ShowInTaskbar"/> property the Framework
    ''' must re-create the form from scratch since Windows ignores changes to 
    ''' that style unless they are in place when the Window is created.
    ''' (As a consequence, you should try to set as many high-level Window 
    ''' style details as possible prior to creating the Window, or at least,
    ''' prior to making it visible).  The <see cref="OnHandleChanged"/> 
    ''' method of this class is called when this happens.  You need to
    ''' re-assign the handle again whenever this occurs.  Unfortunately
    ''' <see cref="OnHandleChanged"/> is not a useful event in which to
    ''' do anything since the window handle at that point contains neither
    ''' a valid old window or a valid new one.  Therefore you need to
    ''' make the call to re-assign at a point when you know the window
    ''' is valid, for example, after styles have been changed, or 
    ''' by overriding <see cref="System.Windows.Forms.Form.OnHandleCreated"/>.
    ''' </remarks>      
    Public Class ClipboardChangeNotifier
        Inherits NativeWindow
        Implements IDisposable

#Region "Unmanaged Code"
        Private Declare Function SetClipboardViewer Lib "user32" ( _
                ByVal hWnd As IntPtr _
            ) As IntPtr

        Private Declare Function ChangeClipboardChain Lib "user32" ( _
                ByVal hWnd As IntPtr, _
                ByVal hWndNext As IntPtr _
            ) As Integer

        Private Declare Auto Function SendMessage Lib "user32" ( _
                ByVal hWnd As IntPtr, _
                ByVal wMsg As Integer, _
                ByVal wParam As IntPtr, _
                ByVal lParam As IntPtr _
            ) As Integer

        Private Const WM_DESTROY As Integer = &H2
        Private Const WM_DRAWCLIPBOARD As Integer = &H308
        Private Const WM_CHANGECBCHAIN As Integer = &H30D
#End Region

#Region "Member Variables"
        ''' <summary>
        ''' The next handle in the clipboard viewer chain when the 
        ''' clipboard notification is installed, otherwise <see cref="IntPtr.Zero"/>
        ''' </summary>
        Protected nextViewerHandle As IntPtr = IntPtr.Zero
        ''' <summary>
        ''' Whether this class has been disposed or not.
        ''' </summary>
        Protected disposed As Boolean = False
        ''' <summary>
        ''' The Window clipboard change notification was installed for.
        ''' </summary>
        Protected installedHandle As IntPtr = IntPtr.Zero
#End Region

#Region "Events"
        ''' <summary>
        ''' Notifies of a change to the clipboard's content.
        ''' </summary>
        Public Event ClipboardChanged As System.EventHandler
#End Region

        ''' <summary>
        ''' Provides default WndProc processing and responds to
        ''' clipboard change notifications.
        ''' </summary>
        ''' <param name="e"></param>
        Protected Overrides Sub WndProc(ByRef e As System.Windows.Forms.Message)
            ' if the message is a clipboard change notification
            Select Case (e.Msg)
                Case WM_CHANGECBCHAIN
                    ' Store the changed handle of the next item 
                    ' in the clipboard chain:
                    Me.nextViewerHandle = e.LParam

                    If Not (Me.nextViewerHandle.Equals(IntPtr.Zero)) Then
                        ' pass the message on:
                        SendMessage(Me.nextViewerHandle, e.Msg, e.WParam, e.LParam)
                    End If

                    ' We have processed this message:
                    e.Result = IntPtr.Zero

                Case WM_DRAWCLIPBOARD
                    ' content of clipboard has changed:
                    Dim clipChange As EventArgs = New EventArgs()
                    OnClipboardChanged(clipChange)

                    ' pass the message on:
                    If Not (Me.nextViewerHandle.Equals(IntPtr.Zero)) Then
                        SendMessage(Me.nextViewerHandle, e.Msg, e.WParam, e.LParam)
                    End If

                    ' We have processed this message:
                    e.Result = IntPtr.Zero

                Case WM_DESTROY
                    ' Very important: ensure we are uninstalled.
                    Uninstall()
                    ' And call the superclass:
                    MyBase.WndProc(e)

                Case Else
                    ' call the superclass implementation:
                    MyBase.WndProc(e)

            End Select

        End Sub

        ''' <summary>
        ''' Responds to Window Handle change events and uninstalls
        ''' the clipboard change notification if it is installed.
        ''' </summary>
        Protected Overrides Sub OnHandleChange()
            ' If we did get to this point, and we're still
            ' installed then the chain will be broken.
            ' The response to the WM_TERMINATE message should
            ' prevent Me.
            Uninstall()
            MyBase.OnHandleChange()
        End Sub

        ''' <summary>
        ''' Installs clipboard change notification.  The
        ''' <see cref="AssignHandle"/> method of this class
        ''' must have been called first.
        ''' </summary>
        Public Sub Install()
            Me.Uninstall()
            If Not (Me.Handle.Equals(IntPtr.Zero)) Then
                Me.nextViewerHandle = SetClipboardViewer(Me.Handle)
                Me.installedHandle = Me.Handle
            End If
        End Sub

        ''' <summary>
        ''' Uninstalls clipboard change notification.
        ''' </summary>
        Public Sub Uninstall()
            If Not (Me.installedHandle.Equals(IntPtr.Zero)) Then
                ChangeClipboardChain(Me.installedHandle, Me.nextViewerHandle)
                'Dim err As Integer = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
                'Debug.Assert((err = 0), _
                'String.Format("{0} Failed to uninstall from Clipboard Chain", Me), _
                'Win32Error.ErrorMessage(err))
                Me.nextViewerHandle = IntPtr.Zero
                Me.installedHandle = IntPtr.Zero
            End If
        End Sub

        ''' <summary>
        ''' Raises the <c>ClipboardChanged</c> event.
        ''' </summary>
        ''' <param name="e">Blank event arguments.</param>
        Protected Sub OnClipboardChanged(ByVal e As EventArgs)
            RaiseEvent ClipboardChanged(Me, e)
        End Sub

        ''' <summary>
        ''' Uninstalls clipboard event notifications if necessary
        ''' during dispose of this object.
        ''' </summary>
        Public Sub Dispose() Implements IDisposable.Dispose
            If Not (Me.disposed) Then
                Uninstall()
                Me.disposed = True
            End If
        End Sub

        ''' <summary>
        ''' Constructs a new instance of this class.
        ''' </summary>
        Public Sub New()
            ' intentionally blank
            MyBase.New()
        End Sub

    End Class


End Namespace


Om de ClipboardChangeNotifier te kunnen gebruiken gooi je onderstaande code in je form_load event:
Visual Basic .NET:
1
2
3
        clipChange = New vbAccelerator.Components.Win32.ClipboardChangeNotifier()
        clipChange.AssignHandle(Handle)
        clipChange.Install()

Ook moet je onderstaande stukje code in general declarations gooien om een event te krijgen:
Visual Basic .NET:
1
Private WithEvents clipChange As vbAccelerator.Components.Win32.ClipboardChangeNotifier


In de codeview kun je bij de dropdown van classnames kiezen voor clipChange_ClipboardChanged.
In dit event kun je de code zetten die je wilt uitvoeren op het moment dat er wat gekopieerd wordt naar je clipboard.

Bij je event formclosing in het hoofdformulier nog even onderstaande stukje code zetten om ervoor te zorgen dat de clipboardchangenotifier netjes wordt afgesloten bij het afsluiten van je applicatie:
Visual Basic .NET:
1
clipChange.Uninstall()


PM maar als je een voorbeeld projectje wilt hebben!

[ Voor 1% gewijzigd door steffex op 11-10-2006 14:30 . Reden: toevoeging ]

Pagina: 1