【A5】Delphi/C++Builderテクニカルセッション「知って得する！現役ヘルプデスクが答える
Delphiテクニカルエッセンス 2.0」
株式会社ミガロ
RAD事業部 技術支援課 顧客サポート
吉原 泰介

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

1

アジェンダ
• ミガロについて• 問合せ分析• よくある問合せQ&A【Q1】DBGridで簡単にソートを行いたい！
【Q2】VB-Report Ver3.0で効率よく出力したい！
【Q3】TreeViewでメニューを制御したい！
【Q4】一覧明細にローカル画像を表示したい！
【Q5】StringGridで文字列を縦表示したい！
• サポートより
本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

21

ミガロについて
株式会社ミガロ －A 100% System i Company－
会社情報
会社情報
所在地：本社 大阪市浪速区湊町2-1-57

所在地：本社 大阪市浪速区湊町2-1-57
難波サンケイビル13F
難波サンケイビル13F
拠点 東京都港区麻布台1-4-3
拠点エグゼクティブタワー麻布台11F
東京都港区麻布台1-4-3
エグゼクティブタワー麻布台11F
事業内容
事業内容
IBM System i 向けのソフトウェア・ツール販売および技術サポート
IBM System i 向けのソフトウェア・ツール販売および技術サポート【開発ツール】【災害対策ソフト】【開発ツール】【災害対策ソフト】
・Delphi/400
・*noMAX・Delphi/400
・*noMAX・JACi400
・JACi400【アプリケーション･ライフサイクル・マネージメント】【アプリケーション･ライフサイクル・マネージメント】
・MKS
・MKS

Delphi/400
DelphiをSystem iに完全対応させたミドルウェア
国内約570社、全世界約5,000社の導入実績

3

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

問合せ分析(コンポーネント)
サポートには月100件弱の問合せや個別技術サポート
Delphi問合せ内容比率【その他1%未満】32%

TDBGrid 16%

コンポーネント別集計

ｺﾝﾎﾟｰﾈﾝﾄ作成
2%

ｻｰﾄﾞﾊﾟｰﾃｨ

TClientDataSet10%

12%

環境・他連携21%

ﾌﾟﾛｸﾞﾗﾑ方法
65%

TStringGrid 8%【プログラム方法】のうちコンポーネントの使い方などの問合せが7割弱。

TMemoEdit
TDateTimePicker
TDBChart
TImage

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

2%
2%
2%
2%

TQuery 8%
TDatabase
4%
TSQLDataSet 4%
TDBEdit4%

TTable 6%42

【Q1】 DBGridで簡単にソートを行いたい！
• 【質問】DBGridの明細をマウスクリックで並び替えができますか？
DBGridの明細をマウスクリックで並び替えができますか？

• 【回答】
OnTitleClickイベントでＣｌｉｅｎｔＤａｔａSetのindexをOnTitleClickイベントでＣｌｉｅｎｔＤａｔａSetのindexを操作することで画面上からのソート機能を持たせる
操作することで画面上からのソート機能を持たせる
ことができます。
ことができます。

5

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

【Q1】 DBGridで簡単にソートを行いたい！
自動ソートの仕組み
自動ソートの仕組み
Field1▲ Field2

Field3Fie ld4▼ Field5

Field6

タイトルクリックイベント

ClientDataSet
ClientDataSet
IndexDefs①【解除状態の場合】ｸﾘｯｸされたField名を昇順のためFieldsに追加③【降順状態の場合】ｸﾘｯｸされたField名を両方のリストから削除
本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

FieldsDescFields

Field1

Field4

Field4・・・

・・・②【昇順状態の場合】ｸﾘｯｸされたField名を降順のためDescFieldsに追加
63

