• Hi All

    Please note that at the Chandoo.org Forums there is Zero Tolerance to Spam

    Post Spam and you Will Be Deleted as a User

    Hui...

  • When starting a new post, to receive a quicker and more targeted answer, Please include a sample file in the initial post.

Clear clipboard contents

YasserKhalil

Well-Known Member
Hello everyone
I have searched a lot for this topic and found a lot of solutions and tried all of them..
One of these solutions
Code:
Declare Function OpenClipboard _
Lib "User32.dll" _
  (ByVal hWndNewOwner As Long) As Long
 
Declare Function EmptyClipboard _
Lib "User32.dll" () As Long
Declare Function CloseClipboard _
Lib "User32.dll" () As Long
Public Sub ClearClipboard()

  Dim Ret
 
    Ret = OpenClipboard(0&)
      If Ret <> 0 Then Ret = EmptyClipboard
    CloseClipboard
   
End Sub

But in fact none of the solutions provided do the task
I need to clean and clear completely the contents of the clipboard
Tried to record macro to Clear All but nothing found in the macro lines
 

Attachments

  • Untitled.png
    Untitled.png
    7.7 KB · Views: 10
There is no way I have ever come across to clear the Office clipboard programmatically, other than perhaps Sendkeys, which is unreliable generally.

Why do you need to do this?
 
Thanks Mr. Hui
I already read this link and it doesn't solve mu issue
Mr. Debaser I need to clear the clipboard completely so as free the memory .. and that is just a request if possible
 
As I said, I'm not aware of any reliable way to do that. The buttons on the Clipboard task pane are windowless so you can't use API calls to simulate clicking them, and there isn't an API for the Office clipboard as far as I am aware.
 
That clears the clipboard task pane for you? I am surprised because it doesn't for me (and I wouldn't expect it to, since they are separate clipboards).
 
That's very odd indeed. It really shouldn't! How many items did you have on the clipboard as a matter of interest?
 
I had select 3 text grabs from the web browser that I had open
each was 20+ lines of text
 
Interesting. It doesn't work on mine. Office Clipboard retains all items.
Excel 2016 32bit, Win 7 64 bit.
Excel 2010 32bit, Win 7 64 bit.
 
Yep, and technically hWndNewOwner should be a LongPtr, but that's not going to cause an issue here.

So, to confirm, you see all three items on the clipboard, run that code, and they all disappear?
 
It doesn't work for me too .. windows 7 32 bit office 2016
Is it working on some platforms and do not work on others?
That's weird...
 
So this morning I did some testing and none of these setups clear the clipboard task pane for me using that code (suitably adjusted for the 64 bit API calls):
All on Windows 10 64bit:
Excel 2003
Excel 2010 32 bit
Excel 2013 32 bit
Excel 2016 32 bit
Excel 2016 64 bit.

Curiouser and curiouser.
 
Hi All ,

Not at all curious !

There is a difference between the Office Clipboard and the Windows Clipboard.

I assumed that what was meant was the latter.

Now I understand that what was meant is the former.

The link I gave does not address OP's issue.

Narayan
 
But Hui says it does work for him, and the fact he mentioned three copy items makes me think he is not talking about the Windows clipboard. It is that that I find curious since, as I said previously, I would not expect this code to work for the Clipboard task pane.
 
After a lot of search I think there is no way to clear the contents of office clipboard.
Is there any workaround using send keys to do the task?
 
Slightly simplifying the code found here, you can do this:
Code:
Option Explicit
Declare Function AccessibleObjectFromWindow Lib "oleacc" ( _
  ByVal hWnd As Long, ByVal dwId As Long, _
  riid As tGUID, ppvObject As Object) As Long

Declare Function AccessibleChildren Lib "oleacc" _
  (ByVal paccContainer As IAccessible, ByVal iChildStart As Long, _
  ByVal cChildren As Long, rgvarChildren As Variant, _
  pcObtained As Long) As Long

Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
  ByVal lpClassName As String, _
  ByVal lpWindowName As String) As Long

