ViewクラスからあるDialogクラスの関数にアクセス

[戻る]
nickt [E-Mail] 2007/10/03(水) 17:40:14
非常に初歩的な質問ですがよろしくお願いいたします。
VC++ 6.0 MFCで、Waveファイルを取り扱うアプリケーションを作り始めましたが、
Viewクラスが大きくなりましたので、Dialogクラスの.hと.cppに関数定義しViewからコ
ールしてみることにしました。

Dialogクラスで下記のように定義し、

 void DlgExtFunc (CDC* pDC)
{
    pDC->TextOut( 50, 50, "External Function Call");

}


Viewクラスで下記のように呼び出したいのですが、

void CFirFilterView::OnMenuAnalyze(CDC* pDC)
{    CDspScale    Dsp;

    //CDspScale::DlgExtFunc(CDC* pDC);
    Dsp->DlgExtFunc(CDC* pDC);

}

コンパイルすると、Viewクラス内に定義されていないのでエラーになってしまいます。

何とか解決方法を見つけて、別のクラスの関数をコールできる形を作りたく、アドバイ
スよろしくお願いいたします。

しま 2007/10/03(水) 22:05:38
>コンパイルすると、Viewクラス内に定義されていないのでエラーになってしまいます。
一体どんなエラーなんでしょうか?
エラーの一言だけでは私には何のことだか分かりません
クラス CDspScale なんか知らないと言っているのですか?
それとも void DlgExtFunc (CDC* pDC) なんて知らないといっているのですか?

>Dialogクラスで下記のように定義し、
>
> void DlgExtFunc (CDC* pDC)
>{
>    pDC->TextOut( 50, 50, "External Function Call");
>}
なんて書いてもダイアログクラスのメンバー関数なんかじゃありませんよ


>何とか解決方法を見つけて、別のクラスの関数をコールできる形を作りたく、
>アドバイスよろしくお願いいたします。
アドバイスがお望みなのでアドバイスしかしません
落ち着いてよく考えましょう

wclrp ( 'o') 2007/10/03(水) 22:22:13
>コンパイルすると、Viewクラス内に定義されていないのでエラーになってしまいます。

何が定義されていないの?

話がそれるけど
そもそもDialogクラス?
Viewクラスが大きくなったからDialogクラス?

+ 2007/10/04(木) 09:00:06
> void DlgExtFunc (CDC* pDC)
だからじゃないの?

たいちう 2007/10/04(木) 09:19:59
> Dialogクラスで下記のように定義し、
> 
>  void DlgExtFunc (CDC* pDC)
> {
>     pDC->TextOut( 50, 50, "External Function Call");
> 
> }

case 1:

これが、Dialog用のcppファイルに記述されているだけならば、
単なるグローバルの関数であり、Viewのcppから参照できません。
Dialog用のhファイルに、

void DlgExtFunc (CDC* pDC);

と宣言し、このhファイルをViewのcppでインクルードすると良いでしょう。
呼出しは、単にDlgExtFunc(CDC* pDC); のみです。


case 2:

CDspScaleというのが、追加したダイアログの名前であり、
このメンバ関数がDlgExtFuncということにしたいのならば、

// hファイル
class CDspScale : public CDialog {
    ...
public:
    void DlgExtFunc (CDC* pDC);
};

// cppファイル
void CDspScale::DlgExtFunc (CDC* pDC) {
    ...
}

とします。

nickt [E-Mail] 2007/10/04(木) 12:04:53
たいちろうさん、wclrp ( 'o')さん、しまさん、

舌足らずの質問への早速の書き込みありがとうございます。
早速試してみました。
整理の意味で、今回はエラーメッセージと該当するソース部分をリストしました。


エラーメッセージは、
「
1>c:\documents and settings\visual studio 2005
\projects\firfilter\firfilterview.cpp(1404) : 
    error C2511: 'void CFirFilterView::OnMenuAnalyze(CDC *)' : 
        オーバーロードされたメンバ関数が 'CFirFilterView' にありませ
ん。
」
「
1>        c:\documents and settings\visual studio 2005
\projects\firfilter\firfilterview.h(13) : 
        'CFirFilterView' の宣言を確認してください。

」
と出てきます。



該当するソースを掲示させてください。

////////////// DspScale.h ファイル
class CDspScale : public CDialog
{
    DECLARE_DYNAMIC(CDspScale)

public:
    CDspScale(CWnd* pParent = NULL);   // 標準コンストラクタ
    virtual ~CDspScale();

// ダイアログ データ
    enum { IDD = IDD_DSPSCALE };
    int        Random_Selected, Delay_Selected;
    double    Delay_Time;//mS

public:
    void DlgExtFunc (CDC* pDC);


protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV サポー
ト

