Link to home
Start Free TrialLog in
Avatar of drnick
drnick

asked on

PlayEnhMethaFile

hi fellows,
i encountered a strange problem i cannot solve that easy:

i want to do the following:
- read an enhanced metafile from disk
- create an new enhanced metafile device context in memory
- play the loaded emf on this context
   (therefore the bounding rectangles should match i think)
- now i can draw on the dc over the loaded emf
- store the new emf on disk
  (the old one is in the background, maybe some text/line is drawn above)

up to now i did in my member function of a class:

dword z = GetEnhMetaFileA(afilename);
if(z)
 {enhmetaheader h;
  if(GetEnhMetaFileHeader(z, sizeof(h), h))
    {
    m_bounds = h.frame;
    m_dc = CreateEnhMetaFileA(m_dc, 0, &m_bounds, IMAGE_NAME);
    if(m_dc)
      {
      if(PlayEnhMetaFile(m_dc, z, &m_bounds))
       {
       m_clip = CreateRectRgnIndirect(&m_bounds);
       if(m_clip)  SelectClipRgn(m_dc, m_clip);              
       }
     else IMAGE_ERROR;
     }
    else IMAGE_ERROR;
    if(!(retval)) Clear();
    }
  else IMAGE_ERROR;
  DeleteEnhMetaFile(z);
  }
else IMAGE_ERROR;

the datatypes, functionprototypes and the macro IMAGE_ERROR look maybe odd
but work definitely
m_bounds is of type rect, a member variable
m_dc and m_clip are also member variables

i had two cases of error:

in the first, a self drawn and stored emf was loaded
(which can be loaded correctly with any graphics software),
the PlayEnhMetaFile fails but GetLastError returnes NO_ERROR.
if i store the result again with CloseEnhMetaFile and CopyEnhMetaFile,
the picture is shrinked to a very small rectangle in a huge white area.

in the second i try to load an emf generated by a graphics suite,
here it works all fine (at the first glance),
but if i try to store the result again, it gives me an empty
picture.

the storing routine works all fine (since i can watch
self-generated and stored emfs)

so what's wrong?
can somebody help me?

the language is either c++ or dephi,
no MFC or predefined components can be used,
we work with directly imported win api

a short code sample would be nice

thanks in advance,
dr. nick
Avatar of DanRollins
DanRollins
Flag of United States of America image

>>PlayEnhMetaFile fails but GetLastError returnes NO_ERROR.

We saw this same 'false error' in this Q:
   https://www.experts-exchange.com/questions/20012402/PlayEnhMetaFile-returns-zero.html
   with no resolution.  Microsoft is mute about what is certainly a system error (but it may be driver related?)

>>the picture is shrinked to a very small rectangle in a huge white area.

Place a breakpoint and verify the correct values are in &m_bounds
-==-=-=-=-=-=-=-
On what platform are you developing/testing?  There are some distinct limitations to the PlayEnhMetaFile API when used on Win9x systems.

-- Dan
Avatar of drnick
drnick

ASKER

first of all, thanks

as far as i read the thread you posted,
i think i can ignore the faulty return value of playenhmetafile,
is that true?

we test on windows 2000 server

the coordinates in the header of the file are correct,
the smallest surrounding rectangle (bounds)
is (0,0,99,99) and the app-defined (frame) is
(0,0,100,100), so there's no special reason for the shrinking behaviour.

but however, i don't need to care about return values if
the picture is at least drawn correctly.
you know, i can load the thing by getenhmetafile and store it with copyenhmetafile again correctly, but i need to edit it.

