Again: Problem with EMF scale in Win 2000, now with code to create EMF/WMF

Again: Problem with EMF scale in Win 2000, now with code to create EMF/WMF

Post by Hans Reic » Mon, 28 May 2001 12:30:50



I am having a curious problem with a VB5 program that generates Enhanced
Windows metafiles. Everything works fine on Win 95/98, but when I create
EMF's on Win 2000 machines the metafile scale becomes dependent on the
screen resolution. In other words, I create the EMF at a certain size in
pixels, if I am at screen resolution of 1024x768 the EMF dimensions are
larger than it should be (the drawing is cropped on bottom and right) if
I switch to 1280x1024 the image is smaller than it should be. When I
create WMF's using the same code and dimensions, they are fine on both
Win 98 and Win 2000 at any screen resolution.

I would really appreciate any help.  Unless I can figure this out my
program can no longer support EMF graphics.

At the suggestion of Stephen Lebans I created a sample project that
illustrates the difficulty (at least on my Win 2000 machine). Start a
new project (Form 1) and place two command buttons: Command1 with
caption="Make EMF" and Command2 with caption="Make WMF".  Also place a
picturebox (Picture1) and Image (Image1) on the form. Paste the code
below into the form, and run the program. The code will create a tiny
metafile (either EMF or WMF), copy it to the clipboard, and put the
Metafile into the picturebox and image control.

On a Win95 system pressing either button produces the identical triangle
that just fits into the picture box.  On a Win 2000 system with screen
resolution 1024x768 the triangle draws fine with WMF but is larger (by
18%) than it should be when an EMF is created, and is now clipped right
and bottom by the boundaries of the picture box. Both WMF and EMF use
exactly the same code and line dimensions.  In other words, when I send
a lineto of 100 pixels, the WMF has a line 100 pixels long and the EMF
has a line 118 pixels long in it.  

Hans Reich

=====================code===========================
Option Explicit

Private Type POINTAPI
  xapi As Long
  yapi As Long
End Type

Private Type RectLng
  Left As Long
  Top As Long
  Right As Long
  Bottom As Long
End Type

Const MM_ANISOTROPIC = 8
Const BS_NULL% = 1
Const TRANSPARENT& = 1
Const WINDING& = 2
Const GMEM_MOVEABLE = &H2
Private Type LOGBRUSH   'OK
  lbStyle As Long
  lbColor As Long
  lbHatch As Long
End Type
Dim mLBCurr As LOGBRUSH
Private Type LOGPEN    '10 Bytes Also in Screen
  Style As Long 'Integer
  Wdth As POINTAPI        'only xapi is used - y is unused
  Color As Long
End Type
Dim mLPCurr As LOGPEN
'-------------------Below needed only for WMF--------------------------
Private Declare Function CopyMetaFile Lib "gdi32" Alias "CopyMetaFileA"
(ByVal hMF As Long, ByVal lpFileName As String) As Long
Private Declare Function CreateMetafile Lib "gdi32" Alias
"CreateMetaFileA" (ByVal lpString As String) As Long
Private Declare Function CloseMetaFile Lib "gdi32" (ByVal hMF As Long)
As Long
Private Declare Function DeleteMetaFile Lib "gdi32" (ByVal hMF As Long)
As Long
Private Declare Function GlobalLock Lib "Kernel32" (ByVal hMem As Long)
As Long
Private Declare Function GlobalUnlock Lib "Kernel32" (ByVal hMem As
Long) As Long
Private Declare Function GlobalAlloc Lib "Kernel32" (ByVal wFlags As
Long, ByVal dwBytes As Long) As Long
Private Declare Sub hmemcpy Lib "Kernel32" Alias "RtlMoveMemory" _
    (hpvDest As Any, hpvsource As Any, ByVal cbCopy As Long)
Private Type METAFILEPICT
    mm As Long
    xExt As Long
    yExt As Long
    hMF As Long
End Type

