新規に作成したクラスからエディトボックスの値を変更するには

[戻る]
たちき 2006/07/13(木) 15:28:46
[環境]Windows2000 VC++6.0MFC

ダイアログベースのプログラムを作成中です。
リソースにエディトボックスを設置し、メンバ変数(m_test)を追加しました。
メイン(?)となるクラスからm_test.SetWindowTextを行うのは全く問題ないのですが、
これとは別にクラスを作成し、このクラスの中からm_testを変更したいと考えています。

新しいクラスにメインのクラスを継承させ、m_test.SetWindowTextと記述すれば
とりあえずコンパイル時にエラーにはならないのですが、
実際には「ハンドルがありません」という感じのエラーが発生して正常に動作しません。
メインのクラスに値を返して処理するという方法もなくはないのですが、
出来れば新しいクラスの中で処理を完結させたいです。

何か方法がございましたらご教授願います。
よろしくお願いいたします。

επιστημη 2006/07/13(木) 15:36:04
ごめんなさい、問題/質問が理解できません。

// メイン(?)となるクラス
class XXXDlg : public CDialog {
public:
  CEdit m_test;
  ...
};

ですか? 

> 別にクラスを作成し、このクラスの中からm_testを変更したいと考えています。

XXXDlgのインスタンス X さえ手に入れれば X.m_test.SetWindowText("...");

たちき 2006/07/13(木) 16:51:18
επιστημη様

質問内容が稚拙で申し訳ありませんでした。
まさに指摘していただいた内容そのものです。

> XXXDlgのインスタンス X さえ手に入れれば

とありますが、インスタンスの作成方法をいまいち理解していないので、
もしよろしければそのインスタンスの作成・入手方法を教えていただけないでしょうか。

XXXDlg *X = new XXXDlg();

というのを新しいクラスで実行して
X->m_test.SetWindowText("...");
としてみたのですが、コンパイルは出来るのですがやはり同様のエラーが発生してしまいます。

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

επιστημη 2006/07/13(木) 17:06:36
> XXXDlg *X = new XXXDlg();
> というのを新しいクラスで実行して
> X->m_test.SetWindowText("...");
> としてみたのですが、コンパイルは出来るのですがやはり同様のエラーが発生してしまいま
す。

XXXDlg をnewしただけではまだ表示されてまいません。
Windowとして現れるまで、エディットボックスはまだこの世に存在しません。
なのでエラーとなります。

Blue 2006/07/13(木) 17:07:47
> XXXDlg *X = new XXXDlg();
ここでつくった X と すでにあるダイアログとは同じではないですよね?
よって NG となるわけです。

> インスタンスの作成・入手方法を教えていただけないでしょうか。
この回答をするには、XXXDlg と 新しく追加した別のクラス YYY との関係を
示してもらわないと、簡単な方法は教えれないと思います。

たとえば、XXXDlgのあるメソッドからYYYを作成し、YYYのあるメソッドを呼んでいると
かそういう情報。

たちき 2006/07/13(木) 17:15:40
επιστημη様、Blue様、返答ありがとうございます。
質問する私もVC++の事をよく理解していないため、
質問内容が意味不明になってしまい申し訳ありません。

プログラムとしては、以下のように作成しています。

class XXXDlg : public CDialog {
public:
  CEdit m_test;
  ...
};

void XXXDlg::OnButton()
{
  ...
  YYY myYYY;
  myYYY.start();
  ...
}

--------------------------

class YYY{
public:
  void start();
  ...
};

void YYY::start()
{
  ...
  m_test.SetWindowText("..."); // ←この記述でエディトボックスに書き込まれると思っ
てました
}

--------------------------

こんな感じですが、情報として必要十分か不安です。
よろしくお願いいたします。

Blue 2006/07/13(木) 17:27:38
引数でエディットボックスのポインタを渡すとか。

class YYY
{
public:
    void start( CEdit* pEdit ); // 変更
};

void YYY::start( CEdit* pEdit ) // 変更
{
  ...
  pEdit->SetWindowText("...");  // 変更
  pEdit->UpdateWindow();        // 更新するために追加
}


void XXXDlg::OnButton()
{
  ...
  YYY myYYY;
  myYYY.start(&m_test); // 変更
  ...
}

用途によって、メンバ変数に持つのもありでしょう。


ほかにも、親のダイアログに独自のメッセージを投げるとか、
親のダイアログそのものをメンバに持つとか。
(これはclassの相互参照になるのでメンドイしつくり的にもよくなさそう)

たちき 2006/07/13(木) 17:56:40
[[解決]]
Blue様、返答ありがとうございます。

メンバ変数を引数で渡すことによって、想定通りの動作が行えることを確認しました。
実はこのXXXDlgは沢山エディトボックスを持っているので、
その全てに綺麗に対応できるようにプログラムを組みたいと考えていますが
この先は、今回の例を参考にして自力で考えたいと思います。

ありがとうございました。

Blue 2006/07/13(木) 18:03:05
> 実はこのXXXDlgは沢山エディトボックスを持っているので
そういうことですか、、、


YYY::startの中で随時更新が必要でなく、YYY::startが終わった後に
必要な文字列を回収することができるのであれば、やはり親のダイアログに処理させる
べきかも。

void XXXDlg::OnButton()
{
  ...
  YYY myYYY;
  myYYY.start();
  // この処理が終わった後、もろもろの文字列を回収する。
  m_testA.SetWindowText(myYYY.m_A);
  m_testB.SetWindowText(myYYY.m_B);
  ...
  m_testZ.SetWindowText(myYYY.m_Z);
}

Blue 2006/07/14(金) 17:53:04
追記

新しいスレで、ワーカスレッドにするとかしないとかそういう話が出ていますが、
今回のやり方は、スレッド処理には向かなさそうなので、スレッドにする場合
> 親のダイアログに独自のメッセージを投げるとか
とか
CEditのポインタでなく、エディットボックスのウィンドウハンドルでSendMessage
する方法でやったほうがよいでしょう。
(CEditのポインタだと、ダイアログスレッドが終わるとアクセスできなくなる。
スレッドになる以上こういう状態はありうる)

たちき 2006/07/14(金) 18:00:29
スレッド上で全てを行おうとしすぎるとダメって事ですね。
何本もスレッドが走るというプログラムは想定していないのですが、
助言に従いダイアログの操作は親のダイアログから操作するように変更します。
ありがとうございました。

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