if i use FengYuan's prog, i get (see below).
this looks quite correct, i think.
have you any other idea?

        hRegion = CreateRectRgn(0,0,100,100);
     ExtSelectClipRgn(hDC, hRegion, RGN_COPY);
     DeleteObject(hRegion);
     hObj[1]=CreateSolidBrush(RGB(0xFF,0,0));
     SelectObject(hDC, hObj[1]);
     SelectObject(hDC, hObj[1]);
     PatBlt(hDC,0,0,100,100,PATCOPY);
     SelectObject(hDC, hObj[1]);
     DeleteObject(hObj[1]);
     hObj[1]=CreateSolidBrush(RGB(0xFF,0xFF,0));
     SelectObject(hDC, hObj[1]);
     SelectObject(hDC, hObj[1]);
     PatBlt(hDC,25,25,51,51,PATCOPY);
     SelectObject(hDC, hObj[1]);
     DeleteObject(hObj[1]);
     SetTextColor(hDC, RGB(0,0,0xFF));
     hObj[1]=CreateFont(-20,0,0,0,700,1,0,0,1,0,0,0,0,"arial");
     SelectObject(hDC, hObj[1]);
     const int Dx_1[]={ 12, 11, 6, 6, 12, 6, 16, 11, 6, 7 };
     ExtTextOutW(hDC, 10,10,0,NULL,L"hallo welt",10,Dx_1);
     DeleteObject(hObj[1]);
     SetTextColor(hDC, RGB(0,0,0xFF));
     hObj[1]=CreateFont(-20,0,0,0,700,1,0,0,1,0,0,0,0,"symbol");
     SelectObject(hDC, hObj[1]);
     const int Dx_2[]={ 13, 14, 12, 12, 12, 6, 15, 10, 12, 10 };
     ExtTextOutW(hDC, 10,40,0,NULL,L"hallo welt",10,Dx_2);
     DeleteObject(hObj[1]);
     hObj[1]=CreateSolidBrush(RGB(0x51,0x93,3));
     SelectObject(hDC, hObj[1]);
     hObj[2]=CreatePen(PS_SOLID, 1, RGB(7,0xB2,1));
     SelectObject(hDC, hObj[2]);
     Chord(hDC, 20, 20, 79, 79, 80, 50, 50, 80);
     DeleteObject(hObj[2]);
     DeleteObject(hObj[1]);
     hObj[1]=CreateSolidBrush(RGB(0,0xFF,0));
     SelectObject(hDC, hObj[1]);
     hObj[2]=CreatePen(PS_SOLID, 1, RGB(0x4C,0,0));
     SelectObject(hDC, hObj[2]);
     Pie(hDC, 10, 20, 29, 39, 67, 54, 23, 56);
     DeleteObject(hObj[2]);
     DeleteObject(hObj[1]);
     hObj[1]=CreateSolidBrush(RGB(0,0x98,0x19));
     SelectObject(hDC, hObj[1]);
     hObj[2]=CreatePen(PS_SOLID, 1, RGB(0,0xF0,0xFF));
     SelectObject(hDC, hObj[2]);
     Ellipse(hDC, 40, 40, 89, 59);
     DeleteObject(hObj[2]);
     DeleteObject(hObj[1]);
     hObj[1]=CreateSolidBrush(RGB(0x62,0xB2,0));
     SelectObject(hDC, hObj[1]);
     hObj[2]=CreatePen(PS_SOLID, 1, RGB(0x3E,0xCA,0x23));
     SelectObject(hDC, hObj[2]);
     RoundRect(hDC, 50, 5, 79, 59, 10, 10);
     DeleteObject(hObj[2]);
     DeleteObject(hObj[1]);
     hObj[1]=CreatePen(PS_SOLID, 1, 0x4098C06);
     SelectObject(hDC, hObj[1]);
     MoveToEx(hDC, 0, 0, NULL);
     LineTo(hDC, 100, 100);
     DeleteObject(hObj[1]);
     hObj[1]=CreatePen(PS_SOLID, 1, RGB(0x20,0xD1,0x88));
     SelectObject(hDC, hObj[1]);
     MoveToEx(hDC, 100, 0, NULL);
     SetArcDirection(hDC, AD_CLOCKWISE);
     Arc(hDC, 0, 0, 99, 99, 20, 20, 90, 70);
     DeleteObject(hObj[1]);
     SetPixelV(hDC, 10, 10, RGB(0xFF,0,0));
     SetPixelV(hDC, 10, 11, RGB(0xFF,0,0));
     SetPixelV(hDC, 11, 11, RGB(0xFF,0,0));
     SetPixelV(hDC, 12, 11, RGB(0xFF,0,0));
     SetPixelV(hDC, 12, 12, RGB(0xFF,0,0));
     SetPixelV(hDC, 13, 13, RGB(0xFF,0,0));
     SetPixelV(hDC, 14, 14, RGB(0xFF,0,0));
     SetPixelV(hDC, 15, 15, RGB(0xFF,0,0));
     hObj[1]=CreateSolidBrush(RGB(0xFF,0,0));
     SelectObject(hDC, hObj[1]);
     SelectObject(hDC, hObj[1]);
     PatBlt(hDC,60,60,10,10,PATCOPY);
     SelectObject(hDC, hObj[1]);
     DeleteObject(hObj[1]);
Avatar of drnick

ASKER

first of all, thanks

as far as i read the thread you posted,
i think i can ignore the faulty return value of playenhmetafile,
is that true?

we test on windows 2000 server

the coordinates in the header of the file are correct,
the smallest surrounding rectangle (bounds)
is (0,0,99,99) and the app-defined (frame) is
(0,0,100,100), so there's no special reason for the shrinking behaviour.

but however, i don't need to care about return values if
the picture is at least drawn correctly.
you know, i can load the thing by getenhmetafile and store it with copyenhmetafile again correctly, but i need to edit it.

