Solved

Put image in picturebox to clipboard

Posted on 2004-09-13
31
870 Views
Last Modified: 2009-07-29
I can't seem to find a way to do this.  I have a picturebox/imagebox that displays photos.  I want to click a button which will place the current image on the clipboard so that it can be pasted in other applications (ie. Word, Outlook, etc).

So far all I've found is API code - but its for strings.. and the DoCmd.RunCommand accmdCopy command requires the control to have the focus (and I can't set focus on the picturebox) ...

Any other ideas?
0
Comment
Question by:Plamodo
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 15
  • 8
  • 5
  • +2
31 Comments
 
LVL 41

Expert Comment

by:shanesuebsahakarn
ID: 12046164
Here's some code to do it:

Option Compare Database
Option Explicit

Public Const GHND = &H42
Public Const CF_TEXT = 1
Private Const CF_ANSIONLY = &H400&
Private Const CF_APPLY = &H200&
Private Const CF_BITMAP = 2
Private Const CF_DIB = 8
Private Const CF_DIF = 5
Private Const CF_DSPBITMAP = &H82
Private Const CF_DSPENHMETAFILE = &H8E
Private Const CF_DSPMETAFILEPICT = &H83
Private Const CF_DSPTEXT = &H81
Private Const CF_EFFECTS = &H100&
Private Const CF_ENABLEHOOK = &H8&
Private Const CF_ENABLETEMPLATE = &H10&
Private Const CF_ENABLETEMPLATEHANDLE = &H20&
Private Const CF_ENHMETAFILE = 14
Private Const CF_FIXEDPITCHONLY = &H4000&
Private Const CF_FORCEFONTEXIST = &H10000
Private Const CF_GDIOBJFIRST = &H300
Private Const CF_GDIOBJLAST = &H3FF
Private Const CF_HDROP = 15
Private Const CF_INITTOLOGFONTSTRUCT = &H40&
Private Const CF_LIMITSIZE = &H2000&
Private Const CF_LOCALE = 16
Private Const CF_MAX = 17
Private Const CF_METAFILEPICT = 3
Private Const CF_NOFACESEL = &H80000
Private Const CF_NOSCRIPTSEL = &H800000
Private Const CF_NOSIMULATIONS = &H1000&
Private Const CF_NOSIZESEL = &H200000
Private Const CF_NOSTYLESEL = &H100000
Private Const CF_NOVECTORFONTS = &H800&
Private Const CF_NOOEMFONTS = CF_NOVECTORFONTS
Private Const CF_NOVERTFONTS = &H1000000
Private Const CF_OEMTEXT = 7
Private Const CF_OWNERDISPLAY = &H80
Private Const CF_PALETTE = 9
Private Const CF_PENDATA = 10
Private Const CF_PRINTERFONTS = &H2
Private Const CF_PRIVATEFIRST = &H200
Private Const CF_PRIVATELAST = &H2FF
Private Const CF_RIFF = 11
Private Const CF_SCALABLEONLY = &H20000
Private Const CF_SCREENFONTS = &H1
Private Const CF_BOTH = (CF_SCREENFONTS Or CF_PRINTERFONTS)
Private Const CF_SCRIPTSONLY = CF_ANSIONLY
Private Const CF_SELECTSCRIPT = &H400000
Private Const CF_SHOWHELP = &H4&
Private Const CF_SYLK = 4
Private Const CF_TIFF = 6
Private Const CF_TTONLY = &H40000
Private Const CF_UNICODETEXT = 13
Private Const CF_USESTYLE = &H80&
Private Const CF_WAVE = 12
Private Const CF_WYSIWYG = &H8000

Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags&, ByVal _
  dwBytes As Long) As Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) _
  As Long
Private Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) _
  As Long
Private Declare Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, _
  ByVal lpString2 As Any) As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" _
  (ByVal lpString As String) As Long

Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) _
  As Long

Private Declare Function OpenClipboard Lib "user32" (ByVal Hwnd As Long) _
  As Long
Private Declare Function CloseClipboard Lib "user32" () As Long
Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As _
  Long) As Long
Private Declare Function EmptyClipboard Lib "user32" () As Long
Private Declare Function SetClipboardData Lib "user32" (ByVal wFormat _
  As Long, ByVal hMem As Long) As Long

Function ClipBoard_SetText(strCopyString As String) As Boolean
  Dim hGlobalMemory As Long
  Dim lpGlobalMemory As Long
  Dim hClipMemory As Long

  ' Allocate moveable global memory.
  '-------------------------------------------
  hGlobalMemory = GlobalAlloc(GHND, Len(strCopyString) + 1)

  ' Lock the block to get a far pointer
  ' to this memory.
  lpGlobalMemory = GlobalLock(hGlobalMemory)

  ' Copy the string to this global memory.
  lpGlobalMemory = lstrcpy(lpGlobalMemory, strCopyString)

  ' Unlock the memory and then copy to the clipboard
  If GlobalUnlock(hGlobalMemory) = 0 Then
    If OpenClipboard(0&) <> 0 Then
      Call EmptyClipboard
      hClipMemory = SetClipboardData(CF_TEXT, hGlobalMemory)
      ClipBoard_SetText = CBool(CloseClipboard)
    End If
  End If