【Q1】 DBGridで簡単にソートを行いたい！
OnTitleClick処理
procedure Tfrm1.DBGrid1TitleClick(Column: TColumn);
varsFieldNM :String; //退避フィールド名begin
with DBGrid1 do
begin// 明細非表示時は処理無効
if DataSource.DataSet.Active = False then Exit;// カラムのフィールド名を退避
sFieldNM := Column.FieldName;with (DataSource.DataSet as TClientDataSet) do
begin// インデックスフィールド作成
if IndexDefs.Count = 0 thenIndexDefs.Add('aIndex', '', []);②【昇順状態の場合】ｸﾘｯｸされたField名を//----------------------------//
降順のためDescFieldsに追加// 明細の表題／並び替えの制御 ////----------------------------//
if AnsiPos('▲', Column.Title.Caption) <> 0 thenbegin// ----- 降順へ ----// 表題設定
Column.Title.Caption :=StringReplace(Column.Title.Caption, '▲', '', [rfReplaceAll]);
Column.Title.Caption := Column.Title.Caption + '▼';// 降順フィールドの設定
if IndexDefs[0].DescFields = '' thenIndexDefs[0].DescFields := sFieldNM
else
IndexDefs[0].DescFields := IndexDefs[0].DescFields + ';' + sFieldNM;// インデックスフィールドのオプション初期化③【降順状態の場合】
IndexDefs[0].Options := [];ｸﾘｯｸされたField名をend
else if AnsiPos('▼', Column.Title.Caption) <> 0 then
両方のリストから削除
begin// ----- 設定解除 ----// 表題設定
Column.Title.Caption :=StringReplace(Column.Title.Caption, '▼', '', [rfReplaceAll]);7

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