if i use FengYuan's prog, i get (see below).
this looks quite correct, i think.
have you any other idea?

        hRegion = CreateRectRgn(0,0,100,100);
     ExtSelectClipRgn(hDC, hRegion, RGN_COPY);
     DeleteObject(hRegion);
     hObj[1]=CreateSolidBrush(RGB(0xFF,0,0));
     SelectObject(hDC, hObj[1]);
     SelectObject(hDC, hObj[1]);
     PatBlt(hDC,0,0,100,100,PATCOPY);
     SelectObject(hDC, hObj[1]);
     DeleteObject(hObj[1]);
     hObj[1]=CreateSolidBrush(RGB(0xFF,0xFF,0));
     SelectObject(hDC, hObj[1]);
     SelectObject(hDC, hObj[1]);
     PatBlt(hDC,25,25,51,51,PATCOPY);
     SelectObject(hDC, hObj[1]);
     DeleteObject(hObj[1]);
     SetTextColor(hDC, RGB(0,0,0xFF));
     hObj[1]=CreateFont(-20,0,0,0,700,1,0,0,1,0,0,0,0,"arial");
     SelectObject(hDC, hObj[1]);
     const int Dx_1[]={ 12, 11, 6, 6, 12, 6, 16, 11, 6, 7 };
     ExtTextOutW(hDC, 10,10,0,NULL,L"hallo welt",10,Dx_1);
     DeleteObject(hObj[1]);
     SetTextColor(hDC, RGB(0,0,0xFF));
     hObj[1]=CreateFont(-20,0,0,0,700,1,0,0,1,0,0,0,0,"symbol");
     SelectObject(hDC, hObj[1]);
     const int Dx_2[]={ 13, 14, 12, 12, 12, 6, 15, 10, 12, 10 };
     ExtTextOutW(hDC, 10,40,0,NULL,L"hallo welt",10,Dx_2);
     DeleteObject(hObj[1]);
     hObj[1]=CreateSolidBrush(RGB(0x51,0x93,3));
     SelectObject(hDC, hObj[1]);
     hObj[2]=CreatePen(PS_SOLID, 1, RGB(7,0xB2,1));
     SelectObject(hDC, hObj[2]);
     Chord(hDC, 20, 20, 79, 79, 80, 50, 50, 80);
     DeleteObject(hObj[2]);
     DeleteObject(hObj[1]);
     hObj[1]=CreateSolidBrush(RGB(0,0xFF,0));
     SelectObject(hDC, hObj[1]);
     hObj[2]=CreatePen(PS_SOLID, 1, RGB(0x4C,0,0));
     SelectObject(hDC, hObj[2]);
     Pie(hDC, 10, 20, 29, 39, 67, 54, 23, 56);
     DeleteObject(hObj[2]);
     DeleteObject(hObj[1]);
     hObj[1]=CreateSolidBrush(RGB(0,0x98,0x19));
     SelectObject(hDC, hObj[1]);
     hObj[2]=CreatePen(PS_SOLID, 1, RGB(0,0xF0,0xFF));
     SelectObject(hDC, hObj[2]);
     Ellipse(hDC, 40, 40, 89, 59);
     DeleteObject(hObj[2]);
     DeleteObject(hObj[1]);
     hObj[1]=CreateSolidBrush(RGB(0x62,0xB2,0));
     SelectObject(hDC, hObj[1]);
     hObj[2]=CreatePen(PS_SOLID, 1, RGB(0x3E,0xCA,0x23));
     SelectObject(hDC, hObj[2]);
     RoundRect(hDC, 50, 5, 79, 59, 10, 10);
     DeleteObject(hObj[2]);
     DeleteObject(hObj[1]);
     hObj[1]=CreatePen(PS_SOLID, 1, 0x4098C06);
     SelectObject(hDC, hObj[1]);
     MoveToEx(hDC, 0, 0, NULL);
     LineTo(hDC, 100, 100);
     DeleteObject(hObj[1]);
     hObj[1]=CreatePen(PS_SOLID, 1, RGB(0x20,0xD1,0x88));
     SelectObject(hDC, hObj[1]);
     MoveToEx(hDC, 100, 0, NULL);
     SetArcDirection(hDC, AD_CLOCKWISE);
     Arc(hDC, 0, 0, 99, 99, 20, 20, 90, 70);
     DeleteObject(hObj[1]);
     SetPixelV(hDC, 10, 10, RGB(0xFF,0,0));
     SetPixelV(hDC, 10, 11, RGB(0xFF,0,0));
     SetPixelV(hDC, 11, 11, RGB(0xFF,0,0));
     SetPixelV(hDC, 12, 11, RGB(0xFF,0,0));
     SetPixelV(hDC, 12, 12, RGB(0xFF,0,0));
     SetPixelV(hDC, 13, 13, RGB(0xFF,0,0));
     SetPixelV(hDC, 14, 14, RGB(0xFF,0,0));
     SetPixelV(hDC, 15, 15, RGB(0xFF,0,0));
     hObj[1]=CreateSolidBrush(RGB(0xFF,0,0));
     SelectObject(hDC, hObj[1]);
     SelectObject(hDC, hObj[1]);
     PatBlt(hDC,60,60,10,10,PATCOPY);
     SelectObject(hDC, hObj[1]);
     DeleteObject(hObj[1]);
Avatar of drnick

ASKER

