■ダウンロード

■起動とインターフェイス

■基本操作

■ショートカット

■データ構造

■Delphiでの運用

■イラストレーターを使った背景の制作

■既知の問題

宣言


レポートデザイナーで作成されるレポートファイルのレコード体設計情報です。
読み込み順序は下記の宣言降順となります。
詳しくは同梱のサンプルコードをご覧ください。




//アイテム情報を格納したレコード体情報です。ItemRangeの数だけループでまわしてください。
type
TPrintData = record
Name :String; //日本語名
KeyName :String;
//対応キー名
mmLeft :Extended;
//Rect
mmTop :Extended;
mmWidth :Extended;
mmHeight :Extended;

//文字情報
FontName :String;
FontStyle :TFontStyles;
FontSize :Integer;
FontColor :TColor;
Alignment :Integer;
//0左寄せ、1中寄せ、2右寄せ
//図形情報
Shape :TShapeType;
PenStyle :TPenStyle;
PenWidth :Integer;
PenColor :TColor;
BrushStyle :TBrushStyle;
BrushColor :TColor;
CornerRound :Integer;

//フィールド情報
Orientation :Integer;//向き
CellWidth :Extended;
//印字セル幅mm
CellHeight :Extended;
//印字セル高mm
SendWidth :Extended;
//送り幅mm
SendHeight :Extended;
//送り高mm
BlockCol :Integer;
//列の数
BlockRow :Integer;
//行の数
//管理変数
Lock :Boolean;//位置固定フラグ
end;

var
ItemList:array of TPrintData;
//TPrintDataクラスの動的配列
ItemRange :Integer;//印刷情報のレコード数を管理する変数
PaleteModified :Boolean;//背景が入っているかどうかのフラグ
BGMetaFile :TMetaFile;//背景用メタファイル。

ストリームファイルの読み込み手続き(procedure)


レポートデザイナーで作成されたrptファイルは以下のルーチンで読みだせます。
下記、手続きをそのまま使って宣言してください。
ストリームの勉強にもなります。
ただし、印刷に使わない項目もあるのでメモリを節約したい場合は、工夫してください。


//先にグローバル変数で背景用メタファイルのインスタンスを生成しておくこと
var
BGMetaFile:Tmetafile;

procedure Form.OnShow(Sender:Object);
begin
BGMetaFile := TMetaFile.Create;
end;


//データの読み出し