Declare Function GetParent Lib "user32" (ByVal hWnd As Long) As Long

Declare Function EnumChildWindows Lib "user32" (ByVal hwndParent _
  As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long

Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Long, _
  ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, _
  ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long

Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, _
  ByVal hWnd2 As Long, ByVal lpClass As String, ByVal lpCaption As String) As Long

Const CHILDID_SELF = 0&
Const ROLE_PUSHBUTTON = &H2B&
Const WM_GETTEXT = &HD

Type tGUID
  lData1  As Long
  nData2  As Integer
  nData3  As Integer
  abytData4(0 To 7)  As Byte
End Type

Type AccObject
  objIA  As IAccessible
  lngChild  As Long
End Type


Dim lngChild  As Long
Dim strClass  As String
Dim strCaption  As String
'Using Active Accessibility to clear Office clipboard
'Assumption:
'this is running within Word or Excel as a macro, thus the global Application object is available
Sub ClearOfficeClipboard()
  Static accButton  As AccObject
  If accButton.objIA Is Nothing Then
  Dim fShown  As Boolean
  fShown = CommandBars("Task Pane").Visible
  If Not (fShown) Then
  CommandBars("Task Pane").Enabled = True
  CommandBars("Task Pane").Visible = True
  End If
  accButton = FindAccessibleChildInWindow(GetOfficeClipboardHwnd(Application), "Clear All", ROLE_PUSHBUTTON)
  End If
  If accButton.objIA Is Nothing Then
  MsgBox "Unable to locate the ""Clear All"" button!"
  Else
  accButton.objIA.accDoDefaultAction accButton.lngChild
  End If
End Sub

'Retrieve window class name
Function GetWndClass(ByVal hWnd As Long) As String
  Dim buf As String
  Dim retval  As Long
   
  buf = Space(256)
  retval = GetClassName(hWnd, buf, 255)
  GetWndClass = Left(buf, retval)
End Function

'Retrieve window title
Function GetWndText(ByVal hWnd As Long) As String
  Dim buf  As String
  Dim retval  As Long
   
  buf = Space(256)
  retval = SendMessage(hWnd, WM_GETTEXT, 255, buf)
  GetWndText = Left(buf, InStr(1, buf, Chr(0)) - 1)
End Function

'The call back function used by EnumChildWindows
Function EnumChildWndProc(ByVal hChild As Long, ByVal lParam As Long) As Long
  Dim found  As Boolean
   
  EnumChildWndProc = -1
  If strClass > "" And strCaption > "" Then
  found = StrComp(GetWndClass(hChild), strClass, vbTextCompare) = 0 And _
  StrComp(GetWndText(hChild), strCaption, vbTextCompare) = 0
  ElseIf strClass > "" Then
  found = (StrComp(GetWndClass(hChild), strClass, vbTextCompare) = 0)
  ElseIf strCaption > "" Then
  found = (StrComp(GetWndText(hChild), strCaption, vbTextCompare) = 0)
  Else
  found = True
  End If

  If found Then
  lngChild = hChild
  EnumChildWndProc = 0
  Else
  EnumChildWndProc = -1
  End If
End Function

'Find the window handle of a child window based on its class and titie
Function FindChildWindow(ByVal hParent As Long, Optional cls As String = "", Optional title As String = "") As Long
  lngChild = 0
  strClass = cls
  strCaption = title
  EnumChildWindows hParent, AddressOf EnumChildWndProc, 0
  FindChildWindow = lngChild
End Function

