- ベストアンサー
VC++でリストコントロールの特定の行だけを太文字にする方法
- 質問者は、VC++でリストコントロールの特定の行だけを太文字にする方法を知りたいです。
- 質問者は、リストコントロール(IDC_LIST)に割り当てられた変数m_xcListの特定の行だけを太文字にする方法を知りたいです。
- 質問者は、既にできているエクセル版のリストコントロールでは、HTML形式で書き出し、太文字のアイテムを一つのフォルダに抽出する仕様であり、リストコントロールの特定の行だけを太文字にする方法を知りたいです。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
太字でない通常のフォントの場合指定するのはFW_NORMALですが、その場合はフォントを作成しなくても、元々選択されているフォントで描画すればいいはずです。定数については、LOGFONTの解説に書かれています。 http://msdn.microsoft.com/ja-jp/library/dd145037.aspx アイテムが選択されているかどうかは、lpDrawItemStruct->itemActionにODA_SELECTが含まれているかを調べるようです。 if (lpDrawItemStruct->itemAction|ODA_SELECT) { // 選択されている場合の描画 } else { // 選択されていない場合の描画 } といった感じでしょうか。
その他の回答 (3)
- m-take0220
- ベストアンサー率60% (477/782)
表示する文字列は、CListCtrl::GetItemTextで取得できます。アイテムのインデックスは、lpDrawItemStruct->itemIDに入っている値だと思います。 lpDrawItemStruct->rcItemは、アイテム全体の矩形じゃないかと思います。サブアイテムを考慮した描画矩形を取得するには、CListCtrl::GetItemRect/GetSubItemRectを使うと取得できるでしょう。
補足
だいぶ進みました。ありがとうございます。 残った疑問は、FW_BOLDの逆の意味の定数は○○? と、後は致命的なことに、アイテムを選択状態にできないことです。その他は大変満足しています。 参考になりそうなのが↓なんですが。。。 http://oshiete.goo.ne.jp/qa/4785511.html 例えば、リストのアイテムすべてを選択するというユーザー関数がうまく行きません。 クリックしても選択できません。 ================================================================ void CFileListCreatorDlg::SelectALL_Func(){ int i = 0; while(i<=m_xcList.GetItemCount() -1){ m_xcList.SetItemState(i, // フォーカス&選択状態にしたいアイテムのインデックス LVIS_FOCUSED | LVIS_SELECTED, // 状態 LVIS_FOCUSED | LVIS_SELECTED); // マスク i++; //ListView_Update(m_xcList, i);//追加しても意味がなかった2011.05.14 } } ================================================================ 後は、参照元のURLとソースコードをのせますね。 void CMylistCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){ // TODO: 指定された項目を描画するためのコードを追加してください。 //コメントアウト:2011.05.14 ////////if(lpDrawItemStruct->itemData == -1 || lpDrawItemStruct->itemData == NULL){ //////// return; ////////} //CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); //pDC->FillSolidRect(&lpDrawItemStruct->rcItem, RGB(0,0,0)/*背景の色*/); //pDC->SetBkColor(RGB(0,0,0)/*文字の後ろの色(背景と一緒にしとくべき)*/); //pDC->SetTextColor(RGB(255,255,255));/*文字の色*/; //▼ http://dejibouzu.com/page/2/ ▼ CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); CRect rect; rect = ( CRect)lpDrawItemStruct->rcItem; int nItem = lpDrawItemStruct->itemID; TCHAR szBuff[MAX_PATH]; CRect nRect; int nCnt = 0; int nIndentPix; CHeaderCtrl *Head = GetHeaderCtrl(); int nMax = Head->GetItemCount(); // CBrush brsh; // rect.left += this->GetColumnWidth( 0 ) ; // brsh.CreateSolidBrush( RGB( 0, 255, 0 ) ); // pDC->FillRect( &rect, &brsh ); // brsh.DeleteObject(); while( nMax > nCnt ) { nIndentPix = 0; //アイテム取得のための設定 LVITEM lvItem; lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_INDENT ;//追加しても意味がなかった2011.05.14 | LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES; lvItem.iItem = nItem; lvItem.iSubItem = nCnt; lvItem.pszText = szBuff; lvItem.cchTextMax = sizeof(szBuff); lvItem.stateMask = LVIS_SELECTED;//-1を LVIS_SELECTEDに変更2011.05.14 //m_xcList.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);//??? if( GetItem(&lvItem) == TRUE ){ if( nCnt == 0){ //アイテムの場合 GetItemRect( nItem, &nRect, LVIR_BOUNDS); }else{ //サブアイテムの場合 GetSubItemRect( nItem, nCnt, LVIR_BOUNDS, nRect); } //if ( m_phbrBkColor ){ //カラーテーブルにブラシが作成されているなら背景を描画 //if ( m_phbrBkColor[ nCnt * GetItemCount() + nItem] ) //{ //アイテムの場合 描画箇所をアイテム部分のみに修正 if( nCnt == 0 ){ nRect.right = GetColumnWidth( 0 ); } //FillRect( pDC->m_hDC, &nRect, m_phbrBkColor[ nCnt * GetItemCount() + nItem ] ); //} //} //===============教えて頂いた部分======================= CFont fontBold, *pfontOld; LOGFONT lf; pDC->GetCurrentFont()->GetLogFont(&lf); lf.lfWeight = FW_BOLD; //FW_BOLDの逆は?教えてください。-1にしたらできましたが、正確な定数名を教えてください。 fontBold.CreateFontIndirect(&lf); pfontOld = (CFont*)pDC->SelectObject(&fontBold); //pDC->SelectObject(pfontOld); //================================================================== //テキスト描画 CString outText = lvItem.pszText; //pDC->TextOut( nRect.left + 10, nRect.top + 2, outText ); nRect.left += 10;//変更2011.05.14 nRect.top +=2;//変更2011.05.14 pDC->DrawText(outText, &nRect, DT_VCENTER | DT_LEFT ); } ++nCnt; } //▲ http://dejibouzu.com/page/2/ ▲ //http://www9.plala.or.jp/sayox/vc/vc14.html //http://msdn.microsoft.com/ja-jp/library/1w31a26y(v=VS.100).aspx //http://msdn.microsoft.com/ja-jp/library/Cc428474 //int DrawText( // HDC hDC, // デバイスコンテキストのハンドル // LPCTSTR lpString, // 描画するテキスト // int nCount, // テキストの長さ // LPRECT lpRect, // テキストを描画する長方形領域 // UINT uFormat // テキスト描画オプション //); //★ http://oshiete.goo.ne.jp/qa/4165655.html //★ http://bingobingobingo.blog49.fc2.com/category4-1.html
- m-take0220
- ベストアンサー率60% (477/782)
コントロールの特定の項目に対してSetFontすることは、少なくともリストコントロールではできません。 > void CFileListCreatorDlg::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct){ MeasureItemを使うのはCListBoxの場合なので、必要ありません。 それに、処理を追加するのはCListCtrlの派生クラスに対してなので、ダイアログのクラスに記述しても呼ばれることはありませんよ。 > void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){ 前述のとおり、CListCtrlの派生クラスのメンバ関数にする必要があります。 > if(CFileListCreatorDlg::lvi.itemData == -1 || CFileListCreatorDlg::lvi.itemData == NULL) サイトの記述間違いです。正しくはlpDrawItemStruct->itemDataになります。 CListCtrlの派生クスについては、下記サイトを参照してみてください。 http://d.hatena.ne.jp/nurs/20091126
補足
>コントロールの特定の項目に対してSetFontすることは、少なくともリストコントロールではできません。 横一行、すべてBoldにはできますか?(繰り返しになってすみません。) Columnまで個別にBoldできなくてもいいです。 教えて頂いたホームページで、慎重に進めました。 OwnerDrawFixed をTrueにすると、リストが真っ白になってしまいます。 ファイルに保存したら、ちゃんとデータが入っています。 分からないので、試験的に■■■に「_T("1111111")」をいれて、ソート機能を実行すると、 「重複NO」に一番左の項目にちゃんと太文字で、表示されました。他の欄は空欄です。 つまり、DrawText()の一番最初の引数に何を入れればいいのか分かりません。 何行目を太文字に、どこで指定しているのかも分かりません。 ========================================================= CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); CFont fontBold, *pfontOld; LOGFONT lf; pDC->GetCurrentFont()->GetLogFont(&lf); lf.lfWeight = FW_BOLD; fontBold.CreateFontIndirect(&lf); pfontOld = (CFont*)pDC->SelectObject(&fontBold); pDC->DrawText(■■■/*lpDrawItemStruct->itemData*/,&lpDrawItemStruct->rcItem,DT_LEFT | DT_VCENTER | DT_SINGLELINE); pDC->SelectObject(pfontOld); ========================================================= ■■■に「lpDrawItemStruct->itemData」を入れてもエラーになります。 LVCOLUMN lvc;//追加2011.05.13 LVITEM lvi;//追加2011.05.13 とpublicで宣言して、■■■に 「&lvc」と入れてもダメです。 ========================================================= わざわざ、ホームページを教えて頂いたのにすみません。m(_ _)m 参考になりそうな(?)ページです。↓ http://oshiete.goo.ne.jp/qa/4165655.html http://bingobingobingo.blog49.fc2.com/category4-1.html
- m-take0220
- ベストアンサー率60% (477/782)
太字というのはフォントの属性になるので、太字設定のフォントを用意して、DrawTextなどの文字描画命令の前にデバイスコンテキストに選択することになります。 CFont fontBold, *pfontOld; LOGFONT lf; pDC->GetCurrentFont()->GetLogFont(&lf); lf.lfWeight = FW_BOLD; fontBold.CreateFontIndirect(&lf); pfontOld = (CFont*)pDC->SelectObject(&fontBold); pDC->DrawText(...); pDC->SelectObject(pfontOld); こんな感じでしょうか。試していないので、エラーがあったらすいません。 フォントは、毎回作成するのではなく、メンバー変数として持って、ウィンドウ作成時にフォントを作成したほうがいいのですが。 リストコントロールの表示フォントをどのようにしているのかがわからなかったので、描画直前に作成しています。
お礼
CFont font; font.CreatePointFont(360, _T("Times New Roman")); GetDlgItem(IDC_LIST)->SetFont(&font); これはうまく行きました。テストボタンを押した時に、実行します。 これで、行が指定できれば、良いのですが…。 もう少し、調べていきます。 CFont font; font.CreatePointFont(360, _T("Times New Roman")); GetDlgItem(IDC_LIST)->****[workRow,workColumn]->SetFont(&font); みたいに書きたいです。 onDraw() onPaint() は、分かりません・・・υ どこから追加するのですか? お礼の欄にすみません。
補足
さっそくの回答ありがとうございます。 ただ、pDCをどこから引っ張ってくるのかが、分かりません。 ========================================================================== 僕が見つけた先ほどのホームページで、 「 lpDrawItemStruct 」に何を入れなければならないか? も、分かっていませんでした。 リストはリストコントロールのみに保存されています。(何か変な日本語ですが・・・) Public に、LVITEM lvi; と書いて見ましたが、ユーザー関数の中にも定義していたり、いなかったりです。 ========================================================================== 「Owner Draw=固定」という項目もありませんでした。 オブジェクト名、ID、クラス名、空間名 、構造体 が、ごっちゃになっている気がしますυ ========================================================================== 一応、今の状態を・・・ エラー 2 error C2228: '.itemData' の左側はクラス、構造体、共用体でなければなりません。 ・・・というエラーが、 リストが張り付いているクラス名は、CFileListCreatorDlg です。 ========================================================================== void CFileListCreatorDlg::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct){ { // TODO : ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。 lpMeasureItemStruct->itemHeight = 10;/*1行の高さを設定*/; } void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){// この関数はリストボックスに行を追加したり削除したりした際に行数の数だけ繰り返し呼び出される。 if(CFileListCreatorDlg::lvi.itemData == -1 || CFileListCreatorDlg::lvi.itemData == NULL) return; CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); pDC->FillSolidRect(&lpDrawItemStruct->rcItem, RGB(0,0,0)/*背景の色*/); pDC->SetBkColor(RGB(0,0,0)/*文字の後ろの色(背景と一緒にしとくべき)*/); pDC->SetTextColor(RGB(255,255,255)/*文字の色*/); pDC->DrawText(_T("色の反転")/*lpDrawItemStruct->itemData*/,&lpDrawItemStruct->rcItem,DT_LEFT | DT_VCENTER | DT_SINGLELINE); } } ========================================================================== 一応、宣言部も載せておきます。 int CFileListCreatorDlg::ListInit(void) { LVCOLUMN lvc; int i; TCHAR caption[][32] = {_T("重複No."), _T("No."), _T("ファイルパス"), _T("ファイル名"),_T("バイト"), _T("実バイト"),_T("修正日"),_T("修正時間"),_T("備考欄")}; const int clmNum = sizeof caption /sizeof caption[0]; int err = 0; m_xcList.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; // 有効フラグ for (i = 0; i < clmNum; i++) { lvc.iSubItem = i; // サブアイテム番号 lvc.pszText = caption[i]; // 見出しテキスト switch(i){ case 0: case 1: lvc.cx = 80; // 横幅 break; case 2: lvc.cx = 0; // 横幅 break; case 3: lvc.cx = 450; // 横幅 break; case 4: lvc.cx = 80; // 横幅 break; case 5: lvc.cx = 0; // 横幅 break; case 6: lvc.cx = 75; // 横幅 break; case 7: lvc.cx = 0; // 横幅 break; case 8: lvc.cx = 80; // 横幅 break; default: MessageBox(_T("不正な列です。")); break; } if (m_xcList.InsertColumn(i, &lvc) == -1) {err = 1; break;} } CFileListCreatorDlg::ItemCount_Func(TRUE); return err; } ========================================================================== ちょっといじりましたが、お教え頂いた方法でする方が、楽にコーディングできますか? マイクロソフトのページのthisに何を入れればいいかも分かりませんυ一応、そのまま動きましたけどυ もうちょっと、頑張ってみます。ヒントをいただけるなら、よろしくお願いします。 【引用元】http://msdn.microsoft.com/ja-jp/library/chxkwcsd(v=VS.100).aspx // The code fragment shows how to create a font object, // select the font object into a DC (device context) for text // drawing, and finally delete the font object. CClientDC dc(this); CFont font; VERIFY(font.CreatePointFont(120, _T("Arial"), &dc)); // Do something with the font just created... CFont* def_font = dc.SelectObject(&font); dc.TextOut(5, 5, _T("Hello"), 5); dc.SelectObject(def_font); // Done with the font. Delete the font object. font.DeleteObject();
お礼
ありがとうございます!! 一から付き合っていただいて…、思ってた通りの動作が確認できました! 以下、最終的なコードです =================================================================================== void CMylistCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){ //▼ http://dejibouzu.com/page/2/ ベースとなるコード ▼ CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); CRect rect; rect = ( CRect)lpDrawItemStruct->rcItem; int nItem = lpDrawItemStruct->itemID; TCHAR szBuff[MAX_PATH]; CRect nRect; int nCnt = 0; int nIndentPix; CHeaderCtrl *Head = GetHeaderCtrl(); int nMax = Head->GetItemCount(); while( nMax > nCnt ) { nIndentPix = 0; //アイテム取得のための設定 LVITEM lvItem; lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_INDENT ;//追加しても意味がなかった2011.05.14 | LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES; lvItem.iItem = nItem; lvItem.iSubItem = nCnt; lvItem.pszText = szBuff; lvItem.cchTextMax = sizeof(szBuff); lvItem.stateMask = LVIS_SELECTED;//-1を LVIS_SELECTEDに変更2011.05.14 //m_xcList.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); if( GetItem(&lvItem) == TRUE ){ if( nCnt == 0){ //アイテムの場合 GetItemRect( nItem, &nRect, LVIR_BOUNDS); }else{ //サブアイテムの場合 GetSubItemRect( nItem, nCnt, LVIR_BOUNDS, nRect); } //if ( m_phbrBkColor ){ //カラーテーブルにブラシが作成されているなら背景を描画 //if ( m_phbrBkColor[ nCnt * GetItemCount() + nItem] ) //{ //アイテムの場合 描画箇所をアイテム部分のみに修正 if( nCnt == 0 ){ nRect.right = GetColumnWidth( 0 ); } //FillRect( pDC->m_hDC, &nRect, m_phbrBkColor[ nCnt * GetItemCount() + nItem ] ); //} //} //http://www.crimson-systems.com/tips/t003.htm //http://oshiete.goo.ne.jp/qa/6645218.html //http://www.tcn.zaq.ne.jp/zxcvbnm/projectc/vcpp/colortextcombo.htm //=======================▼教えて頂いた部分+α▼======================= CFont fontBold, *pfontOld; LOGFONT lf; pDC->GetCurrentFont()->GetLogFont(&lf); // 描画動作が全体の再描画もしくは、 // 選択状態が変化した場合 if( lpDrawItemStruct->itemAction & ( ODA_DRAWENTIRE | ODA_SELECT )) { // コントロールの状態が選択された状態の場合 if( lpDrawItemStruct->itemState & ODS_SELECTED ){ // 選択されている場合の描画 lf.lfWeight = FW_BOLD; //【×】pDC->FillSolidRect(&lpDrawItemStruct->rcItem,RGB(0,0,255));/*文字の後ろの色(背景と一緒にしとくべき)*/ //【×】pDC->SetBkMode(TRANSPARENT); pDC->SetBkMode(OPAQUE);//【○】これがないと背景が描画されない。 pDC->SetBkColor(RGB(0,0,255));/*背景の色*/ pDC->SetTextColor(RGB(255,255,255));/*文字の色*/ }else{//←条件追加 lf.lfWeight = FW_NORMAL; //【×】pDC->FillSolidRect(&lpDrawItemStruct->rcItem,RGB(255,255,255));/*文字の後ろの色(背景と一緒にしとくべき)*/ //【×】pDC->SetBkMode(TRANSPARENT); pDC->SetBkMode(OPAQUE);//【○】これがないと背景が描画されない。 pDC->SetBkColor(RGB(255,255,255));/*背景の色*/ pDC->SetTextColor(RGB(0,0,0));/*文字の色*/ } } else{ // 選択されていない場合の描画 lf.lfWeight = FW_NORMAL; pDC->SetBkMode(OPAQUE);//【○】 pDC->SetBkColor(RGB(255,255,255));/*背景の色*/ pDC->SetTextColor(RGB(0,0,0));/*文字の色*/ } fontBold.CreateFontIndirect(&lf); pfontOld = (CFont*)pDC->SelectObject(&fontBold); //pDC->SelectObject(pfontOld); //=======================▲教えて頂いた部分+α▲======================= //テキスト描画 CString outText = lvItem.pszText; //pDC->TextOut( nRect.left + 10, nRect.top + 2, outText ); nRect.left += 10;//変更2011.05.14 nRect.top +=2;//変更2011.05.14 pDC->DrawText(outText, &nRect, DT_VCENTER | DT_LEFT ); UpdateData(FALSE); } ++nCnt; } //▲ http://dejibouzu.com/page/2/ ▲ // //pDC->DrawText(CListCtrl::GetItemText(workRow,workColumn),/*lpDrawItemStruct->itemData*//*CListCl::GetSubItemRect&lpDrawItemStruct->rcItem*/,/&lpDrawItemStruct->rcItem,DT_LEFT | DT_VCENTER | DT_SINGLELINE); // //MessageBox(CListCtrl::GetItemText(lpDrawItemStruct->itemID-1,workColumn)); // } //} //http://msdn.microsoft.com/ja-jp/library/Cc428474 //int DrawText( // HDC hDC, // デバイスコンテキストのハンドル // LPCTSTR lpString, // 描画するテキスト // int nCount, // テキストの長さ // LPRECT lpRect, // テキストを描画する長方形領域 // UINT uFormat // テキスト描画オプション //); }