2024/09/29

TRichEdit.SelAttributes.Name の欠落

 さて「TRichEdit.SelAttributes.Name の欠落

という事柄に何日も悩まされていたわけですが、どうやら一段落ついたようなので覚え書き。


Delphi2009 前後の RichEdit で「UD デジタル 教科書体 N-B」など少し長い名前の日本語名を持つ文字列をドラッグ&ドロップ或いはクリップボードから貼り付けた場合にフォント名の最後の方が欠落してしまうという問題。

Delphi XE でも発生して、Delphi 11 以降では、TRichEditコンポーネントが、RichEdit 4.1 に変わっているので問題ないらしい。

Delphi5 では問題ないので最初は Delphi が内部で UniCode に対応した時のせいかと思ったんだけど、オリジナルの NanaTree でもおかしくなるので(多分 Delphi6 製)これは結構深い問題かなと、ChatGPT らと話し合いながら色々と探索。


■UniCode 方面から攻めたので最初は「型」と「エンコード」を重点に調べる。

昔から RichEdit くんは、ASCII でずっと頑張っていたから……

VCL ソースを D5 と比較しながら、ちょっと修正してはコンパイル→ここでもない→一旦閉じて→またいじって……

■自分でドラッグ&ドロップやってみれば同じようなことを GREP して探せるのでは?

■どうやってドラッグ中のデータを参照するの? > ChatGPT

ほーん

なる

■どうせなら RichEdit 自身のドラッグ&ドロップ無効にして自分で処理してしまえ!

■出来たんじゃね?

■ペーストも処理しなくちゃだわ

■出来たんじゃね?


満足して微調整(移動する場合元の文字列を削除したりするのもやらなくちゃいけないから SelStart より前にドロップしたとか色々ややこしい)



【実際には TJvRichEdit 使っているので】

■画像とかファイルとかの外部からのドラッグ&ドロップが出来なくなってるじゃん!

これは今までやってきたことすべてリセットやん!


■TJvRichEdit には OnQueryAcceptData イベントがあってここで唯一「IDataObject」を参照することが出来る。

ここに今までやってきたことを全部詰め込めばええやんか


多分これでファイナルアンサー

サンプル♪ヘ(^^ヘ)(ノ^^)ノヘ(^^ヘ)(ノ^^)ノ♪
フォームに TRichEdit 貼り付けて Form.OnCreate で適当に文字列入れてフォント変更。
TRichEdit の OnSelectionChang でフォント名を参照出来るようにする。
uses に(無かったら)ComCtrls, RichEdit, ActiveX の3つを追加。

以下ソース
  
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, JvExStdCtrls, JvRichEdit, ComCtrls, RichEdit, ActiveX;

