goo blog サービス終了のお知らせ 

∵ なぜならば

映画とかネットとかパソコンとかコミックとか音楽とか……

覚え書き:UniCode 混じりの文字列長さ

2020-10-24 10:54:27 | Delphi

その昔日本語(Shift-JIS)は半角と全角しかなかったので「半角文字か2バイト文字」とか判別していた
「半角かな」も混じっていたし当時のコンパイラの長さを求める関数も「あいう」なら「6」と返していた
(秀丸マクロは互換性のためいまでも全角文字は2文字として数えます)
UniCode が広まってもうその考えもほぼほぼ不要になってきて全ての種類を判断して「文字」として数えてくれるようになった
ただ簡単で便利になった反面場合によってはそんな仕様がかえって困ることになる


今回の
┌―――┐
|あいう|
└―――┘
選択文字を罫線で囲むというだけの簡単なマクロでも罫線「―」は全角なので
┌―――┐
|aいう|
└―――┘
の様な場合に判別して後ろに半角スペースを追加しなければならない
このとき UniCode が混ざると昔ながらの方法で単純に「AnsiString」に変換して長さを測るとかは出来ない
┌―――┐
|আ¶£|
└―――┘
とかなるときにどう判断すればいいのかと考えた結果単純な方法でやっつけた



//半角英数字の長さなら何文字か返す
//KiriAge が True なら小数値は切り上げ False なら四捨五入
function ASCIILength(S:string;KiriAge:Boolean):integer;
var
  F:Extended;
begin
  F:=Canvas.TextWidth(S)/Canvas.TextWidth('q');//Canvas が等幅フォント前提
  if KiriAge then
  begin
    if  Frac(F)<>0 then Result:=Trunc(F)+1 else Result:=Trunc(F);
  end else
  begin
    if F>=0 then Result:=Trunc(F+0.5) else Result:=Trunc(F-0.5);
  end;
end;

それは半角英数字の何文字相当なのかという関数
中でやってることは「とりあえず書いたらどれだけの長さになるのか」だけ

多分これで解決したんだけれどもそんなことをやっているとき秀丸を見て気づいたんだけど
同じフォントにしても微妙に違うの笑う

バグ修正時の覚え書き

2020-10-18 22:09:48 | Delphi
『マルチモニタで使用時マイナス座標側で最大化のまま終了したとき次回起動時にメインモニタ側に最大化表示される』
という件の調査と修正を行ったんだけど

フォーム位置の再現はオリジナル(NanaTree)の頃から JEDI の TJvDockVSNetStyle 任せで
彼は本来メインフォームのサイズや位置とかを意識しているわけではなくて全ての窓のドッキング状態を管理するコンポーネントなので最大化なども「WindowState の変更」ではなく「Align := alClient」とかいうことをしているみたいとわかる