'-------------------Below needed only for Enhanced Metafile-----------
Private Declare Function CreateEnhMetaFile Lib "gdi32" Alias
"CreateEnhMetaFileA" (ByVal hdcRef As Long, ByVal lpFileName As String,
lpRect As RectLng, ByVal lpDescription As String) As Long
          'returns 0 on error, handle to ENHMF DC on success
Private Declare Function CloseEnhMetaFile Lib "gdi32" (ByVal hdc As
Long) As Long
'-------------------Below needed for both EMF and WMF------------------
Private Declare Function SetWindowOrgEx Lib "gdi32" (ByVal hdc As Long,
ByVal nX As Long, ByVal nY As Long, lpPoint As POINTAPI) As Long
Private Declare Function SetWindowExtEx Lib "gdi32" (ByVal hdc As Long,
ByVal nX As Long, ByVal nY As Long, lpPoint As POINTAPI) As Long
Private Declare Function SetMapMode Lib "gdi32" (ByVal hdc As Long,
ByVal nMapMode As Long) As Long
Private Declare Function SetBkMode Lib "gdi32" (ByVal hdc As Long, ByVal
nBkMode As Long) As Long
Private Declare Function CreateBrushIndirect Lib "gdi32" (lpLogBrush As
LOGBRUSH) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long,
ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As
Long) As Long
Private Declare Function CreatePenIndirect Lib "gdi32" (lpLogPen As
LOGPEN) As Long
Private Declare Function MoveToEx Lib "gdi32" (ByVal hdc As Long, ByVal
X As Long, ByVal Y As Long, ByVal ptr As Long) As Long
Private Declare Function LineTo Lib "gdi32" (ByVal hdc As Long, ByVal X
As Long, ByVal Y As Long) As Long
Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long)
As Long
Private Declare Function CloseClipboard Lib "user32" () As Long
Private Declare Function SetClipboarddata Lib "user32" Alias
"SetClipboardData" (ByVal wFormat As Long, ByVal hMem As Long) As Long

Private Sub MakeMetafile(MFtype$)
    'This procedure creates an Enhanced Windows Metafile (MFtype$="EMF")
    'or a Windows Metafile (MFtype$="WMF") in the shape of three lines
forming a triangle
    'No text material is placed in the metafile - this is an ultrasimple
example
    'The metafile data is placed in the clipboard and displayed in a
PictureBoc (Picture1)
  Dim EMF As Boolean
  Dim lpRect As RectLng
  Dim hdcMF&    'handle to the MF device context
  Dim PAP As POINTAPI
  Dim ret&      'returnvalue of functions (NO error checking here)
  Dim hMF&      'handle to the metafile
  Dim PixXext&, PixYext&        'pixel dimensions of enclosing box
  Dim TwipsXext&, TwipsYext&    'twips dimension of enclosing box
  Dim HimmXext&, HimmYext&      'HiMetrix dimensions of enclosing box
  Dim CopyMF&, CBhnd&, CBAdr&
  Dim Mp As METAFILEPICT
'------Determine which type to make--------------
  If UCase$(MFtype$) = "EMF" Then EMF = True Else EMF = False
'------Dimensions of the EMF frame---------------
  PixXext& = 100: PixYext& = 100    'enclosing box in pixels
  '56.7 twips/mm  1440 TwipsPerInch/25.4 MmPerInch
  TwipsXext& = PixXext& * Screen.TwipsPerPixelX
  TwipsYext& = PixYext& * Screen.TwipsPerPixelY
  HimmXext& = 100 * TwipsXext& / 56.7 '=2646
  HimmYext& = 100 * TwipsYext& / 56.7 '=2646
  If EMF Then
    lpRect.Left = 0
    lpRect.Top = 0
    lpRect.Right = HimmXext&  'this is width in highmetric units (0.01
mm)
    lpRect.Bottom = HimmYext&  'this is height in highmetric units