hm, this is odd:
when i try to open the newly saved (and thus, shrinked) emf with FengYuan, it fails completely.
the resulting screen is empty.
Avatar of drnick

ASKER

... and when i try it again, it works
... strange

... gives me:

        SaveDC(hDC);
      SetMetaRgn(hDC);
      SelectObject(hDC, GetStockObject(WHITE_BRUSH));
      SelectObject(hDC, GetStockObject(BLACK_PEN));
      SelectObject(hDC, GetStockObject(DEVICE_DEFAULT_FONT));
      SelectPalette(hDC, (HPALETTE)GetStockObject(DEFAULT_PALETTE), TRUE);
      SetBkColor(hDC, RGB(0xFF,0xFF,0xFF));
      SetTextColor(hDC, RGB(0,0,0));
      SetBkMode(hDC, OPAQUE);
      SetPolyFillMode(hDC, ALTERNATE);
      SetROP2(hDC, R2_COPYPEN);
      SetStretchBltMode(hDC, STRETCH_ANDSCANS);
      SetTextAlign(hDC, TA_NOUPDATECP | TA_LEFT | TA_TOP);
      SetBrushOrgEx(hDC, 0, 0, NULL);
      SetMiterLimit(hDC,  0.00000);
      MoveToEx(hDC, 0, 0, NULL);
      SetWorldTransform(hDC, 31.25000,  0.00000,  0.00000, 31.25000,  0.00000,  0.00000);
      ModifyWorldTransform(hDC, 31.25000,  0.00000,  0.00000, 31.25000,  0.00000,  0.00000, 0x4 /*Unknown*/);
      // GdiComment(100, GDIC, 0x2)
      hRegion = CreateRectRgn(0,0,3125,3125);
      ExtSelectClipRgn(hDC, hRegion, RGN_COPY);
      DeleteObject(hRegion);
      hObj[1]=CreateSolidBrush(RGB(0xFF,0,0));
      SelectObject(hDC, hObj[1]);
      SelectObject(hDC, hObj[1]);
      PatBlt(hDC,0,0,100,100,PATCOPY);
      SelectObject(hDC, hObj[1]);
      DeleteObject(hObj[1]);
      hObj[1]=CreateSolidBrush(RGB(0xFF,0xFF,0));
      SelectObject(hDC, hObj[1]);
      SelectObject(hDC, hObj[1]);
      PatBlt(hDC,25,25,51,51,PATCOPY);
      SelectObject(hDC, hObj[1]);
      DeleteObject(hObj[1]);
      SetTextColor(hDC, RGB(0,0,0xFF));
      hObj[1]=CreateFont(-20,0,0,0,700,1,0,0,1,0,0,0,0,"arial");
      SelectObject(hDC, hObj[1]);
      const int Dx_1[]={ 12, 11, 6, 6, 12, 6, 16, 11, 6, 7 };
      ExtTextOutW(hDC, 10,10,0,NULL,L"hallo welt",10,Dx_1);
      DeleteObject(hObj[1]);
      SetTextColor(hDC, RGB(0,0,0xFF));
      hObj[1]=CreateFont(-20,0,0,0,700,1,0,0,1,0,0,0,0,"symbol");
      SelectObject(hDC, hObj[1]);
      const int Dx_2[]={ 13, 14, 12, 12, 12, 6, 15, 10, 12, 10 };
      ExtTextOutW(hDC, 10,40,0,NULL,L"hallo welt",10,Dx_2);
      DeleteObject(hObj[1]);
      hObj[1]=CreateSolidBrush(RGB(0x51,0x93,3));
      SelectObject(hDC, hObj[1]);
      hObj[2]=CreatePen(PS_SOLID, 1, RGB(7,0xB2,1));
      SelectObject(hDC, hObj[2]);
      Chord(hDC, 20, 20, 79, 79, 80, 50, 50, 80);
      DeleteObject(hObj[2]);
      DeleteObject(hObj[1]);
      hObj[1]=CreateSolidBrush(RGB(0,0xFF,0));
      SelectObject(hDC, hObj[1]);
      hObj[2]=CreatePen(PS_SOLID, 1, RGB(0x4C,0,0));
      SelectObject(hDC, hObj[2]);
      Pie(hDC, 10, 20, 29, 39, 67, 54, 23, 56);
      DeleteObject(hObj[2]);
      DeleteObject(hObj[1]);
      hObj[1]=CreateSolidBrush(RGB(0,0x98,0x19));
      SelectObject(hDC, hObj[1]);
      hObj[2]=CreatePen(PS_SOLID, 1, RGB(0,0xF0,0xFF));
      SelectObject(hDC, hObj[2]);
      Ellipse(hDC, 40, 40, 89, 59);
      DeleteObject(hObj[2]);
      DeleteObject(hObj[1]);
      hObj[1]=CreateSolidBrush(RGB(0x62,0xB2,0));
      SelectObject(hDC, hObj[1]);
      hObj[2]=CreatePen(PS_SOLID, 1, RGB(0x3E,0xCA,0x23));
      SelectObject(hDC, hObj[2]);
      RoundRect(hDC, 50, 5, 79, 59, 10, 10);
      DeleteObject(hObj[2]);
      DeleteObject(hObj[1]);
      hObj[1]=CreatePen(PS_SOLID, 1, 0x4098C06);
      SelectObject(hDC, hObj[1]);
      MoveToEx(hDC, 0, 0, NULL);
      LineTo(hDC, 100, 100);
      DeleteObject(hObj[1]);
      hObj[1]=CreatePen(PS_SOLID, 1, RGB(0x20,0xD1,0x88));
      SelectObject(hDC, hObj[1]);
      MoveToEx(hDC, 100, 0, NULL);
      SetArcDirection(hDC, AD_CLOCKWISE);
      Arc(hDC, 0, 0, 99, 99, 20, 20, 90, 70);
      DeleteObject(hObj[1]);
      SetPixelV(hDC, 10, 10, RGB(0xFF,0,0));
      SetPixelV(hDC, 10, 11, RGB(0xFF,0,0));
      SetPixelV(hDC, 11, 11, RGB(0xFF,0,0));
      SetPixelV(hDC, 12, 11, RGB(0xFF,0,0));
      SetPixelV(hDC, 12, 12, RGB(0xFF,0,0));
      SetPixelV(hDC, 13, 13, RGB(0xFF,0,0));
      SetPixelV(hDC, 14, 14, RGB(0xFF,0,0));
      SetPixelV(hDC, 15, 15, RGB(0xFF,0,0));
      hObj[1]=CreateSolidBrush(RGB(0xFF,0,0));
      SelectObject(hDC, hObj[1]);
      SelectObject(hDC, hObj[1]);
      SelectObject(hDC, hObj[1]);
      DeleteObject(hObj[1]);
      // GdiComment(8, GDIC, 0x3)
      RestoreDC(hDC, -1);
