高見知英の技術ログ

技術関係のログをQiitaから移行してきました。プログラミングのほか、使っているアプリの細かい仕様についてなど書いていきます。

LazarusのIDE構成を変更する

このブログはLazarus(FreePascal)アドベントカレンダー19日目の記事です。

qiita.com

今回のお題はIDEの構成。LazarusはIDEの構成を変更することで、機能を追加・削除することができるというユニークな機能を持った開発環境です。

パッケージは基本的に*.lpkという形式のファイルにまとまっているのですが、ごく基本的なパッケージは既にLazarusに同梱されており、「パッケージ」メニューの「パッケージをインストールもしくはアンインストール」メニューから追加・削除することができます。

f:id:TakamiChie:20211213181848p:plain
パッケージのインストールもしくはアンインストール

なお、ここでインストールできるパッケージは基本的に日本語化されていませんので、日本語の設定にしていても英語で表示されます(なお、以降のスクリーンショットWindowsサンドボックスの環境内で撮影したため、全文英語となっています)。

どんなパッケージがあるのか

既に用意されているパッケージといっても様々で、たとえば様々なお役立ちメニューを追加したり・・・。

f:id:TakamiChie:20211213182128p:plain
Codyパッケージにより挿入メニューが増えた

ダイアログつきの簡易ウィザードを提供してくれたり・・・。

f:id:TakamiChie:20211213182227p:plain
MessageComposerPkgパッケージによる簡易ダイアログ生成ツール

なかには最近のDelphi風にウィンドウひとつの開発環境を提供してくれるものもあります( Laz にゃん: Lazarus IDE をドッキング対応にする参照 )。

f:id:TakamiChie:20211213182341p:plain
AnchorDocking, AnchorDockingDsgnパッケージをインストールすると、最近のDelphi風ウィンドウになる。

これらは基本的にパッケージのインストール画面からIDEを再構築することによって使用可能になります。

f:id:TakamiChie:20211213182718p:plain
パッケージのインストールもしくはアンインストール

導入には注意

ただし、このコンポーネント、いくつか組み合わせ次第ではうまく動かないコンポーネントも混じっているようで、便利そうだからとほいほいパッケージをインストールすると、Lazarusが起動しなくなってしまうことがあります。

そのようなときはLazarus自体の再インストールが必要になってしまいますので、Windows 10 / 11 Professionalを利用している方は、Windowsサンドボックス下で試験してから実環境に適用するようにするなど、なんらかの対策が必要になります。

LazarusでDelphiのプロジェクトを読み込む

このブログはLazarus(FreePascal)アドベントカレンダー18日目の記事です。

qiita.com

この機能を使えば昔Delphiで作ったあんなアプリをインポートして、Lazarusで使うことができます。

LazarusのLCLなどのライブラリにはある程度DelphiVCLと互換性があるので、運が良ければそのまま、そうでなくてもそれなりに改修を行なえばLazarusでもプロジェクトを使うことができます。

やってみた

ということで、今回インポートしてみたツールはこちら。とはいってもはるか昔まだOperaがPrestoエンジンを使っていた頃のアプリなので、もちろん今は全く使えないのですが・・・。

www.vector.co.jp

プロジェクトのインポート

とりあえずDelphiのプロジェクトを読み込みます。Delphiのプロジェクトを読み込むには、ツールメニューのDelphi変換を選びます。

f:id:TakamiChie:20211212185738p:plain
Delphi変換メニュー

ここで「DelphiプロジェクトをLazarusプロジェクトに変換」を選ぶと、*.dprのファイルを選択するダイアログが表示され、選択すると確認画面が表示されます。

f:id:TakamiChie:20211212190011p:plain
インポート詳細

このままインポートを開始すると、変換処理が開始されます。ここでやっているのは見た感じ次の通りです。

  • *.dprファイルを*.lprファイルに改名(元のファイルはConverterBackupフォルダにコピーされる)
  • ファイルのエンコードUTF-8に変更する
  • Windows APIを呼び出しているコードのうちLCLなどLazarusが使用できるライブラリで代用可能なものは、それに置き換えする(ShellExecuteOpenDocumentなど)
  • 互換性のないモジュールやプロパティの削除

いちおうこれらについては変換完了後、AutomaticConversion.logというファイルに出力されます。

エラーが起こった場合

なお、参照しようとしているモジュールが見つからなかった場合などは、次のようなダイアログが表示されます。

わたしの場合昔は参照フォルダから呼び出すクラスライブラリ集などを自分で作ってたので大変(幸い過去のライブラリは一つも捨てていないようだったので、時間をかければ復元できそうですが…)。

