お世話になります、fujitomoです。
今回ご意見を頂きたいと思い、質問させて頂きましたのはVCでの仮想リストコントロールにデータを表示する件に関してです。
具体的に申し上げますと、
あるデータが記述されたcsvファイルがあり、そのcsvファイルのある位置から200件のデータを仮想リストコントロールに表示させたいと思っています。
そこで、私が考えたアプリケーションの作りとして、初めにcsvファイルからデータを読み込んでCStringの二次元配列に各セルのデータを保存します。
そしてLVN_GETDISPINFOを受ける関数を作成し、そこでリストコントロールにCStringの二次元配列の値を当てはめていこうと思っています。つまり、関数内でリストの項目とCStringの二次元配列を1対1に対応させています。
しかしここで、LVN_GETDISPINFOを受ける関数は常にCStringの二次元配列の1行目から見てしまい、例えば、リストコントロールに100行目からのデータを表示させたいと思い、LVN_GETDISPINFOを受ける関数内でリストコントロールに表示させる開始行を指定したとしても0~99行目までが空白となって表示されてしまいます。目的の動作としては100行目からの200行をリストに表示させたいと思っているのでこれではダメです。
仮想リストコントロールを使うのは初めてで、どのように使うのが定石なのか分からない為悩んでいるのですが、私の目的の動作を達成させるためには表示させたい200行分のデータをその都度CStringの二次元配列に格納し、その配列とリストの項目をLVN_GETDISOINFOを受ける関数内で対応させるべきなのでしょうか?
文章だけではかなり分かりづらいと思うので、大雑把にですがソースを載せます。
//メンバ変数
CString data[gyo][row] //データを保存するCString二次元配列
CListCtrl m_list; //リストコントロールのコントロール変数
int start; //リスト表示行
//ダイアログの初めに
BOOL C***Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
Read_File(); //csvファイルをCStringの二次元配列に保存
m_list.SetItem(200);//200件表示に設定
return TRUE;
}
LRESULT C***Dlg::DefWindowProc(UINT message,WPARAM wParam,LPARAM lParam)
{
switch(message)
case WM_NOFITY:
return OnGetListInfo(lParam);
}
return CDialog::DefWindowProc;
}
LRESULT C***Dlg::OnGetListInfo(LPARAM lParam)
{
LPNMHDR lpnmh = (LPNMHDR)lParam;
CWnd* hwndListView = GetDlgItem(IDC_LIST1);
LV_DISPINFO* lpDInfo;
switch(lpnmh->code){
case LVN_GETDISPINFO:
lpDInfo = (LV_DISPINFO*)lParam;
if(lpDInfo->iItem.mask & LVIF_TEXT){
if(lpDInfo->item.iItem >= start){
switch(lpDInfo->item.iSubItem){
case 0:
_tcscpy_s(lpDInfo->item.pszText,256,
data[lpDinfo->item.iItem][lpDinfo->item.iSubItem];
break;
}
}
}
break;
}
return 0;
}
といったソースとなっています。
ご意見を宜しくお願い致します。
尚、開発環境は
Windows CE 6.0
Visual Studio 2005
です。
ご回答をお待ちしております。
No.1ベストアンサー
- 回答日時:
定石というのであれば、"m_list.SetItem(gyo);"とするのが定石だと思いますが、"200件を固定で表示する"というのが仕様なのであれば、別に定石にこだわらなくても、
m_start_line = 200; // cvs表示開始セット
_tcscpy_s(lpDInfo->item.pszText,256,
data[m_start_line+lpDinfo->item.iItem][lpDinfo->item.iSubItem];
などとして、コピー開始位置にゲタをはかせてやれば問題は解決すると思いますが、どうでしょう?
tanma3様、早速のご回答ありがとうございます。
おっしゃったように配列の行に下駄を履かせてみたら無事目的の動作をさせることが出来ました。
重ねての質問で申し訳ありませんが、
この表示する仮想リストコントロールの読み込むデータが別の箇所で更新される場合に、そのデータを読み込み、・リストに表示させたい際に、例えば、全てのデータ(例えば4000件)のうちのある200件を表示させたいと考えたときに、全てのデータのうちの表示させたい開始行を今回のように、全てのデータを一度保存した配列に下駄としてはかせる方法と、あらかじめ表示させたい200件を全てのデータを保存した配列から抽出して、別の配列に保存した後にリストに表示させるのではどちらが一般的なのでしょうか?
今回実現したいアプリケーションの動作というのが、ある時間間隔で保存されていく時間データ(csv形式ファイル)のうちの最新の200件をリストコントロールに随時表示させたいと考えています。
No.4
- 回答日時:
>全てのデータを一度保存した配列に下駄としてはかせる方法と、
>あらかじめ表示させたい200件を全てのデータを保存した配列から
>抽出して、別の配列に保存した後にリストに表示させるのでは
>どちらが一般的なのでしょうか?
設計方針によって違ってくると思います。
今回の場合は、リスト更新タイミングによるのではないでしょうか。CSVが更新されたタイミングでリストの方も更新しなければならないのであれば、1つのバッファでデータを管理した方がいいと思いますし、
逆にリスト更新タイミングは一定(たとえば1分毎)で有るのであれば、
CSVとの同期が邪魔になるので、別バッファ管理とした方がいいと思います。
tanma3様、ご回答ありがとうございます。
データが更新されるタイミングの問題ということですね。
設計仕様によって、どちらにするか考えてみたいと思います。
No.3
- 回答日時:
>リストコントローラのスクロールバーが4000件分の長さに変化してしまい、
これは仕方が無いと思いますが、なにか不都合でもあるのでしょうか?
むしろ、スクロールができて便利だと思うのですが。
逆に、200件でいいのなら、仮想リストコントロールにする意味があまりないように思えます。
>その範囲以外の項目が表示されないわけではなく、範囲以外の項目が空白となって、結局4000行分表示されてしまう結果となりました。
意味がよくわからないです。
仮想リストコントロールの場合、表示に必要な分だけのLVN_GETDISPINFOがやってくるはずで、表示範囲外のアイテムについては、LVN_GETDISPINFOはやってこないはずですが。
titokani様ご回答ありがとうございます。
>むしろ、スクロールができて便利だと思うのですが。
逆に、200件でいいのなら、仮想リストコントロールにする意味があまりないように思えます。
現在作成しているアプリケーションの実行環境がWindows CE 6.0という組み込み用のOSのため、少しでもメモリを消費させない方法として仮想リストコントロールを選択しました。
>仮想リストコントロールの場合、表示に必要な分だけのLVN_GETDISPINFOがやってくるはずで、表示範囲外のアイテムについては、LVN_GETDISPINFOはやってこないはずですが。
lpDInfo.item.iItemの表示範囲のコードはどの箇所に入力するのでしょうか?
LVN_GETDISPINFOを受ける関数内でも、DefWindowProc内でも範囲のコードを入力しても、表示に必要な範囲以外の0から最終行までLVN_GETDISPINFOが送信され、値を代入していない行は空白行となって表示されます。
No.2
- 回答日時:
仮想リストコントロールの場合、アイテムの総数にはデータの総数を指定することになると思います。
つまり、全体で4000件なら、
m_list.SetItemCount(4000)
です。
どのアイテムを表示させるかは、lpDInfo->item.iItemをそのまま使えばいいはずです。
titokani様、ご回答ありがとうございます。
私も初めにそう思い、そのようにコードを作成してみたのですが、
m_list.SetItemCount(4000)
とすると、リストコントローラのスクロールバーが4000件分の長さに変化してしまい、
lpDInfo->item.iItemをそのまま使う
って範囲を指定すると、その範囲以外の項目が表示されないわけではなく、範囲以外の項目が空白となって、結局4000行分表示されてしまう結果となりました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) 【困っています】VBA 追加処理の記述を教えてください。 1 2022/08/25 22:54
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- Excel(エクセル) エクセルについて教えてください。 2 2023/06/14 11:11
- PHP 配列の値の更新方法について 1 2022/08/05 09:49
- C言語・C++・C# pythonのファイルの並びでの読み込みとリストについて 4 2022/04/13 03:52
- Excel(エクセル) VLOOKUP が機能しない、その原因は何 ? 8 2022/10/19 12:06
- PHP htmlで複数の個数入力欄を表示させるには 1 2022/09/20 03:11
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- その他(プログラミング・Web制作) pythonリストの特定の値を表示htmlで表示できない 2 2022/05/14 05:48
- Visual Basic(VBA) 【前回の続き続きです、ご教示ください】VBAの記述方法がわかりません。 2 2022/08/24 20:49
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセル 条件を指定した標準...
-
エクセルでエラーを無視して一...
-
ExcelのINDEXとMATCH関数でスピ...
-
Excel オートフィルタのリスト...
-
Excelのセルの色指定をVBAから...
-
array関数で格納した配列の型を...
-
構造体を使った時刻表(C)
-
[エクセル]連続する指定範囲か...
-
Split関数でLong配列に格納する...
-
VBAでの100万行以上のデータの...
-
【VBA】 動的な変数(定数)の指定
-
VBAで指定期間の範囲を抽出し、...
-
エクセルVBAで変数をセルに一行...
-
表にフィルターをかけ、絞った...
-
Datatableへの代入
-
配列のSession格納、及び取得方...
-
SUMPRODUCT関数を用いた最小値
-
VB6.0 ファイルの一括読込み
-
.NET - 配列変数を省略可能の引...
-
Excelのオートフィルタで抽出し...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ExcelのINDEXとMATCH関数でスピ...
-
array関数で格納した配列の型を...
-
Excelのセルの色指定をVBAから...
-
[エクセル]連続する指定範囲か...
-
エクセルで、絶対値の平均を算...
-
VBA listBoxについて
-
表にフィルターをかけ、絞った...
-
VBA 配列に格納した値の平均の...
-
iniファイルのキーと値を取得す...
-
[VBA]改行入りのセルの値を配列...
-
配列がとびとびである場合の書き方
-
エクセルでエラーを無視して一...
-
DataSetから、DataTableを取得...
-
Excel オートフィルタのリスト...
-
Split関数でLong配列に格納する...
-
読み込みで一行おきに配列に格納
-
VB6.0 ファイルの一括読込み
-
SUMPRODUCT関数を用いた最小値
-
INDEX(D:D,L3)の意味は?
-
Dictionaryを使い4つの条件の一...
おすすめ情報