'--------Create a memory enhanced metafile device context
    hdcMF& = CreateEnhMetaFile(0&, vbNullString, lpRect, "WINPLT V 7.1"
& Chr$(0) & "PLT1620 EMF " & Chr$(0) & Chr$(0))
  Else
    hdcMF& = CreateMetafile(vbNullString)  'memory metafile
  End If
'--------Create the Window Extents
'--------the two statements below make no difference for EMF, but are
required for WMF
  ret& = SetWindowExtEx(hdcMF&, PixXext&, PixYext&, PAP) 'ebug.Print
"PrintDrawing Window xtxext&; yext& "; xext&; yext&
  ret& = SetWindowOrgEx(hdcMF&, 0&, 0&, PAP) 'ebug.Print "PrintDrawing
Window Org "; xorig&; yorig&
'----------------------------------------------------
  ret& = SetMapMode(hdcMF&, MM_ANISOTROPIC)
'---------Set up a brush----------------------------
  mLPCurr.Style = vbSolid
  mLPCurr.Wdth.xapi = 1 'Wdth%
  mLPCurr.Color = 0 'Colr&
  mLBCurr.lbStyle = 1 'BS_NULL
  mLBCurr.lbColor = vbWhite
  mLBCurr.lbHatch = 0
  ret& = SetBkMode(hdcMF&, TRANSPARENT)
  'ret& = SetPolyFillMode(hdcMF, WINDING)   'ALTERNATE WINDING
'---------Create a brush--------------------------
  Dim NewBrush&, OldBrush&
  NewBrush& = CreateBrushIndirect(mLBCurr)
  OldBrush& = SelectObject(hdcMF&, NewBrush&)
'---------Set up a pen--------------------------
  mLPCurr.Wdth.xapi = 1 'Wdth%
  mLPCurr.Color = 0 'Colr&
  Dim NewPen&, OldPen&
  NewPen& = CreatePenIndirect(mLPCurr)
  OldPen& = SelectObject(hdcMF&, NewPen&)
'---------Drawing the lines - a triangle that fits snugly inside the
enclosing box
  ret& = MoveToEx(hdcMF, 5, 95, 0&) 'first position the pen
  ret& = LineTo(hdcMF, 50, 5)
  ret& = LineTo(hdcMF, 95, 95)
  ret& = LineTo(hdcMF, 5, 95)
'---------toss the brush and pen----------
  ret& = SelectObject(hdcMF&, OldBrush&)
  ret& = DeleteObject(NewBrush&)
  ret& = SelectObject(hdcMF&, OldPen&)
  ret& = DeleteObject(NewPen&)
'---------Close the metafile-------------
  If EMF Then
    hMF& = CloseEnhMetaFile(hdcMF&)
  Else
    hMF& = CloseMetaFile(hdcMF&)
  End If
'---------to put the MF in clipboard need a form
  Clipboard.Clear
  ret& = OpenClipboard(Form1.hwnd)
  If EMF Then   'place the EMF in the clipboard
    ret& = SetClipboarddata(vbCFEMetafile, hMF&)
  Else          'place the WMF in the clipboard
                'need to put metafilePict structure at front
     CopyMF = CopyMetaFile(hMF&, vbNullString)  'make copy of WMF data
     Mp.mm = MM_ANISOTROPIC
     Mp.xExt = HimmXext&  'this is xextent in highmetric units
     Mp.yExt = HimmYext&  'this is xextent in highmetric units
     Mp.hMF = CopyMF      'handle of the copy of the metafile
     ret& = DeleteMetaFile(hMF&)
     CBhnd& = GlobalAlloc(GMEM_MOVEABLE, Len(Mp))   'get some memory
     CBAdr& = GlobalLock(CBhnd&)                    'lock it
     hmemcpy ByVal CBAdr&, Mp, Len(Mp)              'CBAdr is a Pointer
- must use ByVal! 'copy the MetaStruct
     ret& = GlobalUnlock(CBhnd&)                    'unlock memory
     ret& = SetClipboarddata(vbCFMetafile, CBhnd&)  'put WMF in