End Function

Function ClipBoard_GetText() As String
  Dim hClipMemory As Long
  Dim lpClipMemory As Long
  Dim strCBText As String
  Dim RetVal As Long
  Dim lngSize As Long
  If OpenClipboard(0&) <> 0 Then
    ' Obtain the handle to the global memory
    ' block that is referencing the text.
    hClipMemory = GetClipboardData(CF_TEXT)
    If hClipMemory <> 0 Then
      ' Lock Clipboard memory so we can reference
      ' the actual data string.
      lpClipMemory = GlobalLock(hClipMemory)
      If lpClipMemory <> 0 Then
        lngSize = GlobalSize(lpClipMemory)
        strCBText = Space$(lngSize)
        RetVal = lstrcpy(strCBText, lpClipMemory)
        RetVal = GlobalUnlock(hClipMemory)
        ' Peel off the null terminating character.
        strCBText = Left(strCBText, InStr(1, strCBText, Chr$(0), 0) - 1)
      Else
        MsgBox "Could not lock memory to copy string from."
      End If
    End If
    Call CloseClipboard
  End If
  ClipBoard_GetText = strCBText
End Function

Function CopyOlePiccy(Piccy As Object)
  Dim hGlobalMemory As Long, lpGlobalMemory As Long
  Dim hClipMemory As Long, x As Long

  ' Allocate moveable global memory.
  '-------------------------------------------
  hGlobalMemory = GlobalAlloc(GHND, Len(Piccy) + 1)

  ' Lock the block to get a far pointer
  ' to this memory.
  lpGlobalMemory = GlobalLock(hGlobalMemory)


  'Need to copy the object to the memory here

  lpGlobalMemory = lstrcpy(lpGlobalMemory, Piccy)

  ' Unlock the memory.
  If GlobalUnlock(hGlobalMemory) <> 0 Then
    MsgBox "Could not unlock memory location. Copy aborted."
    GoTo OutOfHere2
  End If

  ' Open the Clipboard to copy data to.
  If OpenClipboard(0&) = 0 Then
    MsgBox "Could not open the Clipboard. Copy aborted."
    Exit Function
  End If

  ' Clear the Clipboard.
  x = EmptyClipboard()

  ' Copy the data to the Clipboard.
  hClipMemory = SetClipboardData(CF_TEXT, hGlobalMemory)

OutOfHere2:
  If CloseClipboard() = 0 Then
    MsgBox "Could not close Clipboard."
  End If
End Function
'*********  Code End   ************

This includes code to copy strings. Use the CopyOlePiccy function to copy an OLE image object to the clipboard.
0
 
LVL 6

Author Comment

by:Plamodo
ID: 12046536
Hmmm... I can't get the code to work.  Maybe I'm using it wrong..

Call CopyOlePiccy(imgPhoto)

It crashes at the len(piccy) command - I guess you can't get the the length of a picture (??)

0
 
LVL 41

Expert Comment

by:shanesuebsahakarn
ID: 12046650
Ah - the image you're trying to copy is an Image control rather than an OLE field, right?
0
Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

 
LVL 6

Author Comment

by:Plamodo
ID: 12046694
Yeah..
0
 
LVL 41

Expert Comment

by:shanesuebsahakarn
ID: 12046810
Is the image's picture embedded or linked?
0
 
LVL 6

Author Comment

by:Plamodo
ID: 12046845
Linked
0
 
LVL 41

Expert Comment

by:shanesuebsahakarn
ID: 12046884
OK, try this. Insert an unbound OLE frame into your form. You can hide it if you need. Then try:

Set Me!MyUnboundOLE.Picture=LoadPicture(Me!MyImageControl.Picture)
CopyOLEPiccy Me!MyUnboundOLE.Picture

Does that do it?
0
 
LVL 6

Author Comment

by:Plamodo
ID: 12048135
I'm getting an error on this line: "Set Me!OLEUnbound3.Picture = LoadPicture(Me!Image0.Picture)"
"Object doesn't support this property or method"

Does this work for you?
0
 
LVL 41

Expert Comment

by:shanesuebsahakarn
ID: 12048327
Hmm, seems not. Let me get back to you on this once I test a few things out.
0
 
LVL 2

Expert Comment

by:ApK
ID: 12051087
In image control's picture property is the path to the file, not the binary data.