'Retrieve the IAccessible interface from a window handle
'Reference:Jean Ross,Chapter 17: Accessibility in Visual Basic,Advanced Microsoft Visual Basic 6.0, 2nd Edition
Function IAccessibleFromHwnd(hWnd As Long) As IAccessible
  Dim oIA  As IAccessible
  Dim tg  As tGUID
  Dim lReturn  As Long

  ' Define the GUID for the IAccessible object
  ' {618736E0-3C3D-11CF-810C-00AA00389B71}

  With tg
  .lData1 = &H618736E0
  .nData2 = &H3C3D
  .nData3 = &H11CF
  .abytData4(0) = &H81
  .abytData4(1) = &HC
  .abytData4(2) = &H0
  .abytData4(3) = &HAA
  .abytData4(4) = &H0
  .abytData4(5) = &H38
  .abytData4(6) = &H9B
  .abytData4(7) = &H71
  End With
  ' Retrieve the IAccessible object for the form
  lReturn = AccessibleObjectFromWindow(hWnd, 0, tg, oIA)
  Set IAccessibleFromHwnd = oIA
End Function

'Recursively looking for a child with specified accName and accRole in the accessibility tree
Function FindAccessibleChild(oParent As IAccessible, strName As String, lngRole As Long) As AccObject
  Dim lHowMany  As Long
  Dim avKids()  As Variant
  Dim lGotHowMany As Long, i  As Integer
  Dim oChild  As IAccessible
  FindAccessibleChild.lngChild = CHILDID_SELF
  If oParent.accChildCount = 0 Then
  Set FindAccessibleChild.objIA = Nothing
  Exit Function
  End If
  lHowMany = oParent.accChildCount
  ReDim avKids(lHowMany - 1) As Variant
  lGotHowMany = 0
  If AccessibleChildren(oParent, 0, lHowMany, avKids(0), lGotHowMany) <> 0 Then
  MsgBox "Error retrieving accessible children!"
  Set FindAccessibleChild.objIA = Nothing
  Exit Function
  End If

  'To do: the approach described in http://msdn.microsoft.com/msdnmag/issues/0400/aaccess/default.aspx
  ' are probably better and more reliable
  On Error Resume Next
  For i = 0 To lGotHowMany - 1
  If IsObject(avKids(i)) Then
  If StrComp(avKids(i).accName, strName) = 0 And avKids(i).accRole = lngRole Then
  Set FindAccessibleChild.objIA = avKids(i)
  Exit For
  Else
  Set oChild = avKids(i)
  FindAccessibleChild = FindAccessibleChild(oChild, strName, lngRole)
  If Not FindAccessibleChild.objIA Is Nothing Then
  Exit For
  End If
  End If
  Else
  If StrComp(oParent.accName(avKids(i)), strName) = 0 And oParent.accRole(avKids(i)) = lngRole Then
  Set FindAccessibleChild.objIA = oParent
  FindAccessibleChild.lngChild = avKids(i)
  Exit For
  End If
  End If
  Next i
End Function

Function FindAccessibleChildInWindow(hwndParent As Long, strName As String, lngRole As Long) As AccObject
  Dim oParent  As IAccessible
  Set oParent = IAccessibleFromHwnd(hwndParent)
  If oParent Is Nothing Then
  Set FindAccessibleChildInWindow.objIA = Nothing
  Else
  FindAccessibleChildInWindow = FindAccessibleChild(oParent, strName, lngRole)
  End If
End Function

'Retrieve the window handle of the task pane
Function GetOfficeTaskPaneHwnd(app As Object) As Long
  GetOfficeTaskPaneHwnd = FindChildWindow(app.hWnd, _
  "MsoCommandBar", Application.CommandBars("Task Pane").NameLocal)
End Function

'Retrieve the window handle of the clipboard child window inside task pane
'The window title of the clipboard window seems to be language independent,
'making it a better start point to searching our UI element than the task pane window
Function GetOfficeClipboardHwnd(app As Object) As Long
  GetOfficeClipboardHwnd = FindChildWindow(app.hWnd, , "Collect and Paste 2.0")
End Function
 
@all

You can clear the office clipboard.

See the solutions in this dutch forum, http://www.helpmij.nl/forum/showthread.php/893233-Klembord-overvol-melding-bij-afsluiten
Message #79 and #84
Code:
Private Declare Function AccessibleChildren Lib "oleacc" (ByVal paccContainer As Office.IAccessible, ByVal iChildStart As Long, ByVal cChildren As Long, ByRef rgvarChildren As Any, ByRef pcObtained As Long) As Long