clipboard
  End If
  ret& = CloseClipboard()
'--------------------------------------------
  Image1.Stretch = False    ' The control resizes to fit the graphic.
  If EMF Then
    Picture1.Picture = Clipboard.GetData(vbCFEMetafile)
    Image1.Picture = Clipboard.GetData(vbCFEMetafile)
  Else
...

read more »

 
 
 

Again: Problem with EMF scale in Win 2000, now with code to create EMF/WMF

Post by Hans Reic » Tue, 29 May 2001 04:23:52


Sorry about the linefeeds. Download the project from the URL below:

http://www.msn.fullfeed.com/~plt/emftest.zip

Hans Reich

 
 
 

Again: Problem with EMF scale in Win 2000, now with code to create EMF/WMF

Post by Stephen Leban » Tue, 29 May 2001 07:23:08


Hans the quick fix is to not include the Frame rectangle when creating
the Enhanced Metafile. Let the GDI calculate it for you. To do this
change the call from:

Private Declare Function Crea*hMetaFile Lib "gdi32" Alias
"Crea*hMetaFileA" (ByVal hdcRef As Long, ByVal lpFileName As String,
lpRect As RectLng, ByVal lpDescription As String) As Long

to:

Private Declare Function Crea*hMetaFile Lib "gdi32" Alias
"Crea*hMetaFileA" (ByVal hdcRef As Long, ByVal lpFileName As String,
lpRect As Any, ByVal lpDescription As String) As Long

Or lpRect as long or ByVal lpRect as long.

So when you call th API do:
hdcMF& = Crea*hMetaFile(0&, vbNullString, ByVal 0&, "WINPLT V 7.1" &
Chr$(0) & "PLT1620 EMF " & Chr$(0) & Chr$(0))

It's interesting when you compare the GDI's Frame versus your own.

GDI:156,156,2969,2969
Yours:0,0,2646,2646

Also I noticed the border of the PictureBox is not allowed for when VB
plays the EMF into the control.

So there is nothing wrong with the actual EMF itself. There is a
difference in how the different versions of Windows interpret the
coordinates of the bounding Frame.

HTH
Stephen Lebans
http://www.veryComputer.com/
Access Code, Tips and Tricks
Please respond only to the newsgroups so everyone can benefit.


Quote:> Sorry about the linefeeds. Download the project from the URL below:

> http://www.veryComputer.com/~plt/emftest.zip

> Hans Reich

 
 
 

Again: Problem with EMF scale in Win 2000, now with code to create EMF/WMF

Post by Hans Reic » Wed, 30 May 2001 15:11:37


Dear Stephen:

Thanks for looking at my stuff. I gather from what you said that you can
reproduce my problem with the test program, so it is not my machine that
is malfunctioning.

The "autoframing" (with lprect = 0&) does not really solve my problem (I
need to be able to specify the dimensions of the enclosing frame) but it
did give me a way to accurately check what is going on.

As you suggested, I set the size in Crea*hMetaFile to a null
pointer.  I set the Form Scalemode to pixels, then created an EMF and
printed out the pixel width and height of the Image controls (with
Stretch=False the control sizes to the metafile).  To make numbers more
accurate I made an EMF with points set at 0,0 and 1000,1000 with
setpixel.  

On Win 98 the Image1.height and Image1.width of the EMF were each 1000,
as they should be.

On Win2000 with a screeen resolution of 1024x768 the metafile height and
width as measured by the Image control were now 1181x1181 pixels - about
18% too large (that is why the image is clipped when the boundary is set
at 1000x1000).  Even more disturbing was what happened when I set screen
resolution to 1280x1024. Now the 1000x1000 EMF actually is 945x886
pixels (i.e., no longer square).  So I don't agree with you that the
metafile is OK.  Win2000 is creating metafiles with pixel dimensions
that change with screen resolution.  From both sets of numbers one can
calculate that at a screen resolution of 1209x907 the EMF's would have
true dimensions (1024*1.181=1209 768*1.181=907; 1280*0.945=1209,
1024*0.886=907).  Are these some kind of magic numbers in Win2K?