    DECLARE_MESSAGE_MAP()
};


////////////// DspScale.cppファイル
IMPLEMENT_DYNAMIC(CDspScale, CDialog)

CDspScale::CDspScale(CWnd* pParent /*=NULL*/)
    : CDialog(CDspScale::IDD, pParent)
{
中略
}

CDspScale::~CDspScale()
{
}

void CDspScale::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
}

中略

void CDspScale::DlgExtFunc (CDC* pDC)
{
    pDC->TextOut( 50, 50, "External Function Call");
}

BEGIN_MESSAGE_MAP(CDspScale, CDialog)
END_MESSAGE_MAP()



///////////// View ファイル FirFilterView.cpp

#include "stdafx.h"
中略
#include "DspScale.h"

/////////////////////////////////////////////////////////////////////////////
// CFirFilterView

IMPLEMENT_DYNCREATE(CFirFilterView, CView)

BEGIN_MESSAGE_MAP(CFirFilterView, CView)
    ON_COMMAND(ID_SCALE_SCALEDISP, OnScaleDisp)
    中略
    ON_COMMAND(IDD_DSPANLZ, OnMenuAnalyze)
END_MESSAGE_MAP()


中略


void CFirFilterView::OnMenuAnalyze(CDC* pDC) 
{    
    DlgExtFunc(CDC* pDC);
}

//////////////////////////////////////////

以上のように定義していますが、コンパイルエラーになってしまいます。

CDCのような書き出し機能を使っているのがいけないのでしょうか。

クラスの考え方が整理されていませんで、混乱しています。
最終的に、スムースに機能追加していく形を作りたく思っています。

よろしくお願いいたします。

たいちう 2007/10/04(木) 13:16:45
ON_COMMANDマクロでどんな関数でも呼び出せるわけではない。
CFirFilterView::OnMenuAnalyze()を引数無しにしたら呼び出せると思うので、
ブレークポイントを設定したりして、呼び出せたことを確認してください。

ここにないけど、CFirFilterViewの宣言の中で、
OnMenuAnalyze()も同じ型で追加しておいてね。

ダイアログの呼出をどうするかはその次の話。

nickt [E-Mail] 2007/10/17(水) 17:54:56
たいちろうさん、wclrp ( 'o')さん、しまさん、

しばらく時間がたってしまいました。すみません。別件で出張が入ったりしてしまいま
した。
お教えいただいた手法でやってみました。
CDC* pDC の受け渡しはできないのですが、関数のコールとして、うまくいきました。以
下はその経緯です。

(1)View内でのON_COMMANDマクロでの引数を取り外し、
    ON_COMMAND(IDD_DSPANLZ, OnMenuAnalyze)

