2011-07-16 139 views
3

不定状態に異なるビットマップを使用するには3状態チェックボックスをどのようにして取得しますか?MFC VC++カスタムチェックボックス画像

3状態チェックボックスで使用するイメージを別のものに変更したい場合は、コントロールはWin98スタイルであり、そのチェックボックスの不確定状態は無効なチェックボックスと区別するのが難しい(これはおそらくWinXPスタイルのコントロールでこれを変更した理由ですが、プロジェクトの他の詳細のために使用できません) 。

私はVisual C++ 2010を使用していますが、VSのリソースエディタで8x8ビットマップを定義しました。ビットマップのIDはIDB_INDET_CHECKです。

私はこのような何かのための標準的な "テクニック"が何であるか完全にはわかりません。私は実際には、WindowsのコントロールとMFCを操作するようになったばかりです。

最初に、CButtonから派生したCTriButtonというクラスを作成し、DrawItem関数をオーバーライドして、自分で描画しようとしました。私はSubclassDlgItemを使って、私のウィンドウ内のチェックボックスの1つをこのクラスに変えました(私は思っていますか?)。これは...作品の一種ですか?チェックボックスは表示されなくなり、空のチェックボックスフレームが表示されますが、何も表示されません(コード内のデバッグメッセージは送信されません)。

ここに関連コードがありますが、わかりませんがこれのは正しいです。まず、私のウィンドウのコードOnInitDialogからのコード。

BOOL CAffixFilterDlg::OnInitDialog() // CAffixFilterDlg is my CDialog-derived window 
{ 
    CDialog::OnInitDialog(); // call basic version 

    // subclass a CButton-derived control with CTriButton 
    if (CBipedHead.SubclassDlgItem(IDC_HEAD, this)) // CBipedHead is a CTriButton member of CAffixFilterDlg, IDC_HEAD is a checkbox 
     SetWindowLong(CBipedHead.m_hWnd, GWL_STYLE, CBipedHead.GetStyle() | BS_OWNERDRAW); // set the ownerdraw style 
    else // subclassing didn't work 
     _ERROR("Subclassing failed."); // I do not see this error message, so SubclassDlgItem worked? 

    // initialization continues, but is not relevant... 
    UpdateWindow(); 
    Invalidate(); 

    return TRUE; 
} 

次に、カスタムボタンのDrawItemのコードです。 OnInitDialogで

void CTriButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{ 
    _DMESSAGE("Drawing TriButton"); // never see this message 

    CDC dc; 
    dc.Attach(lpDrawItemStruct->hDC);  //Get device context object 
    int nWidth = GetSystemMetrics(SM_CXMENUCHECK); 
    int nMargin = (nWidth - 8)/2; 

    CRect textRt = lpDrawItemStruct->rcItem; 
    textRt.right = textRt.right - nWidth - nMargin; 

    CString text; 
    GetWindowText(text); 

    UINT textDrawState = DST_TEXT; 
    if (lpDrawItemStruct->itemState & ODS_DISABLED) 
     textDrawState |= DSS_DISABLED; 

    dc.DrawState(CPoint(textRt.left, textRt.top), textRt.Size(), text, textDrawState, TRUE, 0, (CBrush*)NULL); 

    CRect rt = lpDrawItemStruct->rcItem; // initial rect is for entire button 
    rt.left = rt.right - nWidth;   // set left margin 
    LONG center = (rt.bottom + rt.top)/2; 
    rt.top = center - nWidth/2; 
    rt.bottom = center + nWidth/2; 

    UINT checkDrawState = DFCS_BUTTONCHECK; 
    if (lpDrawItemStruct->itemState & ODS_DISABLED) 
     checkDrawState |= DFCS_INACTIVE; 

    if (lpDrawItemStruct->itemState & ODS_CHECKED) 
     checkDrawState |= DFCS_CHECKED; 

    else if (GetCheck() == BST_INDETERMINATE) { 
     _VMESSAGE("Indeterminate; custom draw."); 

     CBitmap indet_check = CBitmap(); 
     indet_check.LoadBitmap(IDB_INDET_CHECK); 

     CPoint pt = CPoint(rt.left + nMargin, rt.top + nMargin); 
     CSize sz = CSize(8, 8); 

     dc.DrawState(pt, sz, &indet_check, DST_BITMAP|DSS_NORMAL); 
    } 

    dc.DrawFrameControl(rt, DFC_BUTTON, checkDrawState); 
} 
+1

オーナー描画ウィンドウのスタイルはどこで有効にしましたか? – paludarium

+1

あなたの質問は何ですか?トライスタイルを設定するか、ボタンの状態を中間に設定するには、チェックボックスをどこに設定しましたか? – Ajay

