早速質問させていただきます。
OS:Windows2000 XP
VC6でダイアログベースです。
HBRUSH CColorEdit::CtlColor(CDC* pDC, UINT nCtlColor)
{
// TODO: この位置で DC のアトリビュートを変更してください
pDC->SetTextColor( m_colText );
pDC->SetBkColor( m_colBack );
return m_brush;
}
//-----------------------------------------------------------------------------
// 文字色の変更
// ret : なし
// arg1 : (IN) colBack 文字色
//-----------------------------------------------------------------------------
void CColorEdit::SetTextColor( COLORREF colText )
{
m_colText = colText;
}
//-----------------------------------------------------------------------------
// 背景色の変更
// ret : なし
// arg1 : (IN) colBack 背景色
//-----------------------------------------------------------------------------
void CColorEdit::SetBackColor( COLORREF colBack )
{
m_colBack = colBack;
m_brush.DeleteObject();
m_brush.CreateSolidBrush( m_colBack );
if( NULL != m_hWnd )
{
RedrawWindow( NULL, NULL, RDW_FRAME | RDW_INVALIDATE |
RDW_UPDATENOW );
}
}
すみません。途中で送信してしまいました。
上記のように、CEditの派生クラスを作って、
色を変えているのですが、
リソースの設定で「無効」にした場合に、
文字色が変わりません。
ReadOnly(TRUE)にして、TabStopを設定しないというのも
試したのですが、エディットボックス内にカーソルが出てしまいます。
カーソルは出したくないのです。
スタティックテキストにするしか無いのでしょうか?
この場合、入力したくなると困るので、
何か良い方法があればと思い書き込みさせていただきました。
よろしくお願い致します。
私はよく、エディットコントロールのEN_SETFOCUSのイベントハンドラで
別のコントロールにフォーカスを移すようにしています。
void CXXXXDlg::OnEnSetfocusEdit1()
{
//最初のコントロールにフォーカスを移動
CWnd *pWnd=GetWindow( GW_CHILD );
if( pWnd ) pWnd->SetFocus();
}
どとう様、ありがとうございます。
この場合、一つ一つのコントロールのフォーカスを、
移動させなくてはならないのですよね?
今回、この色設定をするエディットボックスが50個くらいあるので、
この対応はかなり厳しそうですが、今後の参考になりました。
カーソル移動させたくないだけなら、
CEditの派生クラスの方にOnLButtonDownとOnContextMenuの
ハンドラを追加してその実装を空にするだけでも
できそうですがどうでしょうか。
かなり前の記憶ですが、EDITを無効化した場合は、
STATICと同じく、WM_CTLCOLORSTATICが送られてきて、
こちらで処理しないといけなかった様な気がします。
よく考えたら、CEditの派生クラスのOnSetFocus()で
前のフォーカスに戻せば良いのではないでしょうか?
void CXXXEdit::OnSetFocus(CWnd* pOldWnd)
{
//CEdit::OnSetFocus(pOldWnd);
//前のフォーカスに戻す
if( pOldWnd ) pOldWnd->SetFocus();
}
カーソルは出なくなりますが、入力もできなくなり
ただのスタティックテキストのようになります。
それで良いのですよね?
Tabで移動できなくなるので、TabStop=FALSEが必要。
subaru様 Hazard52様
ありがとうございます。
subaru様
> カーソル移動させたくないだけなら、
> CEditの派生クラスの方にOnLButtonDownとOnContextMenuの
> ハンドラを追加してその実装を空にするだけでも
> できそうですがどうでしょうか。
この場合、無効にしているエディットボックスは、
理想的な動きをしてくれたのですが、
色を変更したいだけの、有効なエディットボックスも
入力が出来なくなってしまったので、
void CColorEdit::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: この位置にメッセージ ハンドラ用のコードを追加するかまたはデフォル
トの処理を呼び出してください
if( !( GetStyle() & ES_READONLY ))
{
CEdit::OnLButtonDown(nFlags, point);
}
}
こんな感じで、回避してみたのですが、
OnContextMenuの方の対応策が思いつきません。
何か良い方法ありますでしょうか?
--------------------------------------------------------------------
Hazard52様
> かなり前の記憶ですが、EDITを無効化した場合は、
> STATICと同じく、WM_CTLCOLORSTATICが送られてきて、
> こちらで処理しないといけなかった様な気がします。
クラスウィザードを使っているのですが、
WM_CTLCOLORSTATICが見当たりません。
自分で、書かないとダメですか?
よろしくお願い致します。
> ReadOnly(TRUE)にして、TabStopを設定しないというのも
> 試したのですが、エディットボックス内にカーソルが出てしまいます。
> この場合、入力したくなると困るので
文字を範囲選択して Ctrl+C とかされても問題は無いのだけど、カーソルに点滅されると
入力可と誤解されるかもしれないので嫌だ!って可能性もあるのかな。
void CColorEdit::OnSetfocus() {
::DestroyCaret();
}
仮にそうならば上記コードでカーソルを消す事は可能なハズ。
だが、内部的にはカーソルは生きているので Shift + 十字キーとかマウスとかで文字の
範囲選択はできちゃうけどね。
> WM_CTLCOLORSTATICが見当たりません。
MFC では WM_CTLCOLORxxxx 系メッセージは WM_CTLCOLOR に纏めて送られてくる。
で、実際にどの WM_CTLCOLORxxxx が送られてきたか判断するには OnCtlColor() の
nCtlColor を見て判断する仕様になってる。
ぶっちゃけると、花乃さんのコードで WM_CTLCOLORSTATIC で送られてきた時の処理はで
きている。(EDIT にくる WM_CTLCOLORxxxx 系メッセージ全てで同じ処理をしているので
結果的に、と言った方が正しいだろうけど)
>こんな感じで、回避してみたのですが、
>OnContextMenuの方の対応策が思いつきません。
OnLButtonDownと同様
CEdit::OnContextMenu(...);
で既定の処理が行われます。
>クラスウィザードを使っているのですが、
>WM_CTLCOLORSTATICが見当たりません。
>自分で、書かないとダメですか?
MFCの場合はOnCtlColorの引数で判断すること
になるのですがこれは通常ダイアログ側の実装のはず。
#CEditの派生クラスの方に書いてるみたいだけどメッセージくるのかな?
gak様、subaru様、ありがとうございます。
MFCの場合は、OnCtlColor()に纏められて送られて来るですね。
確かに以前作った時は、APIで作ってました。
で終わってしまうのも中途半端なので、CEditの派生クラスで作ってみました。
CEditの派生クラスにOnPaint()を追加して、その中で色付けをすると
無効にしても同じく設定できましたが、いかがでしょうか?
どとう様 gak様 subaru様 Hazard52様
何度も書き込みしてくださってありがとうございます。
どとう様
> よく考えたら、CEditの派生クラスのOnSetFocus()で
> 前のフォーカスに戻せば良いのではないでしょうか?
void CColorEdit::OnSetFocus(CWnd* pOldWnd)
{
if(( GetStyle() & ES_READONLY ))
{
// 前のフォーカスに戻す
if( pOldWnd )
{
pOldWnd->SetFocus();
}
}
else
{
CEdit::OnSetFocus( pOldWnd );
}
}
これで、うまくいきました。
SetReadOnly( TRUE );
設定をした、エディットボックスはカーソルが付かず、
それ以外は普通に入力も出来ました。
勿論、色も変わりました。
ありがとうございます。
--------------------------------------------------------------------
gak様
色々と解説ありがとうございます。
まだまだ、勉強不足でカーソルを消すなんて
思いついても無かったです。
参考になりました。
--------------------------------------------------------------------
subaru様
> OnLButtonDownと同様
> CEdit::OnContextMenu(...);
> で既定の処理が行われます。
void CColorEdit::OnContextMenu(CWnd* pWnd, CPoint point)
{
// TODO: この位置にメッセージ ハンドラ用のコードを追加してください
if( !( GetStyle() & ES_READONLY ))
{
CEdit::OnContextMenu( pWnd, point );
}
}
こちらもうまくいきました。
クラスウィザードで関数を作成したとき、
OnLButtonDownは
CEdit::OnLButtonDown(nFlags, point);
↑この、規定クラスを呼ぶコードが勝手に付いてきたのですが、
OnContextMenuには無かったので、
どうしたものかと、考えてしまいました。
無事に解決しました。
ありがとうございます。
--------------------------------------------------------------------
Hazard52様
> で終わってしまうのも中途半端なので、CEditの派生クラスで作ってみました。
> CEditの派生クラスにOnPaint()を追加して、その中で色付けをすると
> 無効にしても同じく設定できましたが、いかがでしょうか?
ありがとうございます。
こちらの案も試してみたくて、
OnPaint()の追加をして、CtlColorのように色をセットしてみたのですが、
文字が出なくなってしまいました。
この場合、CtlColorは標準に戻すのでしょうか?
それと、OnPaint()関数では、色設定のほかに何をすればよいのでしょうか?
何度もすみませんが教えていただければと思います。
よろしくお願い致します。
OnPaint()は、下記の様に記述しました。
OnChildNotify()が無いと、入力した時に一部しか再描画されません。
ヘッダファイルには、publicで、下の一文を追加して下さい。
virtual BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam,
LRESULT* pLResult);
void CColorEdit::OnPaint()
{
UINT nFormat = DT_SINGLELINE;
COLORREF OldColText;
COLORREF OldColBack;
CString sTitle;
CRect cr1, cr2;
CPen cPen;
CPen* cPenOld;
CPaintDC dc(this); // 描画用のデバイス コンテキスト
// 描画ペン生成
LOGBRUSH logBrush;
logBrush.lbStyle = BS_SOLID;
logBrush.lbColor = RGB(0, 0, 0);
cPen.CreatePen(PS_SOLID | PS_GEOMETRIC, 1, &logBrush);
cPenOld = dc.SelectObject(&cPen);
// 描画文字列取得
GetWindowText(sTitle);
// クライアント矩形描画領域取得
GetClientRect(&cr1);
cr2.left = cr1.left + 1;
cr2.top = cr1.top + 1;
cr2.right = cr1.right - 1;
cr2.bottom = cr1.bottom - 1;
dc.FillSolidRect(cr2, m_ColBack);
OldColText = dc.SetTextColor(m_ColText);
OldColBack = dc.SetBkColor(m_ColBack);
dc.DrawText(sTitle, &cr2, nFormat);
// 変更した属性を戻す
dc.SetTextColor(OldColText);
dc.SetBkColor(OldColBack);
dc.SelectObject(cPenOld);
}
BOOL CColorEdit::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam,
LRESULT* pLResult)
{
Invalidate();
return CEdit::OnChildNotify(message, wParam, lParam, pLResult);
}
あっ。すいません。
CtlColor()は、使用してませんでした。
Hazard52様
親切にしてくださって、ありがとうございます。
教えてくださった方法でも、
希望通りの動作が出来ました。
OnPaint関数では、自分で描画しないといけなかったのですね。
OnChildNotifyの存在も知らなかったので、
本当に勉強になりました。感動です。
ありがとうございました。
一つの事を実現するのに、色々な方法があるのですね。
今回は、OnSetFocusで、前のフォーカスに戻すことに
致しました。
教えてくださった皆さん、ありがとうございました。