f:id:TakamiChie:20211212190738p:plain
インポート中のエラー表示

無事変換が終わると、通常通りプロジェクトが表示されます。F5で実行してみると・・・。

f:id:TakamiChie:20211212190834p:plain
当時のアプリが起動した。

なんとか起動しました。

ただ実際に使ってみると・・・

ただ実際にいろいろ過去のプロジェクトをいじってみたのですが、結構問題があちこちで起こります。

  • 画面上に表示されない範囲でLCLVCLの仕様が異なるところが多く*1、独自の拡張を行なったクラスなどがあった場合、かなりの手直しが必要になる。
  • ピクセル単位で描画処理を行なっている箇所などがあれば、縮尺がずれてしまい正常に表示されないことが多い。
  • dfmファイルがリソースに埋め込まれてしまっている場合などは、それらを削除せずにプログラムを読み込んでしまうため、エラーが発生する。
  • 変換時にソースコード文字コード変換を行なう・・・と思いきやときどき文字コードの変換を行なわずスキップしてしまうファイルが出る*2ため、結局すべての文字コードを確認し直す羽目になる。

このためとりあえずソースコードコンパイルして雰囲気を確認できたら、すべて閉じて一から実装し直し というほうがむしろ効率が良いような気もします。

つかいどころ

2003年頃、Delphi 6 Personalが無償提供され、それに飛びついていた というホビープログラマは、少なくないと思います(当時は無償で提供されている開発環境は貴重でしたので)。

プライベートフォルダに、GitやSVNリポジトリに、当時作っていたツールのソースコードが眠っている なんて方もいらっしゃるのではないでしょうか。

そんな人が、過去の遺産を取り出すには有用な機能ではないかと思います。

もしそんなプログラムがある方は、当時を振り返るという意味でとりあえずこの機能を使ってみる というのもよいのではないでしょうか?

ただ、実際にやる場合、プロジェクトごと変換してしまうと歪みが出るので、「DelphiユニットをLazarusユニットへ変換」メニューを使って参照ファイルを一個ずつ変換する 等というやり方が良いかもしれません・・・(だいぶ痛い目を見た)。

*1:たとえばTLabelがラベルの文字描画をDoDrawTextメソッドに分離せずPaintメソッド内で全部やっているとか、ウィジェットのサイズを自動調整するメソッドがAdjastBoundsではなくAdjastSizeになっているとか

*2:プロジェクト外のモジュールを呼んでいた場合などに起こりやすい様子

Lazarusでコードの折りたたみ

このブログはLazarus(FreePascal)アドベントカレンダー17日目の記事です。

qiita.com

今回は(も)小ネタ。Lazarusでコードの折りたたみブロックを作ります。

やり方は簡単で、折りたたみを開始する箇所を{$REGION 'リージョンの名前'}、終了する箇所を{$ENDREGION}で囲むだけです。

{$REGION 'ActionList'}

procedure TMainForm.メソッド1(Sender: TObject);
begin
end;

procedure TMainForm.メソッド2(Sender: TObject);
begin
end;

procedure TMainForm.メソッド3(Sender: TObject);
begin
end;

{$ENDREGION}

すると$REGIONの位置に折りたたみ用のボタンが表示され、クリックすると折りたたみが可能になります。

f:id:TakamiChie:20211210171426g:plain
コードの折りたたみ

ただし、以前もちょっと触れましたが、コードの折りたたみはコードの文脈を無視してなんでも折りたたんでしまうので、濫用厳禁です。

ただ個人的には宣言部と実装部が分かれているPascalなら、比較的混沌を生みづらいのではないかな?という気がします。しらんけど。

Lazarusにおけるドキュメントコメント

このブログはLazarus(FreePascal)アドベントカレンダー16日目の記事です。

qiita.com

Lazarus(というかPascal)ではメソッドの使用方法などを紹介するために、ドキュメントコメントを設定することができます。

Pascalにおけるドキュメントコメントは、XMLの形式をとっています*1

{・・・}
/// <summary>関数の説明</summary>
/// <param name="ScriptFile">引数1の説明</param>
/// <param name="StdOut">引数2の説明</param>
/// <param name="StdOut">引数3の説明</param>
/// <returns>戻り値の説明</returns>
function Execute(ScriptFile: String; out StdOut: String; out StdErr: String): Integer;
{・・・}

ちゃんと書かれていると、関数をマウスでホバーしたときにヒントが表示されるようになります。