【Q1】 DBGridで簡単にソートを行いたい！
// 並び順の設定解除（降順フィールド）if AnsiPos(sFieldNM + ';', IndexDefs[0].DescFields) <> 0 thensFieldNM := sFieldNM + ';'else if AnsiPos(';' + sFieldNM, IndexDefs[0].DescFields) <> 0 thensFieldNM := ';' + sFieldNM;
IndexDefs[0].DescFields := StringReplace(IndexDefs[0].DescFields,sFieldNM, '', [rfReplaceAll]);// カラムのフィールド名を再取得
sFieldNM := Column.FieldName;// 並び順の設定解除（昇順フィールド）if AnsiPos(sFieldNM + ';', IndexDefs[0].Fields) <> 0 thensFieldNM := sFieldNM + ';'else if AnsiPos(';' + sFieldNM, IndexDefs[0].Fields) <> 0 thensFieldNM := ';' + sFieldNM;
IndexDefs[0].Fields :=StringReplace(IndexDefs[0].Fields, sFieldNM, '‘, rfReplaceAll]);// 並び替え完全解除の場合インデックス名クリア
if IndexDefs[0].Fields = '' then IndexName := '';// インデックスフィールドのオプション初期化
IndexDefs[0].Options := [];end

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

①【解除状態の場合】
else
ｸﾘｯｸされたField名をbegin
昇順のためFieldsに追加// ----- 昇順へ ----// 表題設定
Column.Title.Caption := Column.Title.Caption + '▲';// 昇順フィールドの設定
if IndexDefs[0].Fields = '' thenIndexDefs[0].Fields := sFieldNM
else
IndexDefs[0].Fields := IndexDefs[0].Fields + ';' + sFieldNM;// インデックスフィールドのオプション初期化
IndexDefs[0].Options := [];// インデックス名設定
if IndexName = '' then IndexName := 'aIndex';
end;//データを開いたままソートを適用させるため//Indexを削除して再設定
DeleteIndex('aIndex');IndexName := 'aIndex';
First;
end;
end;
end;

8

4

ご参考資料【Q1】 DBGridで簡単にソートを行いたい！ － C++Builder版
OnTitleClick処理
void __fastcall Tfrm1::DBGrid1TitleClick(TColumn *Column){
AnsiString sFieldNM; //退避フィールド名②【昇順状態の場合】ｸﾘｯｸされたField名を//----------------------------//
降順のためDescFieldsに追加// 明細の表題／並び替えの制御 ////----------------------------//
if(AnsiPos("▲", Column->Title->Caption) != 0) {// ----- 降順へ ----// 表題設定
Column->Title->Caption = StringReplace(Column->Title->Caption, "▲", "",TReplaceFlags() << rfReplaceAll);
Column->Title->Caption = Column->Title->Caption + "▼";// 降順フィールドの設定
if(cds->IndexDefs->Items[0]->DescFields == "")cds->IndexDefs->Items[0]->DescFields = sFieldNM;
else
cds->IndexDefs->Items[0]->DescFields =cds->IndexDefs->Items[0]->DescFields + ";" + sFieldNM;// 明細非表示時は処理無効
if(DBGrid1->DataSource->DataSet->Active == false)
return;// カラムのフィールド名を退避
sFieldNM = Column->FieldName;
TClientDataSet* cds =(TClientDataSet*)(DBGrid1->DataSource->DataSet);// インデックスフィールド作成
if(cds->IndexDefs->Count == 0)
cds->IndexDefs->Add("aIndex", "", TIndexOptions());// インデックスフィールドのオプション初期化
cds->IndexDefs->Items[0]->Options = TIndexOptions();}
else if(AnsiPos("▼", Column->Title->Caption) != 0) {// ----- 設定解除 ----③【降順状態の場合】// 表題設定ｸﾘｯｸされたField名をColumn->Title->Caption =両方のリストから削除
StringReplace(Column->Title->Caption,"▼", "", TReplaceFlags() << rfReplaceAll);

9

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

ご参考資料【Q1】 DBGridで簡単にソートを行いたい！ － C++Builder版// 並び順の設定解除（降順フィールド）if(AnsiPos(sFieldNM + ";", cds->IndexDefs->Items[0]->DescFields) != 0)sFieldNM = sFieldNM + ";";
else if(AnsiPos(";" + sFieldNM, cds->IndexDefs->Items[0]->DescFields) != 0)sFieldNM = ";" + sFieldNM;①【解除状態の場合】ｸﾘｯｸされたField名をelse {
昇順のためFieldsに追加// ----- 昇順へ ----// 表題設定
Column->Title->Caption = Column->Title->Caption + "▲";

cds->IndexDefs->Items[0]->DescFields =StringReplace(cds->IndexDefs->Items[0]->DescFields, sFieldNM, "",TReplaceFlags() << rfReplaceAll);// 昇順フィールドの設定
if(cds->IndexDefs->Items[0]->Fields == "")cds->IndexDefs->Items[0]->Fields = sFieldNM;
else
cds->IndexDefs->Items[0]->Fields =cds->IndexDefs->Items[0]->Fields + ";" + sFieldNM;// カラムのフィールド名を再取得
sFieldNM = Column->FieldName;// 並び順の設定解除（昇順フィールド）if(AnsiPos(sFieldNM + ";",
AnsiString(cds->IndexDefs->Items[0]->Fields)) != 0)sFieldNM = sFieldNM + ";";
else if(AnsiPos(";" + sFieldNM,
AnsiString(cds->IndexDefs->Items[0]->Fields)) != 0)sFieldNM = ";" + sFieldNM;
cds->IndexDefs->Items[0]->Fields =StringReplace(cds->IndexDefs->Items[0]->Fields, sFieldNM, "",TReplaceFlags() << rfReplaceAll);// 並び替え完全解除の場合インデックス名クリア
if(cds->IndexDefs->Items[0]->Fields == "") cds->IndexName = "";}// インデックスフィールドのオプション初期化
cds->IndexDefs->Items[0]->Options = TIndexOptions();

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

// インデックスフィールドのオプション初期化
cds->IndexDefs->Items[0]->Options = TIndexOptions();// インデックス名設定
if(cds->IndexName == "") cds->IndexName = "aIndex";}//データを開いたままソートを適用させるため//Indexを削除して再設定
cds->DeleteIndex("aIndex");cds->IndexName = "aIndex";
cds->First();
}

10

5

【Q2】VB-Report Ver3.0で効率よく出力したい！
• 【質問】

アドバンスソフトウェア株式会社 http://www.adv.co.jp/
アドバンスソフトウェア株式会社 http://www.adv.co.jp/

