お世話になります。
W-NT VC++6.0 MFC ダイアログベース
ダイアログ上にピクチャーボックスとボタン、エディットボックスが配置してあります。
ボタンやエディットボックスの処理はウイザードで作成したxxxDlg.cpp内のCxxx :Public
CDialog クラスにあります。
ピクチャーボックスに関する処理を別クラスCGrphにしたいと考え CGrphクラスをGeneric
CObject で作成し、CxxxクラスのメンバにCGrph m_grph;をいれました。
CGrphのメンバ関数の呼び出しは m_grph.fnc(arg)で行います。
この場合ピクチャボックスのID IDC_PICTやメンバ変数m_pictで求めるデバイスコンテキスト
やボックスサイズはCGrphクラスでどのように求めるのでしょうか?
Cxxx クラス内でGetDlgItem()やGetClientRect()関数などにより求めて、引数argとして渡す
しかないのでしょうか?
基本クラスと派生クラスの考えがよくわかってない者です。
よろしくお願いします。
次のようにしたらどうでしょうか。
① CGrphクラス の親クラスを CStaticにする。
② クラスウイザード で ピクチャーボックス の DDX コントロールを作る。
③ ②で xxxDlg のヘッダーにできた、CStatic の ピクチャーボックスコントロールの
CStatic の部分を ①で作ったクラス名に変更する。
素直にCxxxダイアログのポインタ(this)、もしくはCxxxダイアログのウィンドウハンドル
(m_hWnd)をわたしてあげたらどうでしょう。
312 さん回答ありがとうございます。
操作手順がもう少し具体的になりますか。
恐れいりますがよろしくお願いします。
HEARTS さん回答ありがとうございます。
いまはGetDlgItem()でpicture Boxのポインタ求めてそれを引数としてわたしているのですが
Cxxxダイアログのハンドル/ポインタを引数として渡した場合それからpicture Boxのポイン
タはどのように求めるのでしょうか?
単純な質問ならすみません、よろしくご教示ください。
ハンドルよりもthisポインタを使ったほうが簡単なので
その場合で書きます。
まず,CGrphのヘッダファイルにCxxxのポインタをメンバ変数として
publicで宣言します。
public:
Cxxx * pDlg;
で、次にCxxxダイアログのソースの中でダイアログ自身のポインタを
渡します。
ごめんなさい。まちがえて途中で送っちゃいました。
ハンドルよりもthisポインタを使ったほうが簡単なので
その場合で書きます。
まず,CGrphのヘッダファイルにCxxxのポインタをメンバ変数として
publicで宣言します。
public:
Cxxx * m_pDlg;
で、次にCxxxダイアログのソースの中でダイアログ自身のポインタを
渡します。
m_grph.m_pDlg = this;
もし、Cxxxクラスで、ピクチャーボックスコントロールをCStatic
のメンバ変数として宣言(仮にm_Pictとする)しているなら、
CGraphの中からは
CDC * pDC = m_pDlg->m_Pict.GetDC();
CRect ClientRect;
m_pDlg->m_Pict.GetClientRect(ClientRect);
(ちなみにピクチャーボックスのポインタはCStatic * pStatic = &m_pDlg->m_Pict)
メンバ変数として宣言していないのならば
CStatic * pStatic = (CStatic *)m_pDlg->GetDlgItem(IDC_PICT)
CDC * pDC = pStatic->GetDC();
CRect ClientRect;
pStatic->GetClientRect(ClientRect);
となります。
長くなってごめんなさい.
HEARTS さんありがとうございます。
>まず,CGrphのヘッダファイルにCxxxのポインタをメンバ変数としてpublicで宣言します。
>public:
> Cxxx * m_pDlg;
CxxxのヘッダーにはCGrphのメンバー関数を参照するため次のメンバーが宣言してありますが
CGrph m_grph;
どちらも次のエラーが出ます
error C2143: 構文エラー : ';' が、識別子 '*' の前に必要です。
error C2501: 'Cxxx' : 識別名を宣言するのに、型が指定されていません。
error C2501: 'm_pDlg' : 識別名を宣言するのに、型が指定されていません。
error C2146: 構文エラー : ';' が、識別子 'm_grph' の前に必要です。
error C2501: 'CGrph' : 識別名を宣言するのに、型が指定されていません。
error C2501: 'm_grph' : 識別名を宣言するのに、型が指定されていません。
このエラーがとれないのですが
ごめんなさい.説明が足りなかったですね.
>error C2143: 構文エラー : ';' が、識別子 '*' の前に必要です。
>error C2501: 'Cxxx' : 識別名を宣言するのに、型が指定されていません。
>error C2501: 'm_pDlg' : 識別名を宣言するのに、型が指定されていません。
まず、これですがCGrphのヘッダファイルで、
class CGrph
の上に
class Cxxx;
と打ち込んでください.
>error C2146: 構文エラー : ';' が、識別子 'm_grph' の前に必要です。
>error C2501: 'CGrph' : 識別名を宣言するのに、型が指定されていません。
>error C2501: 'm_grph' : 識別名を宣言するのに、型が指定されていません。
次にこれは、CXxxのヘッダファイルで,CGrphのヘッダファイルをインクルードしてください.
#include Grph.h
これでいけるはずです。
HEARTS さんお手数かけます。
2番目のエラーが取れません。
#include Grph.hはもともとCxxx.hの中に入れてあります。
>error C2146: 構文エラー : ';' が、識別子 'm_grph' の前に必要です。
>error C2501: 'CGrph' : 識別名を宣言するのに、型が指定されていません。
>error C2501: 'm_grph' : 識別名を宣言するのに、型が指定されていません。
ヘッダファイルをインクルードしてあってこのエラーが出ると
いうことは考えられることは1つ2つしかありません。
Cxxx内で宣言されているm_grphのクラス名CGrphと
Grph.hの中で宣言されているクラス名がくいちがってませんか?
また、Cxxx内でインクルードされているファイルは
クラスCGrphが宣言されているへっだふぁいるですか?
もう一度確かめてみてください.
HEARTSさん お世話になります
エラーが解析出来ません、関係する部分のソースを送ります。
何か分かるでしょうか。 //***でコメントしてあります。
名前は CGrph->CRscChkDisp Cxxx->CRscChkDlg に変わっています。
お手数ですがよろしくお願いします。
//***** CGrphに相当するヘッダー
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include RscChkDlg.h //** CXXXに相当するヘッダ
class CRscChkDlg; //***** 追加
class CRscChkDisp : public CObject
{
public:
CRscChkDisp();
virtual ~CRscChkDisp();
CRscChkDlg *m_pDlg; //***** 追加
protected:
CFont m_myFont;
};
//***** CGrphに相当するCpp
#include stdafx.h
#include RscChk.h
#include RscChkDisp.h
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// 構築/消滅
//////////////////////////////////////////////////////////////////////
CRscChkDisp::CRscChkDisp()
{
}
CRscChkDisp::~CRscChkDisp()
{
}
//***** Cxxxに相当するヘッダー
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include RscFileSelect.h
#include RscChkDisp.h //**** Cgrphに相当するヘッダ
// CRscChkDlg ダイアログ
class CRscChkDlg : public CDialog
{
// 構築
public:
CRscChkDlg(CWnd* pParent = NULL); // 標準のコンストラクタ
// ダイアログ データ
//{{AFX_DATA(CRscChkDlg)
enum { IDD = IDD_RSCCHK_DIALOG };
CButton m_cButtonTest;
UINT m_uiEditId;
//}}AFX_DATA
//{{AFX_VIRTUAL(CRscChkDlg)
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV のサ
ポート
//}}AFX_VIRTUAL
protected:
HICON m_hIcon;
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
void PictInitDisp();
CRscChkDisp m_pictDisp;
CRscFileSelect m_fileSelect; //*** CGrphに相当のオブジェクト
//* この部分がエラー箇所
};
//********** Cxxxに相当するcpp
#include stdafx.h
#include RscChk.h
#include RscChkDlg.h
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// CAboutDlg ダイアログ
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
protected:
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
// CRscChkDlg ダイアログ
CRscChkDlg::CRscChkDlg(CWnd* pParent /*=NULL*/)
: CDialog(CRscChkDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CRscChkDlg)
m_uiEditId = 0;
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CRscChkDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CRscChkDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CRscChkDlg, CDialog)
//{{AFX_MSG_MAP(CRscChkDlg)
ON_WM_SYSCOMMAND()
ON_BN_CLICKED(IDC_RADIO_HLP, OnRadioCap)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
ごめんなさい。私の注意が足らなかったようです。
問題は以下のセクションにあります。
//******** CGrphに相当するヘッダー
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//こうしてしまうとRshChkDlg.hを先に見に行ってしまう。
//このインクルードは入れてはいけません。
//#include RscChkDlg.h //** CXXXに相当するヘッダ
//クラスのポインタを宣言する場合はそのクラスを
//このようにclass CRscChkDlg;と宣言するだけでよく、
//実際にそのクラスを宣言しているヘッダをインクルードする必要はありません。
//ちなみに実体を宣言する場合はインクルードが必要になります。
class CRscChkDlg; //***** 追加
class CRscChkDisp : public CObject
{
public:
CRscChkDisp();
virtual ~CRscChkDisp();
//クラスのポインタを宣言
CRscChkDlg *m_pDlg; //******** 追加
protected:
CFont m_myFont;
};
あと余談ですが、このクラス、CObjectの派生にする
必要ないと思うんですけど、どうなんでしょう。
HEARTS さんありがとうございます。
class CRscChkDlg; //******** 追加の宣言
class CRscChkDisp : public CObject
{
追加しましたが
CGrphに相当するクラスCRscChkDispクラスの
(1)と(2)の行でエラーがでました。
(1)CDC *pDC=m_pDlg->m_pict.GetDC();
CRect ClientRect;
(2)m_pDlg->m_Pict.GetClientRect(ClientRect);
error C2027: 認識できない型 'CRscChkDlg' が使われています。
d:\panasert\msr\rscchk\rscchkdisp.h(40) : 'CRscChkDlg' の宣言を確認してく
ださい。
error C2227: '->m_pict' : 左側がクラス、構造体、共用体へのポインタではありません。
確かにコンパイラはCRscChkDlgクラスのメンバはどのように参照するのですか?
>あと余談ですが、このクラス、CObjectの派生にする必要ないと思うんですけど、どうなんで
>しょう。
よく理解したうえでCObjectの派生にした分けではありません。
単純にMFCのクラスCWndやCDCの機能が必要とかんがえただけです。
どのような場合にCObjectを使うのでしょうか?
またこの場合のように表示だけを行うメンバー関数だけのクラスは派生もとはどのように考えれ
ばよいのでしょうか。是非ご教示ください。
酷暑の毎日が続くおりこのようなことにおつき合いさせて申し訳ありません。
長くなりそうなのでとりあえずメールをください。
コンパイルが通る簡単なサンプルプロジェクトを返送しますので。
ちなみにCObjectは自分で作成した複数の類似したクラスを配列や
アレイ、またはリストなどで保持したいときなどにそれぞれの共通基底
クラスとして使用したりします。
たとえば線を描くクラスCDrawLineというクラスと矩形を描くクラスCDrawRect
というクラスのそれぞれをCObjectの派生クラスだとするとCDrawLineのオブジェクトと
CDrawRectのオブジェクトをCObjArrayなどの変数にCObjctにキャストすることによって
いっしょに保持することができるのです。
ほかにも使い道があるのですが、私はほとんど上記のような理由のときに
CObjectを使います。
では、メール待ってます。
HEARTSさん ご面倒かけました。
RscChkDisp.hからはずした#include RscChkDlg.hをRscChkDisp.cppに入れることで
解決できました。
おかげさまでthisポインタについてよく理解できました。
できればもうひとつのウインドハンドルを使う方法についても教えていただけますか?
よろしくお願いします。