f:id:TakamiChie:20211210164828p:plain
メソッドヒント

XMLで書いてる意味ないじゃん!という気がしなくもないです。まあDelphiだともうちょっと読みやすい形式が出てくるようですが。

で、このドキュメントコメントですが、Pascalの場合メソッドの宣言部に書きます。実装部に書いてもなにもないのでご注意ください。

FPDocエディタ

いちおう、Lazarusには入力を支援するツールして、FPDocエディタというものがあります。

f:id:TakamiChie:20211210165250p:plain
FPDoc

ただ個人的には使い方がよくわからなかった・・・ いちおう公式Wikiにも使い方は書いてあるのですが、結局よくわからず・・・。あれ使えている人いるんでしょうかねえ。

ただ、実際にどれほどの効果があるかどうかはともかく、メソッドの使い方がある程度書いてあると第三者が読んだときにかなり解析が楽になります(Free Pascal標準ライブラリのソースを読んだときの感想)。

XML書式を使うかどうかはともかく、積極的にコメントを書いていくと良いでしょう。

*1:の、割にはLCLなどのソースを見ると全く違う書式でドキュメントコメントが書かれているので困惑しますが…。せめてそこは統一して欲しかった

LazarusでHTMLをレンダリングする

このブログはLazarus(FreePascal)アドベントカレンダー15日目の記事です。

qiita.com

最近はなんだかんだちょっと複雑なテキストをレンダリングするには、HTMLビューアを使う というパターンが多いのではないかと思います。

LazarusでHTMLビューアを内蔵したアプリを作るには というと、標準の場合は、IProタブのTIpHtmlPanelというものを使います。

f:id:TakamiChie:20211210160515p:plain
TIpHtmlPanel

このコンポーネントを貼り付けると赤い○に「HTML」とだけ書かれた領域が表示されますので、実行時にHTMLを書き込んで、レンダリングを行ないます。

f:id:TakamiChie:20211210160900p:plain
TIpHtmlPanel(デザイン時)

f:id:TakamiChie:20211210161009p:plain
TIpHtmlPanel(実行時)

HTMLの書き込みには、TIpHtmlPanel#SetHtmlFromStr()というメソッドを使います。簡易的なCSSも解釈してくれるようなので、リソースにあらかじめCSSファイルを読み込ませておき、それをまぜてHTMLとして出力 みたいなコードを書くと楽です。

procedure TMainForm.UpdateStatus(HTML: String);
var
  r: TResourceStream;
  s: TStringStream;
begin
  try
    r := TResourceStream.Create(HINSTANCE, 'STYLE', RT_RCDATA);
    try
      s := TStringStream.Create();
      try
        s.LoadFromStream(r);
        FStatus.SetHtmlFromStr('<html>' +
          '<head>' +
          '<meta http-equiv="content-type" content="text/html; charset=UTF-8">'+
          '<style type="text/css">' +
          s.DataString +
          '</style>' +
          '</head>'+
          '<body>' +
          HTML +
          '</body>' +
          '</html>'
          );
      finally
        s.Free;
      end;
    finally
      r.Free;
    end;
  except
    on E: Exception do MessageDlg('Error:'+ E.Message, mtError, [mbCancel], 0);
  end;
end;

TIpHtmlPanelの対応環境

では、このクラス、どの程度のHTMLに対応しているか?というと、残念ながらそんなに詳細な情報が得られず…。

とりあえずフォーラムに書き込んでみたところ「そんなによくない」とは言われました。

forum.lazarus.freepascal.org

あと、JavaScriptやアニメーションなどの比較的高度なCSS要素には対応していないようです。

このへんについてはソースコードを見てみたところ、たしかに対応してないプロパティは多いっぽい*1

とりあえずしっかりとしたHTML対応を求めるのであれば、fpCEFなどのブラウザコンポーネントの導入を検討してみましょう。

wiki.freepascal.org

wiki.freepascal.org

Lazarusプロジェクトのビルドをコマンドラインで行なう

このブログはLazarus(FreePascal)アドベントカレンダー14日目の記事です。

qiita.com

たとえばリリースパッケージを作りたいときなど、Lazarusのコンパイル以外にも複数の処理を行ないたいのでIDE以外からコンパイル操作を行いたい ということはときどきあります。

そのようなときに、Lazarusのビルド処理だけを行なうツールとして、Lazarusにはlazbuildというツールが存在します。

Lazbuildの在処と使い方

このツールは、Lazarusをインストールしたディレクトリにあります。