VB-Report
VB-ReportVer3.0を使用して帳票・Excelの出力をしてVer3.0を使用して帳票・Excelの出力をしていますが、パフォーマンスを見直すにはどうしたら良いいますが、パフォーマンスを見直すにはどうしたら良いでしょうか？
でしょうか？

• 【回答】
VB-Report
VB-ReportVer3.0の出力パフォーマンスにはフォーマット
Ver3.0の出力パフォーマンスにはフォーマット
となるExcel自体が大きく影響します。
となるExcel自体が大きく影響します。
セル数や属性設定などを見直すことでパフォーマンス
セル数や属性設定などを見直すことでパフォーマンス
を向上させることができます。
を向上させることができます。
本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

11【Q2】VB-Report Ver3.0で効率よく出力したい！
フォーマットExcelと扱いの考慮点
フォーマットExcelと扱いの考慮点①Cellの属性や設定はフォーマット側で事前に設定する。
①Cellの属性や設定はフォーマット側で事前に設定する。
②フォーマット内の情報を少なくする。
②フォーマット内の情報を少なくする。
Cell数、書式、属性、結合、罫線、網掛等
Cell数、書式、属性、結合、罫線、網掛等③可能であれば固定（A1参照や座標）形式で指定する。
③可能であれば固定（A1参照や座標）形式で指定する。
変数指定の場合、変数の位置検索が行われるため、変数指定の場合、変数の位置検索が行われるため、通常の固定指定よりもパフォーマンスが落ちます。
通常の固定指定よりもパフォーマンスが落ちます。
本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

126

【Q2】VB-Report Ver3.0で効率よく出力したい！
フォーマットExcelと扱いの考慮点
フォーマットExcelと扱いの考慮点④位置指定で変数を使用する場合④位置指定で変数を使用する場合
先頭（或いは前処理）行から小さい行、小さい列の順に先頭（或いは前処理）行から小さい行、小さい列の順に処理を行う。
処理を行う。
変数位置検索** A1* * B1

* *C1

** D1

* *E1

** A2

* * B2

* *C2

** D2

* *E2

** A3

* * B3

* *C3

** D3

* *E3

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

13【Q3】TreeViewでメニューを制御したい！
• 【質問】
メニュー内容をDB上のファイルで動的に構成できない
メニュー内容をDB上のファイルで動的に構成できないでしょうか？
でしょうか？

• 【回答】
メニューの作成手法はいろいろありますが、メニューの作成手法はいろいろありますが、
TreeViewを使用すると見やすいメニューを動的制御する
TreeViewを使用すると見やすいメニューを動的制御することができます。
ことができます。

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

147

【Q3】 TreeViewでメニューを制御したい！
Tree
TreeView
View

メニュー管理ファイル
メニュー管理ファイル

マスタ管理
マスタ登録
社員マスタ登録
顧客マスタ登録
商品マスタ登録コード010 000
010 100
010 101
010 102010 103010 200
010 201

タイトル
マス タ管理マス タ登録
社員マスタ登録
顧客マスタ登録
商品マスタ登録マス タ修正
社員マスタ修正

呼出PGM

MAS0 11.EXE
MAS0 21.EXE
MAS0 31.EXE
MAS0 12.EXE

コード順に読み込んでタイトルと起動するプロ
グラムをTreeViewにノードとして追加していく。
コードのルールでノードの親子をブレイクする。

マスタ修正
・・・

クリックされるとノード情報の呼出PGMを元にCreateProcess等で対象を起動

15

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

【Q3】 TreeViewでメニューを制御したい！
～～～～～～type
PTVRec = ^TTVRec;
TTVRec = record
EXENM: string;end;～～～～～～

ノード制御処理

procedure TfrmQ3.LoadMenu;
var
TopNode : TTreeNode;//追加されたトップノード
ChdNode1: TTreeNode;//追加された子ノード
ChdNode2: TTreeNode;//追加された孫ノード
TVRecPtr: PTVRec;//ノード情報
BrkCd1 : string;//大区分
BrkCd2 : string;//中区分
Title : string;//タイトル
MenuCD : string;//メニューコード
begin//既存のノードを削除
TreeView1.Items.Clear;

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

