none
ParameterDialogにおいて読み出したColorDialogの色情報をViewに即反映させるには RRS feed

  • 質問

  • WindowsXp VSC++6.0 MFC です

    現在 Viewで描画する色をParamerDialogで ボタンをおすことで ColorDialogを読み出し それより得ています。
    操作としては マウスカーソルをDialogよりはずしてViewのWindow内に移動すると色が変わります。着色をカーソルを移動しないでも
    即変わるようにしたいのです。助言をお願いします。
    なお、ParameterDialogの他のEditBoxで取得した変数は
    void CParameterDlg::OnChangeEdit1() // for write the changed variable
    {
       UpdateData(TRUE); 
    ((CChildView*)m_pParent)->m_komaNoX = m_KomaX_N;
     略
    ((CChildView*)m_pParent)->Invalidate(); // Viewを更新 
      UpdateData(FALSE); // set the final action

    }
    で 即Viewに反映します。
    そこで
    void CParameterDlg::OnBtn1Gcolor() //ColorPickerButtonのメッセージ関数
    {
    // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
    UpdateData(TRUE);
    ((CChildView*)m_pParent)->m_grdColor = m_BtnGColor.GetColor();//色取得でView色変数に引き渡す
    ((CChildView*)m_pParent)->Invalidate(); // Viewを更新 
    UpdateData(FALSE); // set the final action
    }
    と追加したのですが 即反映されません。ここにはこないです。

    2009年11月24日 21:41

