////////////////////////////////////////////////////////////////////////////////
開発環境 : Visual C++ 6.0
動作環境 : Windows 98 Second Edition
MFC使用 MDIベース
////////////////////////////////////////////////////////////////////////////////
あるCListViewから派生したクラスでダブルクリックのメッセージハンドラを
追加したのですが、ある時から、それ以外のハンドラの追加ができなくなって
しまいました。
追加しようとすると、以下のダイアログが表示されます。
Parsing error: (が必要です。
インプット ライン:virtual afx_msg void OnLButtonDbClk(UINT nFlags, CPoint
point);
ヘッダーファイルのメッセージマップの記述を自分で誤って書き変えてしまった
のかと思ったのですが、下のようになっており、他のクラスのものと比べ
問題がなさそうに見えます。
// 生成されたメッセージ マップ関数
protected:
//{{AFX_MSG(CParamterView)
virtual afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
仮想関数を追加しようとしても同じダイアログが表示されます。他のクラスは問題
ありません。
何か、問題があるのでしょうか。どなたか、よろしくお願い致します。
'virtual'が入っているのはナゼ?
nさん、お返事ありがとうございます。
実は、このヘッダーのクラス(CParameterViewクラス)を基本クラス
とするCAutoViewクラスがあります。
class CAutoView : public CParameterView
実は、言いそびれたのですが、こちらのクラスでも同様に
メッセージハンドラの追加ができません。
こちらのCAutoViewクラスには、よく見ると
// 生成されたメッセージ マップ関数
protected:
//{{AFX_MSG(CAutoView)
//}}AFX_MSG
のような記述が見当たりません。ひょっとして、何か関係があるのでしょうか。
少し調べてみます。
ClassWizardが単に、
//{{AFX_MSG(~)
//}}AFX_MSG
の間の'virtual'というキーワードを読めない、ということだと思います。
>記述が見当たりません
自分で編集してる間にうっかり消してしまったのでは。
改めてその類を追加すれば(クラス名もきちんと付けて)OKです。
nさん、先日はにお返事ありがとうございました。
その後、nさんのご指摘どおり、
//{{AFX_MSG(~)
//}}AFX_MSG
の部分を加えてみたのですが、やはり例のダイアログが表示されてしまい
うまく行きません。
その後、いつからこうなったのだろうと、過去のファイルを探していった
のですが、このようになってしまった問題のファイルを削除してしまったらしく、
原因が突き止めらず思案に暮れています。
もし、nさん以外の方でも知っていたら教えていただきたいのですが、
初期にプロジェクトを立ち上げた時、ファイルに
// アトリビュート
// オペレーション
// インプリメンテーション
などがコメントされており、それぞれの部分に関数などの定義が行われて
いると思いますが、これらの場所などは変えてはいけないのでしょうか。
どうしても、自分らしく見やすく整理しておきたいと思い、位置を変えたり
することがあるのですが、位置を変えても、ハンドラの追加や関数の
オーバーライドなどには問題がないのでしょうか。
すいません補足です。
>改めてその類を追加すれば(クラス名もきちんと付けて)OK
一度、*.clwファイルを消してからClassWizardを開かないと変更が反映されないです。
また、
'virtual'という語を
//{{AFX_MSG(~)
//}}AFX_MSG
の間から取り除けば、「Parsing error: (が必要です」云々のダイアログは出なく
なるはずです。
// アトリビュート
// オペレーション
// インプリメンテーション
の部分の位置や順序は問題ありません。
そのエラーを再現するにはどうするかやってみた。
結論。
AFX_VIRTUALとAFX_MSGを混同しているだろ。
nさんが何度も言ってる『virtualを消してください』というのを無視してるだろ。
class CTestView : public CListView
{
…略…
// オーバーライド
// ClassWizard は仮想関数のオーバーライドを生成します。
//{{AFX_VIRTUAL(CTestView)
public:
virtual void OnDraw(CDC* pDC); // このビューを描画する際にオーバーラ
イドされます。
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual void OnInitialUpdate(); // 構築後の最初の1度だけ呼び出されま
す。
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL
…略…
// 生成されたメッセージ マップ関数
protected:
//{{AFX_MSG(CTestView)
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); // ←ここに
virtualをつけるとダメなんだよ。
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
見づらくなったのでポイントだけ貼りなおすぞ。
class CTestView : public CListView
{
…略…
// オーバーライド
// ClassWizard は仮想関数のオーバーライドを生成します。
//{{AFX_VIRTUAL(CTestView)
…仮想関数のオーバーライドなのでvirtualのオンパレード…
//}}AFX_VIRTUAL
…略…
// 生成されたメッセージ マップ関数
protected:
//{{AFX_MSG(CTestView)
… !! メッセージマップにvirtualをつけると !! …
… !! クラスウィザードが解析できない !! …
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
追記
>class CAutoView : public CParameterView
>実は、言いそびれたのですが、こちらのクラスでも同様に
>メッセージハンドラの追加ができません。
これはpublicクラスがMFCじゃないから無理だよ。
nさん、kajikiさん、お返事、ありがとうございました。
kajikiさんのご指摘どおり、AFX_VIRTUALとAFX_MSGを
混同してたようです。すみません。nさんの言うとおり、
実際、基本クラスのvirtualを消すと
うまくClassWizardが立ち上がるようになりました。
ご指摘されて思い出したのですが、確か、新しいViewクラスを
作った時に、ダブルクリックの処理だけを基本クラスと異なるものにしたいと、
自分で強引にAFX_MSGの前にvirtualをつけてオーバーライドしたのだと
思います。基本クラスがMFCでない限り、このようなことはできないのですね。
きっとかなり基本的なことを質問してたような気がします。nさん、
kajikiさん、申し訳ありませんでした。ですが、これで、次の処理へ
進むことができ、大変助かりました。
ありがとうございました。
>ダブルクリックの処理だけを基本クラスと異なるものにしたい
そういうときはサブクラス化するといいよ。
サブクラス化について調べてみなよ。きっと「これだ!」って思うから。
CParameterView が CListView の派生クラスとして,
> ダブルクリックの処理だけを基本クラスと異なるものにしたい
ために,CParameterView の派生クラス CAutoView を作るという考えは間違っていません。
virtual を付けたのがまずかっただけです。
CAutoView へのメッセージハンドラの追加も問題なく行えます。
ただ,classWizard でメッセージハンドラ追加するためには,
//{{AFX_MSG
//}}AFX_MSG
なんてのを適切に記述しておかないといけません。
追記です。
> CAutoView へのメッセージハンドラの追加も問題なく行えます。
もちろん,CAutoView のヘッダファイルには,
DECLARE_MESSAGE_MAP
ソースファイルには,
BEGIN_MESSAGE_MAP
END_MESSAGE_MAP
が必要です。
# とりあえず CAutoView の基底クラスを CListView にしておいて,
# あとから CListView を CParameterView に置換するという方法もあります。
kajikiさん、kazumaさん、お返事ありがとうございました。
kazumaさん、書込みをして頂いていたのですね。気づきませんでした。
申し訳ありません。
自作の派生クラスで、メッセージハンドラの処理だけをオーバーライド
するということができるのですね。これは助かります。これなら
今後、Viewクラスを次々作っていこうと思っていたので、問題なく
進めていけそうです。
ですが、私自身、問題になっているクラスでkazumaさんの言う
//{{AFX_MSG
//}}AFX_MSG
や
DECLARE_MESSAGE_MAP
BEGIN_MESSAGE_MAP
END_MESSAGE_MAP
を加えてみたのですが、なぜかうまく行きません。
実装する場所などに問題があるのかとも思うのですが
今のところ何が悪いのか見つけれず困っています。
諦めて、kazumaさんいう、基本クラスをはじめCListViewにして、後で
置換してしまうという方法をとろうかとも考えているのですが、
その前に、もし、お忙しくなければ、一つ確認させて下さい。
現在、私の自作クラスCAutoView : public CParameterViewは
クラスビューで右クリックしても、通常のビュークラスで見られる
「Windowsメッセージハンドラの追加(A)」
などの表示が見られません。
>CAutoView へのメッセージハンドラの追加も問題なく行えます。
との事ですが、もしうまく行けば、このようにクラスビューから
ハンドラを追加できると言うことでしょうか。