//初期設定TopNode := nil;
BrkCd1 := '';BrkCd2 := '';//ファイルより追加
with Datamodule1.CdsMenu do
begin
First;
while not eof do
begin//データをセット
New(TVRecPtr);
ノード情報整理//データレコードからノード情報を取得
MenuCD:= ‘メニューコード’;Title:= ‘メニュー上の名称’;
TVRecPtr^.EXENM := ‘メニューからの呼び出すPGM’;

168

【Q3】 TreeViewでメニューを制御したい！
//トップノード
1階層ノード追加
if Copy(MenuCD,1,2) <> BrkCd1 then
begin
TopNode := TreeView1.Items.AddChildObject(nil,Title,TVRecPtr);
end
else
begin
2階層ノード追加
if Copy(MenuCD,3,2) <> BrkCd2 then//子ノードbegin//ノード追加
ChdNode1 := TreeView1.Items.AddChildObject(TopNode,Title,TVRecPtr);
end
else//孫ノードbegin
3階層ノード追加//中分類'00'のとき、親ノードがトップノード
if Copy(MenuCD,3,2) = '00' then
ChdNode1 := TopNode;
ChdNode2 := TreeView1.Items.AddChildObject(ChdNode1,Title,TVRecPtr);
end;
end;

ブレイク用にコード退避//大中分類退避
BrkCd1 := Copy(MenuCD,1,2);
BrkCd2 := Copy(MenuCD,3,2);//次データへ
Next;
end;First;
end;//全ノードを展開
TreeView1.FullExpand;end;

TreeViewのImagesプロパティでTImageListを設定して表示アイコンを持つことができます。
事前にアイコンと登録したり、実際の実行ファイル
からExtractIconを使用して動的にアイコンを取得・設定することも可能です。

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

17【Q3】 TreeViewでメニューを制御したい！
TreeViewの他の使用例
TreeViewの他の使用例
TreeViewは他にも体系的なデータの一覧検索照会画面などで利用することにより、ユーザーが見た目で使い易い画面にすることができます。

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

189

ご参考資料【Q3】 TreeViewでメニューを制御したい！ － C++Builder版～～～～～～
struct TTVRec {AnsiString EXENM;};
typedef TTVRec* PTVRec;～～～～～～

ノード制御処理

void __fastcall TfrmQ3::LoadMenu(){
TTreeNode* TopNode;//追加されたトップノード
TTreeNode* ChdNode1;//追加された子ノード
TTreeNode* ChdNode2;//追加された子ノード
PTVRec
TVRecPtr;//ノード情報
AnsiString BrkCd1;//大区分
AnsiString BrkCd2;//中区分
AnsiString Title;//タイトル
AnsiString MenuCD;//メニューコード
TClientDataSet* CdsMenu;//初期設定TopNode = NULL;
BrkCd1 = "";BrkCd2 = "";//ファイルより追加
CdsMenu = Datamodule1->CdsMenu;
CdsMenu->First();while( ! CdsMenu->Eof ) {//データをセット
TVRecPtr = new TTVRec();//データレコードからノード情報を取得
ノード情報整理
MenuCD= “メニューコード“;Title= “メニュー上の名称”;
TVRecPtr->EXENM = “ メニューから呼び出すPGM";//既存のノードを削除
TreeView1->Items->Clear();19

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

ご参考資料【Q3】 TreeViewでメニューを制御したい！ － C++Builder版
ブレイク用にコード退避
1階層ノード追加//トップノード
if( MidStr(MenuCD,1,2) != BrkCd1 ) {TopNode = TreeView1->Items->AddChildObject(NULL,Title,TVRecPtr);}
else {
2階層ノード追加
if( MidStr(MenuCD,3,2) != BrkCd2 ) {//子ノード//ノード追加
ChdNode1 = TreeView1->Items->AddChildObject(TopNode,Title,TVRecPtr);}
else {
3階層ノード追加//孫ノード//中分類'00'のとき、親ノードがトップノード
if( MidStr(MenuCD,3,2) == "00" )ChdNode1 = TopNode;}}

ChdNode2 = TreeView1->Items->AddChildObject(ChdNode1,Title,TVRecPtr);

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

//大中分類退避
BrkCd1 = MidStr(MenuCD,1,2);
BrkCd2 = MidStr(MenuCD,3,2);//次データへ
CdsMenu->Next();}
CdsMenu->First();}//全ノードを展開
TreeView1->FullExpand();