procedure LoadStream;
var
FS:TFileStream;
cnt:Integer;
Len:Byte;
Bool:Boolean;
Exte:Extended;
Inte:Integer;
StrMem:PChar;
begin
//ファイルを開くと同時にストリームを生成します。
FS := TFileStream.Create(OpenDialog.FileName,fmOpenRead);
//
try
//ストリームのカーソルリセット
FS.Position := 0;
//基本ヘッダ
FS.Read(ItemRange,SizeOf(Integer));
SetLength(ItemList,ItemRange);
//フィールド情報
for cnt := 0 to ItemRange - 1 do
begin
//Name :String;
FS.Read(Len,SizeOf(Len));
StrMem := StrAlloc(Len);
FS.Read(StrMem^,Len);
ItemList[cnt].Name := StrMem;
//KeyName
FS.Read(Len,SizeOf(Len));
StrMem := StrAlloc(Len);
FS.Read(StrMem^,Len);
ItemList[cnt].KeyName := StrMem;
//mmLeft :Extended;
FS.Read(Exte,SizeOf(Extended));
ItemList[cnt].mmLeft := Exte;
//mmTop :Extended;
FS.Read(Exte,SizeOf(Extended));
ItemList[cnt].mmTop := Exte;
//mmWidth :Extended;
FS.Read(Exte,SizeOf(Extended));
ItemList[cnt].mmWidth := Exte;
//mmHeight :Extended;
FS.Read(Exte,SizeOf(Extended));
ItemList[cnt].mmHeight := Exte;
//FontName :String;
FS.Read(Len,SizeOf(Len));
StrMem := StrAlloc(Len);
FS.Read(StrMem^,Len);
ItemList[cnt].FontName := StrMem;
//FontStyle :TFontStyles;
FS.Read(Inte,SizeOf(Integer));
Len := Inte;
ItemList[cnt].FontStyle := TFontStyles(Len);
//FontSize :Integer;
FS.Read(Inte,SizeOf(Integer));
ItemList[cnt].FontSize := Inte;
//FontColor :TColor;
FS.Read(Inte,SizeOf(Integer));
ItemList[cnt].FontColor := TColor(Inte);
//Alignment :Integer;//0左寄せ、1中寄せ、2右寄せ
FS.Read(Inte,SizeOf(Integer));
ItemList[cnt].Alignment := Inte;
//Shape :TShapeType;
FS.Read(Inte,SizeOf(Integer));
ItemList[cnt].Shape := TShapeType(Inte);
//PenStyle :TPenStyle;
FS.Read(Inte,SizeOf(Integer));
ItemList[cnt].PenStyle := TPenStyle(Inte);
//PenWidth :Integer;
FS.Read(Inte,SizeOf(Integer));
ItemList[cnt].PenWidth := Inte;
//PenColor :TColor;
FS.Read(Inte,SizeOf(Integer));
ItemList[cnt].PenColor := TColor(Inte);
//BrushStyle :TBrushStyle;//文字サイズor線の太さ
FS.Read(Inte,SizeOf(Integer));
ItemList[cnt].BrushStyle := TBrushStyle(Inte);
//BrushColor :TColor;
FS.Read(Inte,SizeOf(Integer));
ItemList[cnt].BrushColor := TColor(Inte);
//CornerRound:Integer;
FS.Read(Inte,SizeOf(Integer));
ItemList[cnt].CornerRound := Inte;
//縦横
FS.Read(Inte,SizeOf(Integer));
ItemList[cnt].Orientation := Inte;
//セル幅
FS.Read(Exte,SizeOf(Extended));
ItemList[cnt].CellWidth := Exte;
//セル高
FS.Read(Exte,SizeOf(Extended));
ItemList[cnt].CellHeight := Exte;
//送り幅
FS.Read(Exte,SizeOf(Extended));
ItemList[cnt].SendWidth := Exte;
//送り高
FS.Read(Exte,SizeOf(Extended));
ItemList[cnt].SendHeight := Exte;
//列
FS.Read(Inte,SizeOf(Integer));
ItemList[cnt].BlockCol := Inte;
//行
FS.Read(Inte,SizeOf(Integer));
ItemList[cnt].BlockRow := Inte;
//ロック
FS.Read(Bool,SizeOf(Boolean));
ItemList[cnt].Lock := Bool;

end;
FS.Read(Bool,SizeOf(Boolean));
if Bool = False then
BGMetaFile.LoadFromStream(FS);

FS.Free;
except
FS.Free;
ShowMessage('読み込みに失敗しました。');
end;
end;


※Nameは、印刷に必要ありません。
※Lockは、印刷に必要ありません。
印刷サンプルコード
ここから先は、自由にコーディングしてもらってかまいませんが、一応自分なりにフォーマットがあるんで紹介します。
あまり美しくないかもしれませんが、参考にしてください。
//実行部
var
dpiX,dpiY,PaperPixelX,PaperPixelY,OffsetX,OffsetY:Integer;//デバイス情報格納
cnt,CopyCnt:integer;//ループ回し
ItemT,ItemL,ItemB,ItemR:integer;//
DotX,DotY:Extended;//1mmあたりのドット数
LastPage,SplitLine:Integer;
StartLine,LastLine:Integer;

begin
if PrinterDialog.Execute then
begin
BGMetafile := TMetaFile.Create;
//レイアウトを読み込む
LoadStream;

//印刷準備
OffsetX := GetDeviceCaps(Printer.Handle, PHYSICALOFFSETX);
OffsetY := GetDeviceCaps(Printer.Handle, PHYSICALOFFSETY);

SplitLine := ItemList[0].BlockCol * ItemList[0].BlockRow;
LastPage := (StringGrid.RowCount - 1) div SplitLine + 1;