WindowState だとアクティブなところで最大化するんだけど
「Align」の方では Windows の仕様で常にプライマリモニタの作業領域が基準になる(https://groups.google.com/forum/#!topic/delphicbuilder-ml-archive/OJ1LBlNOMJU)のが原因だったようで

結局終了時に「現在のモニタナンバー」を記録しておいて
Ini.WriteInteger('MonitorNum',Monitor.MonitorNum);
起動時に「最大化していて」なおかつ「前回のモニタを違う」場合
if (IsZoomed(Self.Handle)) and(OldMonitorNum<>Monitor.MonitorNum) then
一端元のサイズに戻し
Self.WindowState:=wsNormal;
前回のモニタ位置に移動してから
Self.Left:=Left+Screen.Monitors[OldMonitorNum].Left;
Self.Top:=Left+Screen.Monitors[OldMonitorNum].Top;
再び最大化する
Self.WindowState:=wsMaximized;
ことで解決しました
(ここはもしかしたら一発で MonitorNum の移動が出来るのかも知れない)

しかしこうやって調べてたら TJvDockVSNetStyle って終了時に記録するとき最大化してたら元の位置を忘れちゃうのね
おいらは今まで TWindowPlacement で「最大化解除した時の位置とサイズを」きちんと保存する習慣があったから結構以外だったわ



余談
Delphi 関連をググってると結構自動翻訳された海外の掲示板とかがヒットするんだけど

モニターが変更された通知を受け取るとき自前で SendMessage で WM_WTSSESSION_CHANGE を送らなければならないと紹介されてて
他の人の発言で

私は古いバージョンDelphi5でこれをテストし、それだけに簡単に働いた:

Screen.Free;
Screen := TScreen.Create(Nil);

こんなアプローチがあって面白かった

TTreeView.Canvas のフォント

2020-09-08 22:06:38 | Delphi
スレで報告もらった「ノードタイトルの個別表示カスタマイズ」バグ
https://egg.5ch.net/test/read.cgi/software/1560074001/281

DrawText するときに
TTreeView のフォントが変われば TTreeView.Canvas のフォントも連動してるものだと思い込んでいたためのバグだと思っていたんだけど
保存されたデータからフォントを取り出すときちゃんと
Result.Style:=TreeView.Font.Style;
Result.Color:=TreeView.Font.Color;
Result.Size:=TreeView.Font.Size;
BackGroundColor:=TreeView.Color;
と TTreeView からベースを読み込んでから読み込んでる(多分本能的な処理)
Result.Name:=TreeView.Font.Name;
の一行が抜けていたのはおいらが抜けていたから

なんのこっちゃという感じのひとり言でした

Delphi

2020-04-01 00:18:03 | Delphi
Delphi Community Edition で Nana を構築しようとしたけどやっぱり古いコンポーネントを多く使っているので全く同じ物は出来ないなと盆正月GWと連休の度に何度か試行錯誤した結果
少々違うところがあっても他の面でよい点を盛り上げていけばいいし
暇を見て一から作っていこうかなと思ってた
……のにいつのまにか Delphi のライセンス条項が変わってきていた
最初にフリーの開発エディションとして発表されたときはボコボコもうけるようなシェアウェアでも作らない限り問題なさそうだったのに
今は「他の収入と合わせて$5000を超えてたらo(*≧□≦)o ダメ~!!」ってなってるらしい
そんなの学生さんかご隠居さんしか使えないではないか
Delphi1を買ったあと D2 D3 D3.1 D5 ...と Pro版買ってきて確かバージョンアップなら数万円だったし新規でも充分手の伸ばせる金額だったんだけど
いまでは最低でも二十万とか……しかも毎年保守料要るし
もう完全に企業相手しか考えてない
黄金期を作ったフリーウェア作家達が離れていったのは当然の帰結であると思う


そこでずっと安定を待っていた Lazarus For Delphi (フリー)なんだけど
新規の簡単なものを作ってみた限り Delphi5 並に使いやすいしちゃんと環境を構築すればモバイルアプリも作れるし最新OS でも問題ないし
今からどんどん成長していくと思うんだけどどどどどど

ちょっとスコープとかおかしくないっすか??
例えばあるソースで

public
function GatturiYomikomu(FileName:string): Integer;

ここの「FileName」でエラー出るからハテナと思ってその上の方を見ると
全然別のtype節にある

property FileName: String read FFileName;

と名前がかぶってると言いやがりやるのですよ
確かに aFileName と書けば済むことなんだけど
「スコープって知ってる?」って言いたくなるのは間違ってないよね?
ならもっと他にも引っかかるとこ出てくるんじゃね?って
もうその時点でやる気なくしちゃってその日は Lazarus 閉じちゃった

TNotePadのSelectionLength

2018-12-04 21:19:36 | Delphi
ちょっと仕事で使うツールを作るとき NanaTerry でもお世話になってる TNotePad を使った
で「テキストが選択されていないとき」というありふれた条件式でおかしな現象になった
こんなん作ったから使ってみてと渡していた同僚からコピーできるときと出来ないときがあると報告が……

(Sender as TAction).Enabled:=NotePad.SelectionLength>0;

本当いつもの通りこの一行だけなのになんでだろう?
といじくっていると右から選択したときだけ条件が False になってる
と Ctrl+Click で飛んで飛んでしていったら
function TNotePad.GetSelectionLength: integer;
begin
  result := FStr.SelEnd - FStr.SelStart;
end;

ここですね
function TNotePad.GetSelectionLength: integer;
begin
  result := Abs(FStr.SelEnd - FStr.SelStart);
end;



参考記事(新たな事実)
TNotePadのSelectionLength 2