(2)Viweからの呼び出しを、
    void CFirFilterView::OnMenuAnalyze() 
        {    
            CDspScale::DlgExtFunc();
        }

     として、
    DspScale.hでのプロトタイプ宣言では、staticをつけ
        static void DlgExtFunc();
    としました。(こうしないと、「静的でないメンバ関数の呼び出しが正しくあ
りません」となってしまうためです。
こうすることで、関数のコールをすることができました。ありがとうございます。

(3)ただ、この場合、DspScale.h内で定義したクラス変数へのアクセスができず、ま
たpDCを引き渡せないのでグラフィックスの描画もできません。
   
(4)OnDrawのなかから直接 CDspScale::DlgExtFunc(pDC); をコールするとpDCの受
け渡しができるようですが、やはり同様にstaticの宣言をしないといけないので、
CDspScaleクラスの変数にはアクセスがかなわないようです。

(5)もうひとつ、ON_COMMAND(IDD_DSPANLZ, CDspScale::DlgExtFunc)と直接コールす
る形をとるとpDCの受け渡しはできませんが、CDspScale無いの変数にはアクセスが可能
です。


お知恵を拝借したいのですが。
今、私が主に関数の定義をしている、FirFilterView.cppに今後更に機能を追加していま
す。
FirFilterView.h内の変数を利用しながら拡張しています。
機能ごとに別ファイルにして増やして行きたいのですが(もし可能であれば)、

A.グローバル変数定義を利用したほうが良いでしょうか?
B.staticとしてプロトタイプ宣言しないと(CDspScale.h)コンパイラが受け付けてくれ
ないのですが、何かいい方法はありますでしょうか。
C.単に、ベースクラスのないクラスを付け足して、pDCを受け渡しグローバル変数のみに
頼って増やしていく形になるのでしょうか。

よいアドバイスありましたらご教示よろしくお願いいたします。

nickt

たいちう 2007/10/17(水) 20:02:05
CFirFilterViewとCDspScaleの関係は?

m_dlgがCFirFilterViewのメンバである
CDspScaleだとすると、次のようになる。
staticは不要。

void CFirFilterView::OnMenuAnalyze()
{
    CClientDC dc(this);
    m_dlg.DlgExtFunc(&dc);
}

そうでない場合は、両者の関係を詳しく書いてください。
どうやってダイアログを表示しているかとか。

菟ー 2007/10/17(水) 21:56:31
だからぁ!

void DlgExtFunc (CDC* pDC)
{
  pDC->TextOut( 50, 50, "External Function Call");

}

と書くのは、Cスコープの関数。
これのプロトタイプはドコでどのように宣言してますか?

CFirFilterViewはC++スコープ・・・。


コンパイラのメッセージ通りみたいですけど?
”オーバーロードされたメンバ関数が 'CFirFilterView' にありません。”

菟ー 2007/10/17(水) 22:02:53
へんなとこで送信してまったorz

やりたいことは、こんなことじゃないの?

void CDspScale::DlgExtFunc (CDC* pDC)
{
  pDC->TextOut( 50, 50, "External Function Call");

}

void CFirFilterView::OnMenuAnalyze(CDC* pDC)
{
    CDspScale    *Dsp;
    Dsp->DlgExtFunc(pDC);
}

菟ー 2007/10/17(水) 22:08:49
>これのプロトタイプはドコでどのように宣言してますか?
は、質問では無く確認してね。って意味ですよ。

菟ー 2007/10/17(水) 22:20:01
>(1)View内でのON_COMMANDマクロでの引数を取り外し、
>    ON_COMMAND(IDD_DSPANLZ, OnMenuAnalyze)
●CFirFilterViewでメニューコマンド受け取るのですね。

>(2)Viweからの呼び出しを、
>void CFirFilterView::OnMenuAnalyze() 
>{
>  CDspScale::DlgExtFunc();
>}
●これ!意味わかりません!
●CDspScaleのインスタンスは?CDspScaleの実体はどこでしょう?
●実体居ないのにDCが渡せるわけもなく。

>(5)もうひとつ、ON_COMMAND(IDD_DSPANLZ, CDspScale::DlgExtFunc)と直接コール>る形をとるとpDCの受け渡しはできませんが、CDspScale無いの変数にはアクセスが可>です。
●CFirFilterViewのイベントハンドラから。ですか??
●ON_COMMANDをMSDNで調べてください。

菟ー 2007/10/17(水) 22:30:25
そもそも。
> VC++ 6.0 MFCで、Waveファイルを取り扱うアプリケーションを作り始めましたが、
> Viewクラスが大きくなりましたので、Dialogクラスの.hと.cppに関数定義しViewから> ールしてみることにしました。
ヘンです。
Viewクラスが大きくなって、なんで突然Dialogクラスなんですか?

通常、1つのクラスが肥大化してどうしょうもないなら、
例えばCView.cppなら、CView01.cppとCView02.cppに分割すると思いますけど?

nickt [E-Mail] 2007/10/18(木) 12:15:08
たいちろうさん、苑一さん、

ソースコードとしてFirFilterView1.cppを追加しました。必要なファイルをインクルー
ドしてうまくいきました。
こんな簡単なことだったんですね。なにやら恥ずかしいような気がします。
いろいろ外部のクラスに関数を埋め込もうとしたり、余計なことしていたようです。
Dialogクラスは勉強した例の中に出てきましたので、特にこのクラスで無いといけない
わけではないです。

アドバイスありがとうございました。大変参考になりました。

ちなみに、CDspScale *dsp; として、インスタンスを生成しようとすると、
「Run-Time Check Failure #3 - The variable 'dsp' is being used without being 
defined.」
となって停止してしまうようです。何か他の方法があればと思います。今後の解決課題
として更に調べてみます。


DlgExtFuncは、
////////////// CDspScale.cpp///////////

// CDspScale ダイアログ

IMPLEMENT_DYNAMIC(CDspScale, CDialog)

BEGIN_MESSAGE_MAP(CDspScale, CDialog)
END_MESSAGE_MAP()

CDspScale::CDspScale(CWnd* pParent /*=NULL*/)
    : CDialog(CDspScale::IDD, pParent)
{
}

CDspScale::~CDspScale()
{
}

void CDspScale::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Radio(pDX, IDC_RADIO1, Delay_Selected);    // supposed to be a 
group
    DDX_Radio(pDX, IDC_RADIO3, Random_Selected);// supposed to be another 
group
    DDX_Text(pDX, IDC_EDIT1, Delay_Time);    // setting delay time
}