try
//印刷開始///////////////////////////////////////////////////////////////////////////////////////////
Printer.BeginDoc;
try
//部数毎印字
if PrinterDialog.Collate then
for CopyCnt := 1 to PrinterDialog.Copies do
begin
for cnt := PrinterDialog.FromPage to PrinterDialog.ToPage do
begin


StartLine := (cnt - 1) * SplitLine + 1;
If LastPage := cnt then
LastLine := (cnt - 1) * SplitLine + 1
else
LastLine := SplitLine * cnt;
Printer.Canvas.Draw(-OffsetX,-OffsetY,GetPrintMetaFile(cnt,LastPage,StartLine,LastLine));


if cnt < frmMain.dlgPrinter.ToPage then
Printer.NewPage;
end;
if CopyCnt < PrinterDialog.Copies then
Printer.NewPage;
end
else
//
for cnt := PrinterDialog.FromPage to PrinterDialog.ToPage do
begin
for CopyCnt := 1 to PrinterDialog.Copies do
begin
StartLine := (cnt - 1) * SplitLine + 1;
If LastPage := cnt then
LastLine := (cnt - 1) * SplitLine + 1
else
LastLine := SplitLine * cnt;
Printer.Canvas.Draw(-OffsetX,-OffsetY,GetPrintMetaFile(cnt,LastPage,StartLine,LastLine));
if CopyCnt < PrinterDialog.Copies then
Printer.NewPage;
end;
if cnt < PrinterDialog.ToPage then
Printer.NewPage;
end;

except
Printer.Abort;
raise;
end;
Printer.EndDoc;
////////////////////////////////////////////////////////////////////////////////////////////////////

finally
BGMetaFile.Free;//解放
end;
end;

プレビューサンプルコード
 

//宣言部
type TOptionFormCreate = function(hWnd:THandle;mmX,mmY,Page:Integer;PrintList:TMemoryStream):WordBool; stdcall;


//実行部
(今回は単ページ印刷)
var
PreviewCreate:TOptionFormCreate;//DLLフォームの呼び出し用
GetModule:HMODULE;
MS:TMemoryStream;
CurrentPage,LastPage,SplitLine:Integer;

begin
BGMetafile := TMetaFile.Create;
LoadStream;
//DLL取得
GetModule := LoadLibrary('PrintUtility.dll');
MS := TMemoryStream.Create;
MS.Position := 0;//書き出しリセット

//印刷範囲を決める
CurrentPage := 1;//用意するページ
SplitLine := 1;//1ページ内の縦横合わせたループ回数
LastPage := 1;//最終ページ
GetPrintMetaFile(CurrentPage,LastPage,SplitLine,1).SaveToStream(MS);//読み込んだ印刷用メタファイルをストリームに変換

MS.Position := 0;//カーソルを戻す
if GetModule <> 0 then
try
if (GetProcAddress(GetModule,'PreviewCreate') <> Nil) and (FindWindow(Nil,'印刷プレビュー') = 0) then
begin
@PreviewCreate := GetProcAddress(GetModule,'PreviewCreate');
PreviewCreate(Application.Handle,Round(ItemList[0].mmWidth),Round(ItemList[0].mmHeight),LastPage,MS);
end;
finally
MS.Free;
BGMetaFile.Free;
end
else
Exit;


end;

////////////////////////////////////////////////////////////////////////////////////////////////////////
//実行部(今回は10ページ印刷
var
PreviewCreate:TOptionFormCreate;
GetModule:HMODULE;
MS:TMemoryStream;
cnt,LastPage,SplitLine:Integer;

begin
BGMetafile := TMetaFile.Create;
LoadStream;
//DLL取得
GetModule := LoadLibrary('PrintUtility.dll');
MS := TMemoryStream.Create;
MS.Position := 0;//書き出しリセット

//印刷範囲を決める
SplitLine := ItemList[0].BlockCol * ItemList[0].BlockRow;//TPrintData配列0のトリック情報から1ページ内のループ回数を計算
LastPage := 10;

for cnt := 1 to LastPage do
begin
GetPrintMetaFile(cnt,LastPage,SplitLine,0).SaveToStream(MS);//読み込んだ印刷用メタファイルをストリームに変換
end;

