-
March 27th, 2013, 09:28 AM
#1
How Can I Paste a Picture?
I want to paste a picture from Paint into my program. My code is:
Code:
HANDLE handle = GetClipboardData( CF_METAFILEPICT );
if ( handle )
{
METAFILEPICT *mfp = (METAFILEPICT*) GlobalLock( handle );
NumBytes = GlobalSize( mfp->hMF );
}
When running the program, all the fields of the METAFILEPICT structure are set to reasonable values, but NumBytes is zero. The debugger also says that mfp->hMF is unused. If I ignore this and try to replay the picture nonetheless, my program crashes. I can however paste the same picture into WordPad with no problem. What's wrong with my program?
Another problem is that my program draws using the Direct2D APIs. I can't find an example on the internet of a program that replays a metafile into Direct2D. From the MS documentation I understand that I should use
Code:
SHCreateMemStream()
ID2D1Factory1::CreateGdiMetafile()
ID2D1DeviceContext::DrawGdiMetafile()
What pointer should I pass to SHCreateMemStream?
Any help is greatly appreciated.
-
March 27th, 2013, 11:38 AM
#2
Re: How Can I Paste a Picture?
From MSDN:
GlobalSize
...
Return Values
If the function succeeds, the return value is the size, in bytes, of the specified global memory object.
If the specified handle is not valid or if the object has been discarded, the return value is zero. To get extended error information, call GetLastError.
Victor Nijegorodov
-
March 27th, 2013, 11:50 AM
#3
Re: How Can I Paste a Picture?
GetLastError() returns 6. I can't find the meaning of this code, however.
GlobalFlags( mfp->hMF ) returns GMEM_INVALID_HANDLE
Last edited by semispin; March 27th, 2013 at 11:54 AM.
-
March 27th, 2013, 12:00 PM
#4
Re: How Can I Paste a Picture?
Error 6 means:
6 The handle is invalid. ERROR_INVALID_HANDLE
Victor Nijegorodov
-
March 27th, 2013, 12:03 PM
#5
Re: How Can I Paste a Picture?
what shall i do to get a valid handle from the METAFILEPICT structure?
-
March 27th, 2013, 12:09 PM
#6
Re: How Can I Paste a Picture?
Originally Posted by semispin
what shall i do to get a valid handle from the METAFILEPICT structure?
Are you sure that the clipboard format is CF_METAFILEPICT?
Did you open the clipboard before calling GetClipboardData?
Victor Nijegorodov
-
March 27th, 2013, 12:18 PM
#7
Re: How Can I Paste a Picture?
Here is the whole function:
Code:
void PerformPaste( Document *doc )
{
HANDLE CDdata;
Note *note;
Rect *R;
PageInfo *page = doc->page;
Layout *L = page->piece;
int ceiling = doc->height;
BOOL PlainTextAvailable = FALSE, PictAvailable = FALSE;
UINT flavor = 0, pick, temp, result = kNoData;
if (! OpenClipboard( NULL ) ) return;
while (flavor = EnumClipboardFormats( flavor ))
{
UINT temp = kNoData;
switch ( flavor )
{
case CF_TEXT:
temp = kPlainTextData;
PlainTextAvailable = TRUE;
break; // manca la bitmap
case CF_METAFILEPICT:
temp = kMetaData;
PictAvailable = TRUE;
break;
default:
if (flavor == CF_iNMR_Page)
temp = kPageData;
else if (flavor == CF_iNMR_Regions)
temp = kRegionsData;
}
if (temp > result)
{
result = temp;
pick = flavor;
}
}
switch( result )
{
case kPageData: PastePage( doc ); goto closing;
case kRegionsData:
if (PasteIntegrals( doc )) // can we accept integral regions ?
goto closing;
result = kPlainTextData; // if not, the list as text is good
pick = CF_TEXT;
}
if ( result )
{
SetDirty( doc );
note = (Note*) calloc( 1, sizeof(Note) );
switch ( result )
{
case kPlainTextData:
{
HANDLE handle = GetClipboardData( CF_UNICODETEXT );
wchar_t *source = (wchar_t*) GlobalLock( handle );
if (note->bytes = TextDataFromClipboard( source ))
TextCleaning( note );
else if (note->bytes = CreateUnicodeData( source, FALSE ))
result = kUnicodeData;
GlobalUnlock( handle );
break;
}
case kMetaData:
{
HANDLE handle = GetClipboardData( CF_METAFILEPICT );
if ( handle )
{
METAFILEPICT *mfp = (METAFILEPICT*) GlobalLock( handle );
int NumBytes = GlobalSize( mfp->hMF );
if ( NumBytes )
{
void *buffer = malloc( NumBytes );
memcpy( buffer, GlobalLock( mfp->hMF ), NumBytes );
CFDataRef data = (CFDataRef) calloc( 1, sizeof(CFData) );
data->p.kind = isData;
data->storage = (unsigned char*) buffer;
data->mark = data->storage + NumBytes;
data->p.length = NumBytes & 0xffff;
note->bytes = data;
note->position.right = mfp->xExt; // when mfp->mm == 8 these values only give the proportions
note->position.bottom = mfp->yExt;
}
else NumBytes = GetLastError();
NumBytes = GlobalFlags( mfp->hMF );
GlobalUnlock( handle );
}
}
}
if (note->bytes)
{
note->flags = (L->mode & kShowClips) != kShowStickyClips ? NoteFloats : 0;
note->kind = result;
if ( HAS_FONT(note) )
{
wchar_t *fn;
if (global->NoteFont != NULL)
{
fn = global->NoteFont;
note->fsize = global->NoteSize;
}
else
{
fn = page->fontface;
note->fsize = page->fontsize;
}
wcscpy( note->fname = (wchar_t*) malloc( 2 * wcslen(fn) + 2 ), fn );
}
if (MonoDimensional( L )) note->flags |= NoteMono; else note->flags &= ~ NoteMono;
if (note->flags & NoteFloats)
{
FixNote( note, doc );
VisibleRange( L, ¬e->f.x, ¬e->f.y, ceiling );
if (result == kArrowData || result == kFrameData)
VisibleRange( L, ¬e->o.x, ¬e->o.y, ceiling );
}
doc->Labels.push_back( note );
L->mode |= note->flags & NoteFloats ? kShowFlowingClips : kShowStickyClips;
note->flags |= NoteIsNew;
R = ¬e->position;
R->top = R->bottom = ceiling >> 2;
R->left = R->right = doc->width >> 2;
if (result > kFrameData) // pictures
{
R->left = 0.5 * (R->left + R->right) + 0.5;
R->top = 0.5 * (R->top + R->bottom) + 0.5;
}
}
else free( note );
}
closing :
CloseClipboard( );
}
It already works when the content of the clipboard is text. As you can see, I use OpenClipboard() and perform a loop with EnumClipboardFormats(), that confirms that CF_METAFILEPICT is there. The rest of the METAFILEPICT structure is OK. mm = 8, which menas MM_ANISOTROPIC ; xExt and yExt more or less correspond to the picture that I have copied.
-
March 27th, 2013, 02:05 PM
#8
Re: How Can I Paste a Picture?
do you have an example project that I can open with Visual Studio 2012 and compare with mine?
-
March 27th, 2013, 02:26 PM
#9
Re: How Can I Paste a Picture?
GetLastError() returns 6. I can't find the meaning of this code, however.
The file WinError.h contains details of the error codes. You can also use the program errlook.exe that comes with Microsoft Visual Studio.
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
March 28th, 2013, 08:57 AM
#10
Re: How Can I Paste a Picture?
I have solved part of the problem. Thanks to those who have helped. It seems that HMETAFILE is not an handle or, more exactly, the Handle functions do not work with HMETAFILE. I can, instead, save the metafile as a file with CopyMetaFile(), which works, then move the bytes from disc to memory. My metadata is now stored into the buffer ptr. The next step is
IStream* stream = SHCreateMemStream( (BYTE*) ptr, length );
which also seems to work. The following step fails instead.
ID2D1GdiMetafile *metafile;
HRESULT hr = ((ID2D1Factory1*) d2dFactory)->CreateGdiMetafile( stream, &metafile );
returns the error D2DERR_UNSUPPORTED_OPERATION.
I have Windows 7 SP1 with Platform Update. I have been able to create the ID2D1Factory1, why doesn't it support all of its methods? If this is impossible with Direct2D, is it possible to playback a picture into a Direct2D render target in any other way?
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|