Ejemplo n.º 1
0
void IW::CRender::Play(HENHMETAFILE hemf)
{
	IW::CDCRender dc(*this);
	bool bHasPal = dc.GetDeviceCaps(BITSPIXEL) <= 8;

	// Create a logical palette from the colors in the color table
	UINT nColors = GetEnhMetaFilePaletteEntries(hemf, 0, NULL);
	CPalette pal;

	if (bHasPal && nColors != GDI_ERROR && nColors != 0)
	{
		bHasPal = false;
		DWORD dwSize = sizeof (LOGPALETTE) + ((nColors - 1) * sizeof (PALETTEENTRY));

		LPLOGPALETTE logPalette = IW_ALLOCA(LPLOGPALETTE, dwSize);

		logPalette->palVersion = 0x300;
		logPalette->palNumEntries = nColors;

		if (nColors == GetEnhMetaFilePaletteEntries(hemf, nColors, logPalette->palPalEntry))
		{
			pal.CreatePalette(logPalette);
		}
	}

	HPALETTE hOldPal = NULL;

	if (bHasPal)
	{
		hOldPal = dc.SelectPalette(pal, TRUE);
		dc.RealizePalette();
	}

	CRect rcClip = _pSurface->GetClipRect();

	int nHeightRender = rcClip.bottom - rcClip.top;
	int nWidthRender = rcClip.right - rcClip.left;

	CBrush brush;
	CRect r(0, 0, nWidthRender, nHeightRender);

	if (brush.CreateSolidBrush(RGB(255,255,255)))
	{		
		dc.FillRect(&r, brush);
	}

	PlayEnhMetaFile(dc, hemf, &r);
	::GdiFlush();

	if (hOldPal)
		dc.SelectPalette(hOldPal, FALSE);
}
Ejemplo n.º 2
0
HPALETTE GetEMFPalette(HENHMETAFILE hEmf, HDC hDC)
{
	// query number of entries
	int no = GetEnhMetaFilePaletteEntries(hEmf, 0, NULL);

	if ( no<=0 )
		return NULL;

	// allocation
	LOGPALETTE * pLogPalette = (LOGPALETTE *) new BYTE[sizeof(LOGPALETTE) + (no-1) * sizeof(PALETTEENTRY)];

	pLogPalette->palVersion    = 0x300;
	pLogPalette->palNumEntries = no;

	// get real data
	GetEnhMetaFilePaletteEntries(hEmf, no, pLogPalette->palPalEntry);

	HPALETTE hPal = CreatePalette(pLogPalette);

	delete [] (BYTE *) pLogPalette;

	return hPal;
}
Ejemplo n.º 3
0
bool CxImageWMF::Decode(CxFile *hFile, long nForceWidth, long nForceHeight)
{
	if (hFile == NULL) return false;

	HENHMETAFILE	hMeta;
	HDC				hDC;
	int				cx,cy;

	//save the current position of the file
	long pos = hFile->Tell();

	// Read the Metafile and convert to an Enhanced Metafile
	METAFILEHEADER	mfh;
	hMeta = ConvertWmfFiletoEmf(hFile, &mfh);
	if (hMeta) {	// ok, it's a WMF

/////////////////////////////////////////////////////////////////////
//	We use the original WMF size information, because conversion to
//	EMF adjusts the Metafile to Full Screen or does not set rclBounds at all
//	ENHMETAHEADER	emh;
//	UINT			uRet;
//	uRet = GetEnhMetaFileHeader(hMeta,					// handle of enhanced metafile 
//								sizeof(ENHMETAHEADER),	// size of buffer, in bytes 
//								&emh); 					// address of buffer to receive data  
//	if (!uRet){
//		DeleteEnhMetaFile(hMeta);
//		return false;
//	}
//	// calculate size
//	cx = emh.rclBounds.right - emh.rclBounds.left;
//	cy = emh.rclBounds.bottom - emh.rclBounds.top;
/////////////////////////////////////////////////////////////////////

		// calculate size
		// scale the metafile (pixels/inch of metafile => pixels/inch of display)
		// mfh.inch already checked to be <> 0

		hDC = ::GetDC(0);
		int cx1 = ::GetDeviceCaps(hDC, LOGPIXELSX);
		int cy1 = ::GetDeviceCaps(hDC, LOGPIXELSY);
		::ReleaseDC(0, hDC);

		cx = (mfh.bbox.right - mfh.bbox.left) * cx1 / mfh.inch;
		cy = (mfh.bbox.bottom - mfh.bbox.top) * cy1 / mfh.inch;

	} else {		// maybe it's an EMF...

		hFile->Seek(pos,SEEK_SET);

		ENHMETAHEADER	emh;
		hMeta = ConvertEmfFiletoEmf(hFile, &emh);

		if (!hMeta){
			strcpy(info.szLastError,"corrupted WMF");
			return false; // definitively give up
		}
		// ok, it's an EMF
		// calculate size
		cx = emh.rclBounds.right - emh.rclBounds.left;
		cy = emh.rclBounds.bottom - emh.rclBounds.top;
	}

	if (info.nEscape) {	// Check if cancelled
		DeleteEnhMetaFile(hMeta);
		strcpy(info.szLastError,"Cancelled");
		return false;
	}

	if (!cx || !cy)	{
		DeleteEnhMetaFile(hMeta);
		strcpy(info.szLastError,"empty WMF");
		return false;
	}

	if (nForceWidth) cx=nForceWidth;
	if (nForceHeight) cy=nForceHeight;
	ShrinkMetafile(cx, cy);		// !! Otherwise Bitmap may have bombastic size

	HDC hDC0 = GetDC(0);	// DC of screen
	HBITMAP hBitmap = CreateCompatibleBitmap(hDC0, cx, cy);	// has # colors of display
	hDC = CreateCompatibleDC(hDC0);	// memory dc compatible with screen
	ReleaseDC(0, hDC0);	// don't need anymore. get rid of it.

	if (hDC){
		if (hBitmap){
			RECT rc = {0,0,cx,cy};
			int bpp = ::GetDeviceCaps(hDC, BITSPIXEL);

			HBITMAP hBitmapOld = (HBITMAP)SelectObject(hDC, hBitmap);

			// clear out the entire bitmap with windows background
			// because the MetaFile may not contain background information
			DWORD	dwBack = XMF_COLOR_BACK;
#if XMF_SUPPORT_TRANSPARENCY
			if (bpp == 24) dwBack = XMF_COLOR_TRANSPARENT;
#endif
		    DWORD OldColor = SetBkColor(hDC, dwBack);
		    ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
			SetBkColor(hDC, OldColor);

			//retrieves optional palette entries from the specified enhanced metafile
			PLOGPALETTE plogPal;
			PBYTE pjTmp; 
			HPALETTE hPal; 
			int iEntries = GetEnhMetaFilePaletteEntries(hMeta, 0, NULL);
			if (iEntries) { 
				if ((plogPal = (PLOGPALETTE)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, 
					sizeof(DWORD) + sizeof(PALETTEENTRY)*iEntries )) == NULL) { 
					DeleteObject(hBitmap);
					DeleteDC(hDC);
					DeleteEnhMetaFile(hMeta);
					strcpy(info.szLastError,"Cancelled");
					return false;
				} 

				plogPal->palVersion = 0x300; 
				plogPal->palNumEntries = (WORD) iEntries; 
				pjTmp = (PBYTE) plogPal; 
				pjTmp += 4; 

				GetEnhMetaFilePaletteEntries(hMeta, iEntries, (PPALETTEENTRY)pjTmp); 
				hPal = CreatePalette(plogPal); 
				GlobalFree(plogPal); 

				SelectPalette(hDC, hPal, FALSE); 
				RealizePalette(hDC); 
			} 
			
			// Play the Metafile into Memory DC
			BOOL bRet = PlayEnhMetaFile(hDC,	// handle to a device context 
									hMeta,	// handle to an enhanced metafile  
									&rc); 	// pointer to bounding rectangle

			SelectObject(hDC, hBitmapOld);
			DeleteEnhMetaFile(hMeta);	// we are done with this one

			if (info.nEscape) {	// Check if cancelled
				DeleteObject(hBitmap);
				DeleteDC(hDC);
				strcpy(info.szLastError,"Cancelled");
				return false;
			}

			// the Bitmap now has the image.
			// Create our DIB and convert the DDB into DIB
			if (!Create(cx, cy, bpp, CXIMAGE_FORMAT_WMF)) {
				DeleteObject(hBitmap);
				DeleteDC(hDC);
				return false;
			}

#if XMF_SUPPORT_TRANSPARENCY
			if (bpp == 24) {
				RGBQUAD	rgbTrans = { XMF_RGBQUAD_TRANSPARENT };
				SetTransColor(rgbTrans);
			}
#endif
		    // We're finally ready to get the DIB. Call the driver and let
		    // it party on our bitmap. It will fill in the color table,
		    // and bitmap bits of our global memory block.
			bRet = GetDIBits(hDC, hBitmap, 0,
			        (UINT)cy, GetBits(), (LPBITMAPINFO)pDib, DIB_RGB_COLORS);

			DeleteObject(hBitmap);
			DeleteDC(hDC);

			return (bRet!=0);
		} else {
			DeleteDC(hDC);
		}
	} else {
		if (hBitmap) DeleteObject(hBitmap);
	}

	DeleteEnhMetaFile(hMeta);

	return false;
}
Ejemplo n.º 4
0
void PLWEMFDecoder::Open (PLDataSource * pDataSrc)
{
	PLASSERT_VALID(this);
  PLASSERT(m_bm == 0);
  PLASSERT(m_memdc == 0);
  PLASSERT(m_hemf == 0);

	SAPMFILEHEADER* pplaceablehdr = NULL;
	bool isadobe = false;
      bool isemf;

	// Get the type of the file (WMF or EMF) from the file name
      if (pDataSrc->NameIsWide()){
        wchar_t* strname = _wcsdup(pDataSrc->GetNameW());
        PLASSERT(strname);
        if (strname == NULL) {
                // This should never happen under 32-Bit, but who knows?
                PLASSERT(false);
                raiseError (PL_ERRNO_MEMORY,"Out of memory during strdup.");
        }
        _wcsupr(strname);
        isemf = wcsstr(strname,L".EMF") != NULL;
        free(strname);
      }
      else{
	char* strname = _strdup(pDataSrc->GetName());
	PLASSERT(strname);
	if (strname == NULL) {
		// This should never happen under 32-Bit, but who knows?
		PLASSERT(false);
		raiseError (PL_ERRNO_MEMORY,"Out of memory during strdup.");
	}
	_strupr(strname);
	bool isemf = strstr(strname,".EMF") != NULL;
	free(strname);
      }

	// Get a DC for the display
	m_dc = ::GetDC(NULL);
	PLASSERT(m_dc);
	if (m_dc == NULL) {
		PLASSERT(false);
		raiseError (PL_ERRNO_MEMORY,"Cannot allocate device context.");
	}

	if (isemf) {
		// We have an enhanced meta file which makes it alot easier
		m_hemf = SetEnhMetaFileBits(pDataSrc->GetFileSize(),pDataSrc->ReadEverything());
	}
	else {
		// Buh, old 16-Bit WMF, Convert it to an enhanced metafile before proceeding.
		// Also, check if this is a placeable metafile with an Adobe Placeable header
		pplaceablehdr = (SAPMFILEHEADER*)pDataSrc->ReadEverything();
		PLBYTE* p = NULL;
		UINT size;
		// If we have an adobe header, skip it to use only the real windows-conform data
		if (pplaceablehdr->key == ALDUSKEY) {
			isadobe = true;
			p = pDataSrc->ReadEverything()+sizeof(SAPMFILEHEADER);
			size = pDataSrc->GetFileSize() - sizeof(SAPMFILEHEADER);
		}
		else {
			// Else use the whole file contents as the metafile and assume
			// a native 16-Bit Windows-conform WMF
			p = pDataSrc->ReadEverything();
			size = pDataSrc->GetFileSize();
		}
		#ifdef _MFC_VER
		PLASSERT(AfxIsValidAddress(p,size,false));
		#endif
		m_hemf = SetWinMetaFileBits(size,p,m_dc,NULL);
	}

	// If m_hemf is NULL, windows refused to load the metafile. If this is
	// the case, we're done. Notify the caller
	if (m_hemf == NULL) {
		raiseError (PL_ERRFORMAT_NOT_SUPPORTED,"Windows Metafile functions failed to load this image.");
	}

	// Get the header from the enhanced metafile, It contains some
	// useful information which will aid us during constuction of
	// the bitmap.
	// The header is of variable length. First get the amount of
	//  memory required for the header
	UINT sizeneeded = GetEnhMetaFileHeader(m_hemf,0,NULL);
	if (sizeneeded == 0) {
		raiseError (PL_ERRFORMAT_UNKNOWN,"No header information in metafile");
	}

	// Allocate storage for the header and read it in
	m_phdr = (LPENHMETAHEADER) new PLBYTE[sizeneeded];
	if (m_phdr == NULL) {
		PLASSERT(false);
		raiseError (PL_ERRNO_MEMORY,"Out of memory during allocation of header.");
	}
	m_phdr->iType = EMR_HEADER;
	m_phdr->nSize = sizeneeded;
	#ifdef _MFC_VER
	PLASSERT(AfxIsValidAddress(m_phdr,sizeneeded,true));
	#endif
	GetEnhMetaFileHeader(m_hemf,sizeneeded,m_phdr);

	int bpp = GetDeviceCaps(m_dc,BITSPIXEL);

	// Calculate the dimensions of the final bitmap. If we have
	// a placeable header in the WMF, we use the dimensions of
	// that image, else we use the calculated dimensions in the
	// EMF
	int width,height;
	if (isadobe) {
		PLASSERT(pplaceablehdr);
		int lpx = GetDeviceCaps(m_dc,LOGPIXELSX);
		int lpy = GetDeviceCaps(m_dc,LOGPIXELSY);
		// Calculate the absolute with and height and transform from twips to pixel
		width  = (int) (pplaceablehdr->Right-pplaceablehdr->Left) * lpx / pplaceablehdr->inch;
		height = (int) (pplaceablehdr->Bottom-pplaceablehdr->Top) * lpy / pplaceablehdr->inch;
	}
	else {
		// Use the rclFrame of the header because it is the true device independent
		// information and also some applications (e.g. Corel) don't fill the
		// rclBounds correctly
		// Using:
		//     MetaPixelsX = MetaWidthMM * MetaPixels / (MetaMM * 100);
		// where:
		//     MetaWidthMM = metafile width in 0.01mm units
		//     MetaPixels  = width in pixels of the reference device
		//     MetaMM      = width in millimeters of the reference device
		// Same applies to the Y axis
		width  = ((m_phdr->rclFrame.right  - m_phdr->rclFrame.left) * m_phdr->szlDevice.cx) / (m_phdr->szlMillimeters.cx*100);
		height = ((m_phdr->rclFrame.bottom  - m_phdr->rclFrame.top) * m_phdr->szlDevice.cy) / (m_phdr->szlMillimeters.cy*100);
	}

	// If this is a very old WMF without a PLACEABLE info,
	// we use somewhat meaningful defaults. Also, if the header was
	// not written correctly, we use this as a fallback
	if (width <= 0) {
		width = 320;
	}
	if (height <= 0) {
		height = 200;
	}

	// Create a device content for the screen, and a memory device
	// content to play the metafile to

	m_memdc = CreateCompatibleDC(m_dc);
	PLASSERT(m_memdc);
	if (m_memdc == NULL) {
		PLASSERT(false);
		raiseError (PL_ERRNO_MEMORY,"Cannot allocate device context.");
	}

	m_bm = CreateCompatibleBitmap(m_dc,width,height);
	if (m_bm == NULL) {
		PLASSERT(false);
		raiseError (PL_ERRNO_MEMORY,"Cannot allocate memory bitmap.");
	}

	m_holdbm = SelectObject(m_memdc,m_bm);

	// If the metafile has a palette, read it in
	UINT pe = GetEnhMetaFilePaletteEntries(m_hemf, 0, NULL);

	// pe is the real number of palette entries. To make the resulting
	// bitmap more useful, we always setup a 256 color palette if the
	// metafile has a palette
  if (pe>0 && pe<256)
  {
    SetBmpInfo (PLPoint (width, height), PLPoint(0,0), 
             PLPixelFormat::L8);
	}
	else 
  {
    SetBmpInfo (PLPoint (width, height), PLPoint(0,0), 
            PLPixelFormat::B8G8R8A8);
  }
}
Ejemplo n.º 5
0
void PLWEMFDecoder::GetImage (PLBmpBase & Bmp)
{
	HPALETTE hpal = NULL;
  LPLOGPALETTE plogpal (0);

  if (GetBitsPerPixel() == 8) {
		plogpal = (LPLOGPALETTE)new PLBYTE[sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 256)];
		memset(plogpal,0x0,sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*256);
		plogpal->palVersion = 0x300;
		plogpal->palNumEntries = 256;
		if (plogpal == NULL) {
			PLASSERT(false);
			raiseError (PL_ERRNO_MEMORY,"Cannot allocate palette.");
		}
    UINT pe = GetEnhMetaFilePaletteEntries(m_hemf, 0, NULL);
		GetEnhMetaFilePaletteEntries(m_hemf, pe, plogpal->palPalEntry);
	}

	// Setup a logical palette for our memory dc and also a
	// paintlib compatible palette for the paintlib bitmap
  PLPixel32 pPal[256];
	if (plogpal) {
		for (UINT i = 0; i < 256; i++) {
			pPal[i] = *(PLPixel32*)&plogpal->palPalEntry[i];
		}

		if ((hpal = CreatePalette((LPLOGPALETTE)plogpal))) {
			m_holdpal = SelectPalette(m_memdc, hpal, false);
			RealizePalette(m_memdc);
		}
		Bmp.SetPalette(pPal);
		delete [] plogpal;
	}

	// Play the metafile into the device context
	// First, setup a bounding rectangle and fill
	// the memory dc with white (some metafiles only
	// use a black pen to draw and have no actual fill
	// color set, This would cause a black on black
	// painting which is rather useless
	RECT rc;
	rc.left = rc.top = 0;
	rc.bottom = GetHeight();
	rc.right = GetWidth();

	FillRect(m_memdc,&rc,(HBRUSH)GetStockObject(WHITE_BRUSH));

	// Heeere we go....
	BOOL bres = PlayEnhMetaFile(m_memdc,m_hemf,&rc);

	// Finally, convert the Windows bitmap into a paintlib bitmap
	PLWinBmp& winbmp = dynamic_cast<PLWinBmp&>(Bmp);
	BITMAPINFO* pBMI = (BITMAPINFO*)winbmp.GetBMI();
	PLBYTE* pBits = (PLBYTE*)winbmp.GetBits();
	if (GetBitsPerPixel() == 8) {
		GetDIBits(m_dc, m_bm, 0, GetHeight(), winbmp.GetBits(), pBMI, DIB_RGB_COLORS);
	}
	else {
		GetDIBits(m_dc, m_bm, 0, GetHeight(), winbmp.GetBits(), pBMI, DIB_PAL_COLORS);
	}
}
Ejemplo n.º 6
0
BOOL KCanvasWindow::Print(void)
{
	HDC             hDCPrinter;
    int             iEntries;
    
    if (hMetaFile == NULL) 
		return FALSE;

	// if (SpoolFile.PlaySpoolFile(CurEmfFileName, NULL, NULL, NULL))
	//	  return TRUE;

	{
		PRINTDLG        pd;
    
		memset(&pd, 0, sizeof(pd));
		pd.lStructSize = sizeof(PRINTDLG);
		pd.hwndOwner   = m_hWnd;
		pd.Flags       = PD_RETURNDC;
		pd.hInstance   = hInstance;

		if (!PrintDlg(&pd) || (pd.hDC==NULL)) 
			return FALSE;

		hDCPrinter = pd.hDC;
	}

	
	// EmfScope.UnlinkClientServer();

	
	{
		DOCINFO         DocInfo;
		char            title[128];

		// put a special tag before the title so spehon32 can ignore it
		strcpy(title, ItsMe);
		GetEnhMetaFileDescription(hMetaFile, sizeof(title)-strlen(title), title+strlen(title));

		memset(&DocInfo, 0, sizeof(DocInfo));
		DocInfo.cbSize      = sizeof(DOCINFO);
		DocInfo.lpszDocName = title;
		DocInfo.lpszOutput  = NULL;
		StartDoc(hDCPrinter, &DocInfo);
	}

    
	StartPage(hDCPrinter);

    
	iEntries = GetEnhMetaFilePaletteEntries(hMetaFile, 0, NULL);

    if (iEntries) 
	{
	    PLOGPALETTE     plogPal;
	    PBYTE           pjTmp;
		HPALETTE        hPal;

        if ((plogPal = (PLOGPALETTE)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
                sizeof(DWORD) + sizeof(PALETTEENTRY)*iEntries )) == NULL) 
		{
            MessageBox(m_hWnd, "Failed in Creating Palette!", "Error", MB_OK);
        }

        plogPal->palVersion = 0x300;
        plogPal->palNumEntries = (WORD) iEntries;
        pjTmp = (PBYTE) plogPal;
        pjTmp += 8;

        GetEnhMetaFilePaletteEntries(hMetaFile, iEntries, (PPALETTEENTRY)pjTmp);
        hPal = CreatePalette(plogPal);
        GlobalFree(plogPal);

        SelectPalette(hDCPrinter, hPal, FALSE);
        RealizePalette(hDCPrinter);
    }


	{
        RECT rc;
		ENHMETAHEADER   EnhMetaHdr;
    
		GetEnhMetaFileHeader(hMetaFile, sizeof(ENHMETAHEADER), &EnhMetaHdr);

        rc.top    = 0;
		rc.left   = 0;
        rc.right  = EnhMetaHdr.szlDevice.cx;
        rc.bottom = EnhMetaHdr.szlDevice.cy;
        
		if (!PlayEnhMetaFile(hDCPrinter, hMetaFile, &rc)) 
		{
            char    text[128];

            wsprintf(text, "Fail in PlayEnhMetaFile! Error %ld\n", GetLastError());
            MessageBox(0, text, "Play", MB_OK);
		}
	}

    EndPage(hDCPrinter);
    EndDoc(hDCPrinter);

	// EmfScope.LinkClientServer();

	return TRUE;
}
Ejemplo n.º 7
0
STDMETHODIMP CDropTarget::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
{
#ifdef _DEBUG
	printf("IDropTarget::Drop\n");
#endif //_DEBUG

	DWORD dwOKEffects = *pdwEffect;
	{
		//We do this because grfKeyState will always have the mouse button used off
		DWORD temp = LastKeyState;
		//Get the position of the drop
		DragOver(grfKeyState, pt, pdwEffect);
		LastKeyState = temp;
	}
	//Remove the effects
	pDataObj = NULL;
	DragLeave();

	bool copying = (*pdwEffect & DROPEFFECT_COPY) != 0;

	size_t totallen = 0;
	BYTE *data = NULL;
	bool gotdata = false;

	UINT *formats = NULL;
	UINT numformats = 0;

	FORMATETC *fel = NULL;
	UINT numfe = 0;

	bool NeedToChooseFormat = true;
	int IndexOfDataToInsert = -1;
	bool NeedToChooseMoveorCopy = (LastKeyState | grfKeyState) & (MK_MBUTTON | MK_RBUTTON) || hexwnd.always_pick_move_copy;

	if (hexwnd.dragging) // Internal data
	{
		hexwnd.dragging = FALSE;
		if (NeedToChooseMoveorCopy)
		{
			int choice = PopupDropMenu(pt);
			if (choice == 0)
			{
				pDataObject->Release();
				*pdwEffect = DROPEFFECT_NONE;
				return S_OK;
			}
			copying = choice != 1;
		}
		int iMove1stEnd = hexwnd.iGetStartOfSelection();
		int iMove2ndEndorLen = hexwnd.iGetEndOfSelection();
		int iMovePosOrg = hexwnd.new_pos;
		if (!copying && hexwnd.new_pos > iMove2ndEndorLen)
			hexwnd.new_pos += iMove1stEnd - iMove2ndEndorLen - 1;
		iMovePos = hexwnd.new_pos;
		iMoveOpTyp = copying ? OPTYP_COPY : OPTYP_MOVE;
		SimpleArray<BYTE> olddata;
		const int len = iMove2ndEndorLen - iMove1stEnd + 1;
		if (grfKeyState & MK_SHIFT) // Overwrite
		{
			if (copying)
			{
				//Just [realloc &] memmove
				if (iMovePos + len > hexwnd.m_dataArray.GetLength()) // Need more space
				{
					olddata.AppendArray(&hexwnd.m_dataArray[iMovePos], hexwnd.m_dataArray.GetLength() - iMovePos);
					if (hexwnd.m_dataArray.SetSize(iMovePos + len))
					{
						hexwnd.m_dataArray.ExpandToSize();
						memmove(&hexwnd.m_dataArray[iMovePos], &hexwnd.m_dataArray[iMove1stEnd], len);
					}
				}
				else // Enough space
				{
					olddata.AppendArray(&hexwnd.m_dataArray[iMovePos], len);
					memmove(&hexwnd.m_dataArray[iMovePos], &hexwnd.m_dataArray[iMove1stEnd], len);
				}
				hexwnd.push_undorecord(iMovePos, olddata, olddata.GetLength(), &hexwnd.m_dataArray[iMovePos], len);
			}
			else //Moving
			{
				if (iMovePos > iMove1stEnd) //Forward
				{
					olddata.AppendArray(&hexwnd.m_dataArray[iMove1stEnd], iMovePosOrg + len - iMove1stEnd);
					hexwnd.move_copy_sub(iMove1stEnd, iMove2ndEndorLen, 0);
					hexwnd.m_dataArray.RemoveAt(iMovePos+len,len);
					hexwnd.push_undorecord(iMove1stEnd, olddata, olddata.GetLength(), &hexwnd.m_dataArray[iMove1stEnd], iMovePosOrg - iMove1stEnd);
				}
				else //Backward
				{
					if (iMove1stEnd-iMovePos>=len)
					{
						olddata.AppendArray(&hexwnd.m_dataArray[iMovePos], iMove1stEnd + len - iMovePos);
						memmove(&hexwnd.m_dataArray[iMovePos],&hexwnd.m_dataArray[iMove1stEnd],len);
						hexwnd.m_dataArray.RemoveAt(iMove1stEnd,len);
					}
					else
					{
						olddata.AppendArray(&hexwnd.m_dataArray[iMovePos], iMove1stEnd + len - (iMovePos + len - iMove1stEnd) - iMovePos);
						memmove(&hexwnd.m_dataArray[iMovePos],&hexwnd.m_dataArray[iMove1stEnd],len);
						hexwnd.m_dataArray.RemoveAt(iMovePos+len,len-(iMovePos + len - iMove1stEnd));
					}
					hexwnd.push_undorecord(iMovePos, olddata, olddata.GetLength(), &hexwnd.m_dataArray[iMovePos], iMove1stEnd - iMovePos);
				}
			}
			hexwnd.iStartOfSelection = iMovePos;
			hexwnd.iEndOfSelection = iMovePos+len-1;
			hexwnd.bFilestatusChanged = true;
			hexwnd.bSelected = true;
			hexwnd.resize_window();
		}
		else // Insert
		{
			hexwnd.CMD_move_copy(iMove1stEnd, iMove2ndEndorLen, 1);
		}
	}
	else // External data
	{
		STGMEDIUM stm;
		HRESULT err = E_UNEXPECTED;

		//Get the formats enumerator
		IEnumFORMATETC *iefe = 0;
		pDataObject->EnumFormatEtc(DATADIR_GET, &iefe);
		if (iefe == 0)
		{
#ifdef _DEBUG
			printf("Unable to create a drag-drop data enumerator\n");
#endif //_DEBUG
			goto ERR;
		}
		iefe->Reset();

		//Get the available formats
		for(;;)
		{
			void *temp = realloc(fel, (numfe + 1) * sizeof(FORMATETC));
			if (temp != NULL)
			{
				fel = (FORMATETC*) temp;
				temp = NULL;
				int r;
				r = iefe->Next(1, &fel[numfe], NULL);
				if (r != S_OK)
					break;//No more formats
				numfe++;
			}
			else if (fel == NULL)
			{
				//We only go here if nothing could be allocated
#ifdef _DEBUG
				printf("Not enough memory for the drag-drop format list\n");
#endif //_DEBUG
				goto ERR_ENUM;
			}
		}
		UINT i;
		/*Check which format should be inserted according to user preferences*/
		if (numfe == 0)
		{
			MessageBox(hexwnd.pwnd, GetLangString(IDS_DD_NO_DATA), MB_OK);
			err = S_OK;
			*pdwEffect = DROPEFFECT_NONE;
			goto ERR_ENUM;
		}
		if (hexwnd.prefer_CF_HDROP)
		{
			for (i = 0 ; i < numfe ; i++)
			{
				if (fel[i].cfFormat == CF_HDROP)
				{
					//Return no effect & let shell32 handle it
					if (S_OK == pDataObject->GetData(&fel[i], &stm))
					{
						hexwnd.dropfiles((HDROP)stm.hGlobal);
					}
					err = S_OK;
					*pdwEffect = DROPEFFECT_NONE;
					goto ERR_ENUM;
				}
			}
		}
		if (numfe == 1)
		{
			IndexOfDataToInsert = 0;
		}
		else if (hexwnd.prefer_CF_BINARYDATA)
		{
			for (i = 0 ; i < numfe ; i++)
			{
				if (fel[i].cfFormat == CF_BINARYDATA)
				{
					NeedToChooseFormat = false;
					IndexOfDataToInsert = i;
					break;
				}
			}
		}
		else if (hexwnd.prefer_CF_TEXT)
		{
			for (i = 0 ; i < numfe ; i++)
			{
				if (fel[i].cfFormat == CF_TEXT)
				{
					NeedToChooseFormat = false;
					IndexOfDataToInsert = i;
					break;
				}
			}
		}
		if (NeedToChooseFormat)
		{
			dialog<DragDropDlg> params;
			params.allowable_effects = dwOKEffects & (DROPEFFECT_COPY | DROPEFFECT_MOVE);
			params.effect = copying;
			params.formatetcs = fel;
			params.numformatetcs = numfe;
			params.formats = NULL;
			params.numformats = 0;
			int ret = params.DoModal(hexwnd.pwnd);
			if (ret < 0)
			{
				//An error occured or the user canceled the operation
				err = S_OK;
				*pdwEffect = DROPEFFECT_NONE;
				goto ERR_ENUM;
			}
			numformats = params.numformats;
			formats = params.formats;
			copying = params.effect;
		}
		else if (NeedToChooseMoveorCopy)
		{
			int choice = PopupDropMenu(pt);
			if (choice == 0)
			{
				err = S_OK;
				*pdwEffect = DROPEFFECT_NONE;
				goto ERR_ENUM;
			}
			copying = choice != 1;
		}

		if (IndexOfDataToInsert >= 0 && formats == NULL)
		{
			formats = (UINT*)&IndexOfDataToInsert;
			numformats = 1;
		}

		//for each selected format
		for (i = 0 ; i < numformats ; i++)
		{
			FORMATETC fe = fel[formats[i]];
			/*It is important that when debugging (with M$VC at least) you do not step __into__ the below GetData call
			  If you do the app providing the data source will die & GetData will return OLE_E_NOTRUNNING or E_FAIL
			  The solution is to step over the call
			  It is also possible that a debugger will be opened & attach itself to the data provider
			*/
			if (pDataObject->GetData(&fe, &stm) == S_OK)
			{
				//Get len
				size_t len = 0;
				switch (stm.tymed)
				{
					case TYMED_HGLOBAL:
						len = GlobalSize(stm.hGlobal);
						break;
#ifndef __CYGWIN__
					case TYMED_FILE:
					{
						int fh = _wopen(stm.lpszFileName, _O_BINARY | _O_RDONLY);
						if (fh != -1)
						{
							len = _filelength(fh);
							if (len == (size_t)-1)
								len = 0;
							_close(fh);
						}
					} break;
#endif //__CYGWIN__
					case TYMED_ISTREAM:
						{
							STATSTG stat;
							if (S_OK == stm.pstm->Stat(&stat, STATFLAG_NONAME))
								len = (size_t)stat.cbSize.LowPart;
						}
						break;
					//This case is going to be a bitch to implement so it can wait for a while
					//It will need to be a recursive method that stores the STATSTG structures (+ the name), contents/the bytes of data in streams/property sets
					case TYMED_ISTORAGE:
						{
							MessageBox(hexwnd.pwnd, GetLangString(IDS_DD_TYMED_NOTSUP), MB_OK);
						} 
						break; // IStorage*
					case TYMED_GDI:
						{
							len = GetObject(stm.hBitmap, 0, NULL);
							if (len)
							{
								DIBSECTION t;
								GetObject(stm.hBitmap, len, &t);
								len += t.dsBm.bmHeight*t.dsBm.bmWidthBytes*t.dsBm.bmPlanes;
							}
						}
						break; // HBITMAP
					case TYMED_MFPICT:
						{
							len = GlobalSize(stm.hMetaFilePict);
							METAFILEPICT *pMFP = (METAFILEPICT*)GlobalLock(stm.hMetaFilePict);
							if (pMFP)
							{
								len += GetMetaFileBitsEx(pMFP->hMF, 0, NULL);
								GlobalUnlock(stm.hMetaFilePict);
							}
						}
						break; // HMETAFILE
#ifndef __CYGWIN__
					case TYMED_ENHMF:
						{
							len = GetEnhMetaFileHeader(stm.hEnhMetaFile, 0, NULL);
							DWORD n = GetEnhMetaFileDescriptionW(stm.hEnhMetaFile, 0, NULL);
							if (n && n != GDI_ERROR)
								len += sizeof(WCHAR) * n;
							len += GetEnhMetaFileBits(stm.hEnhMetaFile, 0, NULL);
							n = GetEnhMetaFilePaletteEntries(stm.hEnhMetaFile, 0, NULL);
							if (n && n != GDI_ERROR)
								len += sizeof(LOGPALETTE) + (n - 1) * sizeof(PALETTEENTRY);
						}
						break; // HENHMETAFILE
#endif //__CYGWIN__
					//case TYMED_NULL:break;
				}
				if (!len)
					continue;

				/*Malloc
				We do this so that if the data access fails we only need free(data)
				and don't need to mess around with the m_dataArray.
				Perhaps in the future the m_dataArray can support undoable actions.*/
				BYTE* t = (BYTE*)realloc(data, len);
				if (!t)
					continue;
				data = t;
				memset(data, 0, len);

				//Get data
				switch (stm.tymed)
				{
					case TYMED_HGLOBAL:
						{
							if (LPVOID pmem = GlobalLock(stm.hGlobal))
							{
								memcpy(data, pmem, len);
								gotdata = true;
								GlobalUnlock(stm.hGlobal);
							}
						}
						break;
#ifndef __CYGWIN__
					case TYMED_FILE:
						{
							int fh = _wopen(stm.lpszFileName, _O_BINARY | _O_RDONLY);
							if (fh != -1)
							{
								if (0 < _read(fh, data, len))
									gotdata = true;
								_close(fh);
							}
						}
						break;
#endif //__CYGWIN__
					case TYMED_ISTREAM:
						{
							LARGE_INTEGER zero = { 0 };
							ULARGE_INTEGER pos;
							if (S_OK == stm.pstm->Seek(zero, STREAM_SEEK_CUR, &pos))
							{
								stm.pstm->Seek(zero, STREAM_SEEK_SET, NULL);
								if (S_OK == stm.pstm->Read(data, len, NULL))
									gotdata = true;
								stm.pstm->Seek(*(LARGE_INTEGER*)&pos, STREAM_SEEK_SET, NULL);
							}
						}
						break;
					//This case is going to be a bitch to implement so it can wait for a while
					//It will need to be a recursive method that stores the STATSTG structures (+ the name), contents/the bytes of data in streams/property sets
					case TYMED_ISTORAGE:
						{
							MessageBox(hexwnd.pwnd, GetLangString(IDS_DD_TYMED_NOTSUP), MB_OK);
							goto ERR_ENUM;
						}
						break;//IStorage*
					case TYMED_GDI:
						{
							int l = GetObject(stm.hBitmap, len, data);
							if (l)
							{
								BITMAP* bm = (BITMAP*)data;
								if (bm->bmBits)
									memcpy(&data[l], bm->bmBits, len-l);
								else
									GetBitmapBits(stm.hBitmap, len-l, &data[l]);
								gotdata = true;
							}
						} break; // HBITMAP
					case TYMED_MFPICT:
						{
							if (METAFILEPICT *pMFP = (METAFILEPICT *)GlobalLock(stm.hMetaFilePict))
							{
								memcpy(data, pMFP, sizeof *pMFP);
								GetMetaFileBitsEx(pMFP->hMF, len - sizeof(*pMFP), &data[sizeof(*pMFP)]);
								GlobalUnlock(stm.hMetaFilePict);
								gotdata = true;
							}
						} break;//HMETAFILE
#ifndef __CYGWIN__
					case TYMED_ENHMF:
						{
							DWORD i = 0, n = 0, l = len;
							n = GetEnhMetaFileHeader(stm.hEnhMetaFile, l, (ENHMETAHEADER*)&data[i]);
							l -= n;
							i += n;
							n = GetEnhMetaFileDescriptionW(stm.hEnhMetaFile,
									l / sizeof(WCHAR), (LPWSTR)&data[i]);
							if (n && n != GDI_ERROR)
							{
								n *= sizeof(WCHAR);l -= n; i += n;
							}
							n = GetEnhMetaFileBits(stm.hEnhMetaFile, l, &data[i]);
							l -= n; i += n;
							n = GetEnhMetaFilePaletteEntries(stm.hEnhMetaFile, 0, NULL);
							if (n && n != GDI_ERROR)
							{
								LOGPALETTE* lp = (LOGPALETTE*)&data[i];
								lp->palVersion = 0x300;
								lp->palNumEntries = (USHORT)n;
								l -= sizeof(lp->palVersion) + sizeof(lp->palNumEntries);
								n = GetEnhMetaFilePaletteEntries(stm.hEnhMetaFile,
										l / sizeof(PALETTEENTRY), &lp->palPalEntry[0]);
								i += n*sizeof(PALETTEENTRY);
							}
							if (i)
								gotdata = true;
						} break; // HENHMETAFILE
#endif //__CYGWIN__
					//case TYMED_NULL:break;
				}

				ReleaseStgMedium(&stm);

				if (gotdata)
				{
					BYTE* DataToInsert = data;
					if (fe.cfFormat == CF_BINARYDATA)
					{
						len = *(DWORD*)data;
						DataToInsert += 4;
					}
					else if (fe.cfFormat == CF_TEXT || fe.cfFormat == CF_OEMTEXT)
					{
						len = strlen((char*)data);
					}
					else if (fe.cfFormat == CF_UNICODETEXT)
					{
						len = sizeof(wchar_t)*wcslen((wchar_t*)data);
					}

					// Insert/overwrite data into m_dataArray
					if (grfKeyState&MK_SHIFT)
					{
						/* Overwite */
						SimpleArray<BYTE> olddata;
						DWORD upper = 1 + hexwnd.m_dataArray.GetUpperBound();
						if (hexwnd.new_pos+len > upper)
						{
							olddata.AppendArray(&hexwnd.m_dataArray[hexwnd.new_pos + (int)totallen], upper - hexwnd.new_pos + (int)totallen);
							/* Need more space */
							if (hexwnd.m_dataArray.SetSize(hexwnd.new_pos + totallen + len))
							{
								hexwnd.m_dataArray.ExpandToSize();
								memcpy(&hexwnd.m_dataArray[hexwnd.new_pos +
										(int)totallen], DataToInsert, len);
								hexwnd.push_undorecord(hexwnd.new_pos + totallen, olddata, olddata.GetLength(), DataToInsert, len);
								gotdata = true;
								totallen += len;
							}
						}
						else
						{
							/* Enough space */
							olddata.AppendArray(&hexwnd.m_dataArray[hexwnd.new_pos + (int)totallen], len);
							memcpy(&hexwnd.m_dataArray[hexwnd.new_pos +
									(int)totallen], DataToInsert, len);
							hexwnd.push_undorecord(hexwnd.new_pos + totallen, olddata, olddata.GetLength(), DataToInsert, len);
							gotdata = true;
							totallen += len;
						}
					}
					else if (hexwnd.m_dataArray.InsertAtGrow(hexwnd.new_pos + totallen, DataToInsert, 0, len))
					{
						/* Insert */
						hexwnd.push_undorecord(hexwnd.new_pos + totallen, NULL, 0, DataToInsert, len);
						gotdata = true;
						totallen += len;
					}
				}
			}

		} // For each selected format

		// Release the data
		free(data);
		data = NULL;
		if (IndexOfDataToInsert < 0)
		{
			free(formats);
			formats = NULL;
		}

		if (gotdata)
		{
			hexwnd.iStartOfSelection = hexwnd.new_pos;
			hexwnd.iEndOfSelection = hexwnd.new_pos + totallen - 1;
			hexwnd.bFilestatusChanged = true;
			hexwnd.bSelected = true;
			hexwnd.resize_window();
			hexwnd.synch_sibling();
		}

		*pdwEffect = copying  ? DROPEFFECT_COPY : DROPEFFECT_MOVE;

		err = S_OK;

ERR_ENUM:
		iefe->Release();
		free(fel);
ERR:
		pDataObject->Release();
		return err;
	}
	pDataObject->Release();

	return S_OK;
}