MS.Position := 0;
if GetModule <> 0 then
try
if (GetProcAddress(GetModule,'PreviewCreate') <> Nil) and (FindWindow(Nil,'印刷プレビュー') = 0) then
begin
@PreviewCreate := GetProcAddress(GetModule,'PreviewCreate');
PreviewCreate(Application.Handle,Round(ItemList[0].mmWidth),Round(ItemList[0].mmHeight),LastPage,MS);
end;
finally
MS.Free;
BGMetaFile.Free;
end
else
Exit;

end;

メタファイル生成コード(親)
Takeは、まずメタファイルに印刷情報をすべてメタファイルに書き出してから、プレビューや印刷するときに印刷用キャンバスにDrawしています。
下のコードは、配列0で設定した共通回数のループを行う場合のコードです。
もし、アイテムのそれぞれに別のループ回数があるようなら下のコードでは対応できません。

GetPrintMetaFile(NowPage,Lastpage,StartLine,LastLine:Integer):TMetafile;
NowPage ノンブルを描画したり、ループ中の内容を計算するため
LastPage PageとLastPageを比べて最後にトータル計算を記述できるから
StartLine ループの最初の入力行
LastLine ループの最後の入力行
TMetaFile 仕上がったメタファイルをお返しします。

※Modeの引数はあくまで複数のレポートを同一処理内で行う場合の仕分けようですから、いらない場合は削除して使ってください。
  TakeはGetPrintMetafaile内で単ページ作成と複数リストページを行うのでModeのような引数が必要でした。
//宣言部
function GetPrintMetaFile(Page,LastPage,StartLine,LastLine:Integer):TMetaFile;

//実行部

function GetPrintMetaFile(Page,LastPage,StartLine,LastLine:Integer):TMetaFile;
var
MergeMF:TMetaFile;//統合メタファイル
DC:HDC;//デバイスコンテキスト
dpiX,dpiY:Integer;//ドットパーインチ
DotX,DotY:Extended;//1mmあたりのドット数
cnt,cntRow,cntCol:Integer;//
ItemT,ItemL,ItemB,ItemR:integer;//矩形範囲ベース
FieldRect:TRect;//矩形範囲
ExportText:String;//出力文字
StartLine,LastLine:Integer;//

MC:TMetaFileCanvas;
begin
////////////////////////////////////////////////////////////////////////////////
//メタファイル中間集約

MergeMF := TMetaFile.Create;
//メタファイルの解像度
DC := GetDC(0);//デバイスコンテキスト取得
MergeMF.Inch := 0;
dpiX := GetDeviceCaps(DC, LOGPIXELSX);
dpiY := GetDeviceCaps(DC, LOGPIXELSY);
//1mmあたりのドット数
DotX := dpiX / 25.4;
DotY := dpiY / 25.4;
//フォント重視でサイズ決定
//フォントサイズはそのまま使用

MergeMF.Height := Round(ItemList[0].mmHeight * DotY);
MergeMF.Width := Round(ItemList[0].mmWidth * DotX);

//メタファイルキャンバスの用意
MC := TMetafileCanvas.Create(MergeMF, 0);

//////////////////////////////////////////////////////////////////////////////
//描画

with MC do
try
//↓背景を記述する部分ここから
if BGMetaFile.PaletteModified = false then
Draw(0,0,,BGMetaFile);
//↑背景を記述する部分ここまで
for cnt := 1 to ItemRange - 1 do//プリント配列に対してキー読み出しループ
begin

//↓ループを使わない描画コードはこの辺に書く
if ItemList[cnt].KeyName = 'IMAGE' then
DrawImageProportional(MC,cnt,1,1,Image.Picture.Graphic.Width,Image.Picture.Graphic.Height,DotX,DotY,Image.Picture);

//↑ループ使わない描画

//トリックループ開始
for cnt := StartLine to LastLine do
begin