I can fix the problem as follows (on my little test program it works),
but it seems like an extreme kludge: In my real program I can calibrate
the system by writing a function like my test program which creates a
1000x1000 metafile, measures its actual dimensions in Win2000, and
calculates a correction factor for x and y (they are different!).  I
then use the correction factors to adjust the x and y coordinates of all
of my Moveto, LineTo, SetPixel, Polyline, Polygon, Textout etc calls
when I actually make metafiles.  There has to be a better way!

Does anyone out there successfully create enhanced metafiles on a
Win2000 system with a VB program (or any program)?

Can anyone suggest another newsgroup where Win2000 peculiarities would
be a regular subject? I can't believe there is not a simple function
call to fix this.

Hans


> Hans the quick fix is to not include the Frame rectangle when creating
> the Enhanced Metafile. Let the GDI calculate it for you. To do this
> change the call from:

> Private Declare Function Crea*hMetaFile Lib "gdi32" Alias
> "Crea*hMetaFileA" (ByVal hdcRef As Long, ByVal lpFileName As String,
> lpRect As RectLng, ByVal lpDescription As String) As Long

> to:

> Private Declare Function Crea*hMetaFile Lib "gdi32" Alias
> "Crea*hMetaFileA" (ByVal hdcRef As Long, ByVal lpFileName As String,
> lpRect As Any, ByVal lpDescription As String) As Long

> Or lpRect as long or ByVal lpRect as long.

> So when you call th API do:
> hdcMF& = Crea*hMetaFile(0&, vbNullString, ByVal 0&, "WINPLT V 7.1" &
> Chr$(0) & "PLT1620 EMF " & Chr$(0) & Chr$(0))

> It's interesting when you compare the GDI's Frame versus your own.

> GDI:156,156,2969,2969
> Yours:0,0,2646,2646

> Also I noticed the border of the PictureBox is not allowed for when VB
> plays the EMF into the control.

> So there is nothing wrong with the actual EMF itself. There is a
> difference in how the different versions of Windows interpret the
> coordinates of the bounding Frame.

> HTH
> Stephen Lebans
> http://www.veryComputer.com/
> Access Code, Tips and Tricks
> Please respond only to the newsgroups so everyone can benefit.



> > Sorry about the linefeeds. Download the project from the URL below:

> > http://www.veryComputer.com/~plt/emftest.zip

> > Hans Reich

 
 
 

Again: Problem with EMF scale in Win 2000, now with code to create EMF/WMF

Post by Paul Hetheringto » Thu, 31 May 2001 00:36:35


I too have had a few problems with EMF files on Win2000/ME vs Win95/98.   I
did some reading on MSDN concerning EMFs.  I may be wrong, but my
interpetation of what the MSDN articsl said is this:

Win95/98 use 16-bit EMF files.  Win2000/ME use 32-bit EMF files.  As a
result an EMF file created in one OS version may/may not be correct in
another.  Certain GDI API's are not available in Win95/98 that the GDI uses
on Win2000/ME.

This may/may not be related to the problem you are having.

Hope it helps some anyways
--
Paul

 
 
 

Again: Problem with EMF scale in Win 2000, now with code to create EMF/WMF

Post by Hans Reic » Sat, 02 Jun 2001 11:32:50


Just for the record, I think I have figured out how to fix the EMF
problem in WinNT/2000.  It looks as if the GDI routines are writing to a
virtual screen of a fixed size, and the metafile that is actually
created is projected from this virtual screen to the actual one,
resulting in distortion if the two are different. The size of the
virtual screen appears to be 1209x907 pix for small fonts and 1510x1134
pix for large fonts.  I got these numbers as described in a previous
post by creating an "autoframing" EMF of 1000x1000 pixels (by passing a
null pointer for the size, and setting points at 0,0 and 1000, 1000),
and then determining the size of the EMF that was actually created at
different screen resolutions and large/small font settings.  I noticed
that both the small and large font screen sizes work out to about
18120x13608 twips.