+0

@paludarium:ありがとうございました。私はそれをすることを知らなかった。私は自分のコードを更新し、ownerdrawスタイルを設定しました。私はそれがすべき場所をクリックするまで、物事は全く描かれていないように見えます。そして、私は空のチェックボックスフレームだけを取得します。私の描画コードは呼び出されないようです(デバッグメッセージは表示されません)。私の質問はこれで更新されました。スタイルを設定していただきありがとうございます! – KRyan

答えて

1
ない 答え

が、答えは:このカスタムCCheckBoxは、私は、多かれ少なかれは私が欲しいものができました。デフォルトでは3つの州を許可するわけではありませんが、私はそれを自分自身の調整の一部で修正しました。私は100%確信しているわけではありません(私はいくつかの問題を抱えていましたが、は私の編集のためにと思われますが、私は確信できません)、それは解決策でした使用された。私は、誰かが私のコードで間違っていたことを偵察することができ、私を照らしたいと思う場合には、これを答えと呼ぶつもりはありません。

3

()あなたはそれ以外の場合は、それを再描画する必要が知らないウィンドウスタイルを変更した後、InvalidateRect()を呼び出す必要があります。また、ウィンドウスタイルを変更した後にUpdateWindow()を呼び出すことをお勧めします。一部の情報は通常、共通のコントロールによってキャッシュされ、UpdateWindow()が呼び出されるまで変更を認識しません。

DrawItem()では、コントロールのすべての状態を描画する必要があります。 CButton :: DrawItem()は何もしないので、呼び出さないでください。私は周りにこの最初の時間を逃したが、SubclassDlgItemへのお電話は、おそらく望ましい効果を持っていないと信じてすることはできません

void CTriButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{ 
    CBitmap indet_check 

    _DMESSAGE("Drawing TriButton"); // I never see this message 
    int checkState = GetCheck(); 

    if (checkState == BST_CHECKED) 
    { 
     indet_check.LoadBitmap(IDB_INDET_CHECK); 
    } 
    else if (checkState == BST_UNCHECKED) 
    { 
     indet_check.LoadBitmap(IDB_INDET_UNCHECKED); 
    } 
    else if (checkState == BST_INDETERMINATE) 
    { 
     indet_check.LoadBitmap(IDB_INDET_INDETERMINATE); 
    } 

    // ... rest of your drawing code here ... 
    // don't forget to draw focus and push states too ;) 

} 

補遺:次のようなものを試してみてください。この呼び出しにより、ボタンのためのメッセージがコントロールの親ウィンドウによって最初に処理されます。 CWnd(CDialogのスーパークラス)の既定の実装DrawItemは何も実行しないため、メッセージはコントロールに渡されません。

[OK]をする必要があり、次のスニペットとすべてのものに置き換えます:ここ

HWND hWndButton; 
GetDlgItem(IDC_HEAD, &hWndButton); 
CBipedHead.SubclassWindow(hWndButton); 

二つのサイドノート:

  1. 両方のクラスに同じ命名規則を使用することは通常は良い考えではありませんし、クラスメンバー。それは混乱した読書のためになります。
  2. 私は常にコンパイルしてリリースモードで実行していると思います。あなたがそうであれば - しないでください。アサーションがスローされるのを防ぎ、何かが間違っていることを知らせます。
+0

'CButton :: DrawItem'は何もしませんか?それは...確かに奇妙です。デフォルトのビットマップをチェックマーク(デフォルトのIDやLoadBitmapで使用できるもの)にロードする方法はありますか?また、DrawItem関数が処理する必要があるものは何ですか?私の主な問題の1つは、私が模倣すべきものを知るための 'DrawItem'の実際の定義を見ることができないということでした...どんな助けもありがとうと思います。 – KRyan

+1

@DragoonWraith MFCの一般的なコントロール表現は、DrawItem()メソッドでレンダリングを実装するものではなく、通常は1行で構成され、ASSERT()ステートメントです。[DRAWITEMSTRUC](http:// msdn.microsoft.com/en-us/library/92fhtw0f%28v=VS.80%29.aspx)構造体には、コントロールの描画方法に関するさまざまなフラグを保持する_itemState_というメンバが含まれています。 ** ODS_DEFAULT **、** ODS_DISABLED **、** ODS_FOCUS **および** ODS_SELECTE D **状態。 AFAIK一般的なコントロールは、一般的に要素のリソースビットマップに依存しません。 –

+0

ありがとう!それはとても役に立ちます。これらのことをする方法を調べるために...私は不確定状態に非デフォルトの "ルック"を望むので、私はビットマップが必要でしょうか? – KRyan

関連する問題