CListCtrlの使い方・・・ – プログラミング – Home

通知
すべてクリア

[解決済] CListCtrlの使い方・・・

固定ページ 1 / 4

KENBO
 KENBO
(@KENBO)
ゲスト
結合: 19年前
投稿: 55
Topic starter  

VC6 XP ダイアログベースです。

リストコントロール(レポート)に1行に4列ある。
1行に文字列を表示したい。
しかし、
以下の関数を実行すると死にます。
この関数は1行分の表示を行なう関数です。
死ぬ理由がわからなくて・・・
間違いはないはずなんですけど・・
誰か何かわかりませんか?

void CLogControlDlg::DispLogData_ListCtl(DWORD index, LOG_INFO *pLog)
{
LV_ITEM item;
CString str;
TIME_INFO *pTim;

// 表示する行番号の設定
item.iItem = index;

// 行の背景色を設定する
switch( pLog->ErrClass ){
case ERROR_PRIORITY_W:
item.lParam = RGB(255,255,0); // 黄
break;
case ERROR_PRIORITY_E:
item.lParam = RGB(255,0,0); // 赤
break;
default:
item.lParam = RGB(255,255,255); // 白
break;
}

// ログ番号表示(1列目)
item.iSubItem = 0;
item.mask = LVIF_TEXT | LVIF_PARAM;
str.Format(%5d,index+1);
item.pszText = str.GetBuffer(0x100);
str.ReleaseBuffer(-1);
m_LstCtl_Ctrl.InsertItem(&item);

// 時刻表示(2列目)
item.mask = LVIF_TEXT;
item.iSubItem = 1;
pTim = (TIME_INFO *)&(pLog->time);
str.Format(%04d/%02d/%02d %02d:%02d:%02d.%03d,pTim->year,pTim-
>month,pTim->day,pTim->hour,pTim->min,pTim->sec,pTim->ms);
item.pszText = str.GetBuffer(0x100);
str.ReleaseBuffer(-1);
m_LstCtl_Ctrl.SetItem(&item);

// 識別コード(3列目)
item.mask = LVIF_TEXT;
item.iSubItem = 2;
str.Format(%s,(1<=pLog->code && pLog->code<=6)? pSikibetuCode[pLog-
>code] : msg_Fumei );
item.pszText = str.GetBuffer(0x100);
str.ReleaseBuffer(-1);
m_LstCtl_Ctrl.SetItem(&item);

// ログ情報(4列目)
item.mask = LVIF_TEXT;
item.iSubItem = 3;
switch( pLog->code ){
case ERROR_ID_MAIN:
str.Format(%s,(0<=pLog->ErrType && pLog->ErrType<=2)? pMainData
[pLog->ErrType] : msg_Fumei );
break;

case ERROR_ID_RS232:
case ERROR_ID_RS422:
str.Format(%s,(0<=pLog->ErrType && pLog->ErrType<=17)? pRs232422
[pLog->ErrType] : msg_Fumei );
break;

case ERROR_ID_HOUCYOU:
str.Format(%s,(0<=pLog->ErrType && pLog->ErrType<=15)? pHoucyou[pLog-
>ErrType] : msg_Fumei );
break;

case ERROR_ID_TCPIP:
str.Format(%s,(0<=pLog->ErrType && pLog->ErrType<=4)? pTcpIp[pLog-
>ErrType] : msg_Fumei );
break;

case ERROR_ID_CMD:
str.Format(%s,msg_Cmd);
break;

default:
str.Format(%s,msg_CodeErr);
}
item.pszText = str.GetBuffer(0x100);
str.ReleaseBuffer(-1);
m_LstCtl_Ctrl.SetItem(&item);
}


引用未解決
トピックタグ
てんてく
 てんてく
(@てんてく)
ゲスト
結合: 20年前
投稿: 92
 

回答とは違いますけど
この関数の どこで エラーが発生するのかデバッグはしてみましたか?
まずはそこからだと思いますが。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

「死ぬ」とは、何を指していますか?
おそらく実行時エラーなのでしょうけど、そのエラーの内容は?
また、ステップ実行してみて、どこで死んでいるのかを突き止めてください。
すぐにわかる注意点としては…CString::GetBuffer はそうやって使うものじゃありませ
ん。

> 間違いはないはずなんですけど・・

十中八九、コードの間違いです。


返信引用
KENBO
 KENBO
(@KENBO)
ゲスト
結合: 19年前
投稿: 55
Topic starter  

すいません。内容が足りませんでした。

>「死ぬ」とは、何を指していますか?
実行時エラーのことです。

エラー内容は以下のとおりです。
Debug Assertion Failed!!
Program : D\xxx.exe
File : winctrl2.cpp
Line :547
For information on how your program can cause an assertion failere, see the
VisualC++ documentation on asserts.
(press Retry to debug the application)