So here is how to get properly sized and framed EMF's in WinNT:

Say you want an EMF that is 100mm by 50mm (xBoxMM!=100, yBoxMM!=50) in
size, with the origin at 0,0.  The graphics units you are using are in
mm.

 '---------------------Use proper dimensions to set up the EMF
  lpRect.Left = 0
  lpRect.Top = 0
  lpRect.Right = 100 * xBoxMM!  'this is width in highmetric units (0.01
mm)
  lpRect.Bottom = 100 * yBoxMM  'this is height in highmetric units
  hdcMF& = CreateEnhMetaFile(0&, vbNullString, lpRect, "MtafileTitle" &
Chr$(0) & Chr$(0))
 '--------------------------------------------------------------

When you actually make the graphics calls, you have to use units of
pixels,
but these pixels must be scaled to correct for the WinNT bug.

'--------------You will need the scaling factors, xPixPerMM!,
yPixPerMM!:
  TwipsPerMM!=56.7
  xPixPerMM! = TwipsPerMM!/Screen.TwipsPerPixelX
  yPixPerMM! = TwipsPerMM!/Screen.TwipsPerPixelY
'--------------These scale factore are correct for WMF, but for EMF we
have
'--------------to add the additional scaling below:
  xPixPerMM! = xPixPerMM! * Screen.Width / 18120      '=1209*15 =1510*12
  yPixPerMM! = yPixPerMM! * Screen.Height / 13608     '=907*15  =1134*12
'--------------now you can properly scale the graphics calls
'--------------to draw a line to mm position xMM!, yMM! use:
  ret& = LineTo(hdcMF&, xMM!*xPixPerMM!, ymm!*yPixPerMM!)
'-------------------------------------------------------
I have tested this at screen resolutions of 1280x1024, 1024x768 and
800x600 with both large and small fonts, and it seems to be accurate to
the pixel.

Andy: I did not try and figure out your numbers, but I presume you are
more or less doing the same thing with the code you posted.

Thanks for the help.

Hans Reich

Hans Reich wrote:

> I am having a curious problem with a VB5 program that generates Enhanced
> Windows metafiles. Everything works fine on Win 95/98, but when I create
> EMF's on Win 2000 machines the metafile scale becomes dependent on the
> screen resolution. In other words, I create the EMF at a certain size in
> pixels, if I am at screen resolution of 1024x768 the EMF dimensions are
> larger than it should be (the drawing is cropped on bottom and right) if
> I switch to 1280x1024 the image is smaller than it should be. When I
> create WMF's using the same code and dimensions, they are fine on both
> Win 98 and Win 2000 at any screen resolution.

> I would really appreciate any help.  Unless I can figure this out my
> program can no longer support EMF graphics.

> At the suggestion of Stephen Lebans I created a sample project that
> illustrates the difficulty (at least on my Win 2000 machine). Start a
> new project (Form 1) and place two command buttons: Command1 with
> caption="Make EMF" and Command2 with caption="Make WMF".  Also place a
> picturebox (Picture1) and Image (Image1) on the form. Paste the code
> below into the form, and run the program. The code will create a tiny
> metafile (either EMF or WMF), copy it to the clipboard, and put the
> Metafile into the picturebox and image control.

> On a Win95 system pressing either button produces the identical triangle
> that just fits into the picture box.  On a Win 2000 system with screen
> resolution 1024x768 the triangle draws fine with WMF but is larger (by
> 18%) than it should be when an EMF is created, and is now clipped right
> and bottom by the boundaries of the picture box. Both WMF and EMF use
> exactly the same code and line dimensions.  In other words, when I send
> a lineto of 100 pixels, the WMF has a line 100 pixels long and the EMF
> has a line 118 pixels long in it.

> Hans Reich

> =====================code===========================
> Option Explicit