Try the PictureData property instead:

CopyOLEPiccy imgPhoto.PictureData

I thought there was an easier way too, using the DataObject class - but that's apparently not available in Access (but I migh try a google hunt to see).

Regards,
Andrew.
0
 
LVL 34

Assisted Solution

by:flavo
flavo earned 20 total points
ID: 12052458
why cant you use accmdcopy??

i just tested with an ole and a form and it all worked ok..

Example:

Dim oWord As Object
Me.pic.SetFocus
DoCmd.RunCommand acCmdCopy
Set oWord = CreateObject("word.application")
oWord.Documents.Add
oWord.Selection.Paste
oWord.Visible = True


Dave
0
 
LVL 6

Author Comment

by:Plamodo
ID: 12145698
I have a moronic question - what is an OLE control?  And where do I get it from?  I've been playing around with Unbound Object Frames.. and it just occured to me, its probably not what I'm supposed to be doing.

0
 
LVL 41

Expert Comment

by:shanesuebsahakarn
ID: 12145763
Bound and Unbound Object Frames are both OLE controls (they're actually the same control). I haven't found a reliable way to do this yet as I'm not really familiar with the ins and outs of the clipboard when working with non-text data.
0
 
LVL 6

Author Comment

by:Plamodo
ID: 12145864
In that case, I don't know how to set the focus on an Unbound Object Frame without getting an error.

Flavo - exactly what control did you use for your last comment?.. because unfortunately it doesn't seem to work for me.
The "Docmd.runcommand accmdcopy" seems like the simplest, most logical way to do things - and looks like the only Access built-in clipboard function .. but the focus dealio is creating some big headaches.

0
 
LVL 41

Expert Comment

by:shanesuebsahakarn
ID: 12174402
0
 
LVL 6

Author Comment

by:Plamodo
ID: 12869957
Wow.. its been a few months since my last comment.  Sorry about that.  I've had a small problem with my EE alerts going into my bulk folder...

Shane, your link is the closest yet, BUT unfortunately it didn't copy the picture properly.  The picture was copied, but when I pasted, the actual image was shrunk to about 10% and the other 90% was black space.  Have you tried this with any success, Shane?

______________________________________

I did find an interesting work-around though... although it still doesn't completely fit my needs.  If I use a web browser control to display the image, I can right-click it and copy and paste it perfectly.  This also handles a problem I was having with image resolution displaying text very poorly in the image control.  HOWEVER, very very unfortunately, the web browser cannot be resized.  I have a feature set up for my photos to be able to zoom-in and zoom-out... and to do so, the control needs to be resized on the fly.  Go figure, eh?

That said.. since the web browser control offered different features and allows very easy copying - does it remind anyone of any other controls that might also serve as a work-around in a similar fashion?
0
 
LVL 6

Author Comment

by:Plamodo
ID: 12876274
I have thought of another work around.  Take the linked photo that is in the image control and place it in a temporary Word document, and then copy the embedded image in the word document to the clipboard.  Problem is, if I close the word document before I try to paste, the clipboard no longer contains the image.  If I paste before I click "OK" in the messagebox in the code below, it works just as planned.

Is there a way to be able to copy from the Word document and retain the image on the clipboard *after* the word document has been closed?

    Dim strFile As String
    Dim wrdObject As Object
    strFile = Image0.Picture
    Set wrdObject = CreateObject("Word.Application")
    wrdObject.Documents.Open "G:\apddb\templates\PhotoHolder.doc", ReadOnly:=True
    wrdObject.activedocument.bookmarks("Photo").Select
    wrdObject.selection.InlineShapes.AddPicture strFile
   
    wrdObject.activedocument.InlineShapes.Item(1).Select
    'wrdObject.selection.InlineShapes(1).ConvertToShape.Select
    wrdObject.selection.Copy
    MsgBox "Photo copied.", vbInformation
    wrdObject.Quit SaveChanges:=0 'wdDoNotSaveChanges
    Set wrdObject = Nothing
0
 
LVL 6

Author Comment

by:Plamodo
ID: 12884211
Increased points to 500
0
 
LVL 120

Assisted Solution

by:Rey Obrero (Capricorn1)
Rey Obrero (Capricorn1) earned 20 total points
ID: 12885022
hope this links help

How to Send Information to the Clipboard
http://support.microsoft.com/?kbid=210216

How to Retrieve Information from the Clipboard
http://support.microsoft.com/?kbid=210213

0
 
LVL 6

Author Comment

by:Plamodo
ID: 12885054
Thanks capricorn.. but those links only cover sending text to the clipboard... images are a different deal all together.
0
 
LVL 2

Expert Comment

by:ApK
ID: 12889519
You seem to keep changing between an OLE control and an Image control. Which one are you using, or are you happy to use either?
0
 
LVL 6

Author Comment

by:Plamodo
ID: 12889768
I'm using an Image control.. but I'm cool to use anything that allows the following:

1)  Copying the image in the control to the clipboard
2)  Resizing the control on the fly to create a zoom-in, zoom-out effect.

