文字列をフォームファイル(DFM)形式に変換する[C++Builder]

「えーと●●●って選択肢のあるRadioGroupはどのフォームだったっけ」とか探したくなることがたまにある。
C++Builderでは(Delphiも)フォーム情報がテキスト形式(DFM)で保存されているので、ソースのあるフォルダでgrepかければ一発、のはずなのだが、英数・記号以外の文字は数値変換されているので、見つからないことがままある。

たとえば変な例だが「叱るButtonAtype」みたいなCaptionはdfmファイルに
Caption = #21489#12427'Button'#65313'type'
と保存される。(”A”も全角なので数値変換されている)

たぶん
・半角英数・記号はそのまま(シングルクオーテーション囲み)
・それ以外は文字コード番号の10進数表記(個々の先頭に”#”)
・さらにサロゲートペアは分割して変換(例の「叱(U+20B9F)」は「#21489#12427」)
というルールっぽい。

というわけで、変換関数を作った。
以下、コード。

[boost]サイト上のシリアライズデータをダウンロードせずにデシリアライズする[C++Builder]

boost::serializatioでシリアライズしたデータがweb上(例えば自分のサイト)にあり、PC上のプログラムから利用したい場合、一時的にダウンロードしてデシリアライズすれば簡単なのだが、後で一時ファイルを削除する手間が生じる。

以下、ダウンロードしないまま利用する方法をメモ。

手順は以下の3ステップ。
(1)UrlからデータをTStreamに読み込む
(2)TStreamからバイト列(char配列)に書き込む
(3)バイト列からデシリアライズ(boost::iostreamsを使う)

C++Builder10.2.3 (Boost1.55.0) / Windows10(22H2)で確認。

[Vcl]AcrobatDCを利用したPDF印刷が失敗する対策

Adobe Acrobatはクラウド版(Acrobat DC)になってから使っていなかったのだが、アプリケーションの印刷ダイアログで選択して使用すると、PDF作成に失敗するようになっていた。

以下は、四角形を1つ描くだけの単純なテストプログラム。

PrintDialogでAdobe PDFを選択すると、下記のダイアログが出たまま止まる。

Microsoft Print to PDF および JUST PDF4 だと問題なくPDFが作成された。

Acrobat DCは最近のアップデートで、どうやら「文書名」が空のままだとダメになったらしい。
というわけで、以下のようにTitleを適当に付加すると正常にPDFが作成された。

C++Builder10.2.3/Windows10(64bit/バージョン21H2)で確認。

[FireMonkey] ImageとBitmapの大きさを揃える

簡単そうなことなのに、ちょっとハマったのでメモ。

FireMonkeyでTImageに文字や図形などを初めて描く場合は、先にImage->Bitmapのサイズを指定する必要がある。
ImageとBitmapのサイズが異なってもよいが(WrapModeで描画結果が変わる)、ここはシンプルに同じ大きさを指定したい場合の話。たとえば以下のように書けば何の問題もない。

だがちょっとまだるっこしいので1行で書きたい。こうも書ける。

Imageの名前(この例では”Image”だが)を3回も書くのも面白くない。TImageにもTBitmapにもSizeプロパティがある。これを使おうと、以下のように書いてみると、エラーになる。

TSizeとTSizeF

FireMonkeyの場合、TImageに限らず、TMemoやTButtonなどTControl派生のコンポーネントは、位置やサイズ情報を実数値(float)でも持つ。VclのTSizeでなくTSizeF、TPointでなくTPointF、そしてTRectの代わりにTRectF
ところがTControl派生でないTBitmapの場合、Sizeプロパティは整数型のTSize。このため単純な代入は出来ない。
たとえば、四角形の領域を、指定されたビットマップから現在のビットマップへコピーするCopyFromBitmapメソッドの宣言。RectもPoint(X,Y)も整数になっている。

で、こうした実数型のクラスには整数型に変換するメンバ関数Round/Trunk/Ceilingが用意されている。それぞれ四捨五入、切り捨て、切り上げ。
 ・
というわけで、以下のように書き換えてみる。

やはりエラー。

TSizeFとTControlSize

実はTControl派生クラスのSizeプロパティはTSizeFでなくTControlSizeだった。
このTControlSizeはPixel値(整数)のメンバHeight / Widthと、TSizeF型のメンバSizeを持つ。ややこしい。

というわけで、ImageのサイズにImage->Bitmapのサイズを合わせるシンプルなコードは以下の通り。

微妙にシンプルでもない気もする。