Sub ClearOfficeClipBoard()
Dim Acc As Office.IAccessible

With Application
.CommandBars("Office Clipboard").Visible = True
DoEvents
Set Acc = .CommandBars("Office Clipboard").accChild(1)
Set Acc = zetAcc(Acc, 3)
Set Acc = zetAcc(Acc, 0)
Set Acc = zetAcc(Acc, 3)
Acc.accDoDefaultAction 2&
.CommandBars("Office Clipboard").Visible = False
End With

End Sub
Private Function zetAcc(myAcc As Office.IAccessible, myChildIndex As Long) As Office.IAccessible
Dim ReturnAcc As Office.IAccessible
Dim Count As Long, List() As Variant

Count = myAcc.accChildCount
ReDim List(Count - 1&)
If AccessibleChildren(myAcc, 0&, ByVal Count, List(0), Count) = 0& Then Set zetAcc = List(myChildIndex)

End Function
and
Code:
Option Explicit

Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function GetDeviceCaps Lib "gdi32.dll" (ByVal hDC As Long, ByVal nIndex As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As Long, ByVal hDC As Long) As Long

Private Const LOGPIXELSX As Long = 88
Private Const LOGPIXELSY As Long = 90
Private Const WM_LBUTTONDOWN As Long = &H201&
Private Const WM_LBUTTONUP As Long = &H202&

Private colWindow As New Collection

Private Function EnumChildProc(ByVal hwnd As Long, ByVal lParam As Long) As Long

Dim lpClassName As String
Dim lResult As Long

lpClassName = Space(256)
lResult = GetClassName(hwnd, lpClassName, 256)
lpClassName = Left(lpClassName, lResult)

colWindow.Add hwnd, lpClassName

EnumChildProc = 1

End Function


Public Sub ClearOfficeClipboardResolutionAndLanguageIndependent() 'alphamax_2016
'clears the office clipboard

Dim bClipboard As Boolean
Dim bScreenUpdating As Boolean
Dim hDC As Long
Dim hwnd As Long
Dim lParameter As Long
Dim lPosition As Long
Dim lWidth As Long

With Application
bScreenUpdating = .ScreenUpdating
If Not bScreenUpdating Then
.ScreenUpdating = True
End If
With Application.CommandBars("Office Clipboard")
bClipboard = .Visible
lPosition = .Position 'backup position
lWidth = .Width 'backup width
If Not bClipboard Then
.Visible = True
End If
.Position = msoBarLeft 'dock left so we can use handle of "bosa_sdm_XL9"
.Width = 0 'make clipboard width narrow so buttons are on top of each other and textsize doesn't determine button size
End With
End With

DoEvents

hwnd = FindWindowEx(Application.hwnd, 0, "EXCEL2", "")
EnumChildWindows hwnd, AddressOf EnumChildProc, ByVal 0& 'build windowdata tree
hwnd = colWindow.Item("bosa_sdm_XL9")

hDC = GetDC(0)
lParameter = 42 * GetDeviceCaps(hDC, LOGPIXELSY) / 96 * 65536 + 16 * GetDeviceCaps(hDC, LOGPIXELSX) / 96
ReleaseDC 0, hDC

PostMessage hwnd, WM_LBUTTONDOWN, 0&, lParameter 'push button
PostMessage hwnd, WM_LBUTTONUP, 0&, lParameter 'release button

Do Until colWindow.Count = 0
colWindow.Remove 1
Loop

With Application
With .CommandBars("Office Clipboard")
.Position = lPosition
.Width = lWidth
If Not bClipboard Then
.Visible = False 'hide office clipboard
End If
End With
If Not bScreenUpdating Then
.ScreenUpdating = False
End If
End With

End Sub
 
Last edited:
Back
Top