はじめまして。どうしても自力で解決出来ないため、質問させて下さい。
環境は、Delphi7 professional/Windows XP sp3 です
①フォームにActionMainMenuBar、ActionManager、ImageListを配置
②Actionを設定し、ActionMainMenuBarにサブアイテムとして追加する
ということを目論んでいます。
しかし、ActionにImageIndexを設定(-1以外)すると、EAccessViolationが発生してしまうのです。
具体的には、
(前略)
type MainForm = class(TForm)
(略)
private
dA : array[0..9] of TAction;
public
end;
implimentation
procedure ToolsLoad;
var i : integer;
AC : TActionClientItem;
begin
AC:=MainForm.ActionManager1.ActionBars[0].Items[0];
for i:=0 to 9 do
begin
dA[i]:=TAction.Create(MainForm.ActionManager1);
dA[i].onExecute:=ToolsActionExecute;//これの中身は今のところ空っぽ。
dA[i].Caption:=○○;//実際にはファイルから読み込む
dA[i].Tag:=i;
dA[i].ImageIndex:=i; //この行をコメントにするとエラーは出ない
with AC.Items.Add do
begin
Action:=dA[i];
end;
end;
end;
順序を逆にしてMenuBarに追加してからImageIndexを指定した場合、何のエラーも出ない代わりに、画像の描画もなされません(そりゃそうだ)ので、恐らく画像を描画する時にエラーが出ていると思われます。
手の内を変えて直接MenuBarのImageIndexを変更しようとすると、
AC.ImageIndex:=0;
これはOKで、エラーも出ず画像も正しく表示されるのですが、
AC.Items[i].imageindex:=0;
という風に、サブアイテムにアクセスしようとすると、同じエラーが出ます。
今まで普通のMainMenuしか使ったことが無く、サブアイテムへのアクセスも手探りな状態で、ほとほと困り果てております(^^;
どんな些細なことでも構いませんので、どこが間違っているのか、御指摘下されば幸いです。
御指導のほど、何卒宜しくお願い申し上げます。
追記です。
エラーはこのprocedureの実行時に発生するのではなく、メニューをクリックしてサブアイテムが展開する瞬間に発生します。
CPUウインドウでも、TCustomActionControl.DrawGlyphのところにエラーが出ているみたいです。
サブアイテムではなく、ルートアイテムにActionを追加した場合は、その追加した瞬間にエラーになります。
この場合はアイテムを追加した後すぐに描画が行われますから、やはり描画時にエラーが発生していると考えています。
「リストのインデックスが範囲を超えています」というエラーは出ませんし、また、
MainForm.ActionManager1.ActionBars[0].Items[0].ImageIndex:=i;
とするとルートアイテムの画像は変えられるので、ImageListとのリンクは問題ないと思うのですが…。
それにしても、上記のは問題ないくせに、
MainForm.ActionManager1.ActionBars[0].Items[0].Items[0].ImageIndex:=i;
とすると、やっぱりEAccessViolationなのが謎です。
MainForm.ActionManager1.ActionBars[0].Items[0].Items[0].free;
とすると、サブアイテムを解放することは出来るので、サブアイテムへのアクセスは間違ってないと思うのですが…。
glyphプロパティがあれば直接書き込めるのに…。などと恨めしく思ってしまいます。
今回、日々仕事で得られる健康診断のデータを入力し、印刷して患者さんに渡し、ゆくゆくは蓄積したデータから検索をかけて臨床研究の助けになうような、そういうアプリケーションを作っていて、その本体自体はもう完成しているのですが、ここの部分だけが解決していない状況です。
このアプリのメインメニューから、仕事の助けになるような外部ツール類を呼び出せるようにしたいと思っていて、そのツール類の登録や削除を誰でも自由に出来るように設計したのですが、どうせなら、そのメニュー項目に外部ツール類のアイコン画像を張り付けたいわけです。
画像を吸い出してImageListに放り込むところまでは問題なく出来ているので、あとはメニューに貼り付けるだけなのですが、簡単に出来るだろうと思っていたら思わぬ落とし穴に嵌ってしまいました。
別に出来なくても支障ないと言えばそれまでですが、どうせならアイコン画像が表示された方が綺麗ですよね(苦笑)
それに、今後の勉強という意味でも、なんとか解決できればと思っています。
私、出た大学も職業も全くコンピュータとは無縁で、教育を受けたこともなく、時々趣味でDelphiをする程度なので、根本的に考え方が間違っているところはあると思います。
インターネットで優れたプログラマーの方々のソースを見るたびに、そう思います。
今回も、どこかで誤りがあるはずなのですが、どうしても自力で解決出来ません。
お手数をお掛けいたしますが、御指導宜しくお願い致します。
ImageListはどのように設定していますか?
はい。フォームにImageListコンポを配置して、
var ic : TIcon;
fn : TFileName;
begin
(略)
try
ic.Handle := ExtractIcon(hInstance, PChar(fn), 0);
ToolsImageList.AddIcon(ic);
finally
ic.Free;
end;
end;
という感じで、アイコン画像を登録しています。
ただ、この部分をコメントにして、元々16×16の画像をリストに登録しておいたものを使っても、同じエラーになってしまいます。
もっと単純化したモデルを作ってみたのですが、アイテムとかサブアイテムとかじゃなくて、新たに追加されたactionにimageindexを指定すると、エラーになるようなのです。
大変お手数ですが、この単純化したモデルを見て頂けませんでしょうか。
http://daisin.pinoko.jp/secret/test.lzh
元々サブアイテムが1個登録されている状態で、
1番目のボタンを押すと、サブアイテムが1つ追加される
2番目のボタンを押すと、元々あったサブアイテムに画像が表示される
3番目のボタンを押すと、追加されたサブアイテムに画像が表示される
というプログラムです。
しかし、実際には、3番目のボタンを押した後でメニューを展開するとエラーになります。
画像さえ貼らなければ、ちゃんとアイテムが追加されるのに…もうわけが分かりません(涙)
BDSのヘルプだけど
通常,アプリケーションではアクションオブジェクトを明示的に作成しません。設計時にアクションマネージャやアクションリストコンポーネントにアクションを追加すると,アクションが自動的に作成されます。実行時に TAction をインスタンス化する場合は,Create メソッドを呼び出してから,
新しいアクションの ActionList プロパティに,TActionList コンポーネントまたは TActionManager コンポーネントを割り当てます。
つまり
procedure TForm1.Button1Click(Sender: TObject);
begin
AC:=Form1.ActionManager1.ActionBars[0].Items[0];
dA:=TAction.Create(Self);
with dA do
begin
caption:='Item1';
onExecute:=Action1Execute;
ActionList := ActionManager1; //■追加
end;
AC.Items.Add.Action:=dA;
end;
でエラーは出なくなる
まさにドンピシャの答えです!
これまでの実験(?)から、ActionManager→ImageListのリンクは機能しているはずなので、ActionそのものがActionManagerの「子」になっていないことが原因ではないかと、思ってはいました。
そこでこっそり、parent:= とか試してみたのですが、未定義の識別子と怒られてしまいました(笑)
しかし、ImageIndexさえ指定しなければエラーは出ないので、それもあって混乱していました。
なるほど、ActionListプロパティというのがあったのですね〜。
この度は御丁寧な御解答を賜り、大変ありがとうございました。
お陰様で、このソフトだけでなく、私自身大変勉強になりました。
今後また機会がございましたら、御指導御鞭撻の程宜しくお願い申しあげます。
ツイート | ![]() |