type
  TForm1 = class(TForm)
    JvRichEdit1: TJvRichEdit;
    procedure JvRichEdit1QueryAcceptData(Sender: TObject;
      const ADataObject: IDataObject; var AFormat: Word;
      ClipboardOperationKind: Cardinal; Really: Boolean; IconMetaPict: Cardinal;
      var Handled: Boolean);
    procedure FormCreate(Sender: TObject);
    procedure JvRichEdit1SelectionChange(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function InsertRTF(Target:TRichEdit;RTF:string):Boolean;
var
  SL:TStringList;
  ES:TEditStream;
  Rich:TRichEdit;
  MS:TMemoryStream;

  // コールバック関数
  function myCallback(dwCookie:DWORD; pbBuff:PByte;
    cb:Longint; var pcb:Longint):DWORD; stdcall;
  var
    MS:TMemoryStream;
  begin
    Result:=0;
    MS:=TMemoryStream(dwCookie);
    pcb:=MS.Read(pbBuff^, cb);
  end;

begin
  SL:=TStringList.Create;
  try
    SL.Add(RTF);

    Rich:=TRichEdit.Create(nil);
    try
      Rich.Visible:=False;
      Rich.Parent:=Application.MainForm;
      Rich.PlainText:=False;//.StreamFormat:=sfRichText;

      MS:=TMemoryStream.Create;
      try
        MS.Position:=0;
        SL.SaveToStream(MS,TEncoding.ASCII);
        MS.Position:=0;
        ES.dwCookie:=DWORD(MS);
        ES.dwError:=0;
        ES.pfnCallback:=@myCallback;

        Target.Perform(EM_STREAMIN, SF_RTF or SFF_SELECTION, LParam(@ES));

      finally
        MS.Free;
      end;
    finally
      Rich.Free;
    end;
  finally
    SL.Free;
  end;
  Result:=True;
end;

procedure TForm1.FormCreate(Sender: TObject);
const
  TestText='ABCDE';
  FontName='UDデジタル教科書体 N-B';
begin
  Font.Size:=12;//←我、老眼なので
//ここだけわからん何故かデフォのTahomaだとD&Dのあと日本語が文字化けする
  Font.Name:='MS ゴシック';

  JvRichEdit1.Lines.Text:=TestText;
  JvRichEdit1.SelStart:=0;
  JvRichEdit1.SelLength:=1;
  JvRichEdit1.SelAttributes.Name:=FontName;
  JvRichEdit1.SelAttributes.Color:=clRed;
  JvRichEdit1.SelAttributes.Style:=[fsBold];
end;

procedure TForm1.JvRichEdit1SelectionChange(Sender: TObject);
begin
  Caption:=JvRichEdit1.SelAttributes.Name;
end;

procedure TForm1.JvRichEdit1QueryAcceptData(Sender: TObject;
  const ADataObject: IDataObject; var AFormat: Word;
  ClipboardOperationKind: Cardinal; Really: Boolean; IconMetaPict: Cardinal;
  var Handled: Boolean);
var
  FormatEtc: TFormatEtc;
  RtfText: string;
  Medium: TStgMedium;
  GlobalMem: HGlobal;
  pText: PAnsiChar;
  CF_RTF: UINT;
begin
  if Really then
  begin
// IDataObjectからデータを取得
    CF_RTF:=RegisterClipboardFormat('Rich Text Format');
    FormatEtc.cfFormat := CF_RTF;  // CF_RTFを登録
    FormatEtc.ptd := nil;
    FormatEtc.dwAspect := DVASPECT_CONTENT;
    FormatEtc.lindex := -1;
    FormatEtc.tymed := TYMED_HGLOBAL;
//リッチエディタ上でのD&D
    if ADataObject.GetData(FormatEtc, Medium) = S_OK then
    begin
      GlobalMem := Medium.hGlobal;
      pText := GlobalLock(GlobalMem);
      SetString(RtfText, pText, GlobalSize(GlobalMem));
      GlobalUnlock(GlobalMem);
      ReleaseStgMedium(Medium);
      Handled:=True;//これがきも!
      InsertRTF(TRichEdit(JvRichEdit1),RtfText);
    end;
  end;
end;

end.

そして出来上がったのがこちらです。

ドラッグ&ドロップで移動しても他のソフトから貼り付けても「UD デジタル 教科書体 N-B」のフォント名は壊れていない
(ちなみに Ctrl+ でコピードラッグです)

ここまでやって凄く不思議な現象が。
今、上で追加したソースの InsertRTF と QueryAcceptData の部分を削除して実行したらフォント名の欠落は起きないんだよなー。
まあ最新の開発環境を使えってはなしなんだけどそれはそれで最初のリンク先読んで貰ったらわかるけど
RichEdit 4.x がウンチなんよね

2020/02/14

覚え書き

多分今まで出ていたアプリケーションエラー全ての根源がわかった
オリジナルからあったサブマリンバグ

オリジナル当初からノード破棄したときのイベントで
・ノードごとに持っていたデータを破棄して(このデータに対してはちゃんとFreeAndNilっていう破棄したあと「nil(ヌル)」を代入してる)
・ノードのタイトルに「」を代入
・ノード移動履歴から削除
という三つの処理をしてたんだけどノード自体に「nil(ヌル)」を入れていなかった

オリジナルもおいらもノードを参照するときは必ず
Assigned 関数というのを使ってそのノードがちゃんと使えるのか確認してるんだけど
その関数は「変数または手続き型変数が nil (値が割り当てられていない) かをテストします」というもので
オリジナルではあんまり込み入ったことをしていなかったから表面化していなかっただけ
ただ一つだけこれが原因だろうなというのが UniCode ファイルを読み込んで
---------------------------
警告
---------------------------
xx.nnaをnanaファイルとして読み込めませんでした。
テキストファイルとして読み込んでみますか?
---------------------------
はい(Y)   いいえ(N) 
---------------------------

いいえを選ぶと Access violation になってタスクキルしか出来なくなる



オリジナルソース
//----------------------------------------
// ノード破棄
//----------------------------------------


procedure TTreeForm.TreeViewFreeNode(Sender: TBaseVirtualTree;
  Node: PVirtualNode);
begin
  FreeAndNil(NodeData(Node).Strings);
  NodeData(Node).Caption := '';
  MainForm.TreeViewFreeNode(Sender);
//↓に一行入れるだけで多い日も安心
  Node:=nil;
end;

2020/02/08

四捨五入

普段は何も考えてなかったけどやっぱり四捨五入はちゃんとしないとね

↓の「Roundoff 関数」は Delphi5 のヘルプ「Round 関数」のところに載ってる
通常の四捨五入を使う場合には以下の関数を使用してください』というやつ

100/6=16.6666666...
Trunc だと切り捨てられちゃう





function Roundoff(X: Extended):integer; begin if x >= 0 then Result := Trunc(x + 0.5) else Result := Trunc(x - 0.5); end; procedure TForm1.Button1Click(Sender: TObject); var i:integer; begin for i:=1 to 10 do begin Memo1.Lines.Add(IntToStr(Roundoff(100/i))+' '+IntToStr(Trunc(100/i))); end; end; 

2019/11/17

ぬるぽ

これはわかりやすい画像

if Assigned(トイレットペーパー) then//トイレットペーパーにアクセスできたら
ShowMessage(IntToStr(Length(トイレットペーパー)));//長さを表示

↓この一行がないと
if Assigned(トイレットペーパー) then
右に見に行ったときに「トイレットペーパー?そんなのねーじゃん!」ってエラーになる
左側なら「ゼロだよ~♪」って返ってくる

2014/07/01

でるけどは残念ながら休刊となりました

>6ヶ月間発行がなく、残念ながら休刊となりました
>
>・メルマガID   :0000016258
>・メルマガタイトル:Delphi 買ったけど。。
>・最新発行日   :2013/12/01
>-------------------------------------------------
>
>上記メールマガジンにつきましては、
>長期に渡り発行されていないため、まことに残念ではありますが
>休刊措置を行わせていただきました。

XEシリーズになってから一つもさわっていないので
もう新しい話題とかついていけません
こちらには何か思いついたこととかあればまた書くこともあるかも知れません

それでは(^.^)/~~

2013/01/05

XE3 での TImage / TImageControl / TImageViewer

メモ

[要注意コンポーネント (2) - DEKO のアヤシいお部屋]
http://ht-deko.minim.ne.jp/ft1301.html#130105_01

2013/01/01

リストのインデックスが範囲を超えています

さすがに「それって for to do ぢゃなくて downto ぢゃね?」っていうのはもう十年以上前に卒業したけど

i,j:integer;

とかの多重ループで Items[i]  と Items[j]  を間違ってしまってなかなか気付かない
思い込みがあるから何度読み返してもわからなくて悩んでしまう

2012/10/27

知らなかった

XE3への移植時の問題(exe の肥大化)
http://hpcgi1.nifty.com/MADIA/DelphiBBS/wwwlng.cgi?print+201210/12100029.txt

DEKO 2012/10/27(土) 04:58:10

余談ですが、Delphi XE 以降のデフォルトアイコンは Vista アイコンに対応しており、256x256 アイコンが含まれています。


...ここまではいいのですが、アイコンには以下のリソースが含まれています。

256x256 Bitmap ARGB
48x48 Bitmap ARGB
32x32 Bitmap ARGB
24x24 Bitmap ARGB
16x16 Bitmap ARGB
48x48 Bitmap 256 Color
32x32 Bitmap 256 Color
24x24 Bitmap 256 Color
16x16 Bitmap 256 Color

アフォな事に 256x256 アイコンが PNG 形式ではありません。
このため、アイコンだけで 290KB もあります (XE2 以降)。

256x256 アイコンを PNG 形式にすれば、Vista / 7 /8 で特大アイコンが使える上に、サイズが 90KB 程度になります。
つまり、EXE のサイズも 200KB 程小さくなります。

なお、2005~2010 の デフォルトアイコンは 33KB、Delphi 7 より前のデフォルトアイコンは 4KB を超える事はありません。

2012/10/25

UXとUI

恥ずかしながら UX と言う言葉を知らなかったのでググってみた いろいろと説明があったけどここが一番わかりやすかった 写真が語るUXとUIの違い - Nothing ventured, nothing gained.
UXはUXのハニカム構造という図でも知られているように、役に立つか(Useful)、使いやすいか(Usable)、望ましいか(Desirable)、価値があるか(Valuable)、見つけやすいか(Findable)、アクセスしやすいか(Accessible)、信頼できるか(Credible)などにより構成される。
http://design.org/blog/difference-between-ux-and-ui-subtleties-explained-cereal

2011/12/27

64bitのProgram Filesを指すショートカット

メモ

|おそらくですが、64bit版のWindowsで、秀丸エディタは32bit版で、対象のシ
|ョートカットは64bitアプリが入る"Program Files"("Program Files (x86)"で
|はない)を指しているときかと思います。
|
|32bit版のアプリケーションが64bitのProgram Filesを指すショートカットを解
|釈すると勝手にx86のほうにリダイレクトされてしまうということがあるようで
|す。
|そのため、x86のほうを読みに行こうとして失敗します。
|
|こういった問題は32bitのアプリケーション全てで起きるようで、例えばChrome
|は32bit版だと思いますが、Chromeにドロップしても同じことが起きると思いま
|す。
|
|インストーラのショートカットの確認でも似た問題に直面していろいろ調べたこ
|とがあったのですが、結局これを回避する手段は無さそうで、インストーラに関
|しては無理やりショートカットを作成するような対策しかできませんでした。
|
|64bit版のWindowsでは64bit版のアプリケーションを使うとこういった問題は起
|きないようです。

RE:30704 カレントフォルダへの移動に失敗します - 秀丸エディタ&関連ソフトサポート会議室

2011/10/17

XE2 UD1

Update 1の詳細については、こちらの記事をご覧ください。
・Delphi XE2 および C++Builder XE2 の重要な製品アップデート
 ⇒ http://edn.embarcadero.com/jp/article/41659

Update 1に含まれる120件を超えるバグ修正については、こちらをご覧ください。
・Delphi XE2 / C++Builder XE2 Update 1 における不具合修正リスト
 ⇒ http://edn.embarcadero.com/jp/article/41673


120件を超えるバグ修正

そんな自慢げに言うことでは無かろう……

2011/09/04

XE2

http://togetter.com/li/183468

インストール祭り状態?
正負いろんな意見が入り乱れてますねー

2011/02/26

Resource Workshop

Windows7-64 を入れてから初めて「Resource Workshop」を起動しました
エラーです
そういえばこれはちゃんとインストールしないといけないのでした
インストール……
出来ませんでした(T▽T)

16bti アプリでしたねぇこれ
NT 系(NT3.51~Vista32 含む)でも全く問題なく使えていたので忘れていました
Vista32 では 16bit Icon のロードがすでに拒否されていましたが
64Bit OS ではとうとう全く使えなくなってしまったということですね
とても使いやすかったんですが
まぁサブマシンは XP なのでそちらで使ってもいいのですが
それもまたぢゃまくさいし

とりあえず「アイコン作成ソフト DotWork」の方は問題ないみたいです

2011/01/22

エクスプローラ VCL

ExplorerBrowserの作成 - EternalWindows
この記事を見て
エクスプローラが簡単に作れそう!
絶対ググれば Delphi で書いてる人はいるはず!

やっぱりあったね
さすがさすがの Mr.XRAY さん!
Delphi(Win32)サンプルプログラム集「947_ExplorerBrowser

Vistaよりも前のOSではコンパイル不可.EXEの実行も不可
しかたないでしょう
Delphi 2010よりも前のDelphiではコンパイル不可
それもまた、仕方……
げげーー!
なんたルチア!

2009 でコンパイルしましたが確かにエラーが出ました
自分で定義するなりすればどうにかなるんでしょうかね?
当分まとまった時間がとれないのでまたしばらく棚上げです……

2011/01/04

G4

Delphi 買ったけど。。No.0225
で「どうせなら G4 まで待てよ」とか書いてたけど
Intel SSD の話なんで「G3」の間違いですね

どんだけ待つつもりなんだよって…

Windows7 と Delphi2009

なぜ自動アップデートではないのかわからないけど
Hotfix 2
を入れないと「Ctrl + F2」とかしたときに
- "Assertion failure: "(!SetThreadContext failed")" ..." というメッセージのエラーが発生する。
- Windows 7 では、デバッガの下で実行すると、デバッグ対象アプリケーションが停止時にクラッシュするおそれがある。

公式サイトでログインすれば落とせるけど D5 みたいに
落とせなくなったときのために探したらここにあった
http://proisk.ru/?q=codegear+radstudio+2009+hf

2010/11/05

Delphiで風景画を描いてみた

goo

【Delphiで風景画を描いてみた】
という動画を観た

「Terragen」みたいなソフトを作るんだと思ったら全然違った

登録タグは、こんな感じ
描いてみた
Delphi
風景画
プログラミング
TurboDelphi
ね、簡単でしょう?
才能の無駄遣い
絵描きは5:10から

2010/08/30

そーなんだー

Delphi はずっと使っているが、Delphi の仕事を受注したことは過去に 2 回しかない
中村拓男さん - 「Delphi15y Meetup」参加記 - 酒と蕎麦と IT と