//ずらし処理カウンタ
//0行目台紙用のトリック情報を共通ループ回数として使用
if ItemList[0].Orientation = 0 then
//縦
begin
cntRow := cnt mod ItemList[0].BlockRow;
cntCol := cnt div ItemList[0].BlockRow + 1;
end
else
//横
begin
cntRow := cnt div ItemList[0].BlockCol;
cntCol := cnt mod ItemList[0].BlockCol + 1;
end;

//個別に描画
if ItemList[cnt].KeyName = 'ZIP' then//検索文字を照会
WriteText(MC,cnt,cntCol,cntRow,DotX,DotY,frmItemInfo.lblLot.Caption); //子手続きにキャンバスを渡して、描画させる

if ItemList[cnt].KeyName = 'MEMO' then
WriteMemo(MC,cnt,cntCol,cntRow,DotX,DotY,Memo.Text);


end;//ループ終了
//描画終了
finally
Free;
Result := MergeMF;//返り血にメタファイルを返す。
end;
end;
メタファイル生成コード(子)
文字列やメモ形式、画像などの描画を仕分けて描画させます。
//宣言部
procedure WriteText(MetaCanvas:TMetafileCanvas;Line,Col,Row:Integer;DotX,DotY:Extended;ExportStr:String);
procedure WriteMemo(MetaCanvas:TMetafileCanvas;Line,Col,Row:Integer;DotX,DotY:Extended;ExportStr:String);
procedure DrawImageProportional(MetaCanvas:TMetafileCanvas;Line,Col,Row,iWidth,iHeight:Integer;DotX,DotY:Extended;ExportImg:TPicture);

//実行部
//文字とシェイプ描画コード//////////////////////////////////////////////////////////////////////////////////////
//指定されたトリック情報セルサイズ・送りサイズを意識しながら文字やシェイプを描画します。
//一番オーソドックスなコードです。

procedure WriteText(MetaCanvas:TMetafileCanvas;Line,Col,Row:Integer;DotX,DotY:Extended;ExportStr:String);
var
FieldRect:TRect;//矩形範囲
ItemT,ItemL,ItemB,ItemR:integer;//矩形範囲ベース
begin
with MetaCanvas do
begin
ItemT := Round((ItemList[Line].SendHeight * (Row - 1) + ItemList[Line].mmTop) * DotY);
ItemB := Round((ItemList[Line].SendHeight * (Row - 1) + ItemList[Line].CellHeight + ItemList[Line].mmTop) * DotY);
ItemL := Round((ItemList[Line].SendWidth * (Col - 1) + ItemList[Line].mmLeft) * DotX);
ItemR := Round((ItemList[Line].SendWidth * (Col - 1) + ItemList[Line].CellWidth + ItemList[Line].mmLeft) * DotX);
FieldRect := Rect(ItemL,ItemT,ItemR,ItemB);
Pen.Style := ItemList[Line].PenStyle;
Pen.Color := ItemList[Line].PenColor;
Pen.Width := ItemList[Line].PenWidth;
Brush.Style := ItemList[Line].BrushStyle;
Brush.Color := ItemList[Line].BrushColor;
//シェイプの描画
case ItemList[Line].Shape of
stRectAngle:Rectangle(FieldRect);
stEllipse:Ellipse(FieldRect);
stRoundRect:RoundRect(ItemL,ItemT,ItemR,ItemB,ItemList[Line].CornerRound,ItemList[Line].CornerRound);
else
Brush.Style := bsClear;
end;
//文字の描画
Font.Name := ItemList[Line].FontName;
Font.Style:= ItemList[Line].FontStyle;
Font.Color:= ItemList[Line].FontColor;
Font.Size := ItemList[Line].FontSize;
case ItemList[Line].Alignment of
0:DrawTextEX(Handle,PChar(ExportStr),Length(PChar(ExportStr)),FieldRect,DT_SINGLELINE + DT_VCENTER + DT_LEFT,Nil);
1:DrawTextEX(Handle,PChar(ExportStr),Length(PChar(ExportStr)),FieldRect,DT_SINGLELINE + DT_VCENTER + DT_CENTER,Nil);
2:DrawTextEX(Handle,PChar(ExportStr),Length(PChar(ExportStr)),FieldRect,DT_SINGLELINE + DT_VCENTER + DT_RIGHT,Nil);
end;
end;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//メモ帳形式の描画コード
//文字の描画を長方形の左上から開始して、横幅を超えると自動的に改行します。

