[Back to WIN-OS2 SWAG index]  [Back to Main SWAG index]  [Original]

{
From: ZWEITZE@ET.TUDelft.NL (Zweitze de Vries)

>Metafiles made in BP won't import into Word for Windows, while
>CorelDraw accepts the files. Does anyone know what's causing
>this problem?

Yes. There is not one Metafile format, there are three (!)
(excluding NT formats). The original is meant for internal
usage, like fast painting. Later this original was saved to
file to enable graphics exchange. This gave problems,
because of different mapping modes, and device resolutions.
Still, MS wanted to encourage exchange, so two new metafile
formats were developed, metafile to clipboard and the
placeable metafile (which is saved to file).

Word only accepts clipboard and placeable metafiles.
A placeable metafile is an original metafile with a 22 byte
header, which is called the placeable metafile header.
This 22 byte record is documented in your online help topic
'Metafile format'. The record type def is not implemented
in BP, so you've got to type it yourself. (Or use my copy
below)

Hereby I supply my metafile output code. There are two
entry points, which make the metafile go to clipboard or
file. In case of file, a common dialog is displayed.


{*****************************************************************************}
{*                   Werkgroep Elektrotechnisch Practicum                    *}
{*                       Faculteit der Elektrotechniek                       *}
{*                       Technische Universiteit Delft                       *}
{*****************************************************************************}
{*                               project : CATE                              *}
{* program      :  cateshell (werktitel)             date     :  Oct 1994    *}
{* filename   :  APPCHILD.PAS                     version  :  0.61           *}
{* author     :  Z.A. de Vries                    compiler :  BPW 7.0        *}
{* description:  Performs basic MDI child window handling                    *}
{*****************************************************************************}

uses
  CommDlg, WinProcs, WinTypes, Objects, OWindows, Strings, Win31;

{...}

{ Not found in runtime libs, this structure is the header of a so-called
  Placeable metafile. A Placeable metafile is a standard metafile with 
  this 22byte header. This header is documented in the online help under 
  'Metafile Format' }
type
  PPlaceableMF = ^TPlaceableMF;
  TPlaceableMF = record
    Key:      LongInt;
    hMF:      THandle;
    BBox:     TRect;
    Inch:     Integer;
    Reserved: LongInt;
    Checksum: Integer;
  end;

procedure TChildWndBase.MetafileToFile;
var
  szNewName: PChar;
  szFilter: array [0..100] of Char;
  szExt: array [0..3] of Char;
  pFilter: PChar;
  SaveRec: TOpenFileName;
  wmfFile: PBufStream;
  wmfHeader: TPlaceableMF;
  hMetafile: THandle;
  pMetafile: PMetaHeader;
  ScrnDC: HDC;
begin
  GetMem(szNewName, fsCompleteName);    { const fsCompleteName = 144 }

  FillChar(szFilter, SizeOf(szFilter), 0);
  StrCopy(szFilter, 'Windows Metafiles (*.WMF)');
  pFilter := StrEnd(szFilter);
  Inc(pFilter);
  pFilter := StrECopy(pFilter, '*.WMF');
  Inc(pFilter);
  pFilter := StrECopy(pFilter, 'All files (*.*)');
  Inc(pFilter);
  StrCopy(pFilter, '*.*');

  StrCopy(szNewName, '*.WMF');
  FillChar(SaveRec, SizeOf(SaveRec), 0);
  with SaveRec
    do begin
      hwndOwner     := Application^.MainWindow^.hWindow;
      lStructSize   := SizeOf(SaveRec);
      lpstrFile     := szNewName;
      nMaxFile      := fsCompleteName;
      Flags         := ofn_NoReadOnlyReturn or ofn_OverwritePrompt or
                       ofn_PathMustExist or ofn_ShowHelp or ofn_HideReadOnly;
      lpstrDefExt   := 'WMF';
      lpstrFilter   := szFilter;
      nFilterIndex  := 1;
    end;

  if GetSaveFileName(SaveRec)
    then begin
      ScrnDC := GetDC(hWindow);
      with wmfHeader
        do begin
          Key := $9AC6CDD7;
          hMF := 0;
          GetClientRect(hWindow, BBox);
          Inch := (GetDeviceCaps(ScrnDC, LogPixelsX) +
                   GetDeviceCaps(ScrnDC, LogPixelsY)) div 2;
          Reserved := 0;
          Checksum := $9AC6 xor $CDD7 xor BBox.Right xor BBox.Bottom xor Inch;
        end;
      ReleaseDC(hWindow, ScrnDC);

      hMetafile := DrawMetafile(nil);

      wmfFile := new(PBufStream, Init(szNewName, stCreate, 2048));
      wmfFile^.Write(wmfHeader, SizeOf(wmfHeader));
      pMetafile := GlobalLock(hMetafile);
      wmfFile^.Write(pMetafile^, pMetafile^.mtSize * 2);
      GlobalUnlock(hMetaFile);
      wmfFile^.Done;

      DeleteMetafile(hMetafile);
    end;

  FreeMem(szNewName, fsCompleteName);