すべての返信

  • CParameterDlg::OnBtn1Gcolor() が呼び出されない原因として考えられることはいろいろあるとは思います。
    しかし以前、Dialogで得た変数を ChildViewの変数に渡す に書いたことがあると思いますが、
    CColorPickerButtonのリフレクトメッセージの扱いが原因なのではないか? と疑ってみることにします。
    2009年11月25日 0:14
  • ((CChildView*)m_pParent)->Invalidate(); // Viewを更新 
      UpdateData(FALSE); // set the final action

    }
    で 即Viewに反映します。
    Invalidate()しただけではParentにWM_PAINTは発行されません。
    UpdateWindow()してみてはどうでしょう。

      CChildView*  Parnet_View = ( CChildView*)m_pParent;
      UpdateData( FALSE); // set the final action
      Parnet_View->Invalidate( NULL, FALSE);  // 無効にしただけ。そのうちにWM_PAINTが発行されるかもネ・・・の状態
      Parnet_View->UpdateWindow();             // WM_PAINTの発行を強制
    2009年11月25日 1:50
  • ご検討ありがとうございます
    さっそく
    void CParameterDlg::OnBtn1Gcolor() 
    {
    // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
    // 現在効かない
    MessageBox(_T("here pass"));
    UpdateData(TRUE);
    ((CChildView*)m_pParent)->m_grdColor = m_BtnGColor.GetColor(); // ColorPickerButton の色をViewに送る
    // ((CChildView*)m_pParent)->Invalidate(); // Viewを更新 UpdateView(); の代わり
     
    CChildView*  Parnet_View = (CChildView*)m_pParent;
    UpdateData(FALSE); // set the final action
    Parnet_View->Invalidate(FALSE);  // 無効にしただけ。そのうちにWM_PAINTが発行されるかもネ・・・の状態
    Parnet_View->UpdateWindow();     // WM_PAINTの発行を強制
    }
    としたのですが、これでは ColorPickerボタンを押して ColorDialogの色を得てボタンに着色しても このメッセージ関数に来ません。
    Messageが出ない。CColorPickerButtonでの扱いがわるいのでしょう。

    そこでは
    void CColorPickerButton::OnClicked() 
    {
    // カスタムカラー配列を独自指定して呼び出し
    if( ColorDlg( this->m_hWnd, &crSelected, crFirst ,TRUE, dwCustomColor ) )
    {
    SetColor(crSelected);// 選択された色をcrSelectedから受け取ります。
    // 2009/10/22 色ボタンが押されたら m_SwellMode に強制的に=3 を与える
    // m_SwellModeはパラメータダイアログの変数であり、// これを変えただけでは
    // 描画キャンバスであるChildViewの表示は更新されない。
    // 親ウィンドウであり描画キャンバスであるChildViewの
    // m_swellも更新してはじめて描画毎(OnPaint)に色が更新されるようになる。
    CParameterDlg* pParamDlg = (CParameterDlg*)GetParent(); // パラメータダイアログの参照を取得
    pParamDlg->m_SwellMode = 3; // m_SwellModeを3に
    pParamDlg->UpdateData(FALSE); // コントロールボックス表示に反映させる
    }
    }
    /////////////end
    となっており、ColorDialogの色はボタンに着色するまでは行っているのですが、
    Viewに即(カーソルをViewWindowに入れなくても)反映するようにはなりません。

    なんとか 助言をいただきたいです

    2009年11月25日 13:50
  • ありがとうございます
    はい 以前 伺った内容は 現在解決したのですが、
    その後 便利に カーソルを移動させなくても 即座に反映させる ことで新しく質問することにしました
    よろしく おねがいします

    >CColorPickerButtonはON_CONTROL_REFLECT()を使って、CColorPickerButton自身がBN_CLICKEDを受け取っている。
    ファイルから検索で しらべたのですが ON_CONTROL_REFLECT() も ON_CONTROL_REFLECT_EX()  があらわれません。
    BEGIN_MESSAGE_MAP(CColorPickerButton, CButton)
    //{{AFX_MSG_MAP(CColorPickerButton)
    ON_CONTROL_REFLECT(BN_CLICKED, OnClicked)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    とは あるのですが。
    2009年11月25日 21:29
  • >CColorPickerButtonはON_CONTROL_REFLECT()を使って、CColorPickerButton自身がBN_CLICKEDを受け取っている。
    ファイルから検索で しらべたのですが ON_CONTROL_REFLECT() も ON_CONTROL_REFLECT_EX()  があらわれません。
    字面だけ見るのではなくて、書いていることの意味を汲み取ってほしいです。

    BEGIN_MESSAGE_MAP(CColorPickerButton, CButton)
    //{{AFX_MSG_MAP(CColorPickerButton)
    ON_CONTROL_REFLECT(BN_CLICKED, OnClicked)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    とは あるのですが。
    要するにここのメッセージマップでは、ON_CONTROL_REFLECTの方を使っていますので、
    通常、ボタンを押すと親ウィンドウに通知されるBN_CLICKEDは、親ウィンドウには通知されません。
    だから、ボタンの親ウィンドウのハンドラCParameterDlg::OnBtn1Gcolor()が呼び出されないのです。

    対処方法は以前Dialogで得た変数を ChildViewの変数に渡すに書いたとおりです。
    2009年11月26日 0:06
  • 以前のレスでも書きましたが、CColorPickerButtonをわざわざ作成して中でダイアログを処理してしまっているが故に
    事態をややこしくしてしまっていると思います。御自身の知識が不足しているのに難しくなるような方向に自ら進んでいる
    状態なのではないかと思います。

    コントロールの中にダイアログを出す機能を入れると言う発想をどこから得たのかまでは分からないのですが、
    なぜダイアログ側で色選択のコモンダイアログを出してボタンに設定するという方法をとらなかったのでしょう。
    そうしていれば、話はもっとシンプルになったはずです。

    いっその事、この辺もひっくるめてシンプルにしてしまった方が今後のことを考えると良いのではと思います。


    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    2009年11月26日 1:14
  • ありがとう

    CColorPickerButton,で
    ColorPickerButton.h
    COLORREF m_Color; // 保持している色

    // 生成されたメッセージ マップ関数
    //{{AFX_MSG(CColorPickerButton)
    //2009/11/26
    // afx_msg void OnClicked();
    //2009/11/26
    afx_msg BOOL OnClicked(UINT nID): 
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
    };
    \ColorPickerButton.h(53) : error C2059: 構文エラー : 'private'
    なるのですが どうしてでしょうか?




    2009年11月26日 8:33
  • ありがとうございます
    ダイアログ側で色選択のコモンダイアログを出してボタンに設定するという方法
    と言う意味は ソースの手続きはちがっても、操作は同じにできることですか?
    ParameterDialog内の色設定(4つある)のボタンを押すとColorDialogが出て、それで選択すると
    同時にボタンが着色され 即座にViewの色も変わるという操作をしたいのです。
    たしかに 以前と違いParameterDialogのOKボタンを無くし、カーソルがViewWIndow内にあれば
    即Viewに反映するようにしたので
    ボタンの着色の意義が低下したのですが、4つの色の内の2つはViewである操作 ”色線のTraceアニメ”をしないと
    表示されないので
    やはり ボタンでの色表示(見本)はほしいところです。
    ボタンでなく 別に色区画を置けばということもあるのですが
    ボタンと色区画と兼ねたのは 小生の単純な好みです。場所もひとつですむという。

    2009年11月26日 8:44
  • \ColorPickerButton.h(53) : error C2059: 構文エラー : 'private'
    なるのですが どうしてでしょうか?
    コンパイルエラーが出るたびに掲示板で質問するのでしょうか?
    こんなことでは、一生かかってもソフトウェアはでき上がらないと思いますよ。

    そもそも、ご自分でどのくらい調べたのでしょうか?
    53行目付近をどのくらいの時間をかけてチェックしたでしょうか?
    http://msdn.microsoft.com/ja-jp/library/t8xe60cf(VS.80).aspx?ppud=4 くらいは見ましたか?
    2009年11月26日 8:58
  • と言う意味は ソースの手続きはちがっても、操作は同じにできることですか?
    ParameterDialog内の色設定(4つある)のボタンを押すとColorDialogが出て、それで選択すると
    同時にボタンが着色され 即座にViewの色も変わるという操作をしたいのです。
    たしかに 以前と違いParameterDialogのOKボタンを無くし、カーソルがViewWIndow内にあれば
    即Viewに反映するようにしたので
    ボタンの着色の意義が低下したのですが、4つの色の内の2つはViewである操作 ”色線のTraceアニメ”をしないと
    表示されないので
    やはり ボタンでの色表示(見本)はほしいところです。
    ボタンでなく 別に色区画を置けばということもあるのですが
    ボタンと色区画と兼ねたのは 小生の単純な好みです。場所もひとつですむという。
    何もかもボタンにやらせようとするから話がややこしくなってしまいます。
    ボタンは外部から指定された色をボタン上に表示出来れば良いだけの話ですよね。
    ボタンが色選択ダイアログを出す必要は何処にもないはずです。
    ダイアログ側で色選択のダイアログを表示し、OKで戻ってきたタイミングで色選択ダイアログから
    色情報を取得してボタンに設定すれば、同じ事ができると思いますよ。
    ボタンクラス側を通常のボタンクラスから派生させて指定された色で描画する機能を付ければ、
    実現できると思いませんか?
    単機能で考えて組み合わせて解決すると言う思考方法を使った方が一つ一つの内容が
    単純化されるので対応しやすくなります。

    あと、実装の組み立てを行う場合に行き当たりばったりに行なうのはやめた方が良いです。
    自分で書いたソースも半年も経てば他人が書いたソースと変わりません。
    要は複雑な実装をしてしまうと自分でも読み解くのに時間が掛かると言う事です。
    コメントを詳しく入れておくと言う方法もありますが、無意味に複雑にしても分かりにくくなるだけで
    メリットは有りません。より自然な思考を心がけて実装の組み立てを行う方がメンテナンス性も格段に上がります。
    今回のケースで言えば、色の管理はダイアログが行なうべきで、ボタン上の表示はユーザーに状況を提示できれば、
    良いだけです。ですから、色の管理に関するイニシアティブはダイアログが持つべきで、ボタンは単なるインジケーターと
    考えた方が自然だと思います。
    あえて複雑な実装を選ぶケースも皆無とは言いませんが、
    現在、説明されている範囲で理解できる状況からするとそういうケースに当てはまるとも思えません。
    知識が足りない状況でやっているのですからより単純な方法で解決できるように考えて行く事が大事だと思います。

    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    2009年11月27日 3:04