procedure WriteMemo(MetaCanvas:TMetafileCanvas;Line,Col,Row:Integer;DotX,DotY:Extended;ExportStr:String);
var
FieldRect:TRect;//矩形範囲
ItemT,ItemL,ItemB,ItemR:integer;//矩形範囲ベース
begin
with MetaCanvas do
begin
ItemT := Round((ItemList[Line].SendHeight * (Row - 1) + ItemList[Line].mmTop) * DotY);
ItemB := Round((ItemList[Line].SendHeight * (Row - 1) + ItemList[Line].CellHeight + ItemList[Line].mmTop) * DotY);
ItemL := Round((ItemList[Line].SendWidth * (Col - 1) + ItemList[Line].mmLeft) * DotX);
ItemR := Round((ItemList[Line].SendWidth * (Col - 1) + ItemList[Line].CellWidth + ItemList[Line].mmLeft) * DotX);
FieldRect := Rect(ItemL,ItemT,ItemR,ItemB);
Pen.Style := ItemList[Line].PenStyle;
Pen.Color := ItemList[Line].PenColor;
Pen.Width := ItemList[Line].PenWidth;
Brush.Style := ItemList[Line].BrushStyle;
Brush.Color := ItemList[Line].BrushColor;
//シェイプの描画
case ItemList[Line].Shape of
stRectAngle:Rectangle(FieldRect);
stEllipse:Ellipse(FieldRect);
stRoundRect:RoundRect(ItemL,ItemT,ItemR,ItemB,ItemList[Line].CornerRound,ItemList[Line].CornerRound);
else
Brush.Style := bsClear;
end;
//文字の描画
Font.Name := ItemList[Line].FontName;
Font.Style:= ItemList[Line].FontStyle;
Font.Color:= ItemList[Line].FontColor;
Font.Size := ItemList[Line].FontSize;
DrawTextEx(Handle, PChar(ExportStr), -1,FieldRect,DT_LEFT or DT_WORDBREAK,nil);
end;
end;

//画像描画コード//////////////////////////////////////////////////////////////////////////////////////////////
//指定された長方形内に、画像を縦横比率を合わせて縮小します。

procedure DrawImageProportional(MetaCanvas:TMetafileCanvas;Line,Col,Row,iWidth,iHeight:Integer;DotX,DotY:Extended;ExportImg:TPicture);
var
FieldRect:TRect;//矩形範囲
ItemT,ItemL,ItemB,ItemR:integer;//矩形範囲ベース
Ratio,RatioX,RatioY:Extended;
CenterX,CenterY:Integer;
begin
with MetaCanvas do
begin
//倍率設定
RatioX := iWidth / (ItemList[Line].CellWidth * DotX);//800
RatioY := iHeight / (ItemList[Line].CellHeight * DotY);//600
if RatioX > RatioY then
Ratio := RatioX
else
Ratio := RatioY;
//中心軸
CenterX := Round((ItemList[Line].mmLeft + (ItemList[Line].CellWidth / 2)) * DotX);
CenterY := Round((ItemList[Line].mmTop + (ItemList[Line].CellHeight / 2)) * DotY);
//位置決定

ItemT := CenterY - Round(iHeight / 2 / Ratio);
ItemB := CenterY + Round(iHeight / 2 / Ratio);
ItemL := CenterX - Round(iWidth / 2 / Ratio);
ItemR := CenterX + Round(iWidth / 2 / Ratio);
FieldRect := Rect(ItemL,ItemT,ItemR,ItemB);

MetaCanvas.StretchDraw(FieldRect,ExportImg.Graphic);
end;
end;
///////////////////////////////////////////////////////////////////////////////////////////////////////////


自身のソフトからの移植なんで、コンポーネント名称の書き換えに不備があるかもしれません。
ご了承ください。

Copyright 2011 studio-take All Rights Reserved.