Abbiamo riscontrato un problema con l'output di TMetaFileCanvas quando si disegna un'immagine su una coordinata esterna alla risoluzione dello schermo. Le operazioni vettoriali sembrano non avere problemi, ma le operazioni di immagine sono semplicemente "ignorate". Se disegniamo la stessa immagine su una coordinata all'interno dei limiti dello schermo, non ci sono problemi.Copia di un elemento grafico su TMetaFileCanvas all'esterno delle dimensioni dello schermo
Ad esempio. Questo SSCCE produrrà 4 file di output. La variante bitmap non ha problemi e verrà visualizzata come previsto con il quadrato rosso nell'angolo in alto a sinistra per inscreen.bmp
e il quadrato rosso nell'angolo in basso a destra per outsidescreen.bmp
. Il meta file inscreen.emf
funziona come previsto con il quadrato rosso disegnato nell'angolo in alto a sinistra. outsidescreen.emf
non funziona e viene disegnata solo la linea.
program Project6;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Types,
Windows,
Vcl.Graphics;
const
SIZECONST = 3000; // should be larger than your screen resolution
OFFSET = 1500;
function GetMyMetafile(const aHDC: HDC): TMetafile;
var
metcnv: TMetafileCanvas;
begin
Result := TMetafile.Create;
Result.SetSize(500, 500);
metcnv := TMetafileCanvas.Create(Result, aHDC);
metcnv.Brush.Color := clRed;
metcnv.FillRect(Rect(0, 0, 500, 500));
metcnv.Free;
end;
procedure OutputToMetaFile(const aFilename: string; const aStartOffset,
aEndOffset, aMaxSize: Integer; aGraphic: TGraphic; aHDC: HDC);
var
metafile: TMetafile;
metcnv: TMetafileCanvas;
begin
metafile := TMetafile.Create;
try
metafile.SetSize(aMaxSize, aMaxSize);
metcnv := TMetafileCanvas.Create(metafile, aHDC);
try
// draw it somewhere offscreen
metcnv.StretchDraw(Rect(aStartOffset, aStartOffset, aEndOffset, aEndOffset), aGraphic);
metcnv.MoveTo(aStartOffset, aStartOffset);
metcnv.LineTo(aEndOffset, aEndOffset);
finally
metcnv.Free;
end;
metafile.SaveToFile(aFilename);
finally
metafile.Free;
end;
end;
procedure OutputToBitmap(const aFilename: string; const aStartOffset,
aEndOffset, aMaxSize: Integer; aGraphic: TGraphic);
var
bmp: TBitmap;
begin
bmp := TBitmap.Create;
try
bmp.SetSize(aMaxSize, aMaxSize);
bmp.Canvas.StretchDraw(Rect(aStartOffset, aStartOffset, aEndOffset, aEndOffset), aGraphic);
bmp.Canvas.MoveTo(aStartOffset, aStartOffset);
bmp.Canvas.LineTo(aEndOffset, aEndOffset);
bmp.SaveToFile(aFilename);
finally
bmp.Free;
end;
end;
var
mygraph: TMetafile;
bigBitmap: TBitmap;
begin
bigBitmap := TBitmap.Create;
try
bigBitmap.PixelFormat := pf24bit;
Assert(bigBitmap.HandleType = bmDIB, 'Handle Type should be a DIB');
bigBitmap.Width := SIZECONST;
bigBitmap.Height := SIZECONST;
mygraph := GetMyMetafile(bigBitmap.Canvas.Handle);
OutputToMetaFile('inscreen.emf', 0, 1000, SIZECONST, mygraph, bigBitmap.Canvas.Handle);
OutputToMetaFile('outsidescreen.emf', OFFSET, SIZECONST-1, SIZECONST, mygraph, bigBitmap.Canvas.Handle);
// do the same using bitmap
OutputToBitmap('inscreen.bmp', 0, 1000, SIZECONST, mygraph);
OutputToBitmap('outsidescreen.bmp', OFFSET, SIZECONST-1, SIZECONST, mygraph);
finally
bigBitmap.Free;
mygraph.Free;
end;
end.
Qualcuno può vedere qual è il problema o sai di un lavoro in giro per questo?
Aggiornamento
, avrei compreso questo quando ho inizialmente fatto la domanda. Abbiamo testato utilizzando l'HDC per una bitmap di grandi dimensioni e che presentava lo stesso problema. Ho aggiornato il codice di esempio per dimostrarlo.
Aggiornamento 2
Purtroppo la soluzione è ancora sfuggente, anche dopo la generosità. Qualsiasi operazione BitBlt al di fuori della dimensione dello schermo non viene disegnata.
Ecco un'estrazione delle operazioni Metafile quando l'immagine è nei limiti dello schermo coordinate:
R0001: [001] EMR_HEADER (s=108) {{ Bounds(500,500,18138,18129), Frame(0,0,105000,105000), ver(0x10000), size(688), recs(33), handles(2), pals(0), dev_pix(1080,1920), dev_mil(381,677), pixf_size(0), pixf_ofs(0), openGL(0) }}
R0002: [033] EMR_SAVEDC (s=8)
R0003: [115] EMR_SETLAYOUT (s=12) {iMode(0=<default>)}
R0004: [028] EMR_SETMETARGN (s=8)
R0005: [037] EMR_SELECTOBJECT (s=12) {Stock object: 0=OBJ_BRUSH.(BS_SOLID)}
R0006: [037] EMR_SELECTOBJECT (s=12) {Stock object: 7=OBJ_PEN.(PS_SOLID | COSMETIC)}
R0007: [037] EMR_SELECTOBJECT (s=12) {Stock object: 14=OBJ_FONT}
R0008: [025] EMR_SETBKCOLOR (s=12) {0x00FFFFFF}
R0009: [024] EMR_SETTEXTCOLOR (s=12) {0x00000000}
R0010: [018] EMR_SETBKMODE (s=12) {iMode(2=OPAQUE)}
R0011: [019] EMR_SETPOLYFILLMODE (s=12) {iMode(1=ALTERNATE)}
R0012: [020] EMR_SETROP2 (s=12) {iMode(13=R2_COPYPEN)}
R0013: [021] EMR_SETSTRETCHBLTMODE (s=12) {iMode(1=BLACKONWHITE)}
R0014: [022] EMR_SETTEXTALIGN (s=12) {iMode(0= TA_LEFT TA_TOP)}
R0015: [013] EMR_SETBRUSHORGEX (s=16) {ptlOrigin(0,0)}
R0016: [058] EMR_SETMITERLIMIT (s=12) {Limit:0.000}
R0017: [027] EMR_MOVETOEX (s=16) { ptl(0,0)}
R0018: [035] EMR_SETWORLDTRANSFORM (s=32) {xform(eDx:500.000000, eDy:500.000000, eM11:5.039683, eM12:0.000000, eM21:0.000000, eM22:5.037203)}
R0019: [036] EMR_MODIFYWORLDTRANSFORM (s=36) {iMode(4=MWT_??), xform(eDx:500.000000, eDy:500.000000, eM11:5.039683, eM12:0.000000, eM21:0.000000, eM22:5.037203)}
R0020: [115] EMR_SETLAYOUT (s=12) {iMode(0=<default>)}
R0021: [070] EMR_GDICOMMENT (s=40) {GDI.Begin Group}
R0022: [039] EMR_CREATEBRUSHINDIRECT (s=24) {ihBrush(1), style(0=BS_SOLID, color:0x000000FF)}
R0023: [037] EMR_SELECTOBJECT (s=12) {Table object: 1=OBJ_BRUSH.(BS_SOLID)}
R0024: [037] EMR_SELECTOBJECT (s=12) {Table object: 1=OBJ_BRUSH.(BS_SOLID)}
R0025: [076] EMR_BITBLT (s=100) {rclBounds(500,500,18138,18129), Dest[x:0, y:0, cx:3500, cy:3500)], dwRop(0x00F00021), Src[x:0, y:0, xform(eDx:0.000000, eDy:0.000000, eM11:1.000000, eM12:0.000000, eM21:0.000000, eM22:1.000000), BkColor:0x00000000, iUsage:0, offBmi:0, Bmi:0, offBits:0, Bits:0]}
R0026: [037] EMR_SELECTOBJECT (s=12) {Table object: 1=OBJ_BRUSH.(BS_SOLID)}
R0027: [037] EMR_SELECTOBJECT (s=12) {Stock object: 0=OBJ_BRUSH.(BS_SOLID)}
R0028: [040] EMR_DELETEOBJECT (s=12) {ihObject(1)}
R0029: [070] EMR_GDICOMMENT (s=20) {GDI.End Group}
R0030: [034] EMR_RESTOREDC (s=12) {iRelative(-1)}
R0031: [027] EMR_MOVETOEX (s=16) { ptl(500,500)}
R0032: [054] EMR_LINETO (s=16) { ptl(1000,1000)}
R0033: [014] EMR_EOF (s=20) {nPalEntries:0, offPalEntries:16, nSizeLast:20}
Ecco un'estrazione delle operazioni Metafile quando l'immagine è fuori dai limiti delle coordinate dello schermo :
R0001: [001] EMR_HEADER (s=108) {{ Bounds(1500,1500,2999,2999), Frame(0,0,105000,105000), ver(0x10000), size(588), recs(32), handles(2), pals(0), dev_pix(1080,1920), dev_mil(381,677), pixf_size(0), pixf_ofs(0), openGL(0) }}
R0002: [033] EMR_SAVEDC (s=8)
R0003: [115] EMR_SETLAYOUT (s=12) {iMode(0=<default>)}
R0004: [028] EMR_SETMETARGN (s=8)
R0005: [037] EMR_SELECTOBJECT (s=12) {Stock object: 0=OBJ_BRUSH.(BS_SOLID)}
R0006: [037] EMR_SELECTOBJECT (s=12) {Stock object: 7=OBJ_PEN.(PS_SOLID | COSMETIC)}
R0007: [037] EMR_SELECTOBJECT (s=12) {Stock object: 14=OBJ_FONT}
R0008: [025] EMR_SETBKCOLOR (s=12) {0x00FFFFFF}
R0009: [024] EMR_SETTEXTCOLOR (s=12) {0x00000000}
R0010: [018] EMR_SETBKMODE (s=12) {iMode(2=OPAQUE)}
R0011: [019] EMR_SETPOLYFILLMODE (s=12) {iMode(1=ALTERNATE)}
R0012: [020] EMR_SETROP2 (s=12) {iMode(13=R2_COPYPEN)}
R0013: [021] EMR_SETSTRETCHBLTMODE (s=12) {iMode(1=BLACKONWHITE)}
R0014: [022] EMR_SETTEXTALIGN (s=12) {iMode(0= TA_LEFT TA_TOP)}
R0015: [013] EMR_SETBRUSHORGEX (s=16) {ptlOrigin(0,0)}
R0016: [058] EMR_SETMITERLIMIT (s=12) {Limit:0.000}
R0017: [027] EMR_MOVETOEX (s=16) { ptl(0,0)}
R0018: [035] EMR_SETWORLDTRANSFORM (s=32) {xform(eDx:1500.000000, eDy:1500.000000, eM11:15.108969, eM12:0.000000, eM21:0.000000, eM22:15.101533)}
R0019: [036] EMR_MODIFYWORLDTRANSFORM (s=36) {iMode(4=MWT_??), xform(eDx:1500.000000, eDy:1500.000000, eM11:15.108969, eM12:0.000000, eM21:0.000000, eM22:15.101533)}
R0020: [115] EMR_SETLAYOUT (s=12) {iMode(0=<default>)}
R0021: [070] EMR_GDICOMMENT (s=40) {GDI.Begin Group}
R0022: [039] EMR_CREATEBRUSHINDIRECT (s=24) {ihBrush(1), style(0=BS_SOLID, color:0x000000FF)}
R0023: [037] EMR_SELECTOBJECT (s=12) {Table object: 1=OBJ_BRUSH.(BS_SOLID)}
R0024: [037] EMR_SELECTOBJECT (s=12) {Table object: 1=OBJ_BRUSH.(BS_SOLID)}
R0025: [037] EMR_SELECTOBJECT (s=12) {Table object: 1=OBJ_BRUSH.(BS_SOLID)}
R0026: [037] EMR_SELECTOBJECT (s=12) {Stock object: 0=OBJ_BRUSH.(BS_SOLID)}
R0027: [040] EMR_DELETEOBJECT (s=12) {ihObject(1)}
R0028: [070] EMR_GDICOMMENT (s=20) {GDI.End Group}
R0029: [034] EMR_RESTOREDC (s=12) {iRelative(-1)}
R0030: [027] EMR_MOVETOEX (s=16) { ptl(1500,1500)}
R0031: [054] EMR_LINETO (s=16) { ptl(2999,2999)}
R0032: [014] EMR_EOF (s=20) {nPalEntries:0, offPalEntries:16, nSizeLast:20}
Si può vedere molto chiaramente che manca l'operazione BilBlt (R0025 nella prima).
Abbiamo provato. Avrei dovuto includerlo nella domanda. Aggiornerò la domanda con un esempio di codice utilizzando una bitmap di grandi dimensioni che presenta lo stesso problema. – Graymatter
Bounty assegnato a questa risposta. Penso che la risposta risieda nel dispositivo di riferimento che deve essere creato o dobbiamo aspettare una correzione di Windows al problema. – Graymatter