The webbrowser control lets me do 1), but not 2)
The image control lets me do 2), but not 1)

And a workaround I found was to embed the image (because at run-time I know the file name and location), into a word document with word automation, and copy the object to the clipboard.  This works, UNTIL the document is closed... which seems unavoidable...
0
 
LVL 2

Expert Comment

by:ApK
ID: 12890318
The CopyOLEPiccy code that Shane posted should work except for a few things:

1. The Piccy argument is being passed in as an object, but then treated as raw data. You should pass in the Image object, but then reference it's .PictureData property (in the two places it's used), OR, change the Piccy argument to type Byte() (i.e. Byte array) and pass in the Image.PictureData property.

2. It calls SetClipboardData() with the CF_TEXT argument - I think it should be CF_ENHMETAFILE, but I haven't tried it (you are copying an image, not text).

Try 1 first, then try 2 if it doesn't work.

Note you could also resize an img in a web control. But it depends on how you are pointing the webcontrol at the image - either as a direct path (as in: WebControl.Navigate(myImgPath) ) - or as a HTML document with an IMG tag. If it's the latter, you could do the following to resize it programmatically:
webcontrol.Document.All("myImageName").Width = x
webcontrol.Document.All("myImageName").Height = y

Andrew.
0
 
LVL 41

Assisted Solution

by:shanesuebsahakarn
shanesuebsahakarn earned 20 total points
ID: 12891165
What about using an OLE object, setting the focus to the control and then using RunCommand acCmdCopy?

Can't remember if someone suggested that already....
0
 
LVL 6

Author Comment

by:Plamodo
ID: 12892578
apk - I'm trying your suggestions... I'll return with my results in a bit.. and yes, I'm using the webcontrol.navigate format of the webbrowser control, so I guess your suggestion wouldn't apply.

Shane - Yeah.. I've tried the OLE object with acCmdCopy.. but I get errors when I try to set the focus on the OLE.
0
 
LVL 6

Author Comment

by:Plamodo
ID: 12892674
apk - actually.. can you specify where to use the .picturedata property.. After weeding throught the code, I realized I don't know what I'm doing :)

I remember the last time I tried this, it crashed at the len(piccy) statement.
0
 
LVL 2

Expert Comment

by:ApK
ID: 12896935
Change:
   hGlobalMemory = GlobalAlloc(GHND, Len(Piccy) + 1)
to:
   hGlobalMemory = GlobalAlloc(GHND, Len(Piccy.PictureData) + 1)
and change:
   lpGlobalMemory = lstrcpy(lpGlobalMemory, Piccy)
to:
   lpGlobalMemory = lstrcpy(lpGlobalMemory, Piccy.PictureData)

0
 
LVL 6

Author Comment

by:Plamodo
ID: 14126909
Damn.. never got the notification about apk's last comment back in december.
For the record, apk, I just tried making the changes you indicated, but I get type mismatch error at:

lpGlobalMemory = lstrcpy(lpGlobalMemory, Piccy.PictureData)  '<--- on the picturedata property


Apk - have you actually gotten this to work?
0
 
LVL 2

Accepted Solution

by:
ApK earned 440 total points
ID: 14128074
No I hadn't tried it.

I am not so familiar with what needs to be changed with the sample code (other than needing to use PictureData property, not the control), but I have done this before using sample code from the following page: http://www.lebans.com/imagecontroltoclipboard.htm.

Andrew.
0
 
LVL 6

Author Comment

by:Plamodo
ID: 14153399
ApK - you nailed it.  Works fantastic. (the lebans solution, I mean)

You get the bulk of the points.  I'm gonna give out a few more for everyone else who tried to help me on this one.  What an epic.
0

Featured Post

Three Reasons Why Backup is Strategic

Backup is strategic to your business because your data is strategic to your business. Without backup, your business will fail. This white paper explains why it is vital for you to design and immediately execute a backup strategy to protect 100 percent of your data.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Overview: This article:       (a) explains one principle method to cross-reference invoice items in Quickbooks®       (b) explores the reasons one might need to cross-reference invoice items       (c) provides a sample process for creating a M…
In earlier versions of Windows (XP and before), you could drag a database to the taskbar, where it would appear as a taskbar icon to open that database.  This article shows how to recreate this functionality in Windows 7 through 10.
What’s inside an Access Desktop Database. Will look at the basic interface, Navigation Pane (Database Container), Tables, Queries, Forms, Report, Macro’s, and VBA code.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

710 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question