仮想リストコントロール SetItemCountExで落ちてしまいます。  – プログラミング – Home

仮想リストコントロール SetItem...
 
通知
すべてクリア

[解決済] 仮想リストコントロール SetItemCountExで落ちてしまいます。 

固定ページ 1 / 2

大泉
 大泉
(@大泉)
ゲスト
結合: 19年前
投稿: 10
Topic starter  

VC++6.0 MFC WindowsXP sp2

分割した二つのウィンドウがありまして
右側はツリー構造、左側はリストビューを利用しております。
右側のツリーフォルダを選択した時に、左側のリストビューにその中身を表示するような
システム構造になっております。
また、リストビューは仮想リストコントロールを利用します。

そこで、仮想リストコントロールのSetItemCountExでシステムエラーになって落ちてし
まいます。
エラーメッセージは

// ウィンドウ生成
BOOL CMainFrame::OnCreateClient( LPCREATESTRUCT /*lpcs*/,
CCreateContext* pContext)
{
// 分割ウィンドウを作成します
CRect cr;
BOOL rc;
if (!m_wndSplitter.CreateStatic(this,1,2)){// 1行2列のビューを作成
TRACE0(Failed to create split bar );
return FALSE; // failed to create
}

GetClientRect(&cr); // ウィンドウの幅を取得
CSize paneSize(230, cr.Height()); // 左
側ペインの幅を設定
CSize paneSize1(cr.Width()-230 , cr.Height()); // 右側ペインの
幅を設定
((CCADExplorerApp*)AfxGetApp())->m_pDoc=(CXXXXXDoc*)(pContext-
>m_pCurrentDoc);
pContext->m_pCurrentFrame=this;
rc=m_wndSplitter.CreateView(0, 0,pContext->m_pNewViewClass,paneSize,
pContext );
if(!rc)return FALSE;

pContext->m_pNewViewClass=RUNTIME_CLASS(CCADExplorerView);
pContext->m_pCurrentDoc=((CXXXXApp*)AfxGetApp())->m_pDoc;
pContext->m_pCurrentFrame=this;
rc=m_wndSplitter.CreateView(0,1,pContext-
>m_pNewViewClass,paneSize1,pContext);
m_wndSplitter.RecalcLayout();
m_wndSplitter.SetActivePane(0,1);
}

extern pXXXXXView;

void CLeftView::OnInitialUpdate()
{
CTreeView::OnInitialUpdate();

// Treeを構築
SetTree();

CListCtrl& ListCtrl = pXXXXXView->GetMyListCtrl();

// ここでリストの数を設定しているが、SetItemCountExで落ちる。
ListCtrl.SetItemCountEx( m_List.size(), LVSICF_NOINVALIDATEALL |
LVSICF_NOSCROLL );
ListCtrl.Invalidate();
}

// ###################################
// 落ちたときのエラー箇所 winctrl2.cpp 378行目
// ###################################
BOOL CListCtrl::SetItemCountEx(int iCount, DWORD dwFlags /* =
LVSICF_NOINVALIDATEALL */)
{
ASSERT(::IsWindow(m_hWnd));

// can't have dwFlags on a control that isn't virutal
ASSERT(dwFlags == 0 || (GetStyle() & LVS_OWNERDATA));<<======ここで落
ちる

return (BOOL) ::SendMessage(m_hWnd, LVM_SETITEMCOUNT, (WPARAM) iCount,
(LPARAM) dwFlags);
}


引用未解決
トピックタグ
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

そこのコメントにあるとおり、
仮想リストビューでは、dwFlagsを指定してはいけないということでしょう。


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

> そこのコメントにあるとおり、
> 仮想リストビューでは、dwFlagsを指定してはいけないということでしょう。

逆ですね。コメントは、仮想リストビューでない場合はdwFlagsを指定しない、
となっています。

仮想リストビューと言っておきながら、リストビューのスタイルに LVS_OWNERDATA
スタイルが立っていないのではないですか?
PreCreateWindowで、LVS_OWNERDATAスタイルを付加するようにしましょう。


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

この設定をしていますが、先ほどのエラーになります。
間違っている箇所はございますか?

