Halbowさんのサイトを頼りに、サブクラス化でScrollBoxのスクロールを検知して、処理を加えたかったんですが、コンパイル後にFormのOncreate部で「そのウィンドウにスクロールバーはありません」とエラーが出ます。
TScrollBox.WindowProcに任意の手続きを突っ込んだところでエラーが出るのは分かったんですが、理由が不明で困ってます。
最初は、スクロールバーが表示されてない状態だから起きたのかを思って、Halbowさんのサンプルを少しずつ削ったりして、検証したんですがサンプルの方だとスクロールバーがなくても全然問題ないみたいだし…
//////////////////////////
private
{ Private 宣言 }
public
{ Public 宣言 }
OriginalProc:TWndMethod;
procedure GetMessage(var Msg:TMessage);
//////////////////////////
//////////////////////////
procedure TfrmMain.FormCreate(Sender: TObject);
begin
OriginalProc := sbxArtBoard.WindowProc;
sbxArtBoard.WindowProc := GetMessage;
end;
procedure TfrmMain.GetMessage(var Msg: TMessage);
begin
//無記述
end;
//////////////////////////
> Halbowさんのサンプルを少しずつ削ったりして、検証したんですがサンプルの方だとスクロールバーがなくても全然問題ないみたいだし
Halbowさんのサンプルは何も削らずそのままで問題なかったということですか?
> FormのOnCreate部で「そのウィンドウにスクロールバーはありません」とエラーが出ます。
Halbowさんのサンプルの FormCreate ではサブクラスを実行する前に
Label1.Left := 1000;
Label1.Top := 1000;
の2行があり、これでスクロールバーを表示させている事にはお気づきですか。
追伸
私は Halbow さんの弟子ですので(本人は弟子にした覚えはないようですが)何のことか解るので気にもしませんでしたが、こういう場合は必ず出所を書きましょう。
今回の件は
http://homepage2.nifty.com/Mr_XRAY/Halbow/VCL03.html
です。
配慮足らずで失礼しました。
まずサンプル通りに作成して問題ないのを確認して、
次の
//Memo1.ScrollBars := ssVertical;
//Label1.Left := 1000;
//Label1.Top := 1000;
コメント化してコンパイルして通ったんで、スクロールバーの非表示以外で原因があるのかなと思ったんです。
ScrollBoxはタブコントロール上にあります。
> procedure TfrmMain.GetMessage(var Msg: TMessage);
> begin
> // 無記述
> end;
実際に「無記述」のままコンパイルしたのであれば、何かと問題がおこりそうです。
inherited が必要でしょう。
この場合
procedure TfrmMain.GetMessage(var Msg: TMessage);
begin
OriginalProc(Msg); // <---
// 無記述 ここに追加したい(例えばスクロールを感知する)機能を記述
end;
ありがとうございます。
なんとか動くようになりました。
が、なぜこの処理を記述するのかがよくわかってません。
お手数ですが解説もらってもいいでしょうか?
また、inheritedについても「コンポーネント開発のときに、特定の親クラスを指すことができないプロパティ制御のときだけ前に宣言する」としか覚えてないんです。
間違った覚え方でしょうか?
inherit(相続・継承する)の意味の inherited は、上位クラスのどのメソッドを使うか、相続することにするかを指定します。
サブクラス化というのは、コンポーネントやオブジェクトのように「継承」を使わず「そのものに成り代わる」という手法を使って用意されていない機能を追加します。
今回の場合、TScrollBox.WindowProc を TfrmMain.GetMessage に取り替えたわけです。
したがって、inherited そのものは使いませんし、使えません。
しかし、TScrollBox を機能させるためには、通常 TScrollBox.WindowProc で行っていることをまず実行させないといけません。
そのためには TfrmMain.GetMessage の中にそれをすべて記述しないといけないのですが、そんなことをしなくても
OriginalProc(Msg);
と1行書けば済むわけです。
この行為がオブジェクト・コンポーネントでの inherited の役割に当たるという意味で 「inherited が必要」と書いてしまいました。
混乱させて申し訳ない。
ついでに述べると、「スクロールを検知して、処理を加えたかった」という処理がどういうものか解りませんが、できるならサブクラス化を使わず ScrollBox を継承したコンポーネントにしてしまうのが一番良いでしょう。
しかし、簡単な処理をするだけだし、今後同じような事を必要とする可能性も少なく、わざわざコンポーネントを作るよりも簡単に済ませたい場合やコンポーネントにしたいが採用に値するコンポが見つからない場合、あるいは作っている余裕が無い場合にはサブクラス化も悪くありません。
良いコンポがあったとしても、実行ファイルサイズを少しでも小さくした場合も有効でしょう。
Halbow さんのこの章に学んでスクロールイベントを実装した ScrollBox のソースを公開していますので、よければ参考にしてください。
http://sadoyama.sakura.ne.jp/world/htm/compo/scrollbox.htm
丁寧に教えて頂いて、ありがとうございます。
また少し、Delphiの応用知識が増えました。
使いこなすにはまだ熟練が足りませんが、掘り下げていきたいと思います。
ツイート | ![]() |