Avatar of drnick

ASKER

... and when i try it again, it works
... strange

... gives me:

        SaveDC(hDC);
      SetMetaRgn(hDC);
      SelectObject(hDC, GetStockObject(WHITE_BRUSH));
      SelectObject(hDC, GetStockObject(BLACK_PEN));
      SelectObject(hDC, GetStockObject(DEVICE_DEFAULT_FONT));
      SelectPalette(hDC, (HPALETTE)GetStockObject(DEFAULT_PALETTE), TRUE);
      SetBkColor(hDC, RGB(0xFF,0xFF,0xFF));
      SetTextColor(hDC, RGB(0,0,0));
      SetBkMode(hDC, OPAQUE);
      SetPolyFillMode(hDC, ALTERNATE);
      SetROP2(hDC, R2_COPYPEN);
      SetStretchBltMode(hDC, STRETCH_ANDSCANS);
      SetTextAlign(hDC, TA_NOUPDATECP | TA_LEFT | TA_TOP);
      SetBrushOrgEx(hDC, 0, 0, NULL);
      SetMiterLimit(hDC,  0.00000);
      MoveToEx(hDC, 0, 0, NULL);
      SetWorldTransform(hDC, 31.25000,  0.00000,  0.00000, 31.25000,  0.00000,  0.00000);
      ModifyWorldTransform(hDC, 31.25000,  0.00000,  0.00000, 31.25000,  0.00000,  0.00000, 0x4 /*Unknown*/);
      // GdiComment(100, GDIC, 0x2)
      hRegion = CreateRectRgn(0,0,3125,3125);
      ExtSelectClipRgn(hDC, hRegion, RGN_COPY);
      DeleteObject(hRegion);
      hObj[1]=CreateSolidBrush(RGB(0xFF,0,0));
      SelectObject(hDC, hObj[1]);
      SelectObject(hDC, hObj[1]);
      PatBlt(hDC,0,0,100,100,PATCOPY);
      SelectObject(hDC, hObj[1]);
      DeleteObject(hObj[1]);
      hObj[1]=CreateSolidBrush(RGB(0xFF,0xFF,0));
      SelectObject(hDC, hObj[1]);
      SelectObject(hDC, hObj[1]);
      PatBlt(hDC,25,25,51,51,PATCOPY);
      SelectObject(hDC, hObj[1]);
      DeleteObject(hObj[1]);
      SetTextColor(hDC, RGB(0,0,0xFF));
      hObj[1]=CreateFont(-20,0,0,0,700,1,0,0,1,0,0,0,0,"arial");
      SelectObject(hDC, hObj[1]);
      const int Dx_1[]={ 12, 11, 6, 6, 12, 6, 16, 11, 6, 7 };
      ExtTextOutW(hDC, 10,10,0,NULL,L"hallo welt",10,Dx_1);
      DeleteObject(hObj[1]);
      SetTextColor(hDC, RGB(0,0,0xFF));
      hObj[1]=CreateFont(-20,0,0,0,700,1,0,0,1,0,0,0,0,"symbol");
      SelectObject(hDC, hObj[1]);
      const int Dx_2[]={ 13, 14, 12, 12, 12, 6, 15, 10, 12, 10 };
      ExtTextOutW(hDC, 10,40,0,NULL,L"hallo welt",10,Dx_2);
      DeleteObject(hObj[1]);
      hObj[1]=CreateSolidBrush(RGB(0x51,0x93,3));
      SelectObject(hDC, hObj[1]);
      hObj[2]=CreatePen(PS_SOLID, 1, RGB(7,0xB2,1));
      SelectObject(hDC, hObj[2]);
      Chord(hDC, 20, 20, 79, 79, 80, 50, 50, 80);
      DeleteObject(hObj[2]);
      DeleteObject(hObj[1]);
      hObj[1]=CreateSolidBrush(RGB(0,0xFF,0));
      SelectObject(hDC, hObj[1]);
      hObj[2]=CreatePen(PS_SOLID, 1, RGB(0x4C,0,0));
      SelectObject(hDC, hObj[2]);
      Pie(hDC, 10, 20, 29, 39, 67, 54, 23, 56);
      DeleteObject(hObj[2]);
      DeleteObject(hObj[1]);
      hObj[1]=CreateSolidBrush(RGB(0,0x98,0x19));
      SelectObject(hDC, hObj[1]);
      hObj[2]=CreatePen(PS_SOLID, 1, RGB(0,0xF0,0xFF));
      SelectObject(hDC, hObj[2]);
      Ellipse(hDC, 40, 40, 89, 59);
      DeleteObject(hObj[2]);
      DeleteObject(hObj[1]);
      hObj[1]=CreateSolidBrush(RGB(0x62,0xB2,0));
      SelectObject(hDC, hObj[1]);
      hObj[2]=CreatePen(PS_SOLID, 1, RGB(0x3E,0xCA,0x23));
      SelectObject(hDC, hObj[2]);
      RoundRect(hDC, 50, 5, 79, 59, 10, 10);
      DeleteObject(hObj[2]);
      DeleteObject(hObj[1]);
      hObj[1]=CreatePen(PS_SOLID, 1, 0x4098C06);
      SelectObject(hDC, hObj[1]);
      MoveToEx(hDC, 0, 0, NULL);
      LineTo(hDC, 100, 100);
      DeleteObject(hObj[1]);
      hObj[1]=CreatePen(PS_SOLID, 1, RGB(0x20,0xD1,0x88));
      SelectObject(hDC, hObj[1]);
      MoveToEx(hDC, 100, 0, NULL);
      SetArcDirection(hDC, AD_CLOCKWISE);
      Arc(hDC, 0, 0, 99, 99, 20, 20, 90, 70);
      DeleteObject(hObj[1]);
      SetPixelV(hDC, 10, 10, RGB(0xFF,0,0));
      SetPixelV(hDC, 10, 11, RGB(0xFF,0,0));
      SetPixelV(hDC, 11, 11, RGB(0xFF,0,0));
      SetPixelV(hDC, 12, 11, RGB(0xFF,0,0));
      SetPixelV(hDC, 12, 12, RGB(0xFF,0,0));
      SetPixelV(hDC, 13, 13, RGB(0xFF,0,0));
      SetPixelV(hDC, 14, 14, RGB(0xFF,0,0));
      SetPixelV(hDC, 15, 15, RGB(0xFF,0,0));
      hObj[1]=CreateSolidBrush(RGB(0xFF,0,0));
      SelectObject(hDC, hObj[1]);
      SelectObject(hDC, hObj[1]);
      SelectObject(hDC, hObj[1]);
      DeleteObject(hObj[1]);
      // GdiComment(8, GDIC, 0x3)
      RestoreDC(hDC, -1);