end;

procedure TChildWndBase.MetafileToClipboard;
const
  HiMetricPerInch = 2540;
var
  hMetafile, hMetafileClipboardHeader: THandle;
  pMetafileClipboardHeader: PMetafilePict;
  rcWindow: TRect;
  RefDC: HDC;
begin
  if not OpenClipboard(hWindow)
    then Exit;
  EmptyClipboard;

  hMetafile := DrawMetafile(nil);

  hMetafileClipboardHeader :=
          GlobalAlloc(gmem_DDEShare, SizeOf(TMetaFilePict));
  if (hMetafile = 0) or (hMetafileClipboardHeader = 0)
    then begin
      CloseClipboard;
      if hMetafile <> 0
        then GlobalFree(hMetafile);
      if hMetafileClipboardHeader <> 0
        then GlobalFree(hMetafileClipboardHeader);
      Exit;
    end;

  pMetafileClipboardHeader :=
          PMetaFilePict(GlobalLock(hMetafileClipboardHeader));
  with pMetafileClipboardHeader^
    do begin
      mm   := mm_Anisotropic;
      hMF  := hMetafile;
      GetClientRect(hWindow, rcWindow);  { Size is window size }
      with rcWindow
        do begin
          RefDC := GetDC(hWindow);
          xExt := MulDiv(Right - Left, HiMetricPerInch,
                         GetDeviceCaps(RefDC, LogPixelsX));
          yExt := MulDiv(Bottom - Top, HiMetricPerInch,
                         GetDeviceCaps(RefDC, LogPixelsY));
          ReleaseDC(hWindow, RefDC);
        end;
    end;

  GlobalUnlock(hMetafileClipboardHeader);
  SetClipboardData(cf_MetafilePict, hMetafileClipboardHeader);
  CloseClipboard;
end;


function TChildWndBase.DrawMetafile(szOutput: PChar): THandle;
var
  MetaDC      : HDC;
  PaintStruct : TPaintstruct;
begin
  MetaDC := CreateMetaFile(szOutput);
  SetMapMode(MetaDC, mm_anisotropic);
  SetWindowOrg(MetaDC, 0, 0);

  with PaintStruct
    do begin
      hdc    := MetaDC;
      fErase := false;
      GetClientRect(hWindow, rcPaint);
      with rcPaint
        do begin
                   { Its size is exact the same as the window size }
          SetWindowExt(MetaDC, Right - Left, Bottom - Top);

                   { Setup a clipping rectangle }
          IntersectClipRect(MetaDC, Left, Top, Right, Bottom);

                   { Setup the background color of the metafile 
                     which is the same as the window background }
          SelectObject(MetaDC, GetClassWord(hWindow, gcw_hbrBackground));
          PatBlt(MetaDC, Left, Top, Right, Bottom, PatCopy);
          SelectObject(MetaDC, GetStockObject(Hollow_Brush));
        end;
    end;

  DrawContents(MetaDC, PaintStruct); 
       { DrawContents does the actual drawing. It is also called by
         my painting and printing handlers. DrawContents assumes it
         is working in MM_TEXT mode, when the output is going to a
         metafile, the actual mapping mode is MM_ANISOTROPIC, but
         resembling MM_TEXT on any device. }

  DrawMetafile := CloseMetaFile(MetaDC);
end;


[Back to WIN-OS2 SWAG index]  [Back to Main SWAG index]  [Original]