void CDspScale::DlgExtFunc (CDC* pDC)
{ 
    ccc = aaa + bbb;

  pDC->TextOutA(100, 200, "DspScale DlgExtFunc Calling !!!! Using local class 
variables aaa, bbb, ccc");

}
///////////////////////////////////////

//////// FirFilterView.cpp////////////
void CFirFilterView::DoIntSpr5(CDC* pDC)
{
    CDspScale *dsp;

    pDC->TextOutA(100, 100, "File Addition FirFilterView1.cpp");

    dsp->DlgExtFunc(pDC);    //エラー発生!!!
                // Run-Time Check Failure #3 - The 
variable 'dsp' is being used without being defined.

}

/////////////////////////////////////////

たいちう 2007/10/18(木) 13:16:30
> ちなみに、CDspScale *dsp; として、インスタンスを生成しようとすると、

これはCDspScaleへのポインタを定義しただけで、インスタンスはできていません。
ポインタにはゴミが入っていて、どこも指していません。

> ソースコードとしてFirFilterView1.cppを追加しました。必要なファイルをインクル> ドしてうまくいきました。

何がしたかったことで、どううまくいったのか判らない。

> となって停止してしまうようです。何か他の方法があればと思います。今後の解決課> として更に調べてみます。

他の方法というけど、何をしたいのか判らないので説明できない。
コンパイルエラーを消すのが目的ならば、コメントアウトすればいいだけだし。
ダイアログはいらないんでしょ?

nickt [E-Mail] 2007/10/18(木) 19:51:23
たいちろうさん、

オープンエンドですみません。
わたしが参考にした例のプログラムではダイアローグクラスが多用されていて、Viewク
ラスから関数をコールする場合、肥大化したViewクラスに関数を定義しないで他のクラ
ス(今回はダイアローグですが)に関数定義をすることで拡張性を持たせることができ
るのかと思い、いくつか試した後に書き込みしました。
Viewクラスの肥大化についてはソースファイルを追加することで避けられそうですが、
当初、こんな簡単にできるとは思わず、きっとクラス定義を経由するかして拡張してい
くのではと思いこんな方向に来てしまったようです。
皆さんのお時間を使ってすみません、私の「クラス」についての理解が不十分なのが原
因です。

すみませんでした。
nickt

たいちう 2007/10/18(木) 21:35:04
まだよく判らないけど、当初の問題は解決(or 消滅)したのですか?
解決したのなら解決チェックをしましょう。
まだなら問題点を具体的に。
当初の問題と関連の薄い問題ならば、このスレを閉じて別スレを立てましょう。


MFCでプログラムを組むためには、ざっと以下の要素が必要だと思います。
・Windowsの知識(OS提供のAPIを呼び出すだけでなく、
  OSから呼び出される関数というのが判りにくい)
・C言語の知識(WinAPIは基本的にC言語向けです)
・WinAPIのラッパーとしてのMFCの知識
・C++とオブジェクト指向の知識

MFCの入門書で簡単なサンプルをなぞっているうちは余り困りませんが、
プログラムの規模が大きくなるほど、それぞれを深く理解する必要があります。

それぞれがそれなりに癖がある上、それらが影響しあっているので、
初心者は泥沼にはまります。私も10年近く前のことを思い出します。
参考にした本が誤植だらけだったのにも困ったな。

まずはコマンドプロンプトで動くコンソールのプログラムを作って、
C++の理解を深めることをお勧めします。
おさらい程度でもMFCの理解度が格段に変わりますよ。


このHPが役に立つのではないかと。
http://www7b.biglobe.ne.jp/~robe/
http://www7b.biglobe.ne.jp/~robe/cpphtml/index.html

nickt [E-Mail] 2007/10/22(月) 20:39:32
[[解決]]
たいちうさん、

今回の書き込みに関する問題は解決(消滅)いたしました。
大変ありがとうございました。
また、丁寧なご説明とリンク情報ありがとうございます。大いに活用させていただきま
して、次はもう少し発展した形での書き込みをしたいと思います。
大変助かりました。
また、次の機会にはよろしくご指導お願いいたします。

nickt

古いスレッドには追加発言できません。