CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    May 2012
    Posts
    15

    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.

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,395

    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

  3. #3
    Join Date
    May 2012
    Posts
    15

    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.

  4. #4
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,395

    Re: How Can I Paste a Picture?

    Error 6 means:
    6 The handle is invalid. ERROR_INVALID_HANDLE
    Victor Nijegorodov

  5. #5
    Join Date
    May 2012
    Posts
    15

    Re: How Can I Paste a Picture?

    what shall i do to get a valid handle from the METAFILEPICT structure?

  6. #6
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,395

    Re: How Can I Paste a Picture?

    Quote Originally Posted by semispin View Post
    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

  7. #7
    Join Date
    May 2012
    Posts
    15

    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, &note->f.x, &note->f.y, ceiling );
    				if (result == kArrowData || result == kFrameData)
    					VisibleRange( L, &note->o.x, &note->o.y, ceiling );
    			}
    			doc->Labels.push_back( note );
    			L->mode |= note->flags & NoteFloats ? kShowFlowingClips : kShowStickyClips;
    			note->flags |= NoteIsNew;
    			R = &note->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.

  8. #8
    Join Date
    May 2012
    Posts
    15

    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?

  9. #9
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    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)

  10. #10
    Join Date
    May 2012
    Posts
    15

    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
  •  





Click Here to Expand Forum to Full Width

Featured