Avatar of drnick

ASKER

sorry for double posting, hit reload by accident
Avatar of drnick

ASKER

(had hit it twice, i think..)

hello again, i detected that the error (shrinking) also
occures when i do (with the purpose to store and keep on
editing my emf):

c_boolean     SC   CImage::Close                
(void)                             //VMT 3
  {boolean retval = true;
  if( (!(m_file)) || (m_changed) )
    {
    if(m_file)
      {
      retval = DeleteEnhMetaFile(m_file);
      if(!retval) IMAGE_ERROR;
      m_file = 0;
      }
    if(retval)
      {
      retval = false;

      if(m_dc)
        {
        m_file = CloseEnhMetaFile(m_dc);
        if(m_file)
          {
          p_rect boundsptr = 0;
          if( (m_bounds.bottom >  m_bounds.top) &&
              (m_bounds.right  > m_bounds.left) )
boundsptr = &m_bounds;
          m_dc = CreateEnhMetaFileA(0, 0, boundsptr,
IMAGE_NAME);
          if(m_dc)
            {          
            PlayEnhMetaFile(m_dc, m_file, boundsptr);
            m_changed = false;
            if(m_clip)
              {
              SelectClipRgn(m_dc, m_clip);
              }
            retval = true;
            }
          else IMAGE_ERROR;        
          }
        else IMAGE_ERROR;
        }
      else IMAGE_EMPTY;
      } }  
  return retval;
  }