BOOL CXXXXView::PreCreateWindow(CREATESTRUCT& cs)
{
 int DisplayMode = atoi(GetRegistry( DisplayMode ));

 // 0:アイコン 1:一覧 2:詳細
 if( DisplayMode == 0 )
   cs.style |= ( LVS_ICON | LVS_SHOWSELALWAYS | LVS_OWNERDATA );//アイコン

 if( DisplayMode == 1 )
   cs.style |= ( LVS_LIST | LVS_SHOWSELALWAYS | LVS_OWNERDATA );//一覧

 if( DisplayMode == 2 )
   cs.style |= ( LVS_REPORT | LVS_SHOWSELALWAYS | LVS_OWNERDATA );//詳細

   cs.dwExStyle |= ( LVS_EX_TWOCLICKACTIVATE |
              LVS_EX_INFOTIP |
              LVSICF_NOINVALIDATEALL |
              LVSICF_NOSCROLL);

 return CListView::PreCreateWindow(cs);
}


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

補足として
GetRegistry( DisplayMode )はレジストりから、
前回、画面を終了した時、ビューの表示形式を取得している箇所なので今回のエラーと
は関係ありません。
無視してください。


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

すみません、逆でしたね。失礼しました。


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

> cs.dwExStyle |= ( LVS_EX_TWOCLICKACTIVATE |
>            LVS_EX_INFOTIP |
>            LVSICF_NOINVALIDATEALL | <==?
>            LVSICF_NOSCROLL); <==?

ここが少し変ですが、今回の件とはあまり関係なさそうです。

本当に LVS_OWNERDATA スタイルが立っているのであれば、
原因はちょっとわかりません。

念のため、SetItemCountExを呼び出す前に、

ASSERT(ListCtrl.GetStyle() & LVS_OWNERDATA);

↑を入れてみてはいかがでしょうか?


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

ASSERT(ListCtrl.GetStyle() & LVS_OWNERDATA);を入れました。
結果ですが、
ASSERT(ListCtrl.GetStyle() & LVS_OWNERDATA);の箇所でエラーになりました。

どういう事なのでしょうか?


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

別のビューにLVS_OWNERDATAスタイルを立てている、
とかいうことはないですよね?


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

ぢつは GetRegistry で 0, 1, 2 以外の値が取得されちゃって、LVS_OWNERDATA が立って
ないとか。

LVS_SHOWSELALWAYS | LVS_OWNERDATA は、どの表示モードであるかにかかわらず設定する
のであれば、if 文の外に追い出しちゃうとか。


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

あと、考えられる可能性としては、

> CListCtrl& ListCtrl = pXXXXXView->GetMyListCtrl();

このpXXXXXViewやListCtrlが正しいリストビューを指しているかどうか。
強引なキャストを行っている箇所はないかどうか。

ASSERT_KINDOF(CListView, pXXXXXView);
ASSERT_KINDOF(CListCtrl, &ListCtrl);

などでチェックしてみる、とか。


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

ASSERT_KINDOF(CListView, pXXXXXView);の箇所で落ちる事がわかりました。
ということは、OnInitialUpdateの実行しているタイミングでは、
pXXXXXViewは実体化されていないという事のでしょうか?

CMainFrame::OnCreateClientの箇所で、
先にLeftViewをクリエイトしているので、その段階ではまだpXXXXXViewを生成していま
せん。
それが原因なのでしょうか?
wndSplitter.CreateView(0,0 -----);// ツリー側
wndSplitter.CreateView(0,1 -----);// リストビュー側


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

すみません、微妙に間違っていました。
先ほど、ASSERT_KINDOF(CListView, pXXXXXView);の箇所で落ちるといいましたが、
ASSERT_KINDOF(CListCtrl, &ListCtrl);で落ちてました。


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

> ASSERT_KINDOF(CListCtrl, &ListCtrl);で落ちてました。

だとすると、返されたListCtrlがCListCtrlクラスではない、
ということになると思います。

> CListCtrl& ListCtrl = pXXXXXView->GetMyListCtrl();

ここのGetMyListCtrl()はどのような実装になっているのですか?
CXXXXViewがCListView派生であるならば、
CListView::GetListCtrl()を使用していないのはなぜでしょうか?


返信引用
syo
 syo
(@syo)
ゲスト
結合: 19年前
投稿: 1
 

CListView::GetListCtrl() は単に *(CListCtrl*)this を返すだけの嘘つきなので、

CListCtrl& List = GetListCtrl();
ASSERT_KINDOF(CListCtrl, &List);

としてもエラーになります。
実体は、あくまでも CListView なのです。


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

返信する

投稿者名

投稿者メールアドレス

タイトル *

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