モーダルダイアログ

[戻る]
ヨッピー 2008/04/15(火) 21:05:49
タイトルにもありますが、モーダルダイアログを使用したプログラムを作成してます。
やりたいことは初歩的で申し訳ないのですが、
子ダイアログのエディットボックス内の値を親ダイアログで使用できるようにしたいん
です。
具体的には子ダイアログに4つのエディットボックスとOKボタンとキャンセルボタン
があって、エディットボックス内にセットされた数値を読みっ取って親ダイアログで条
件式で使用したいと考えてます。
モーダルダイアログは作成できています。


//モーダルダイアログ作成(親ダイアログ)
void CParentDlg::OnCbnSelchangeXXX();
{
  int i;
   i = m_XXX.GetCursel();          
   if(i=2){
         CChildDlg dlg(this);
         dlg.DoModal();
}

//子ダイアログのエディットボックス内数値取得
void CChildDlg::OnBnClickedButton1()
{
  CString B,C,D,E;
 
  GetDlgItemText(IDC_EDIT1, B);
  GetDlgItemText(IDC_EDIT2, C);
  GetDlgItemText(IDC_EDIT3, D);
  GetDlgItemText(IDC_EDIT4, E);

  int b = atoi(B);
  int c = atoi(C);
  int d = atoi(D);
  int e = atoi(E);

  OnOK();
}

//親ダイアログの条件式に子ダイアログの値を使用
void CParentDlg::XXXXX() 
{
    int        nSts;
    CString msg;
    BOOL    check;
    DWORD    timeCount = 0;
    int a=0;
    DWORD    timeCount2 =0;

       if(i==2){
          Sleep(b);
        〜省略〜
    
    while(a<e){
         timeCount = GetTickCount();
         timeCount2 = 0;
    while(timeCount2<c){            
          timeCount2 = GetTickCount() - timeCount;
                  }
                
         〜省略〜                 
        Sleep(d);        

        〜省略〜        
            a=a++;
     }

どうすれば親ダイアログでエディット内で取得したb,c,d,e使用できるようになるでしょ
うか?

環境はWindows XP,VS2005 VC++です。

よろしくお願いします。

επιστημη [HomePage] 2008/04/15(火) 21:45:41
子ダイアログに入力値を返すpublicメソッドを用意し、
親がそれを呼ぶ。

ヨッピー 2008/04/15(火) 21:58:42
επιστημηさん

早いレス有難うございます。
初心者な為、具体的に教えていただけると有り難いです。

επιστημη [HomePage] 2008/04/15(火) 22:20:36
class CChildDlg : CDialog {
...
public:
  CString GetUSerInput() {
    入力値を返す
  }
};

ヨッピー 2008/04/16(水) 00:05:41
επιστημηさん

ありがとうございます。
図々しい質問で申し訳ないのですが、
入力値を返すのとこにはなにかコーディングが必要ですか?
また、親が呼ぶのはどうしたらよいですか?

επιστημη [HomePage] 2008/04/16(水) 01:16:08
> 入力値を返すのとこにはなにかコーディングが必要ですか?

当然です。

CString CChildDlg::GetUserInput() {
}

これじゃコンパイルエラー。

> また、親が呼ぶのはどうしたらよいですか?

CChildDlg dlg(this);
if ( dlg.DoModal() == IDOK ) {
  CString userInput = dlg.GetUserInput();
  ...
}

ヨッピー 2008/04/16(水) 08:48:26
επιστημηさん

ありがとうございます。
たびたびで申し訳ないのですが、

> 入力値を返すのとこにはなにかコーディングが必要ですか?
>当然です。
>CString CChildDlg::GetUserInput() {
>}

なにをコーディングしたらよろしいいですか?

maru 2008/04/16(水) 11:32:46
親は子の数値が欲しいですよね。

class CChildDlg : CDialog {
  int m_b;
  int m_c;
  int m_d;
  int m_e;
public:
  int GetB() { return m_b;}
  int GetC() { return m_c;}
  int GetD() { return m_d;}
  int GetE() { return m_e;}
};

void CChildDlg::OnBnClickedButton1()
{
  BOOL bTranslated = FALSE;
  int work = GetDlgItemInt(IDC_EDIT1, &bTranslated);
  if (bTranslated)
  {  m_b = work;
  } else
  {  /* 変換できない文字が入力されているので適切なエラーメッセージ等 */
  }
  /* 以下略 */
  OnOK(); /* 入力値が全て変換出来た時のみ呼び出すこと! */
}

> また、親が呼ぶのはどうしたらよいですか?
  CChildDlg dlg(this);
  if (dlg.DoModal() == IDOK) 
  {
    int b =dlg.GetB();
    /* 以下略 */
  }

# 次から次へと質問するより、もう少しC++言語を勉強されることをお勧めいたします。

maru 2008/04/16(水) 11:47:51
余計な事だけど、元のソース中の
>            a=a++;
は、どういう結果になるんでしたっけ? 未定義/未規定?

tetrapod 2008/04/16(水) 14:31:13
C++ JIS X3014:2003 5.式 (4)
相続く2つの副作用完了点の間では、1つの式の評価によってスカラオブジェクトの
格納値が変わるのは、高々1回でなければならない。
C99 JIS X3010:2003 6.5.式
直前の副作用完了点から次の副作用完了点までの間に、式の評価によって
1つのオブジェクトに格納された値を変更する回数は、高々1回でなければならない
に反するので未定義っすね

以下感想というか重箱の隅というか

X3014 の訳文は ISO/IEC 14882 の原文中における a scalar object の a を
訳出していないので不正確(1つのスカラオブジェクトとする必要がある)
i=++a+b--; は副作用完了点の間に3つの副作用があるけど正しい式文

ISO/IEC 14882 5.(4) で挙げられているサンプルには unspecified とあって
X3014 もそれを忠実に訳しているので未規定とあるが、
これは 14882 がそもそも間違っていると思われる

maru 2008/04/16(水) 18:29:14
なるほど、そうですか。解説、ありがとうございます。

元々は a++; か、a = a + 1;と書きたかったんだろうけど、なんだかなぁ。
最初のコードには
>   if(i=2){
なんてのもあるし。

ヨッピー [HomePage] 2008/04/16(水) 23:18:12
皆様コメント有難うございます。

>class CChildDlg : CDialog {
>  int m_b;
>  int m_c;
>  int m_d;
>  int m_e;
>public:
>  int GetB() { return m_b;}
>  int GetC() { return m_c;}
>  int GetD() { return m_d;}
>  int GetE() { return m_e;}
>};
はCChildDlg.hにコーディングですよね?

>  CChildDlg dlg(this);
>  if (dlg.DoModal() == IDOK) 
>  {
>    int b =dlg.GetB();
>    /* 以下略 */
>  }
はCPararentDlg.cppにコーディングですよね?

それでやってみたのですが、
b,c,d,eは定義されてないとエラーになるのですが、
CParentDlg.cpp側でもb,c,d,eは定義する必要があるんでしょうか?
できたら最初に書いたソースで教えていただけると助かります。

質問ばかりで申し訳ないのですが、ご教授下さい。
本当に申し訳ないです。よろしくお願いいたします。

επιστημη [HomePage] 2008/04/16(水) 23:23:13
> b,c,d,eは定義されてないとエラーになるのですが、

定義されてないんでしょうねぇ。

現象を正確に伝えるために、書いたコードとエラー・メッセージを
そのまま貼り付けてください。

ヨッピー 2008/04/17(木) 08:50:02
書いたコードは
CChildDlg.gに
class CChildDlg : public CDialog
{
    DECLARE_DYNAMIC(CCustumDlg)

    int m_b;
    int m_c;
    int m_d;
    int m_e;
public:
    int GetB() { return m_b;}
    int GetC() { return m_c;}
    int GetD() { return m_d;}
    int GetE() { return m_e;}

public:
    CChildDlg(CWnd* pParent = NULL);   // 標準コンストラクタ
    CString GetUserInput(){
    }
    virtual ~CCustumDlg();
 〜省略〜


CParentDlg.cppに
void CParentDlg::XXXXX() 
{
    DWORD    timeCount = 0;
    int a=0;
    DWORD    timeCount2 =0;
    int i;
    i = m_combobox.GetCurSel();

    BeginWaitCursor();

if(i==2){
    CCustumDlg dlg(this);
    if (dlg.DoModal() == IDOK) {
          CString userInput = dlg.GetUserInput();
          int b =dlg.GetB();
         int c =dlg.GetC();
         int d =dlg.GetD();
         int e =dlg.GetE();    
        }
          
         〜処理〜
while(a<e){
    timeCount = GetTickCount();
    timeCount2 = 0;
while(timeCount2<c+1){            
    timeCount2 = GetTickCount() - timeCount;
       }
         〜処理〜        
     Sleep(d);        
    
         〜処理〜
    a=a++;
  }
 }
   EndWaitCursor();
}
です。

エラーは
error C2065: 'e' : 定義されていない識別子です。

int eで定義しているので出ないと思うのですが・・・

宜しくお願いします

Pen 2008/04/17(木) 09:08:44
int eはスコープを抜けてますよ。

ヨッピー 2008/04/17(木) 09:12:19
すいません。書き間違えました。

EndWaitCursor();の前に}でした。

それでやってみましたが、子ウィンドの値を取得できませんでした。

επιστημη [HomePage] 2008/04/17(木) 09:13:55
...なんだかなー

http://cid-07c558f8e11e708f.skydrive.live.com/self.aspx/%e5%85%ac%e9%96%
8b/VS2005Trials.zip

たいちう 2008/04/17(木) 10:07:43
↑2005がないから開けなかったので、それっぽい所を何とかしてみた。
警告は出るけど2003で開けた。

*.sln 2行目
Microsoft Visual Studio Solution File, Format Version 9.00
↓
Microsoft Visual Studio Solution File, Format Version 8.00

*.vcproj 4行目
    Version="8.00"
↓
    Version="7.10"

επιστημη [HomePage] 2008/04/17(木) 10:14:13
お手数おかけしましたー
# インスコしとかにゃいかんかなぁ、VS2003とかVC++6とか。
# VirtualPCに突っ込んどきゃ邪魔にはならんが...ディスクの肥やしやなー

maru 2008/04/17(木) 11:34:43
> それでやってみましたが、子ウィンドの値を取得できませんでした。
CChildDlg側でエディットボックスの入力値は取れているの?
void CChildDlg::OnBnClickedButton1() の内容を確認すること。

PATIO 2008/04/17(木) 11:47:02
あのー。めっちゃ気になっているんですが。

ここ
> class CChildDlg : public CDialog
と

ここ
>     CCustumDlg dlg(this);
で

クラス名が違うわけだから取れなくて当たり前と言う話はなし?
単にパンチミスならわかるけれど、
これだとそもそもビルドが通らないはずだし。
どうなってるんでしょ。

maru 2008/04/17(木) 12:49:02
あれま。 ほんと、ぐちゃぐちゃ。
>    DECLARE_DYNAMIC(CCustumDlg)
とか、
>    virtual ~CCustumDlg();
とか。

前に指摘した
>    a=a++;
もそのまま残っているし。

# 実際のプロジェクトからコピペしていないに一票。

たいちう 2008/04/17(木) 16:11:19
> # 実際のプロジェクトからコピペしていないに一票。

質問者はビルドできていないって書いてますよ。


> エラーは
> error C2065: 'e' : 定義されていない識別子です。
> 
> int eで定義しているので出ないと思うのですが・・・

int eが定義されているけど、それを参照できない場所で
エラーになっているのです。
エラーメッセージにはファイル名とか行番号とか書いてありませんか?


それと既に指摘されていますが、CChildDlgとCCustumDlgは、
それぞれ必要なのですか?
もしも混同していたり何のことか判らないようならば、
統一してください。それとa=a++;の修正もね。

maru 2008/04/17(木) 16:55:01
>質問者はビルドできていないって書いてますよ。
あれ?

じゃあ、
> それでやってみましたが、子ウィンドの値を取得できませんでした。
はどういう意味だろう?

PATIO 2008/04/17(木) 17:20:58
とにかく、質問者の方で一度状況を再整理して
全く状況が分からない人に一から説明するつもりで
内容を補足して貰わないと混乱するだけだと思います。

少なくとも提示するコードは、その現象がきちんと
再現する物で無いと提示する事でかえって混乱します。

正直な話、まずクラスとかその辺の勉強からした方が
良いのでは無いかと言う気もしますね。
C++言語の文法とかクラスの概念とかを理解しないと
MFCを使ってプログラミングするのは無理があると思います。

どこかでも書きましたけれど、
VC++でMFCを使ってアプリを作る勉強と
C++言語その物の勉強を同時にするのは無理です。
他の言語でもいいからきちんとプログラミングについて
理解した上でならまだ解りますけれど、
どうも書き込み内容を見る限りではその段階まで
至っていないような気がします。
恐らくこちらの説明も理解できないでいるのではないか
という気がします。

ヨッピー 2008/04/17(木) 22:06:43
皆様、いろいろと有難うございます。

もう一度内容を説明いたします。
やりたいことは
親ウィンドのコンボボックスで3番目の項目を選択→子ウィンドが開かれる→子ウィンド
にある4つのエディットボックスに任意で数値をセット→子ウィンドにあるセットボタ
ンを押すとセットされた任意の数値を取得→エディットボックスで代入された数値を親
ウィンド側で受け取る→親ウィンドで撮影ボタンを押すとエディットボックス内の数値
を使用してカメラを動作させる
という流れです。

次にソースの説明をします。
//モーダルダイアログ作成(親ダイアログ)
void CParentDlg::OnCbnSelchangeComboBox1();
{
  int i;
   i = m_XXX.GetCursel();          
   if(i=2){       //コンボボックスの3番目が選択されたら子ウィンドを開く
         CChildDlg dlg(this);
         dlg.DoModal();
}

//子ダイアログのエディットボックス内数値取得
void CChildDlg::OnBnClickedButton1()
{
  CString B,C,D,E;
 
  GetDlgItemText(IDC_EDIT1, B);  //エディットボックス1の数値を取得
  GetDlgItemText(IDC_EDIT2, C);  //エディットボックス2の数値を取得
  GetDlgItemText(IDC_EDIT3, D);   //エディットボックス3の数値を取得
  GetDlgItemText(IDC_EDIT4, E);   //エディットボックス4の数値を取得
//文字列から数字へ変換
  int b = atoi(B);  
  int c = atoi(C);
  int d = atoi(D);
  int e = atoi(E);

  OnOK();  //子ウィンドを閉じる
}

//親ダイアログの条件式に子ダイアログの値を使用
void CParentDlg::OnBnClickedRecord()
{
    int        nSts;
    CString msg;
    BOOL    check;
    DWORD    timeCount = 0;
    int a=0;
    DWORD    timeCount2 =0;

       if(i==2){
          Sleep(b);  //ボタンを押してからb秒間待つ
        〜撮影開始処理省略〜
    
    while(a<e){   //aがe回になるまで繰り返す
         timeCount = GetTickCount();
         timeCount2 = 0;
    while(timeCount2<c){            //c秒間撮影
          timeCount2 = GetTickCount() - timeCount;
                  }
                
         〜撮影停止処理省略〜                 
        Sleep(d);        //次の撮影までd秒間待つ
       
            a=a+1;      //aに1を足す
     }

という感じです。

やりたいことは分かっていただけたでしょうか?
子ウィンドでは値は取得出来ていますが親ウィンドで子ウィンドで取得した値は使用で
きません。
取得した値を使用できるようにしたいんです。
ご指導お願いいたします。


ちなみに今まで書いたソースのCCustumDlgはCChildDlgと同じです。

επιστημη [HomePage] 2008/04/17(木) 22:10:00
いやだから
 僕のコードは
  読んだのか

ヨッピー 2008/04/17(木) 23:06:05
επιστημηさん
いつもありがとうございます

//CChildDlg.h
class CChildDlg : CDialog {
  int m_b;
   int m_c;
   int m_d;
   int m_e;
 
public:
  CString GetUSerInput() {
    int GetB() { return m_b;}
    int GetC() { return m_c;}
    int GetD() { return m_d;}
    int GetE() { return m_e;}
  }
};

//CParentDlg.cpp内に
CChildDlg dlg(this);
if ( dlg.DoModal() == IDOK ) {
  CString userInput = dlg.GetUserInput();
}

ですよね?

子ウィンドを開くスコープと子ウィンドで取得した値を使用するスコープが
異なる場所なんですがこれでつかえますか?

子ウィンドを開く→void CParentDlg::OnCbnSelchangeComboBox1();内
取得した値を使用→void CParentDlg::OnBnClickedRecord();内

PSB 2008/04/17(木) 23:26:59
>子ウィンドを開くスコープと子ウィンドで取得した値を使用するスコープが
>異なる場所なんですがこれでつかえますか?

当然使えないから、CParentDlgのメンバにコピーするしかないでしょうね。

maru 2008/04/17(木) 23:27:20
> ですよね?
違う!!
どこからこんなコードが出てくるんだ!?

悪いことは言わないから、
> 正直な話、まずクラスとかその辺の勉強からした方が
> 良いのでは無いかと言う気もしますね。
に従って、勉強してから出直してきたら。

2008/04/18(金) 01:40:59
話がかみ合わないようなので
もういっそのこと、グローバル変数にしてみては?

たいちう 2008/04/18(金) 09:34:32
最終的にはコンボボックスの選択からカメラの動作までやりたいとしても、
小さなステップで確実に進みましょう。

このスレッドで質問していることは、
『親ウィンドで子ウィンドで取得した値は使用したい』でしょ?
επιστημηさんが簡潔なサンプルを作ってくれているので、
まずそれを実行してみたらどうですか?

そうすれば、その仕組みを自分のプログラムで使うにはどうすればよいか
考えられると思います。
その上でもし判らない点があれば、その点を改めて質問すればよいでしょう。

# 見よう見まねで飛行機を作りましたが飛びません、
# どこを直したら良いですか?
# ↓
# επιστημη氏>つ 紙飛行機
# PATIO氏、maru氏> 航空力学を勉強しる

maru 2008/04/18(金) 11:09:18
> # επιστημη氏>つ 紙飛行機
> # PATIO氏、maru氏> 航空力学を勉強しる
いや、だから、私も拙いながら紙飛行機を作って見せたんですがね。
どうも折り方が悪かったようななので、紙の折り方から勉強したら?
って言ってるつもりなんですけど。

# 飛行機を作ろうとしている人に紙の折り方は必要ないか。

ヨッピー 2008/04/18(金) 11:10:55
maruさんの方法:
if (dlg.DoModal() == IDOK) 
{
 int b =dlg.GetB();
 int c =dlg.GetC();
 int d =dlg.GetD();
 int e =dlg.GetE();
 UpdateData(TRUE);
}
で親ウィンドで値を取得できました。

しかし、子ウィンドを開くスコープと取得した値を使用するスコープが違う場合は
どうしたらよいのでしょうか?

子ウィンドを開く→void CParentDlg::OnCbnSelchangeComboBox1();内
取得した値を使用→void CParentDlg::OnBnClickedRecord();内

ヨッピー 2008/04/18(金) 11:17:28
[[解決]]
自己レスですいません。

グローバルにすればいいだけでした。
今回、皆様には大変ご迷惑をおかけしました。

申し訳ありませんでした。
質問ばっかりしてしまいましたが、これからしっかり勉強していきたいと思います。

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

シャノン 2008/04/18(金) 11:21:15
> しかし、子ウィンドを開くスコープと取得した値を使用するスコープが違う場合は
> どうしたらよいのでしょうか?

その質問は、モーダルダイアログから値を取得することとまったく関係ないということは
わかりますか?
その答えは、
 PSB 2008/04/17(木) 23:26:59
 と 2008/04/18(金) 01:40:59
のご両名が書いてくださっています。
これらは実践しましたか?
「よくわからない用語があるから読み飛ばした」のでは、いつまでたってもプログラムな
ど作れるようになりませんよ。
内容がわからないのであれば、別の話題ですから別途質問するか(その場合は、新しいス
レに、このスレのURLを書いておきましょう)、または
 maru 2008/04/17(木) 23:27:20
のアドバイスに従うのがよろしいでしょう。

# 時刻を含めたコピペのため敬称略

PATIO 2008/04/18(金) 12:12:20
> # επιστημη氏>つ 紙飛行機
> # PATIO氏、maru氏> 航空力学を勉強しる

紙飛行機の中身を知るために必要な内容(C++言語)を勉強しては
と言う話が、航空力学まで行っちゃうと言うのはどうかなぁ。
C++言語に関しては、maruさんが書かれているように紙飛行機の
折り方の話だと思うけれど。

とにかく動くものを作りたいと言うのもわかるんだけど
提示された物のコピペでは応用が利かないし、
間違った覚え方をしてしまうかもしれない。
まあ、それでも作れればいいんだと言う話なら
私もそれ以上は言いませんけれど。

ある程度の基礎知識が付けば、習うより慣れろでも良いと
思うんですけれど、基礎知識が怪しい段階でひたすら
作ろうとするのは勉強方法としては効率が悪いし、
途中で面白くなくなるんではないかなと思います。

PATIO 2008/04/18(金) 12:19:51
グローバル変数にするには楽なんですけれど、
C++言語的に考えるとあまり良い実装とはいえ無いので
その辺も含めてC++言語の勉強をした方がいいです。
その方が自分で解決できる可能性も高くなりますし。

掲示板は色々教えてもらえて便利ですけれど、
自分で解決できた方がスピード的には数段早いので
自分で解決できるようになる為にも基礎的な部分の
勉強をされることをお勧めします。

まあ、今後どのようにされるのかはその人次第なのですけれど。

PATIO 2008/04/18(金) 12:22:22
あうあう、誤字

誤)
グローバル変数にするには楽なんですけれど、

正)
グローバル変数にするのは楽なんですけれど、

επιστημη [HomePage] 2008/04/18(金) 13:17:40
> グローバルにすればいいだけでした。

グローバル変数は万策尽きたときの最後の手段。
「わからない」からグローバル は下策。

1> 子ウィンドを開く→void CParentDlg::OnCbnSelchangeComboBox1();内
2> 取得した値を使用→void CParentDlg::OnBnClickedRecord();内

メンバ変数を用意し、[1]で書いて[2]で読むだけのこと。

たいちう 2008/04/18(金) 13:39:17
例えの出来が悪かったようですね。
間抜けな話ですが一応書いておくと私の意図は、、、

・自分のプログラムをどう直すかにとらわれ、
  単純なサンプルをわざわざ作成・実行することは重要でないと考え、
  原理の理解が不十分なまま闇雲にプログラム修正をしがちである。
・他の方々も勧めているように、基本から勉強したほうが上達が早い。

です。少なくとも後者については伝えることに失敗していますね。
前者についても質問者に伝わったかどうか。
揶揄されたように感じたのかもしれません。
誰も気分を害していなければ良いのですが。

PATIO 2008/04/18(金) 15:58:46
特に気分を害するとかは無いですよ。

ただ、あの例えだと多分たいちうさんの言いたい事は伝わって無いと思います。
航空力学だとちょっと高度過ぎかなと感じたので。
「紙飛行機の折り方を勉強しなさい」ならわかりやすかったかなと。

maru 2008/04/18(金) 16:52:58
> グローバルにすればいいだけでした。
επιστημηさんが書いた通り、メンバー変数を用意すればいいだけの話。
επιστημηさんの書いたコードや私の書いたコードを理解すれば自然とメンバー変数と
いう結論になるはず。この辺からもちゃんと勉強してよ、という気持ちになる。

# そこまで期待するのは無理か。

たいちうさん
> 誰も気分を害していなければ良いのですが。
いえ、私は全く。
逆に、たいちうさんのコメントに逆らうような事を書いたので、たいちうさんの方が
気分を害しているんじゃないかと心配しています。
あの例えは、どちらかというとうまいことを言うなぁ、と感心しています。
ただ、PATIOさんが書いたとおり、航空力学というほど高度な事を要求したつも
りはないぞ、とは思いましたけど。

# だからといって、我ながら「紙の折り方」が適切とも思えないのが難点。

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