とっておきの「まかない飯」を教えて下さい!

http://oshiete.goo.ne.jp/qa/6729285.html で質問した者ですが、

DrawMenuBar();

を追加するだけで、メニューバーが通常表示されました。
コマンド名が全く分からずにすみません。

また、質問させていただきたいのですが、m_xcList という変数を割り当てたリストコンロール(IDC_LISTというID)のある特定の行だけを、太文字にしたいです。

( http://www.g-ishihara.com/mfc_lc_01.htm を参考にしました)

後は、 http://www5d.biglobe.ne.jp/~yasukiyo/vc.html に辿りついて、
「◇ リストボックス(CListBox)の項目(行)毎に色を変更する」 はできそうのですが、
色ではなく、「太文字」にしたいです。

なぜかというと、(既にできている エクセル版では、)リストをHTML形式で書き出し、太文字のアイテムを一つのフォルダに抽出するという仕様の為です。赤色にしたアイテムは別の意味を持っています。あまり、沢山の色を使いたくないです。

どのコマンドを使えばいいのでしょうか?そもそもできないのでしょうか。。。?
(もしできないのなら、なにか他のコントロールを使ったほうがいいですか?また、リストボックスとリストコントロールは別物ですか?)

今できそうなのは、さっきのホームページを参考にして、背景を黒に、文字を白にすることぐらいでしょうか?
でも、できればエクセル版と形式をそろえたいです。

(VC++2010, MFC, ダイアログベースのファイルリスト作成ソフトを(VBAより)移植中です。)

どうか、教えてください!

A 回答 (4件)

太字でない通常のフォントの場合指定するのはFW_NORMALですが、その場合はフォントを作成しなくても、元々選択されているフォントで描画すればいいはずです。

定数については、LOGFONTの解説に書かれています。

http://msdn.microsoft.com/ja-jp/library/dd145037 …

アイテムが選択されているかどうかは、lpDrawItemStruct->itemActionにODA_SELECTが含まれているかを調べるようです。

if (lpDrawItemStruct->itemAction|ODA_SELECT) {
// 選択されている場合の描画
}
else {
// 選択されていない場合の描画
}

といった感じでしょうか。
    • good
    • 0
この回答へのお礼

ありがとうございます!!

一から付き合っていただいて…、思ってた通りの動作が確認できました!

以下、最終的なコードです

===================================================================================

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/c …

//=======================▼教えて頂いた部分+α▼=======================

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 // テキスト描画オプション
//);
}

お礼日時:2011/05/14 13:15

表示する文字列は、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 …

 //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- …

補足日時:2011/05/14 09:49
    • good
    • 0

コントロールの特定の項目に対して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
LVITEMlvi;//追加2011.05.13

とpublicで宣言して、■■■に 「&lvc」と入れてもダメです。

=========================================================

わざわざ、ホームページを教えて頂いたのにすみません。m(_ _)m

参考になりそうな(?)ページです。↓
http://oshiete.goo.ne.jp/qa/4165655.html
http://bingobingobingo.blog49.fc2.com/category4- …

補足日時:2011/05/13 21:26
    • good
    • 0

太字というのはフォントの属性になるので、太字設定のフォントを用意して、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);

こんな感じでしょうか。試していないので、エラーがあったらすいません。
フォントは、毎回作成するのではなく、メンバー変数として持って、ウィンドウ作成時にフォントを作成したほうがいいのですが。
リストコントロールの表示フォントをどのようにしているのかがわからなかったので、描画直前に作成しています。

この回答への補足

さっそくの回答ありがとうございます。


ただ、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 …

// 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();

補足日時:2011/05/13 13:45
    • good
    • 0
この回答へのお礼

 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()

は、分かりません・・・υ

どこから追加するのですか?

お礼の欄にすみません。

お礼日時:2011/05/13 15:07

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報

このQ&Aを見た人がよく見るQ&A