> Private Type POINTAPI
>   xapi As Long
>   yapi As Long
> End Type

> Private Type RectLng
>   Left As Long
>   Top As Long
>   Right As Long
>   Bottom As Long
> End Type

> Const MM_ANISOTROPIC = 8
> Const BS_NULL% = 1
> Const TRANSPARENT& = 1
> Const WINDING& = 2
> Const GMEM_MOVEABLE = &H2
> Private Type LOGBRUSH   'OK
>   lbStyle As Long
>   lbColor As Long
>   lbHatch As Long
> End Type
> Dim mLBCurr As LOGBRUSH
> Private Type LOGPEN    '10 Bytes Also in Screen
>   Style As Long 'Integer
>   Wdth As POINTAPI        'only xapi is used - y is unused
>   Color As Long
> End Type
> Dim mLPCurr As LOGPEN
> '-------------------Below needed only for WMF--------------------------
> Private Declare Function CopyMetaFile Lib "gdi32" Alias "CopyMetaFileA"
> (ByVal hMF As Long, ByVal lpFileName As String) As Long
> Private Declare Function CreateMetafile Lib "gdi32" Alias
> "CreateMetaFileA" (ByVal lpString As String) As Long
> Private Declare Function CloseMetaFile Lib "gdi32" (ByVal hMF As Long)
> As Long
> Private Declare Function DeleteMetaFile Lib "gdi32" (ByVal hMF As Long)
> As Long
> Private Declare Function GlobalLock Lib "Kernel32" (ByVal hMem As Long)
> As Long
> Private Declare Function GlobalUnlock Lib "Kernel32" (ByVal hMem As
> Long) As Long
> Private Declare Function GlobalAlloc Lib "Kernel32" (ByVal wFlags As
> Long, ByVal dwBytes As Long) As Long
> Private Declare Sub hmemcpy Lib "Kernel32" Alias "RtlMoveMemory" _
>     (hpvDest As Any, hpvsource As Any, ByVal cbCopy As Long)
> Private Type METAFILEPICT
>     mm As Long
>     xExt As Long
>     yExt As Long
>     hMF As Long
> End Type

> '-------------------Below needed only for Enhanced Metafile-----------
> Private Declare Function CreateEnhMetaFile Lib "gdi32" Alias
> "CreateEnhMetaFileA" (ByVal hdcRef As Long, ByVal lpFileName As String,
> lpRect As RectLng, ByVal lpDescription As String) As Long
>           'returns 0 on error, handle to ENHMF DC on success
> Private Declare Function CloseEnhMetaFile Lib "gdi32" (ByVal hdc As
> Long) As Long
> '-------------------Below needed for both EMF and WMF------------------
> Private Declare Function SetWindowOrgEx Lib "gdi32" (ByVal hdc As Long,
> ByVal nX As Long, ByVal nY As Long, lpPoint As POINTAPI) As Long
> Private Declare Function SetWindowExtEx Lib "gdi32" (ByVal hdc As Long,
> ByVal nX As Long, ByVal nY As Long, lpPoint As POINTAPI) As Long
> Private Declare Function SetMapMode Lib "gdi32" (ByVal hdc As Long,
> ByVal nMapMode As Long) As Long
> Private Declare Function SetBkMode Lib "gdi32" (ByVal hdc As Long, ByVal
> nBkMode As Long) As Long
> Private Declare Function CreateBrushIndirect Lib "gdi32" (lpLogBrush As
> LOGBRUSH) As Long
> Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long,
> ByVal hObject As Long) As Long
> Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As
> Long) As Long
> Private Declare Function CreatePenIndirect Lib "gdi32" (lpLogPen As
> LOGPEN) As Long
> Private Declare Function MoveToEx Lib "gdi32" (ByVal hdc As Long, ByVal
> X As Long, ByVal Y As Long, ByVal ptr As Long) As Long
> Private Declare Function LineTo Lib "gdi32" (ByVal hdc As Long, ByVal X
> As Long, ByVal Y As Long) As Long
> Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long)
> As Long
> Private Declare Function CloseClipboard Lib "user32" () As Long
> Private Declare Function SetClipboarddata Lib "user32" Alias
> "SetClipboardData" (ByVal wFormat As Long, ByVal hMem As Long) As Long

