A
Anthony
I have an Outlook COM Add-in written in VB6. It must run on Outlook
versions 2000-2003. It currently saves the clipboard data, uses the
clipboard to add images to custom commandbar buttons and restores the
clipboard so the users' information is preserved.
This all works well _except_ when multiple documents (of the same type,
say Word 2003) are copied from a mail message from within Outlook (the
preview pane or an inspector). The user presses 'New'(Mail Message) in
Outlook and my custom toolbar is added to the inspector (including usage
of the clipboard). When the user pastes the attachments into this new
email they _see_ all of the correct document filenames but the contents
of all the files are the same as the first attachment (they should be
unique). If these documents were copied from Windows Explorer they paste
into the new email without issue.
I have narrowed the issue down to a difference in available clipboard
formats between a Copy from within Outlook and a Copy from Windows
Explorer - the Outlook copy lacks the CF_HDROP data format but instead
has the FileContents and FileGroupDescriptor types instead.
Has anyone seen this before? I either need a better way to use the
clipboard (so as to re-constitute the documents correctly) or avoid
using the clipboard for New MailItems. I attempted to create my
Inspector toolbar in the Outlook Explorer, on start-up, so I could copy
it (without the need to use the clipboard) when an inspector was opened
but I do not think this is possible).
Sorry for so many words.
Regards,
Anthony
The essence of the clipboard code.
Private Type clipContents
formatType As Long
dataGlobal As Long
clipSize As Long
End Type
Private m_clipContents() As clipContents
Private m_clipCount As Integer
Public Sub StoreEx()
On Error GoTo err_Handler
Dim p_clipGlobal As Long
Dim p_clipData As Long
Dim p_clipSize As Long
Dim p_savedGlobal As Long
Dim p_savedData As Long
Dim p_tmpFormat As Long
Erase m_clipContents
m_clipCount = 0
'// Open the clipboard with the current process as the owner
If OpenClipboard(0) = 0 Then
Exit Sub
End If
p_tmpFormat = EnumClipboardFormats(0)
Do Until p_tmpFormat = 0
'// Obtain a handle the the memory owned by the clipboard
p_clipGlobal = GetClipboardData(p_tmpFormat)
If p_clipGlobal > 0 Then
p_clipData = GlobalLock(p_clipGlobal)
'// If we don't have a handle then we barf
If p_clipData > 0 Then '// Failure
'// Identify the amount of memory we need to make a copy
of the data
p_clipSize = GlobalSize(p_clipGlobal)
If p_clipSize > 0 Then
'// Allocate enough memory to copy into
p_savedGlobal = GlobalAlloc(GMEM_MOVEABLE,
p_clipSize)
If p_savedGlobal > 0 Then
'// Retrieve a pointer to the first byte of the
memory block we just allocated (This also protects this piece of memory
being destroyed inadvertantly)
p_savedData = GlobalLock(p_savedGlobal)
If p_savedData > 0 Then
'// Copy the clipboard data into our memory
CopyMemory ByVal p_savedData, ByVal
p_clipData, p_clipSize
Dim p_Iclip As clipContents
With p_Iclip
.formatType = p_tmpFormat
.dataGlobal = p_savedGlobal
.clipSize = p_clipSize
End With
ReDim Preserve m_clipContents(m_clipCount +
1)
m_clipContents(m_clipCount) = p_Iclip
m_clipCount = m_clipCount + 1
GlobalUnlock (p_savedGlobal)
End If
End If
End If
GlobalUnlock (p_clipGlobal)
End If
End If
p_tmpFormat = EnumClipboardFormats(p_tmpFormat)
Loop
'// Release the clipboard
CloseClipboard
Exit Sub
err_Handler:
CloseClipboard
CleanUp
End Sub
Public Sub RestoreEx()
Dim p_cnt As Integer
On Error GoTo err_Handler
'// Open the clipboard with the current process as the owner
If OpenClipboard(0) > 0 Then
If EmptyClipboard > 0 Then
For p_cnt = 0 To m_clipCount - 1
'// Place our piece of memory in the clipboard
If SetClipboardData(m_clipContents(p_cnt).formatType,
m_clipContents(p_cnt).dataGlobal) = 0 Then
' Err.Raise Err.LastDllError, "Clipboard",
"SetClipboardData: " & _
DecodeAPIErrors(Err.LastDllError) '// Failure
End If
Next p_cnt
End If
End If
CloseClipboard
Exit Sub
err_Handler:
CloseClipboard
CleanUp
End Sub
versions 2000-2003. It currently saves the clipboard data, uses the
clipboard to add images to custom commandbar buttons and restores the
clipboard so the users' information is preserved.
This all works well _except_ when multiple documents (of the same type,
say Word 2003) are copied from a mail message from within Outlook (the
preview pane or an inspector). The user presses 'New'(Mail Message) in
Outlook and my custom toolbar is added to the inspector (including usage
of the clipboard). When the user pastes the attachments into this new
email they _see_ all of the correct document filenames but the contents
of all the files are the same as the first attachment (they should be
unique). If these documents were copied from Windows Explorer they paste
into the new email without issue.
I have narrowed the issue down to a difference in available clipboard
formats between a Copy from within Outlook and a Copy from Windows
Explorer - the Outlook copy lacks the CF_HDROP data format but instead
has the FileContents and FileGroupDescriptor types instead.
Has anyone seen this before? I either need a better way to use the
clipboard (so as to re-constitute the documents correctly) or avoid
using the clipboard for New MailItems. I attempted to create my
Inspector toolbar in the Outlook Explorer, on start-up, so I could copy
it (without the need to use the clipboard) when an inspector was opened
but I do not think this is possible).
Sorry for so many words.
Regards,
Anthony
The essence of the clipboard code.
Private Type clipContents
formatType As Long
dataGlobal As Long
clipSize As Long
End Type
Private m_clipContents() As clipContents
Private m_clipCount As Integer
Public Sub StoreEx()
On Error GoTo err_Handler
Dim p_clipGlobal As Long
Dim p_clipData As Long
Dim p_clipSize As Long
Dim p_savedGlobal As Long
Dim p_savedData As Long
Dim p_tmpFormat As Long
Erase m_clipContents
m_clipCount = 0
'// Open the clipboard with the current process as the owner
If OpenClipboard(0) = 0 Then
Exit Sub
End If
p_tmpFormat = EnumClipboardFormats(0)
Do Until p_tmpFormat = 0
'// Obtain a handle the the memory owned by the clipboard
p_clipGlobal = GetClipboardData(p_tmpFormat)
If p_clipGlobal > 0 Then
p_clipData = GlobalLock(p_clipGlobal)
'// If we don't have a handle then we barf
If p_clipData > 0 Then '// Failure
'// Identify the amount of memory we need to make a copy
of the data
p_clipSize = GlobalSize(p_clipGlobal)
If p_clipSize > 0 Then
'// Allocate enough memory to copy into
p_savedGlobal = GlobalAlloc(GMEM_MOVEABLE,
p_clipSize)
If p_savedGlobal > 0 Then
'// Retrieve a pointer to the first byte of the
memory block we just allocated (This also protects this piece of memory
being destroyed inadvertantly)
p_savedData = GlobalLock(p_savedGlobal)
If p_savedData > 0 Then
'// Copy the clipboard data into our memory
CopyMemory ByVal p_savedData, ByVal
p_clipData, p_clipSize
Dim p_Iclip As clipContents
With p_Iclip
.formatType = p_tmpFormat
.dataGlobal = p_savedGlobal
.clipSize = p_clipSize
End With
ReDim Preserve m_clipContents(m_clipCount +
1)
m_clipContents(m_clipCount) = p_Iclip
m_clipCount = m_clipCount + 1
GlobalUnlock (p_savedGlobal)
End If
End If
End If
GlobalUnlock (p_clipGlobal)
End If
End If
p_tmpFormat = EnumClipboardFormats(p_tmpFormat)
Loop
'// Release the clipboard
CloseClipboard
Exit Sub
err_Handler:
CloseClipboard
CleanUp
End Sub
Public Sub RestoreEx()
Dim p_cnt As Integer
On Error GoTo err_Handler
'// Open the clipboard with the current process as the owner
If OpenClipboard(0) > 0 Then
If EmptyClipboard > 0 Then
For p_cnt = 0 To m_clipCount - 1
'// Place our piece of memory in the clipboard
If SetClipboardData(m_clipContents(p_cnt).formatType,
m_clipContents(p_cnt).dataGlobal) = 0 Then
' Err.Raise Err.LastDllError, "Clipboard",
"SetClipboardData: " & _
DecodeAPIErrors(Err.LastDllError) '// Failure
End If
Next p_cnt
End If
End If
CloseClipboard
Exit Sub
err_Handler:
CloseClipboard
CleanUp
End Sub