It looks like the sequence lines up after the first few records.  The first few records are setting the scaling options.  When you said...

>>- create an new enhanced metafile device context in memory

perhaps the reference hdc that you use is screwy or something.  What if you nullify or clear out the WorldTransform for the new metafile, the problem will go away.  Or maybe the mapping mode has been tweaked...

Show the code you use to create the metafile you use as the destination.

-- Dan
Avatar of drnick

ASKER

hm, the code is below.
the clip region is needed, because else the emf would
grow if i draw across the borders.
i use 0 as refDC, so it would use the screen by default,
so i do by loading.
if i replace the refdc by GetDC(0), i get the same result.
you're right, the world transform is somewhat strange.
but the 31.25 result from the proportion of screen pixel width to metric measures: ther're exactly 31.25 0.01 mm units per pixel says the calculator.
how can i nulify the worldtransform stuff?
what is it with mapping mode?
however, thanks for your effords so far.

c_boolean     SC   CImage::Create  (c_dword awidth, c_dword aheight)
  {
  boolean retval = false;
  if(Clear())
    {
    p_rect boundsptr = 0;
    if((awidth > 0) && (aheight > 0))
      {
      m_bounds.bottom = aheight;
      m_bounds.right  = awidth;
      boundsptr       = &m_bounds;
      m_clip          = CreateRectRgnIndirect(boundsptr);
      }
    m_dc = CreateEnhMetaFileA(0, 0, boundsptr, IMAGE_NAME);
    if(m_dc)
      {
      if(m_clip) SelectClipRgn(m_dc, m_clip);        
      retval = true;
      }
    else IMAGE_ERROR;
    }
  return retval;
  }
Avatar of drnick

ASKER

p.s. awidth and aheight are both 100 in my testing example
Just a guess... Try using
    SetMapMode( hdcDestFroMetafile, MM_TEXT );

before playing the metafile.  Worth a try.

-- Dan
Avatar of drnick

ASKER

hm, you got me going:

without setmapmode, i get a very small image in the upper left corner, any subsequent drawing actions will also be shrinked and placed there

the same result with SetMapMode(... MM_TEXT), i think that's the default behaviour

but with SetMapMode(... MM_HIMETRIC) subsequent drawing actions appear with the right size at the right place.
the bad thing is, playenhmetafile does nothing...

but good idea, i'll keep working on that and report findings
Avatar of drnick

ASKER

aha, in the hi_metric case,
the bounds field of the emf-header is evaluated to
(0, -79, 99, 0) but it should be (0, 0, 99, 99).
Avatar of drnick

ASKER

nope, that helps nothing.
i can try to setworldtranform, but it changes anything.
the graphic is not drawn.
however, that thing with mapmode was not bad.
at least, i've now the proper size
Glad to help.  I'd trot it back throud that FenYuan thing to see if you are getting closer to the desired settings.

-- Dan
Avatar of drnick

ASKER

already done: i get the same stuff like in last posting.
strange
Avatar of drnick

ASKER

any other ideas?
ASKER CERTIFIED SOLUTION
Avatar of DanRollins
DanRollins
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of drnick

ASKER

i give 'em 100 and 100.

i think i found one possible source of my problem:
(i started all up from the bottom again meanwhile)
right before playenhmetafile plays to a dc,
it SaveDC the dc, then it resets the
dc's mapping mode to MM_TEXT and also
initialized SetWorldTransform.
so whatever values i pass to SetMapMode and
SetViewPortExtEx and SetWorldTransform will be
overridden rightaway and 'll have no effect at all.
so that approach was nonsense.

now i'm going to test out now if i get the stuff working
when i set up the picture in proportions to my screen
resolution, as you suggested.
this is a way i'd rather liked to avoid,
because calculating of coordinates may lead to
incorrect values due to rounding and trucating,
but i give it a try.

thanks so far,
dr. nick
Avatar of drnick

ASKER

.. i take it all back and state the opposite:

 i _can_ draw the saved emfs to the new emfs by
 specifiying an projection with viewport and
 window.
 the savedc/restoredc in the playenhmetafile mean nothing.

 the solution was

if(SetMapMode(adc, MM_ANISOTROPIC))
 {
 SetWindowExtEx(adc, MM_X(m_bounds.right), MM_Y(m_bounds.bottom), 0);
 SetViewportExtEx(adc, (m_bounds.right), (m_bounds.bottom), 0);
 SetWindowOrgEx(adc, 0, 0, 0);
 SetViewportOrgEx(adc, 0, 0, 0);
 }

with

