Examples / metafiles_gui / delphi

Metafiles Gui

A complete, runnable delphi program — 632 lines, shipped in your download.

Demonstrates Images

Same example, other languages: activex_cpp c cpp cpp_linux csharp python vbnet

examples/delphi/metafiles_gui/Unit1.pas 632 lines
unit Unit1;

interface

uses
  Windows, SysUtils, Classes, Forms, ComCtrls, ShellAPI, ImgList, ExtCtrls,
  ShellCtrls, Dialogs, Controls, StdCtrls, ToolWin, Graphics, LumasPdfApi, UMetafile;
  
type
  TForm1 = class(TForm)
    Splitter1: TSplitter;
    ImageList1: TImageList;
    ToolBar1: TToolBar;
    tbConvert: TToolButton;
    tbZoomIn: TToolButton;
    tbZoomOut: TToolButton;
    ToolButton4: TToolButton;
    Panel6: TPanel;
    PaintBox: TPaintBox;
    ToolButton5: TToolButton;
    SaveDialog1: TSaveDialog;
    Panel1: TPanel;
    cbZoom: TComboBox;
    tbConvertAll: TToolButton;
    Panel2: TPanel;
    Panel4: TPanel;
    Label1: TLabel;
    cbxDebug: TCheckBox;
    cbxClipView: TCheckBox;
    cbxUseRclBounds: TCheckBox;
    cbxNoTextScale: TCheckBox;
    cbxUnicode: TCheckBox;
    cbxCompress: TCheckBox;
    cbxUseTextScaling: TCheckBox;
    Tree: TShellTreeView;
    Panel3: TPanel;
    Panel5: TPanel;
    ProgressBar: TProgressBar;
    lbProgress: TLabel;
    lbCurrent: TLabel;
    cbxClippingRgn: TCheckBox;
    cbxJPEG: TCheckBox;
    cbxCMYK: TCheckBox;
    cbxNoUnicode: TCheckBox;
    cbxScale: TCheckBox;
    cbxUseRclFrame: TCheckBox;
    cbxBkTransparent: TCheckBox;
    cbxGDIFontSelection: TCheckBox;
    cbxRclFrameEx: TCheckBox;
    cbxDisableRasterEMF: TCheckBox;
    cbxClipRclBounds: TCheckBox;
    cbxNoBBoxCheck: TCheckBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure PaintBoxPaint(Sender: TObject);
    procedure PaintBoxMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure PaintBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure TreeClick(Sender: TObject);
    procedure FormMouseWheelDown(Sender: TObject; Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
    procedure FormMouseWheelUp(Sender: TObject; Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
    procedure cbxDebugClick(Sender: TObject);
    procedure cbxCompressClick(Sender: TObject);
    procedure tbConvertClick(Sender: TObject);
    procedure tbZoomInClick(Sender: TObject);
    procedure tbZoomOutClick(Sender: TObject);
    procedure ToolButton4Click(Sender: TObject);
    procedure cbZoomChange(Sender: TObject);
    procedure tbConvertAllClick(Sender: TObject);
    procedure cbxUnicodeClick(Sender: TObject);
    procedure cbxNoUnicodeClick(Sender: TObject);
    procedure cbxClipViewMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure cbxUseRclBoundsClick(Sender: TObject);
    procedure cbxUseRclFrameClick(Sender: TObject);
    procedure cbxRclFrameExClick(Sender: TObject);
  private
    PDF: TPDF;
    FDC: HDC;
    FBMP: HBITMAP;
    FBMPInfo: tagBITMAPINFO;
    FBuffer: Pointer;
    FView: TRect;
    FX, FY, FLastX, FLastY: Integer;
    FZoom: Double;
    MFile: TMetafileEx;
    FWidth: Integer;
    function GetFlags: Integer;
  public
end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// LumasPDF error callback function
function ErrProc(const Data: Pointer; ErrCode: Integer; const ErrMessage: PAnsiChar; ErrType: Integer): Integer; stdcall;
begin
   if MessageDlg(String(ErrMessage), mtError, [mbOK, mbCancel], 0) = mrCancel then
      Result := -1
   else
      Result := 0;
end;

// Callback function to initialize the progress bar. This function is executed by the classic API before the
// the callback function Progress is called the first time.
function InitProgress(const Data: Pointer; ProgType: TProgType; MaxCount: Integer): Integer; stdcall;
begin
   case ProgType of
      ptImportPage: Form1.lbProgress.Caption := 'Read page: ';  // Occurs only when importing an external PDF file
      ptWritePage:  Form1.lbProgress.Caption := 'Write page: '; // Writing a page to the file.
   end;
   Form1.ProgressBar.Position := 0;
   Form1.ProgressBar.Max      := MaxCount;
   Result := 0;
end;

// This callback function is called by the classic API before writing a page to the file. The reading case
// cannot occur because we do not import an external PDF file in this application.
function Progress(const Data: Pointer; ActivePage: Integer): Integer; stdcall;
begin
   Form1.lbCurrent.Caption := Format('%d of %d', [ActivePage, Form1.ProgressBar.Max]);
   Form1.ProgressBar.StepIt;
   Application.ProcessMessages; // Update the label and progress bar
   Result := 0;
end;

const MARGIN: Integer = 10;

procedure PlaceEMFCentered(PDF: TPDF; const MFile: TMetafileEx; Width, Height: Double); overload;
var x, y, w, h, sx: Double; r: TRectL;
begin
   PDF.GetLogMetafileSizeEx(MFile.Buffer, MFile.BufSize, r);
   w      := r.Right - r.Left;
   h      := r.Bottom - r.Top;
   Width  := Width  - 2.0 * MARGIN;
   Height := Height - 2.0 * MARGIN;
   sx := Width / w;
   if (h * sx <= Height) then begin
      x := MARGIN;
      y := MARGIN;
      PDF.InsertMetafileEx(MFile.Buffer, MFile.BufSize, x, y, Width, 0.0);
      h := h * sx;
      PDF.SetStrokeColor(clRed);
      PDF.Rectangle(x, y, Width, h, fmStroke);
   end else begin
      sx := Height / h;
      w  := w * sx;
      x  := MARGIN + (Width - w) / 2.0;
      y  := MARGIN;
      PDF.InsertMetafileEx(MFile.Buffer, MFile.BufSize, x, y, 0.0, Height);
      PDF.SetStrokeColor(clRed);
      PDF.Rectangle(x, y, w, Height, fmStroke);
   end;
end;

procedure PlaceEMFCentered(PDF: TPDF; const MFile: String; Width, Height: Double); overload;
var x, y, w, h, sx: Double; r: TRectL;
begin
   PDF.GetLogMetafileSize(AnsiString(MFile), r);
   w      := r.Right - r.Left;
   h      := r.Bottom - r.Top;
   Width  := Width  - 2.0 * MARGIN;
   Height := Height - 2.0 * MARGIN;
   sx := Width / w;
   if (h * sx <= Height) then begin
      x := MARGIN;
      y := MARGIN;
      PDF.InsertMetafile(AnsiString(MFile), x, y, Width, 0.0);
      //PDF.SetStrokeColor(clRed);
      //PDF.Rectangle(x, y, Width, h, fmStroke);
   end else begin
      sx := Height / h;
      w  := w * sx;
      x  := MARGIN + (Width - w) / 2.0;
      y  := MARGIN;
      PDF.InsertMetafile(AnsiString(MFile), x, y, 0.0, Height);
      //PDF.SetStrokeColor(clRed);
      //PDF.Rectangle(x, y, w, Height, fmStroke);
   end;
end;

function TForm1.GetFlags(): Integer;
begin
   Result := 0;
   if cbxDebug.Checked then Inc(Result, mfDebug);
   if cbxClipView.Checked then Inc(Result, mfClipView);
   if cbxClipRclBounds.Checked then Inc(Result, mfClipRclBounds);
   if cbxGDIFontSelection.Checked then Inc(Result, mfGDIFontSelection);
   if cbxUnicode.Checked then Inc(Result, mfUseUnicode);
   if cbxNoUnicode.Checked then Inc(Result, mfNoUnicode);
   if cbxScale.Checked then Inc(Result, mfFullScale);
   if cbxDisableRasterEMF.Checked then Inc(Result, mfDisableRasterEMF);
   if cbxNoBBoxCheck.Checked then Inc(Result, mfNoBBoxCheck);

   if cbxClippingRgn.Checked then Inc(Result, mfNoClippingRgn);
   if cbxNoTextScale.Checked then Inc(Result, mfNoTextScaling);
   if cbxUseTextScaling.Checked then Inc(Result, mfUseTextScaling);
   if cbxUseRclBounds.Checked then Inc(Result, mfUseRclBounds);
   if cbxUseRclFrame.Checked then Inc(Result, mfUseRclFrame);
   if cbxRclFrameEx.Checked then Inc(Result, mfRclFrameEx);

   if cbxBkTransparent.Checked then Inc(Result, mfDefBkModeTransp);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   try
      PDF := TPDF.Create;
   except
      on E: Exception do MessageDlg(E.Message, mtError, [mbOK], 0);
   end;
   if PDF <> nil then begin
      PDF.SetOnErrorProc(nil, @ErrProc);
      // We use flate compression for better transparency support.
      // Due to the color interpolation when using JPEG compression
      // it is not possible to mask an image exactly with this filter.
      // Flate is a loss-less filter that produces no side effects.
      PDF.SetCompressionFilter(cfFlate);
      PDF.SetJPEGQuality(70);
   end;
   // Memory DC and DIB to render a metafile in background to avoid flicker.
   FDC  := CreateCompatibleDC(0);
   FillChar(FBMPInfo, sizeof(FBMPInfo), 0);
   FBMPInfo.bmiHeader.biBitCount := 24;
   FBMPInfo.bmiHeader.biPlanes   := 1;
   FBMPInfo.bmiHeader.biWidth    :=  Screen.Width;
   FBMPInfo.bmiHeader.biHeight   := -Screen.Height;
   FBMPInfo.bmiHeader.biSize     := 40;
   FBMP := CreateDIBSection(FDC, FBMPInfo, DIB_RGB_COLORS, FBuffer, 0, 0);
   SelectObject(FDC, FBMP);
   FZoom  := 1.0;
   FX     := 0;
   FY     := 0;
   FLastX := 0;
   FLastY := 0;
   FView  := ClientRect;
   MFile  := nil;
   cbZoom.ItemIndex := 3;
   Application.HintHidePause := -1;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
   DeleteDC(FDC);
   DeleteObject(FBMP);
   if PDF <> nil then PDF.Free;
end;

procedure TForm1.PaintBoxPaint(Sender: TObject);
var bw, bh, frw, frh, ow, oh, iw, ih, sw, sh, op, x, y: Integer; sx, sy: Double; r: TRectL; xf: TXFORM; pen: HPEN; oldObj: HGDIOBJ;
begin
   FillRect(FDC, PaintBox.ClientRect, GetStockObject(WHITE_BRUSH));
   if MFile = nil then Exit;
   pdf.SetMetaConvFlags(GetFlags());
   pdf.GetLogMetafileSizeEx(MFile.Buffer, MFile.BufSize, r);
   with r do begin
      ow := Right - Left;
      oh := Bottom - Top;
   end;
   with MFile.Header.rclBounds do begin
      bw := Right -Left;
      bh := Bottom - Top;
   end;
   with MFile.Header.rclFrame do begin
      frw := Right -Left;
      frh := Bottom - Top;
   end;

   sx := (PaintBox.ClientWidth - 20) / ow;
   iw := Trunc(ow * sx * FZoom);
   ih := Trunc(oh * sx * FZoom);

   FWidth := iw;
   x := MARGIN - FX;
   y := MARGIN - FY;

   op := SaveDC(FDC);
   if cbxClipView.Checked then begin
      IntersectClipRect(FDC, x, y, iw+x, ih+y);
   end;

   {
      This calculation does not consider the flags mfUseRclBounds, mfUseRclFrame, or mfRclFrameEx.
   }

   // Check whether the header is valid. This computation fails in very rare cases.
   if cbxNoBBoxCheck.Checked or (bw < frw * 75 / 100) or (bh < frh * 75 / 100) then begin
      xf.eM11 := sx * FZoom;
      xf.eM12 := 0.0;
      xf.eM21 := 0.0;
      xf.eM22 := sx * FZoom;
      xf.eDx  := -r.Left * sx * FZoom + x;
      xf.eDy  := -r.Top  * sx * FZoom + y;
      SetGraphicsMode(FDC, GM_ADVANCED);
      ModifyWorldTransform(FDC, xf, MWT_LEFTMULTIPLY);
      PlayEnhMetafile(FDC, MFile.Handle, TRect(r));
   end else begin
      // The rclFrame rectangle seems to be invalid. We try to compute the correct image size.
      with MFile.Header.szlMillimeters do begin
         sw := cx * 100;
         sh := cy * 100;
      end;
      sx := frw / sw;
      sy := frh / sh;
      sw := Trunc(MFile.Header.szlDevice.cx * sx);
      sh := Trunc(MFile.Header.szlDevice.cy * sy);

      SetMapMode(FDC, MM_ANISOTROPIC);
      SetWindowExtEx(FDC, ow, oh, nil);
      SetViewPortOrgEx(FDC, x, y, nil);
      SetViewPortExtEx(FDC, sw, sh, nil);
      PlayEnhMetafile(FDC, MFile.Handle, Rect(0,0,iw,ih));
   end;
   RestoreDC(FDC, op);

   SelectObject(FDC, GetStockObject(NULL_BRUSH));
   pen := CreatePen(PS_SOLID, 1, 255);
   oldObj := SelectObject(FDC, pen);
   Rectangle(FDC, x, y, iw+x, ih+y);
   DeleteObject(SelectObject(FDC, oldObj));

   GDIFlush;
   SetDIBitsToDevice(PaintBox.Canvas.Handle, 0, 0, PaintBox.ClientWidth, PaintBox.ClientHeight, 0, 0, 0, PaintBox.ClientHeight, FBuffer, FBMPInfo, DIB_RGB_COLORS);
end;

procedure TForm1.PaintBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
   FView.Left   := X;
   FView.Top    := Y;
   FView.Right  := X;
   FView.Bottom := Y;
   FLastX       := FX;
   FLastY       := FY;
   if ssRight in Shift then begin
      FZoom  := 1.0;
      FX     := 0;
      FY     := 0;
      FLastX := 0;
      FLastY := 0;
      cbZoom.ItemIndex  := 3;
      tbZoomIn.Enabled  := true;
      tbZoomOut.Enabled := true;
      PaintBoxPaint(nil);
   end;
end;

procedure TForm1.PaintBoxMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
   if (ssLeft in Shift) then begin
      FX := FView.Left - X + FLastX;
      FY := FView.Top - Y + FLastY;
      FView.Right  := X;
      FView.Bottom := Y;
      PaintBoxPaint(nil);
   end;
end;

procedure TForm1.FormMouseWheelDown(Sender: TObject; Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
begin
   if MousePos.X < Form1.Left + Splitter1.Left + Splitter1.Width then Exit;
   Inc(FY, 40);
   Handled := true;
   PaintBoxPaint(nil);
end;

procedure TForm1.FormMouseWheelUp(Sender: TObject; Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
begin
   if MousePos.X < Form1.Left + Splitter1.Left + Splitter1.Width then Exit;
   if FY = 0 then begin
      Handled := true;
      Exit;
   end;
   Dec(FY, 40);
   if FY < 0 then FY := 0;
   Handled := true;
   PaintBoxPaint(nil);
end;

procedure TForm1.cbxDebugClick(Sender: TObject);
begin
   cbxCompress.OnClick := nil;
   cbxCompress.Checked := false;
   cbxCompress.OnClick := cbxCompressClick;
end;

procedure TForm1.cbxCompressClick(Sender: TObject);
begin
   cbxDebug.OnClick := nil;
   cbxDebug.Checked := false;
   cbxDebug.OnClick := cbxDebugClick;
end;

procedure TForm1.TreeClick(Sender: TObject);
var ext: String;
begin
   ext := LowerCase(ExtractFileExt(Tree.Path));
   if (ext = '.emf') or (ext = '.wmf') then begin
      FZoom  := 1.0;
      FX     := 0;
      FY     := 0;
      FLastX := 0;
      FLastY := 0;
      cbZoom.ItemIndex := 3;
      tbZoomIn.Enabled  := true;
      tbZoomOut.Enabled := true;
      if MFile <> nil then MFile.Free;
      MFile := TMetafileEx.Create;
      try
         MFile.LoadFromFile(Tree.Path);
         tbConvert.Enabled    := true;
         tbConvertAll.Enabled := true;
         PaintBoxPaint(nil);
      except
         MFile.Free;
         MFile := nil;
      end;
   end else begin
      tbConvert.Enabled    := false;
      tbConvertAll.Enabled := false;
   end;
end;

procedure TForm1.tbConvertClick(Sender: TObject);
var s: String;
begin
   if PDF = nil then begin
      MessageDlg('No active PDF instance!'#13'Forgotten to copy the LumasPdf.dll into a Windows search path?', mtError, [mbOK], 0);
      Exit;
   end;
   s := Tree.Path;
   s := ChangeFileExt(s, '.pdf');
   SaveDialog1.FileName := s;
   if SaveDialog1.Execute = false then Exit;
   if not PDF.CreateNewPDF('') then Exit;

   if (cbxCompress.Checked) then
      PDF.SetCompressionLevel(LumasPdfApi.clDefault)
   else
      PDF.SetCompressionLevel(LumasPdfApi.clNone);
   if cbxJPEG.Checked then
      PDF.SetCompressionFilter(cfJPEG)
   else
      PDF.SetCompressionFilter(cfFlate);
   if cbxCMYK.Checked then
      PDF.SetColorSpace(csDeviceCMYK)
   else
      PDF.SetColorSpace(csDeviceRGB);
   Application.ProcessMessages;
   PDF.SetMetaConvFlags(GetFlags());
   PDF.SetPageCoords(pcTopDown);
   PDF.Append;
   PDF.SetResolution(300);
   PDF.SetJPEGQuality(70);
   PlaceEMFCentered(PDF, MFile, PDF.GetPageWidth, PDF.GetPageHeight);
   PDF.EndPage;
   if PDF.HaveOpenDoc then begin
      while not PDF.OpenOutputFile(SaveDialog1.FileName) do begin
         if SaveDialog1.Execute = false then begin
            PDF.FreePDF;
            Exit;
         end;
      end;
      if PDF.CloseFile = true then
         ShellExecute(Handle, PChar('open'), PChar(SaveDialog1.FileName), nil, nil, SW_SHOWMAXIMIZED);
   end;
end;

procedure TForm1.tbZoomInClick(Sender: TObject);
begin
   cbZoom.ItemIndex := cbZoom.ItemIndex +1;
   if cbZoom.ItemIndex = 11 then tbZoomIn.Enabled := false;
   tbZoomOut.Enabled := true;
   cbZoomChange(nil);
end;

procedure TForm1.tbZoomOutClick(Sender: TObject);
begin
   cbZoom.ItemIndex := cbZoom.ItemIndex -1;
   if cbZoom.ItemIndex = 0 then tbZoomOut.Enabled := false;
   tbZoomIn.Enabled := true;
   cbZoomChange(nil);
end;

procedure TForm1.ToolButton4Click(Sender: TObject);
begin
   FZoom  := 1.0;
   FX     := 0;
   FY     := 0;
   FLastX := 0;
   FLastY := 0;
   cbZoom.ItemIndex  := 3;
   tbZoomIn.Enabled  := true;
   tbZoomOut.Enabled := true;
   PaintBoxPaint(nil);
end;

procedure TForm1.cbZoomChange(Sender: TObject);
var oldZoom: Double;
begin
   oldZoom := FZoom;
   case cbZoom.ItemIndex of
      0: FZoom := 0.125;
      1: FZoom := 0.25;
      2: FZoom := 0.5;
      3: FZoom := 1.0;
      4: FZoom := 1.5;
      5: FZoom := 2.0;
      6: FZoom := 4.0;
      7: FZoom := 8.0;
      8: FZoom := 16.0;
      9: FZoom := 32.0;
      10: FZoom := 64.0;
      11: FZoom := 128.0;
   end;
   FX := Trunc(FX / oldZoom * FZoom);
   FY := Trunc(FY / oldZoom * FZoom);
   PaintBoxPaint(nil);
end;

procedure TForm1.tbConvertAllClick(Sender: TObject);
var i, count, nextAlloc: Integer; s, ext: String; sr: TSearchRec; paths: array of String;
begin
   if PDF = nil then begin
      MessageDlg('No active PDF instance!'#13'Forgotten to copy the LumasPdf.dll into a Windows search path?', mtError, [mbOK], 0);
      Exit;
   end;
   s := ExtractFilePath(Tree.Path);
   SaveDialog1.FileName := s + 'EmfFiles.pdf';
   if SaveDialog1.Execute = false then Exit;

   if not PDF.CreateNewPDF(SaveDialog1.FileName) then Exit;

   if (cbxCompress.Checked) then
      PDF.SetCompressionLevel(LumasPdfApi.clDefault)
   else
      PDF.SetCompressionLevel(LumasPdfApi.clNone);
   if cbxCMYK.Checked then
      PDF.SetColorSpace(csDeviceCMYK)
   else
      PDF.SetColorSpace(csDeviceRGB);
   PDF.SetMetaConvFlags(GetFlags());
   PDF.SetPageCoords(pcTopDown);
   // The resolution is used to convert images from the metafile, not to convert the metafile itself.
   PDF.SetResolution(300);

   if FindFirst(s + '*.*', faAnyFile, sr) <> 0 then begin
      PDF.FreePDF;
      MessageDlg('No Metafiles found!', mtError, [mbOK], 0);
      Exit;
   end;
   // We disconnect the error callback to avoid multiple warnings if more than one metafile is corrupt.
   PDF.SetOnErrorProc(nil, nil);
   // We count the files first so that we can initialize the progress bar.
   count := 0;
   nextAlloc := 100;
   SetLength(paths, nextAlloc);
   try
      repeat
         if sr.Name[1] = '.' then continue;
         ext := LowerCase(ExtractFileExt(sr.Name));
         if (StrComp(PChar(ext), PChar('.emf')) <> 0) and (StrComp(PChar(ext), PChar('.wmf')) <> 0) then continue;
         paths[count] := sr.Name;
         Inc(count);
         if (count = nextAlloc) then begin
            Inc(nextAlloc, 100);
            SetLength(paths, nextAlloc);
         end;
      until (FindNext(sr) <> 0);
   finally
      FindClose(sr);
   end;
   ProgressBar.Position := 0;
   ProgressBar.Max      := count;
   ProgressBar.Step     := 1;
   ProgressBar.Visible  := true;
   lbProgress.Caption   := 'In progress:';
   for i := 0 to count -1 do begin
      lbCurrent.Caption := paths[i];
      ProgressBar.StepIt;
      Application.ProcessMessages;
      PDF.Append;
      PlaceEMFCentered(PDF, s + paths[i], 595.0, 842.0);
      PDF.EndPage;
   end;
   // Connect the error callback now again.
   PDF.SetOnErrorProc(nil, @ErrProc);
   // We connect also the progress bar because the file can be large.
   PDF.SetProgressProc(nil, @InitProgress, @Progress);
   PDF.CloseFile;
   // It makes no sense to use a progress bar for single page files, so we disconnect it.
   PDF.SetProgressProc(nil, nil, nil);
   lbProgress.Caption := '';
   lbCurrent.Caption  := '';
   ProgressBar.Visible := false;
   ShellExecute(Handle, PChar('open'), PChar(SaveDialog1.FileName), nil, nil, SW_SHOWMAXIMIZED);
end;

procedure TForm1.cbxUnicodeClick(Sender: TObject);
begin
   cbxNoUnicode.Checked := false;  
end;

procedure TForm1.cbxNoUnicodeClick(Sender: TObject);
begin
   cbxUnicode.Checked := false;
end;

procedure TForm1.cbxClipViewMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
   PaintBoxPaint(nil);
end;

procedure TForm1.cbxUseRclBoundsClick(Sender: TObject);
begin
   PaintBoxPaint(nil);
end;

procedure TForm1.cbxUseRclFrameClick(Sender: TObject);
begin
   PaintBoxPaint(nil);
end;

procedure TForm1.cbxRclFrameExClick(Sender: TObject);
begin
   PaintBoxPaint(nil);
end;

end.

This file is in the SDK at examples/delphi/metafiles_gui/Unit1.pas. The build fails if this page and that file ever differ.