TreeViewのImagesプロパティでTImageListを設定して表示アイコンを持つことができます。
事前にアイコンと登録したり、実際の実行ファイル
からExtractIconを使用して動的にアイコンを取得・設定することも可能です。

20

10

【Q4】一覧明細にローカル画像を表示したい！
• 【質問】
ファイルサーバやローカルにある画像ファイルを一覧検索
ファイルサーバやローカルにある画像ファイルを一覧検索の明細に表示できますか？
の明細に表示できますか？

• 【回答】
DBのテーブル上にない画像を表示する場合、TImageを
DBのテーブル上にない画像を表示する場合、TImageを使用します。
使用します。DBCtrlGrid上で一覧明細として表示したい
DBCtrlGrid上で一覧明細として表示したい
場合は、OnPaintPanelイベントを利用することで実現が場合は、OnPaintPanelイベントを利用することで実現が
可能です。
可能です。
またScrollBoxを使用しても同様の内容は作成できます。
またScrollBoxを使用しても同様の内容は作成できます。
21

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

【Q4】一覧明細にローカル画像を表示したい！
OnPaintPanel処理
procedure Tfrm1.DBCtrlGrid1PaintPanel(DBCtrlGrid: TDBCtrlGrid; Index: Integer);
begin
with DBCtrlGrid.DataSource.DataSet do
begin
if not(Active) then Exit;//画像出力try//画像を読み込み(bmp画像)
Image1.Picture.LoadFromFile(‘フィールド内容で画像を指定’);
excepttry
Image1.Picture.LoadFromFile(‘対象画像ファイルがない場合の画像');
except
end;
end;
end;
end;

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

DBEditでDB上のデータと連動
描画処理でDB以外から随時画像を読込

2211【Q4】一覧明細にローカル画像を表示したい！
ScrollBoxで作成する場合
ScrollBoxで作成する場合
ScrollBox
ScrollBox
画像

Frame

生成

画像
画像

画像

生成
全てを動的に生成するの全てを動的に生成するのは手間がかかるので、は手間がかかるので、FrameでフォーマットをFrameでフォーマットを作成しておく
作成しておく生成

23

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

【Q4】一覧明細にローカル画像を表示したい！
ScrollBoxで作成する場合
ScrollBoxで作成する場合
複数の明細を用意しておけば複数の明細を用意しておけばデータによって扱うFrameを選択することもデータによって扱うFrameを選択することも
簡単です。
簡単です。

Frame１
画像

Frame２
画像

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

画像

画像

24

12

【Q5】 StringGridで文字列を縦表示したい！
• 【質問】
StringGridで表示される文字列を縦表示したいのですが、StringGridで表示される文字列を縦表示したいのですが、可能でしょうか？
可能でしょうか？

• 【回答】
OnDrawCellイベントで対象のフォントを回転させてOnDrawCellイベントで対象のフォントを回転させてTextOutやDrawtextで出力させることで縦描写を
TextOutやDrawtextで出力させることで縦描写を行うことができます。
行うことができます。

25

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

【Q5】 StringGridで文字列を縦表示したい！
フォントの回転フォントの回転回転したフォントを作成し、CanvasのFontに割り当てることで表示を調整します。

45度

90度

SingleByte文字とDoubleByte文字では縦書き用のフォントを使用す
ると回転による実際の向きが異なるので注意

270度

Single-Byte
ABCDEFGHIJ
MS ゴシック@MS ゴシック

MS ゴシック@MS ゴシック

MS ゴシック@MS ゴシック

Double-Byte
あいうえお

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

2613

【Q5】 StringGridで文字列を縦表示したい！
OnDrawCell処理//描画領域が持っているFontと入れ替えます。
NFont := CreateFontIndirect(LFont);
OFont := SelectObject(Canvas.Handle, NFont);
procedure TfrmQ5.StringGrid1DrawCell(Sender: TObject;//描画領域の内容をFillRectでクリアします。
ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
Canvas.FillRect(Rect);var//Fontが変更された状態で描画領域へ文字列を書込みます。
LFont: TLogFont;
Canvas.TextOut(CellRect(ACol, ARow).Left + 9,
NFont, OFont: HFont;
CellRect(ACol, ARow).top + 85,
begin
Cells[ACol, ARow]);with StringGrid1 do//入れ替えたFontを元に戻し、新たに設定したFont情報をbegin//開放します。
Canvas.Font.Size := 20;
NFont := SelectObject(Canvas.Handle, OFont);//Fontを取得し、回転させます。
DeleteObject(NFont);
GetObject(Canvas.Font.Handle, SizeOf(LFont), @LFont);
end;
with LFont do
フォントの回転調整
end;
begin
lfEscapement:= 900; //通常：0、左：900、右：2700
lfCharSet:= DEFAULT_CHARSET;
lfOutPrecision := OUT_DEFAULT_PRECIS;
lfClipPrecision := CLIP_DEFAULT_PRECIS;
縦書用フォント指定の場合、DoubleByte文字の回転方向がlfQuality:= DEFAULT_QUALITY;
DrawTextで出力する場合はSingleByte文字の回転と向きがlfPitchAndFamily := DEFAULT_PITCH;
DT_NOCLIPを指定する必要が若干異なります。
lfFaceName:= ‘@ＭＳ ゴシック’;
あります。
end;

27

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

ご参考資料【Q5】 StringGridで文字列を縦表示したい！ － C++Builder版
OnDrawCell処理
void __fastcall TfrmQ5::StringGrid1DrawCell(TObject *Sender,
int ACol, int ARow,
TRect &Rect, TGridDrawState State){
TLogFont LFont;
HFONT NFont, OFont;//描画領域が持っているFontと入れ替えます。
NFont = CreateFontIndirect(&LFont);
OFont = SelectObject(StringGrid1->Canvas->Handle, NFont);//描画領域の内容をFillRectでクリアします。
StringGrid1->Canvas->FillRect(Rect);//Fontが変更された状態で描画領域へ文字列を書き込みます。
StringGrid1->Canvas->TextOut(
StringGrid1->CellRect(ACol, ARow).Left + 9,
StringGrid1->CellRect(ACol, ARow).top + 85,
StringGrid1->Cells[ACol][ARow]);

StringGrid1->Canvas->Font->Size = 20;//入れ替えたFontを元に戻し、新たに設定したFont情報を解放します。
//Fontを取得し、回転させます。
NFont = SelectObject(StringGrid1->Canvas->Handle, OFont);
GetObject(
DeleteObject(NFont);
StringGrid1->Canvas->Font->Handle, sizeof(LFont), &LFont);}
LFont.lfEscapement= 900; //通常：0、左：900、右：2700
LFont.lfCharSet= DEFAULT_CHARSET;
LFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
フォントの回転調整
LFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
LFont.lfQuality= DEFAULT_QUALITY;
LFont.lfPitchAndFamily = DEFAULT_PITCH;
StrCopy(LFont.lfFaceName, "@ＭＳ ゴシック");

縦書用フォント指定の場合、DoubleByte文字の回転方向がSingleByte文字の回転と向きが若干異なります。

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

DrawTextで出力する場合は
DT_NOCLIPを指定する必要が
あります。

28

14

サポートより• 弊社ではIBM System i向けのソフトウェア・ツール販売および受託開発をしておりますが、Delphiという共通分野の情報は積極的にフィードバックしていきたいと考えています。
フィードバック
フィードバック
MIGARO
System i
System i
DB2/400
DB2/400
DBMS
DBMS

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

OracleInterBaseSQLServer
・・・

Delphi
Delphi29

15