このツールに、Lazarusのプロジェクトファイル(*.lpi)を指定すると、コンパイル処理が走って、ファイルで定義した場所に実行ファイルが出力されます。

このパスをヒント無しで探したい場合…。レジストリのインストール時情報にパスに書き込まれているので、そこから読み取るくらいでしょうか・・・*1

LazBuildでいつもと違う構築モードのコンパイルを行なう

このlazbuildには、--build-modeというオプションがあり、これを指定すれば、構築モードを切り替えてのコンパイルも可能。

たとえば普段のコンパイルでは構築モード「Debug」を使っているが、このときは「Release」を使いたい という場合はlazbuild .\application.lpi --build-mode=Releaseなどというコードを書いておけばOKです。

なお、この処理を行なうと*.lpsファイルが書き換えられてアクティブな構築モードが「Release」に変わってしまうので、それが気になる場合は、--no-write-projectオプションを加えます。

ビルドスクリプトを書く

また、同梱物がほかにもある場合は、コンパイル用のスクリプトを作っておくと良いです。

ZIPファイルにまとめる場合など、PowerShellを使っても良いですが、Pythonあたりで作って置くとバンバン呼び出せて良いですね。

lpiファイルはXMLファイルなので、Pythonからいじりたい場合はxml.etree.ElementTreeあたりを使うとよいでしょう。

ただし、xml.etree.ElementTree#writeで作成できるXMLはLazarusが出力するlpiファイルとは若干書式が異なるのでご注意ください*2

github.com

*1:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\lazarus_is1\InstallLocation

*2:わたしはXMLファイルを作成したあと、ファイルを読み込んで直接編集しました

ClipboardMonitor作りました

このブログはLazarus(FreePascal)アドベントカレンダー13日目の記事です。

qiita.com

13日目はそもそもLazarusを触るきっかけにもなったアプリ、ClipboardMonitorについて。

github.com

このアプリは、クリップボードを常に監視し、テキストがコピーされたらその文字数やURLの指し示すページのタイトルなどを表示するツールです。

クリップボード内の内容を確認する処理はPythonスクリプトで実装されているので、自分で追加することで自由に処理を追加することもできます。

f:id:TakamiChie:20211212161756p:plain
動作風景

また、変換スクリプトメニューからテキストを変換するスクリプトを呼び出すことも可能です。

こちらもPythonスクリプトなので、好きな処理を追加することができます。

f:id:TakamiChie:20211212162731p:plain
変換スクリプト

個人的にはクリップボードの履歴や引用記号をつけるなどのテキスト処理はClipboard Historyというツールを使っているのでちょっと少なめですが、ぼちぼち増やしていこうかなーと。

作成動機

作成動機はなにより、とくにクリップボード履歴ツールなどを使っていると「今クリップボードに何がコピーされているのか」が分かりづらいから。

とくにClipboard Historyにはスタッククリップボードという機能があり、これを使っていると特に「今何がクリップボードにコピーされているのか」は分かりづらい。

とくに配信中など、「今クリップボードに入っているテキストを配信画面に出して良いか」が分かりづらいのが個人的に悩みでした。

そのために作成したのがこのツールです。

Lazarusを使った理由

Lazarusを使った理由については、以前にもちょっと触れましたが、GUIがデザイナーで作れて、コンパイルができ(そこそこに早く起動でき)て、開発環境もそこそこに軽く使いやすいこと。

GUIがデザイナーで作れると言えばVisual Studioもありますが、開発環境が十数GBと重いのもあるし、久しぶりに触ったとき開発環境のアップデートなどで時間を食い潰されるのがいやだったので選びませんでした。たぶん今後そんなに頻繁には触れないということを考えると、その度にアップデート というのはしんどいですし。

まあ、Delphiっぽい環境に懐かしさを感じて というのもあるにはありますが。

今後の予定

今後は、まだまだ機能的に足りないなと思う部分もありますし、改善したいところものこっているので、それらの修正や、スクリプトの追加は行ないたいと思っています。ただ、しばらく忙しいのもありそんなに積極的には弄れないかも。

もともとクリップボードまわりのアプリは使い勝手が良く便利には使っていたのですが、アプリが途中で開発停止になってしまうことが多く、そんなときでも最低限他の人が関われるようにと思ってオープンソースにしています。なので、もしできる人がいれば、プルリクエストなどなんらかの形で関わっていただけると嬉しいなあ と。

いちおうリリースにはベータをつけていますが、ベータがとれるところまでは少なくとも開発を進めたいですねー。

github.com