dword     MaxX_MM   = 0;
dword     MaxY_MM   = 0;
dword     MaxX_PX   = 0;
dword     MaxY_PX   = 0;
double  MMPerPX_X   = 0;
double  MMPerPX_Y   = 0;


void          FC   ImageSetUp           (void)
  {
  dword dc = GetDC(0);
  if(dc)
    {
    MaxX_MM   = GetDeviceCaps(dc, HORZSIZE);
    MaxY_MM   = GetDeviceCaps(dc, VERTSIZE);
    MaxX_PX   = GetDeviceCaps(dc, HORZRES);
    MaxY_PX   = GetDeviceCaps(dc, VERTRES);
    MMPerPX_X = (((double)MaxX_MM) * 100.0) / ((double)MaxX_PX);
    MMPerPX_Y = (((double)MaxY_MM) * 100.0) / ((double)MaxY_PX);

    WriteLog("Calculating screen resolution relations.");
    LogDWord("MaxX (0.01 mm)        %s", MaxX_MM);
    LogDWord("MaxY (0.01 mm)        %s", MaxY_MM);
    LogDWord("MaxX (pixels)         %s", MaxX_PX);
    LogDWord("MaxY (pixels)         %s", MaxY_PX);
    LogDWord("0.01 mm per pixel (x) %s", (dword)MMPerPX_X);
    LogDWord("0.01 mm per pixel (y) %s", (dword)MMPerPX_Y);
    ReleaseDC(0, dc);
    }
  else IMAGE_LOG_ONLY("No display device attached or using Windows 95 and earlier.");


  }


c_dword       FC   MM_X                 (c_dword ax)
  {
  return (c_dword)(ceil( ((double)ax) * MMPerPX_X ) );
  }

c_dword       FC   MM_Y                 (c_dword ay)
  {
  return (c_dword)(ceil( ((double)ay) * MMPerPX_Y ) );
  }

c_dword       FC   PX_X                 (c_dword ax)
  {
  return (c_dword)(((double)ax) / MMPerPX_X);
  }


c_dword       FC   PX_Y                 (c_dword ay)
  {
  return (c_dword)(((double)ay) / MMPerPX_Y);
  }

(just in case another poor soul has to wrestle with this).

however, i'll reward you (Dan) for your effords and good ideas with the points. thanks.
In this and the other thread there is lots of screwy code; i.e, what is a c_dword?  and why clutter your cosde with that?.  Here is some code I used for testing:

RECT     m_Bounds= {0,0,100,100};
char     m_szFile[]= "c:\\temp\\MS.EMF";
HBITMAP  m_hbmpImage= 0;

// Create a 24-bit-per-pixel surface.
HBITMAP Create24BPPDIBSection(HDC hDC, int iWidth, int iHeight)
{
     BITMAPINFO rBMI;
     HBITMAP    hbm;
     void *     pBits;

     ZeroMemory( &rBMI, sizeof(rBMI) );

     rBMI.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
     rBMI.bmiHeader.biWidth = iWidth;
     rBMI.bmiHeader.biHeight = iHeight;
     rBMI.bmiHeader.biPlanes = 1;
     rBMI.bmiHeader.biBitCount = 24;
     rBMI.bmiHeader.biCompression = BI_RGB;

     hbm= CreateDIBSection(hDC, &rBMI, DIB_RGB_COLORS, &pBits, NULL, 0);

     return( hbm );
}


void CD06Dlg::OnButton1()
{
     int nWide= 100;
     int nHigh= 100;

     HDC hdcRef= ::GetDC( m_hWnd );  // compatible with screen
    HDC hdc=    CreateCompatibleDC( hdcRef );
     if ( !hdc) {
          // TBD: handle the error
     }
     ::ReleaseDC(m_hWnd, hdcRef );

     HBITMAP hbmpCanvas= Create24BPPDIBSection( hdc, nWide, nHigh );
     HBITMAP hbmpOld= (HBITMAP)::SelectObject( hdc, hbmpCanvas );

     int nRet= SetMapMode( hdc, MM_TEXT ); // needed?

     RECT rBox= {20,20,80,80};  // test a GDI fn
     ::FillRect( hdc, &rBox, (HBRUSH) (COLOR_WINDOW+1) );

     RECT rBound= {0,0,0,0};
     rBound.right= nWide; rBound.bottom= nHigh;

     // errors reading WMF, gut GetLastError shows 0 !
     HENHMETAFILE hEMF= ::GetEnhMetaFile( m_szFile );
     DWORD nErr= GetLastError();

     ::PlayEnhMetaFile( hdc, hEMF, &rBound );
     
     BOOL fRet= GdiFlush(); // needed?
     fRet=      DeleteEnhMetaFile( hEMF );

     ::SelectObject( hdc, hbmpOld );
     ::DeleteDC(hdc);
     m_hbmpImage= hbmpCanvas; // save result
}

void CD06Dlg::OnButton2()
{
     // display the bitmap
     m_ctlImage.SetBitmap( m_hbmpImage );
}