いつもお世話になっております。
VC++6.0を使用しています。
MFC AppWizard(exe)のSDIで基本クラスをCListViewに選択した場合、
例えばメニューからアイテムを追加したいのですが、どこを変更すれば良いでしょうか?CMFCAddressView::OnInitialUpdate()の中でしょうか?
書籍やWeb上にはCListBoxの説明は多々あるのですが、CListViewを基本クラスとして扱うものは少なく、小生の理解できるサンプルはありませんでした。
MFCAddressというのはプロジェクト名です。
言葉足らず申し訳在りません。
下記のようにした場合、実行時にFor infomation on how your program can cause an assertion failure, see the Visual C++ documentation on asserts.とエラーが出てしまいます。何が悪いのでしょうか。
void CMFCAddressView::OnInitialUpdate()
{
CListView::OnInitialUpdate();
// TODO: GetListCtrl() メンバ関数の呼び出しを通して直接そのリスト コントロールに
// アクセスすることによって ListView をアイテムで固定できます。
m_lv.SetItemState( 1, LVIS_SELECTED , LVIS_SELECTED );
m_lv.SetFocus();
UpdateData(FALSE);
}
メニューからアイテムを追加したいならメニューハンドラに書くのが普通です。
どうもありがとうございます。
メニューハンドラに書く、というのは
C***View::on***()
の中に書くということですよね?
ここでListBoxなら
CListBox* mylist=(CListBox*)GetDlgItem(IDC_LIST1);
mylist->InsertString(-1, "ABC");
のように書くのだと思いますが、
ListViewの場合、サンプルが無く、何を書いていいのかわからないのです。
ご教示お願いできないでしょうか?
// listViewはCListView
CListCtrl &ctrl = listView.GetListCtrl(); // CListCtrlを取得して...
ctrl.InsertItem(...); // CListCtrlに対してInsert
のような感じでOKかと思います。
自分自身のメンバ関数を呼び出すには、下記のようにします。
void CMFCAddressView::XXXX()
{
CListCtrl& ctrl = GetListCtrl(); //CMFCAddressView::GetListCtrl()の呼び出し
ctrl.InsertItem(...);
ctrl.SetItemState(...);
}
どうもありがとうございます。
追記:OnInitialUpdate() は、起動時にID_FILE_NEW=CWinApp::OnFileNew()を経由して
呼び出されます。
そして、「ファイルを開く」lD_FILE_OPEN=CWinApp::OnFileOpen()で、
ファイル選択成功後にも呼び出されます。
「新規作成」と「ファイルを開く」の呼び出しの違いは、
CDocument::GetPathName() が返す値が空文字ならば、「新規作成」。
空文字でなければ、「ファイルを開く」と判断します。
CListViewにはドキュメントクラスへのアクセス関数を持っているので、
CString sPathName = GetDocument()->GetPathName();
とすれば、ファイル名が取得できます。
CWnd::UpdateData(FALSE);は、CWnd::DoDataExchange(CDataExchange*pDX);
を、CDataExchange::m_bSaveAndValidate=FALSE(=読み出しモード)で、呼び出します。
なので、リストビューへ、ヘッダーを書き込んでからアイテム+サブアイテムの順に、
1個1個書き込んでいくループを組んでください。
ソースの例。
<pre>
CListCtrl& rList = GetListCtrl();
// 列数を取得し、ヘッダーも含めてすべて削除する。
int iMaxSubItems = 0;
CHeaderCtrl* pHead = rList.GetHeaderCtrl();
if (pHead)
{
iMaxSubItems = pHead->GetItemCount();
}
BOOL bResult = rList.DeleteAllItems();
for (int iSubItem = iMaxSubItems -1; bResult && 0 <= iSubItem; iSubItem--)
{
bResult = rList.DeleteColumn(iSubItem);
}
CString sPathName = GetDocument()->GetPathName();
if (bResult && !sPathName.IsEmpty())
{
// ここからアイテムの追加になります。
// 例として、5列×100行の情報を ListView へ書き込みます。
for (iItem = 0; bResult && iItem < 100; iItem++)
{
for (iSubItem = 0; bResult && iSubItem < 5; iSubItem++)
{
CString sValue;
if (!iItem)
{
// ヘッダー列の追加
sValue.Format(_T("Title%d"), iSubitem + 1);
bResult = rList.InsertColumn(iSubItem, LVCFMT_LEFT, 98, sValue);
}
if (bResult)
{
// 行追加
sValue.Format(_T("Item%d-%d"), iItem + 1, iSubItem + 1);
if (!iItem)
{
// アイテムの追加
bResult = iItem == rList.InsertItem(iItem, sValue);
}
else
{
// サブアイテムの追加
bResult = rList.SetItemText(iItem, iSubItem, sValue);
}
}
};
};
}
</pre>
OnInitialUpdate()へUpdateData(FALSE);の代わりに書き込んでもよいですし、
説明した通り、DoDataExchange()をCListView()の継承クラス上に新たに起こして、
書き込んでも良いですし、、、
意味がわかるなら、OnUpdate()関数を別途新たに起こして書き込んでもよいです。
確か、ビューの切り替えボタンには、何も実装されていないので、
詳細表示ができないと思いますので、
ビューモードの切り替えは、別途調べてください。
つ、疲れた。。。
ツイート | ![]() |