この関数を実行中に死ぬわけではないのです。
関数を出た後に死にます。
しかし、この関数をコメントして実行すると死にません。
なぜ?やっぱりこの関数が原因なのでしょうか?

>CString::GetBuffer はそうやって使うものじゃありませ
ん。
どうやって使うのですか?
ではCString型の文字列の先頭アドレスを欲しい場合はどうするのですか?


返信引用
ねこたま
 ねこたま
(@ねこたま)
ゲスト
結合: 19年前
投稿: 8
 

使い方云々はとりあえず置いておいて

解放後の CString 操作でバッファが再確保されることがあるので、GetBuffer 関数から返さ
れるアドレスは、ReleaseBuffer 関数を呼び出した後では無効になります。CString のを長さ
を変更しないときは、バッファの再確保は行われません。

と、MSDNにもあるようにReleaseBufferした後で参照してるからでないのかな?


返信引用
KENBO
 KENBO
(@KENBO)
ゲスト
結合: 19年前
投稿: 55
Topic starter  

>と、MSDNにもあるようにReleaseBufferした後で参照してるからでないのかな?
今回のようにGetBufferで直接item.pszTextにポインタを代入してるので、
ReleaseBufferは必要ないということですか?
言われてみればそうですね・・・(戻り値をポインタに代入してるわけではないから)


返信引用
KENBO
 KENBO
(@KENBO)
ゲスト
結合: 19年前
投稿: 55
Topic starter  

CStringの使い方は死ぬ原因とは無関係ですよね。
上の記述でも、
item.pszTextに正確に代入されてますし・・・


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

> ReleaseBufferは必要ないということですか?
は必要ですよ。

まぁCStringでは色々面倒なので普通に TCHAR型配列を用意してやるほうが楽なのでは。

> str.Format(%5d,index+1);
> item.pszText = str.GetBuffer(0x100);
> str.ReleaseBuffer(-1);

TCHAR str[ 0x100 ];

_stprintf( str, %5d, index + 1 );
item.pszText = str;


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

訂正
> _stprintf( str, %5d, index + 1 );
_stprintf( str, _T( %5d ), index + 1 );

ほかのところは全部char型(TCHARを意識していないので)なので動き的には変わらないけ
ど。


返信引用
KENBO
 KENBO
(@KENBO)
ゲスト
結合: 19年前
投稿: 55
Topic starter  

>まぁCStringでは色々面倒なので普通に TCHAR型配列を用意してやるほうが楽なので
>は。
楽なのはわかってもす。
しかし、せっかくVCなのでできるだけC言語は使わないでやってみたかったもの
で・・・


返信引用
ねこたま
 ねこたま
(@ねこたま)
ゲスト
結合: 19年前
投稿: 8
 

関係ないかもですが、item.iItem にInsertの結果を代入せんくていいのかな?
ていうか、SetItemで適当なアドレスに値セットに行ってたりしない?
InsertItemの戻り値とindexが同じならいいですけど、ここがちがったりしない?


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

GetBufferで試してみました。やはりそこが原因ではなさそうです。
一応
> item.pszText = str.GetBuffer(0x100);
> str.ReleaseBuffer(-1);
> m_LstCtl_Ctrl.SetItem(&item);
item.pszText = str.GetBufferSetLength( str.GetLength() );
m_LstCtl_Ctrl.SetItem(&item);
str.ReleaseBuffer();
のほうがよさそうだけど。

ということで、
> 「死ぬ」
ということを明確にしてください。
もしかしてデバッグができないのでしょうか?


返信引用
KENBO
 KENBO
(@KENBO)
ゲスト
結合: 19年前
投稿: 55
Topic starter  

> 「死ぬ」ということを明確にしてください。
winctrl2.cppの547行目、
以下の関数のASSERTを実行すると死にます。

void CListCtrl::DrawItem(LPDRAWITEMSTRUCT)
{
ASSERT(FALSE);
}

この関数はいつコールされてるのでしょうか?


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

> この関数はいつコールされてるのでしょうか?
デバッグして、コールスタックをさかのぼってください。

意味がわからないのであれば、ある程度ブレイクポイントを仕掛けて、
F5実行でここまでは大丈夫、ここでASSERTが出る。じゃぁもう少しブレイクポイントの
範囲を狭くしてみようと言う行為をして、絞り込んでください。


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

あれ?
> void CListCtrl::DrawItem(LPDRAWITEMSTRUCT)
ってことは、もしかしたらオーナドローをするのにその処理がないってことかな?

リストビューのプロパティをいじったのであればその情報がほしいです。
(レポート形式にしたのしかワカラン)

で、将来的にカスタムドローかオーナドローをするようなんですが、そこら辺の情報も
ください。


返信引用
固定ページ 1 / 4

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました