大同特殊鋼健康保険組合...Title けんしんナビ申込手順_A4 Created Date 3/5/2019 5:54:10 PM
devcamp 20 A3.ppt [互換モード] -...
-
Upload
hoangthien -
Category
Documents
-
view
231 -
download
8
Transcript of devcamp 20 A3.ppt [互換モード] -...
17Th
Developer Camp
【A3】Delphi/C++Builderテクニカルセッション
「アンドキュメンテッド(?) VCL 逆引きVCL新機能 」
【A3】Delphi/C++Builderテクニカルセッション
~逆引きVCL新機能~」
株式会社 エスプリフォート
筑木真志筑木真志
1
自己紹介
• 名前:筑木 真志 (ちくぎ しんじ)– 多分、同姓同名はいません
– 「流しのプログラマ」としてJavaやっています
– でも、ホームグラウンドはC++のつもり
2
株式会社エスプリフォートについて
• URL: http://www.esprit-fort.co.jp/• 次代をともに創造するシステムインテグレーター
– 基幹/情報システム
– Webシステム/モバイルシステム開発
– データベースソリューション開発
– 制御アプリケーション開発
• 社是社是
– 高い技術レベルをもってIT技術を利用し、卓越した価値創造企業を目指します。
– 共存共栄の精神を持ち、イノベーションにより未来の創造をします。
3
アジェンダ
• 文字列処理あれこれ文 列処 あ
• ファイル処理あれこれ
• GUI関連のあれこれ• GUI関連のあれこれ
• まとめ・Q&A
4
何故「アンドキュメンテッド(?)」なのか
• リリースノートにクラス名だけ追加されている
– 製品リリース後のヘルプに反映されていない
– あっても、クラス名とかメソッド名だけで概要がないあ 、 ラ 名 名 概要
– 製品アップデートのリリースノートにさりげなく記述されていたり
– コンポーネント名でググるとホワイトペーパーが見つかる
– Delphi2009 HANDBOOKで解説されているp• いくつかネタを拝借しています
• ロードマップに「ドキュメントの整備」があるのはお約束
– Wiki化で徐々に改善
– Help Updateによる反映
5
p p よる反映
17Th
Developer Camp
文字列処理あれこれ文字列処理あれこれその1:1 その文字列を構築する
1
6
文字列を能率良く構築する
• TStringBuilderクラス– http://docwiki.embarcadero.com/VCL/ja/SysUtils.TStringBuilder– 文字列を構築するユーティリティクラス
J のj l St i B ild に相当• Javaのjava.lang.StringBuilderに相当
• .NET FrameworkのSystem.Text.StringBuilderに相当
– 単純に文字列を「+」で連結するとその分インスタンスが生成され非– 単純に文字列を「+」で連結するとその分インスタンスが生成され非能率
– Appendメソッドで文字列を「構築」
– AppendFormatメソッドで書式化も可能
• 戻り値は「自分自身」なので、連続してコールできる
• いわゆる「メソッドチェ ン」• いわゆる「メソッドチェーン」
– ToStringメソッドで「構築」した文字列を取得
7
コードサンプル(Delphi)
procedure TForm1.Button1Click(Sender: TObject);var
sb : TStringBuilder;sb : TStringBuilder;x, y : Double;
beginsb := TStringBuilder.Create;x := 123 456;x := 123.456;y := 789.123;
// 出⼒ログ⽂字列を⽣成するsb Append(DateTimeToStr(Now))sb.Append(DateTimeToStr(Now))
.Append(' [Info]')
.Append(' AreaName = ')
.Append(Edit1.Text)AppendFormat(' Point = (%9 3f %9 3f) ' [x y]).AppendFormat( Point = (%9.3f, %9.3f) , [x, y])
.Append(' ShopCount = ')
.Append(Memo1.Lines.Count);
// TMemoに出⼒// TMemoに出⼒Memo1.Lines.Add(sb.ToString);// IDEのデバッグウィンドウに出⼒OutputDebugString(PWideChar(sb.ToString));
end;
8
end;
コードサンプル(C++Builder)
void __fastcall TForm1::Button1Click(TObject *Sender){
std::unique ptr<TStringBuilder> sb(new TStringBuilder());std::unique_ptr<TStringBuilder> sb(new TStringBuilder());double x = 123.456;double y = 789.123;
// 出⼒ログ⽂字列を⽣成する
注意:Appendメソッドにワイド文字列リテラルを
渡すと、暗黙的型変換の優先順位により// 出⼒ログ⽂字列を⽣成するsb‐>Append(DateTimeToStr(Now()))
‐>Append(" [Info]")‐>Append(" AreaName = ")>Append(Edit1 >Text)
渡すと、暗黙的型変換の優先順位によりboolにキャストされる。
× Append(L"AreaName = ")‐>Append(Edit1‐>Text)‐>AppendFormat(" Point = (%9.3f, %9.3f) ", ARRAYOFCONST((x, y)))‐>Append(" ShopCount = ")‐>Append(Memo1‐>Lines‐>Count);
// TMemoに出⼒Memo1‐>Lines‐>Add(sb‐>ToString());
// IDEのデバッグウィンドウに出⼒// IDEのデバッグウィンドウに出⼒OutputDebugString(sb‐>ToString().w_str());
}
9
17Th
Developer Camp
文字列処理あれこれ文字列処理あれこれその2:2 その正規表現
2
10
正規表現を使う
• 正規表現とは、文字列の集合を一つの文字列で表現す規表 表る方法の一つである。
– Wikipediaより引用
• 「メタ文字」によって文字の集合を表現する
• 「メタ文字」は文字だけではなく、位置も表現するメタ文字」は文字だけではなく、位置も表現する
メタ文字 意味
. 任意の1文字
[] []内にある任意の1文字
¥w 単語を構成する任意の1文字
^ 行の先頭^ 行の先頭
* 直前の表現の0回以上の繰り返し
¥b 単語の境界
11
Delphi/C++Builderで使用可能な正規表現エンジン
• 標準で使用可能
– TRegex (XE以降)
– boost::regex / std::tr1::regex (C++Builderのみ)g g ( )
• サードパーティー製
– SkRegExpSkRegExp– 鬼車
– BREGEXP DLLBREGEXP.DLL– など
• エンジンによって挙動が変わるので注意!!メタ文字の種類 Unicodeの扱いなど
12
– メタ文字の種類、Unicodeの扱いなど
正規表現を使う
• TRegExクラスg クラ– http://docwiki.embarcadero.com/VCL/ja/RegularExpressions.TR
egEx
ド– Matchesメソッドでマッチ• 戻り値は、マッチ部分のコレクション(TMatchCollection型)
TR E はオブジ クトを生成して次々とマ チさせること– TRegExはオブジェクトを生成して次々とマッチさせることも可能
13
コードサンプル
procedure TForm1.btnMatchClick(Sender: TObject);varreg : TRegEx;match: TMatchCollection;m: TMatch;
beginbegin
// 正規表現reg := TRegEx.Create(edtPattern.Text);
// 正規表現がマッチするか?match := reg.Matches(edtText.Text);
// 結果をListBoxに表⽰lstMatched.Clear;for m in match do beginl h d dd( l )lstMatched.Items.Add(m.Value);
end;end;
14
日本語ハッシュタグにマッチする正規表現
• Twitterのハッシュタグが日本語に対応
– http://blog.jp.twitter.com/2011/07/blog-post.html
• 条件
– #(ハッシュマーク) で始まる#(ハッシュマ ク) で始まる
– 半角、全角のどちらでも可
– 英数字 ひらがな カタカナ 漢字 ハングルおよびキリ– 英数字、ひらがな、カタカナ、漢字、ハングルおよびキリル文字
– ハッシュタグの前後には空白または句読点ッシ タグの前後には空白または句読点
– 記号や絵文字は使用不可
15
日本語ハッシュタグにマッチする正規表現
• VCLにおける注意点
– 文字コードはUTF-16– 全角と半角の違い角 半角 違
– 濁音・半濁音と合成文字(「ガ」/「カ」+「゛」/「カ」+「゙」)
• Unicode正規化が必要
• 詳細は過去のデベロッパーキャンプの資料を参照!– 漢字・仮名にマッチするメタ文字
メタ文字 意味 TRegex boost::regex
¥w 単語構成文字 × ○
¥x{hex} 16進数指定(任意長) ○ ○
¥uhex Unicodeコードポイント(16進数4桁) × ×
¥p{prop} Unicodeプロパティ × ×
16
p{p p} Unicodeプ ティ
日本語ハッシュタグにマッチする正規表現
procedure TForm1.Button1Click(Sender: TObject);var
m : TMatchCollection;本当は、• テキストの正規化;
I : Integer;begin
m := TRegEx.Matches(Edit1.Text,'(#|¥x{FF03})' + // ハッシュマーク'([¥w ' + // 英数字+アンダースコア
• テキストの正規化• 先読みと戻り読みで前後の空白チェック• ハングルとキリル文字のチェックが必要
([¥w_ + // 英数字+アンダ スコア'¥x{3041}‐¥x{3094}¥x{3099}‐¥x{309C}¥x{30A1}‐¥x{30FA}¥x{30FC}' + // ひらがな・カタカナ'¥x{3400}‐¥x{D7FF}' + // 漢字‘¥x{FF10}‐¥x{FF19}¥x{FF20}‐¥x{FF3A}¥x{FF41}‐¥x{FF5A}¥x{FF66}‐¥x{FF9F}]+)’); // 全⾓形・半⾓形
);
Memo1.Clear;if m.Count > 0 then
for I := 0 to m.Count ‐ 1 do beginMemo1.Lines.Add(m.Item[I].Value);( [ ] )
endelse
ShowMessage('ハッシュタグはありません');end;
17
17Th
Developer Camp
フ イル処理あれこれファイル処理あれこれその1:3 そのファイル名・パス名処理
3
18
ファイル名、パス名の処理
• SysUtilsユニットで定義されていたファイル、パス名処理関連の関数が整理され、IOUtilsユニットで再定義
• http://docwiki.embarcadero.com/VCL/ja/IOUtils– TDirectoryクラス: ディレクトリ操作関数
ク 操作関数– TFileクラス : ファイル操作関数
– TPathクラス: パス操作関数
• SysUtilsユニットで定義されていた関数は使用可能
• 全てのパス関連の関数が整理されたわけではない• 全てのパス関連の関数が整理されたわけではない– 例)IncludeTrailingPathDelimiter
19
パス名関連処理の比較1:拡張子を変更する
• IOUtils.TPath.ChangeExtension関数– http://docwiki.embarcadero.com/VCL/ja/IOUtils.TPath.ChangeEx
tension拡張子を変更する– 拡張子を変更する
– SysUtils.ChangeFileExtと使い方は同じ
– 拡張子にピリオドが無くても自動的に付加してくれる拡張子 リオ 無く も自動的 付加し くれる
procedure TForm1.Button2Click(Sender: TObject);begin
edtRes lt1 Te t : ChangeFileE t(edtFileName Te t edtE t Te t);edtResult1.Text := ChangeFileExt(edtFileName.Text, edtExt.Text);edtResult2.Text := TPath.ChangeExtension(edtFileName.Text, edtExt.Text);
end;
20
パス名関連処理の比較2:ファイルの検索
• TDirectory.GetFiles関数
– http://docwiki.embarcadero.com/VCL/ja/IOUtils.TDirectory.GetFiles
/ / C 代替関数– FindFirst / FindNext / FindCloseの代替関数
– ワイルドカード、再帰検索も可能procedure TForm1.Button1Click(Sender: TObject);procedure TForm1.Button1Click(Sender: TObject);var
Dir, f: string;Root: WideString;Files: TStringDynArray;
beginDir := GetMyDocumentsPath(CSIDL_PERSONAL);
ダ だif SelectDirectory('フォルダを選択してください。', Root, Dir, [sdNewUI]) thenEdit1.Text := Dir;
// ファイルを検索Files := TDirectory.GetFiles(Edit1.Text, '*.pas', TSearchOption.soAllDirectories);
// ファイル情報を取得// ファイル情報を取得with Memo1 do begin
Clear;Lines.BeginUpdate;for f in Files do Lines.Add(f);Lines.EndUpdate;
end;
21
end;end;
IOUtilsユニットで再定義された関数の例
• ファイル名の取得
– SysUtils.ExtractFileName → TPath.GetFileName– http://docwiki.embarcadero.com/VCL/ja/IOUtils.TPath.GetFileNa
me
• ファイルの有無
– SysUtils.FileExists → TFile.Exists– http://docwiki.embarcadero.com/VCL/ja/IOUtils.TFile.Exists
• フォルダの作成
– SysUtils.CreateDir → TDirectory.CreateDirectory– http://docwiki.embarcadero.com/VCL/ja/IOUtils.TDirectory.Create
Directory22
Directory
17Th
Developer Camp
フ イル処理あれこれファイル処理あれこれその2:4 そのエンコーディング判定
4
23
TEncoding.GetBufferEncodingの問題
• GetBufferEncodingはBOMを必要とするg• BOM無しUTF-8をDefaultとして解釈してしまう。
// エンコーディングを判別して、TEncodigを取得(?)// ンコ ディングを判別して、TEncodigを取得(?)enc := nil;ms.Position := 0;res := TEncoding.GetBufferEncoding(ms.Memory, enc);
24
エンコーディングの自動判別
• エンコーディング判別ライブラリは外部のを使用
– mlang.dll• Windows標準
• BOM無しUTF-8を正しく判別しない場合がある
– Universalchardet• Mozillaのエンコーディング判別部分をDLL化• http://www.void.in/wiki/Universalchardet
– EncodeDetect• http://www.watercolor-city.net/ct_delphi/delphi_tiburon/
25
Universalchardet.dllを使用する
• DLLの関数を参照するユニットunit universalchardet;
interface
typechardet_t = Pointer;
constCHARDET MAX ENCODING NAME = 64;CHARDET_MAX_ENCODING_NAME = 64;
function chardet_create(var pdet: chardet_t): integer;stdcall; external 'universalchardet.dll' name '_chardet_create';
procedure chardet_destroy(det: chardet_t);stdcall; external 'universalchardet.dll' name '_chardet_destroy';
( )function chardet_handle_data(det: chardet_t; const data: PAnsiChar; len: Cardinal): integer;stdcall; external 'universalchardet.dll' name '_chardet_handle_data';
function chardet_data_end(det: chardet_t): integer;stdcall; external 'universalchardet.dll' name '_chardet_data_end';
function chardet reset(det: chardet t): integer;_ ( _ ) g ;stdcall; external 'universalchardet.dll' name '_chardet_reset';
function chardet_get_charset(det: chardet_t; namebuf: PAnsiChar; buflen: Cardinal): integer;stdcall; external 'universalchardet.dll' name '_chardet_get_charset';
implementationend
26
end.
Universalchardet.dllを使用する
• chardet_handle_data関数でエンコーディングを判別_ _– バッファとして、TMemoryStream.Memoryプロパティがそのまま使用できる。
• chardet get charset関数でエンコーディング名を取得_g _
• TEncoding.GetEncoding関数で、エンコーディング名TEncoding.GetEncoding関数で、 ンコ ディング名からTEncodingを取得する
• 本当は、EUC-JP(CP51932)とCP21932の処理が必要
– 今回は省略
27
今回は省略
コードサンプル
procedure TForm1.Button1Click(Sender: TObject);varms: TMemoryStream;enc: TEncoding;encname: array[0..CHARDET_MAX_ENCODING_NAME] of AnsiChar;det: chardet t;det: chardet_t;res: Integer;
beginms := TMemoryStream.Create;
// ファイルをストリームへ読み込むIdHTTP1.Get('http://www.yahoo.co.jp', ms);
// universalchardet.dllでエンコーディングの判別det := nil;chardet_create(det);
h d h dl d (d i )res := chardet_handle_data(det, ms.Memory, ms.Size);chardet_data_end(det);
28
コードサンプル(続き)
// エンコーディング名の取得chardet_get_charset(det, encname, CHARDET_MAX_ENCODING_NAME);chardet_destroy(det);
// エンコーディング名からTEncodigを取得// エンコ ディング名からTEncodigを取得enc := nil;tryenc := TEncoding.GetEncoding(encname);
excepton EEncodingError doenc := TEncoding.Default;
end;end;
// オフセットをストリームの先頭にms.Position := 0;
i d ( )Memo1.Lines.LoadFromStream(ms, enc);ms.Free;
end;
29
end;
ストリームI/Oの注意
• TStrings.LoadFromStreamのように、ストリームから読gみ込むときは、必ず、Positionプロパティを0にして、ストリームの先頭にする
// オフセットをストリームの先頭にms.Position := 0;;Memo1.Lines.LoadFromStream(ms, enc);ms.Free;
30
17Th
Developer Camp
GUI関連のあれこれGUI関連のあれこれその1:5 そのリストビュー
5
31
リスト ビューのグルーピング
• リスト ビューのグルーピングはVista以降でサポート
• TListView.Groupsプロパティ
– ヘッダ、フッタ、サブタイトルッダ、フッタ、サブタイトル
– イメージの指定
– グループ毎にアイテムを表示/非表示グル プ毎にアイテムを表示/非表示
– タイトルの表示のみXPでサポート
• http://docwiki embarcadero com/VCL/ja/ComCtrls TL• http://docwiki.embarcadero.com/VCL/ja/ComCtrls.TListView
32
TListGroupクラスの主なプロパティ
Headerプロパティ:TitleImageプロパティ:TListView.GroupHeaderImagesのインデックス
eade プ ティグループヘッダのタイトル
Subtitleプロパティ:グループヘッダのサブタイトルFooterプロパティ:
グループ化されたLIstViewItemの下部に表示するテキスト
33
下部に表示するテキスト
リスト ビューのグルーピング
• TListView.GroupViewプロパティをTrueにするp
• TListView.Groups.Addメソッドでグループヘッダを追加
34
リスト ビューのグルーピング
procedure TForm1.Button1Click(Sender: TObject);varGr: TListGroup;Item: TListItem;
beginGr := ListView1.Groups.Add(); // グループヘッダを追加Gr : ListView1.Groups.Add(); // グル プヘッダを追加with Gr do beginGroupID := ListView1.Groups.NextGroupID; // 「次」のグループIDを取得Header := 'Header' + IntToStr(GroupID);
( )Footer := 'Footer' + IntToStr(GroupID);DisplayName := 'DisplayName' + IntToStr(GroupID);Subtitle := 'Subtitle' + IntToStr(GroupID);TitleImage := GroupID mod ImageList1.Count;TitleImage : GroupID mod ImageList1.Count;State := [lgsNormal, lgsCollapsible];
end;end;
35
17Th
Developer Camp
GUI関連のあれこれGUI関連のあれこれその2:6 そのバルーンヒント
6
36
TBalloonHintを動的に表示する
• TBalloonHintコンポーネントを使って、任意の位置にヒントを表示する
• http://docwiki.embarcadero.com/VCL/ja/Controls.TBp jalloonHint
• ヘルプの表示はShowHintメソッドを使用する
– 指定する座標はスクリーン座標指定する座標はスクリ ン座標
– フォームの座標ではない
37
コードサンプル
procedure TForm1.Button1Click(Sender: TObject);begin
BalloonHint1 Title := 'ヒントのタイトル';BalloonHint1.Title := ヒントのタイトル ;BalloonHint1.Description := 'バルーンヒントを表⽰してみる。';BalloonHint1.HideAfter := 2000;
BalloonHint1 ShowHint(BalloonHint1.ShowHint(Button1.ClientToScreen(CenterPoint(Button1.ClientRect)));
end;
void __fastcall TForm1::Button1Click(TObject *Sender){
BalloonHint1‐>Title = T("ヒントのタイトル");a oo t > t e _ ( ヒントのタイトル );BalloonHint1‐>Description = _T("バルーンヒントを表⽰してみる。");BalloonHint1‐>HideAfter = 2000;
BalloonHint1‐>ShowHint(BalloonHint1 >ShowHint(Button1‐>ClientToScreen(Button1‐>ClientRect.CenterPoint()));
}
38
バルーンヒントを使う上での注意
• TBalloonHintは動的に生成しないでフォームに貼る
• ShowHintメソッドはヒントを表示したらすぐに終了するShowHintメソッドはヒントを表示したらすぐに終了する
– HideAfterで指定した値の間は停止する訳ではない
• TApplicationEvent.OnShowHintイベントが発生しない
QC#70888– QC#70888
39
17Th
Developer Camp
GUI関連のあれこれGUI関連のあれこれその3:7 そのコントロールの自動配置
7
40
コントロールを自動的にレイアウトする
• コントロールの位置・サイズはピクセル単位
• TForm.OnResizeイベントなどで位置・サイズを再計算
41
コントロールを自動的にレイアウトする
• コンポーネントの位置・サイズを自動計算するパネル
– TGridPanel• コンポーネントを格子状に配置
• http://docwiki.embarcadero.com/VCL/ja/ExtCtrls.TGridPanel
– TFlowPanel• コンポーネントを縦方向・横方向に配置
• http://docwiki.embarcadero.com/VCL/ja/ExtCtrls.TFlowPanel
42
コントロールを格子状にレイアウトする
• TGridPanelをフォームにドロップ
• ColumnCollection/RowCollectionでパネル内部の配置を決定する
• SizeStyleプロパティ : グリッドサイズの単位
– ssAbsolute : ピクセル単位
– ssAuto : 自動計算
– ssPercent : 割合(パーセント単位)V l プロパティ グリ ドサイズ• Valueプロパティ: グリッドサイズ
43
コントロールを格子状にレイアウトする
• ColumnCollection/RowCollectionの調整
– オブジェクトインスペクタのは少々使いづらいので、エディタで値を直接編集する
ColumnCollection = <item
Value = 50.000000000000000000endenditem
Value = 50.000000000000000000enditem
d>
• 注意:C++Builderではヘッダファイルが破壊される
end>
注意:C Builderでは ッダファイルが破壊される(QC#81162)ので、ヘッダファイルの末尾にダミーのコメント行を追加しておく。
44
コントロールを格子状にレイアウトする
• コントロールをGridPanel上にドロップすると、ControlCollectionプロパティにコントロールが追加される
45
コントロールを格子状にレイアウトする
• コントロールのサイズを調整する
– ControlCollectionプロパティでサイズを調整
– TControlItem型のコレクション
• TControlItemの主なプロパティTControlItemの主なプロパティ
– Columnプロパティ:配置するセルの横座標
– Rowプロパティ:配置するセルの縦座標Rowプロパティ:配置するセルの縦座標
– ColumnSpanプロパティ:セルの横サイズ
– RowSpanプロパティ:セルの縦サイズ– RowSpanプロパティ:セルの縦サイズ
– Controlプロパティ:配置するコントロール
46
コントロールを格子状にレイアウトする
• 本文
– 本文
• 本文
フォームをリサイズしても、コントロールは自動的に配置さントロ ルは自動的に配置される
47
17Th
Developer Camp
まとめ8 ま め8
48
アンドキュメンテッド(?)に如何にして対処するか?
• まずdocwikiを参照する!!– docwikiは随時更新しています。– http://docwiki.embarcadero.com/RADStudio/ja/Main_Page
• 試してみる
• ググるググる
• RTLのソースコードを読む
– “Use the Source Luke ”の原則Use the Source, Luke. の原則
• QCに投稿
投稿は英語だけど Google翻訳とかでOK– 投稿は英語だけど、Google翻訳とかでOK。
49
アフターフォローとか
• 今日のアフターフォローは以下で行います
– 自分のBlog:http://d.hatena.ne.jp/A7M/– Twitterハッシュタグ: #dcamp jpp_jp– Twitter ID : A7M3J
50
17Th
Developer Camp
Q & AQ &
51
後に
ご清聴ありがとうございました!!ご清聴ありがとうございました!!<( )><(_ _)>
52