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

質問
-
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}と追加したのですが 即反映されません。ここにはこないです。
すべての返信
-
CParameterDlg::OnBtn1Gcolor() が呼び出されない原因として考えられることはいろいろあるとは思います。
しかし以前、Dialogで得た変数を ChildViewの変数に渡す に書いたことがあると思いますが、
CColorPickerButtonのリフレクトメッセージの扱いが原因なのではないか? と疑ってみることにします。 -
((CChildView*)m_pParent)->Invalidate(); // Viewを更新
Invalidate()しただけではParentにWM_PAINTは発行されません。UpdateData(FALSE); // set the final action}で 即Viewに反映します。
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の発行を強制 -
ご検討ありがとうございますさっそく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 actionParnet_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に入れなくても)反映するようにはなりません。なんとか 助言をいただきたいです
-
ありがとうございますはい 以前 伺った内容は 現在解決したのですが、その後 便利に カーソルを移動させなくても 即座に反映させる ことで新しく質問することにしましたよろしく おねがいします>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_MAPEND_MESSAGE_MAP()とは あるのですが。
-
>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_MAPEND_MESSAGE_MAP()とは あるのですが。
通常、ボタンを押すと親ウィンドウに通知されるBN_CLICKEDは、親ウィンドウには通知されません。
だから、ボタンの親ウィンドウのハンドラCParameterDlg::OnBtn1Gcolor()が呼び出されないのです。
対処方法は以前Dialogで得た変数を ChildViewの変数に渡すに書いたとおりです。 -
以前のレスでも書きましたが、CColorPickerButtonをわざわざ作成して中でダイアログを処理してしまっているが故に
事態をややこしくしてしまっていると思います。御自身の知識が不足しているのに難しくなるような方向に自ら進んでいる
状態なのではないかと思います。
コントロールの中にダイアログを出す機能を入れると言う発想をどこから得たのかまでは分からないのですが、
なぜダイアログ側で色選択のコモンダイアログを出してボタンに設定するという方法をとらなかったのでしょう。
そうしていれば、話はもっとシンプルになったはずです。
いっその事、この辺もひっくるめてシンプルにしてしまった方が今後のことを考えると良いのではと思います。
解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。 -
ありがとうCColorPickerButton,でColorPickerButton.h略COLORREF m_Color; // 保持している色// 生成されたメッセージ マップ関数//{{AFX_MSG(CColorPickerButton)//2009/11/26// afx_msg void OnClicked();//2009/11/26afx_msg BOOL OnClicked(UINT nID)://}}AFX_MSGDECLARE_MESSAGE_MAP()};\ColorPickerButton.h(53) : error C2059: 構文エラー : 'private'なるのですが どうしてでしょうか?
-
ありがとうございますダイアログ側で色選択のコモンダイアログを出してボタンに設定するという方法と言う意味は ソースの手続きはちがっても、操作は同じにできることですか?ParameterDialog内の色設定(4つある)のボタンを押すとColorDialogが出て、それで選択すると同時にボタンが着色され 即座にViewの色も変わるという操作をしたいのです。たしかに 以前と違いParameterDialogのOKボタンを無くし、カーソルがViewWIndow内にあれば即Viewに反映するようにしたのでボタンの着色の意義が低下したのですが、4つの色の内の2つはViewである操作 ”色線のTraceアニメ”をしないと表示されないのでやはり ボタンでの色表示(見本)はほしいところです。ボタンでなく 別に色区画を置けばということもあるのですがボタンと色区画と兼ねたのは 小生の単純な好みです。場所もひとつですむという。
-
\ColorPickerButton.h(53) : error C2059: 構文エラー : 'private'
コンパイルエラーが出るたびに掲示板で質問するのでしょうか?なるのですが どうしてでしょうか?
こんなことでは、一生かかってもソフトウェアはでき上がらないと思いますよ。
そもそも、ご自分でどのくらい調べたのでしょうか?
53行目付近をどのくらいの時間をかけてチェックしたでしょうか?
http://msdn.microsoft.com/ja-jp/library/t8xe60cf(VS.80).aspx?ppud=4 くらいは見ましたか? -
と言う意味は ソースの手続きはちがっても、操作は同じにできることですか?ParameterDialog内の色設定(4つある)のボタンを押すとColorDialogが出て、それで選択すると同時にボタンが着色され 即座にViewの色も変わるという操作をしたいのです。たしかに 以前と違いParameterDialogのOKボタンを無くし、カーソルがViewWIndow内にあれば即Viewに反映するようにしたのでボタンの着色の意義が低下したのですが、4つの色の内の2つはViewである操作 ”色線のTraceアニメ”をしないと表示されないのでやはり ボタンでの色表示(見本)はほしいところです。ボタンでなく 別に色区画を置けばということもあるのですがボタンと色区画と兼ねたのは 小生の単純な好みです。場所もひとつですむという。
ボタンは外部から指定された色をボタン上に表示出来れば良いだけの話ですよね。
ボタンが色選択ダイアログを出す必要は何処にもないはずです。
ダイアログ側で色選択のダイアログを表示し、OKで戻ってきたタイミングで色選択ダイアログから
色情報を取得してボタンに設定すれば、同じ事ができると思いますよ。
ボタンクラス側を通常のボタンクラスから派生させて指定された色で描画する機能を付ければ、
実現できると思いませんか?
単機能で考えて組み合わせて解決すると言う思考方法を使った方が一つ一つの内容が
単純化されるので対応しやすくなります。
あと、実装の組み立てを行う場合に行き当たりばったりに行なうのはやめた方が良いです。
自分で書いたソースも半年も経てば他人が書いたソースと変わりません。
要は複雑な実装をしてしまうと自分でも読み解くのに時間が掛かると言う事です。
コメントを詳しく入れておくと言う方法もありますが、無意味に複雑にしても分かりにくくなるだけで
メリットは有りません。より自然な思考を心がけて実装の組み立てを行う方がメンテナンス性も格段に上がります。
今回のケースで言えば、色の管理はダイアログが行なうべきで、ボタン上の表示はユーザーに状況を提示できれば、
良いだけです。ですから、色の管理に関するイニシアティブはダイアログが持つべきで、ボタンは単なるインジケーターと
考えた方が自然だと思います。
あえて複雑な実装を選ぶケースも皆無とは言いませんが、
現在、説明されている範囲で理解できる状況からするとそういうケースに当てはまるとも思えません。
知識が足りない状況でやっているのですからより単純な方法で解決できるように考えて行く事が大事だと思います。
解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。