天天看點

C++剪切闆程式設計中遇到的一個問題

        之前在開發一個新功能的時候,需要将檔案的路徑資訊通過剪切闆傳遞給指定的目标。于是就需要将檔案資訊寫入到剪切闆中,擷取方則從剪切闆中讀取想要擷取的路徑資訊。剪切闆是通過全局記憶體來共享資料的,存放資料的記憶體是通過GlobalAlloc來配置設定的。問題就出在這個用GlobalAlloc來配置設定的的記憶體上,在将檔案資訊寫入到剪切闆之後,想當然的就調用GlobalFree來釋放之前申請來的記憶體,于是導緻了後續的複制/粘貼功能的異常。經查閱,找出了對應的原因:不需要GlobalFree來記憶體,因為記憶體已經有剪切闆托管了,最終由剪切闆來釋放。相關代碼如下所示:

// 将圖檔檔案拷貝到剪切闆(将包含檔案名的檔案完整路徑添加到剪切闆中)
void CCatchScreenDlg::CopyCatchFileToClipboard( CString strFilePath )
{
	DROPFILES dropFiles;
	UINT uGblLen, uDropFilesLen;
	HGLOBAL hGblFiles, hGblEffect;
	char *szData, *szFileList;
	
	DWORD *pdwDropEffect;
	
	hGblEffect = GlobalAlloc( GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, sizeof(DWORD) );
	if ( hGblEffect == NULL )
	{
		return;
	}

	pdwDropEffect = (DWORD*)GlobalLock( hGblEffect );
	*pdwDropEffect = DROPEFFECT_COPY;
	GlobalUnlock( hGblEffect );
	
	uDropFilesLen = sizeof(DROPFILES);
	dropFiles.pFiles = uDropFilesLen;
	dropFiles.pt.x = 0;
	dropFiles.pt.y = 0;
	dropFiles.fNC = FALSE;
	dropFiles.fWide = TRUE;
	
	uGblLen = uDropFilesLen + strFilePath.GetLength()*2 + 8;
	hGblFiles = GlobalAlloc( GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, uGblLen );
	if ( hGblFiles == NULL )
	{
		GlobalFree( hGblEffect );
		return;
	}

	szData = (char*)GlobalLock( hGblFiles );
	memcpy( szData, (LPVOID)(&dropFiles), uDropFilesLen );
	szFileList = szData + uDropFilesLen;
	
	LPWSTR lpWStrBmpFileName = NULL; // 注意:Bitmap::Save接口第一個參數是寬位元組參數
#ifdef _UNICODE
    lpWStrBmpFileName = strFilePath.GetBuffer( 0 ); // 如果是_UNICODE模式,直接使用
#else
	WCHAR wchBmpFileName[MAX_PATH*2] = {0};
	MultiByteToWideChar( CP_ACP, 0, strFilePath.GetBuffer(0), -1, wchBmpFileName, strlen(strFilePath)+1 ); // 将窄字元轉化為寬字元
	lpWStrBmpFileName = wchBmpFileName;
#endif 
	
	wmemcpy( (WCHAR *)szFileList, lpWStrBmpFileName, wcslen( lpWStrBmpFileName )+2 );
	
	GlobalUnlock( hGblFiles );
	
	if( ::OpenClipboard( NULL ) )
	{
		::EmptyClipboard();
		::SetClipboardData( CF_HDROP, hGblFiles );
		::SetClipboardData( m_dwScreenCatchClipFormat, hGblEffect );
		::CloseClipboard();
	}

	// 此處是剪切闆程式設計,用GlobalAlloc申請來記憶體好像被ClipBoard托管了,無需使用GlobalFree來釋放
        // 了,如果調用GlobalFree來釋放會出現一些異常,2012/06/02
// 	GlobalFree( hGblEffect );
// 	GlobalFree( hGblFiles );
},
           

繼續閱讀