> Private Sub MakeMetafile(MFtype$)
>     'This procedure creates an Enhanced Windows Metafile (MFtype$="EMF")
>     'or a Windows Metafile (MFtype$="WMF") in the shape of three lines
> forming a triangle
>     'No text material is placed in the metafile - this is an ultrasimple
> example
>     'The metafile data is placed in the clipboard and displayed in a
> PictureBoc (Picture1)
>   Dim EMF As Boolean
>   Dim lpRect As RectLng
>   Dim hdcMF&    'handle to the MF device context
>   Dim PAP As POINTAPI
>   Dim ret&      'returnvalue of functions (NO error checking here)
>   Dim hMF&      'handle to the metafile
>   Dim PixXext&, PixYext&        'pixel dimensions of enclosing box
>   Dim TwipsXext&, TwipsYext&    'twips dimension of enclosing box
>   Dim HimmXext&, HimmYext&      'HiMetrix dimensions of enclosing box
>   Dim CopyMF&, CBhnd&, CBAdr&
>   Dim Mp As METAFILEPICT
> '------Determine which type to make--------------
>   If UCase$(MFtype$) = "EMF" Then EMF = True Else EMF = False
> '------Dimensions of the EMF frame---------------
>   PixXext& = 100: PixYext& = 100    'enclosing box in pixels
>   '56.7 twips/mm  1440 TwipsPerInch/25.4 MmPerInch
>   TwipsXext& = PixXext& * Screen.TwipsPerPixelX
>   TwipsYext& = PixYext& * Screen.TwipsPerPixelY
>   HimmXext& = 100 * TwipsXext& / 56.7 '=2646
>   HimmYext& = 100 * TwipsYext& / 56.7 '=2646
>   If EMF Then
>     lpRect.Left = 0
>     lpRect.Top = 0
>     lpRect.Right = HimmXext&  'this is width in highmetric units (0.01
> mm)
>     lpRect.Bottom = HimmYext&  'this is height in highmetric units
> '--------Create a memory enhanced metafile device context
>     hdcMF& = CreateEnhMetaFile(0&, vbNullString, lpRect, "WINPLT V 7.1"
> & Chr$(0) & "PLT1620 EMF " & Chr$(0) & Chr$(0))
>   Else
>     hdcMF& = CreateMetafile(vbNullString)  'memory metafile
>   End If
> '--------Create the Window Extents

...

read more »

 
 
 

1. Problem with EMF scale in Win 2000

I am having a curious problem with a VB5 program that generates Enhanced
Windows metafiles. Everything works fine on Win 95/98, but when I create
EMF's on Win 2000 machines the metafile scale becomes dependent on the
screen resolution. In other words, I create the EMF at a certain size in
pixels, if I am at screen resolution of 1024x768 the EMF dimensions are
larger than it should be (the drawing is cropped on bottom and right) if
I switch to 1280x1024 the image is smaller than it should be. Presumably
at some intermediate screen resolution things would be fine.  
When I create WMF's using the same code and dimensions, they are fine on
both Win 98 and Win 2000 at any screen resolution.

This is driving me crazy.  I have checked all internal dimensions in my
VB program and I am pretty sure I have not messed up somewhere. I am not
playing any games with viewports and such.  Any help would be
appreciated.

Hans Reich

2. GLUT Lisencing question

3. WMF/EMF -- Scaling

4. E:FC model

5. how to create emf/wmf file?

6. How do I crop a bitmap?

7. creating emf/wmf files

8. Visualization '91 Conference Announce

9. How to create metafiles (wmf, emf) ?

10. WMF-EMF problem

11. EMF scaling problems

12. Druck von EMF-Daten / Print EMF-Data