ページ 1 / 1
レジストリ
Posted: 2009年3月06日(金) 15:28
by ざこ
先日のプログラムにレジストリの機能をいれようとおもいましたがいきづまってしまいました。
エデットボックス入力した値をリストビューに貼り付けます。
それを複数回やります。その値をレジストリに格納します。
CString str_index
int index=-1;
while((index=m_list.GetNextItem(index,LVNI_ALL))!=-1){
str_index=m_list.GetItemText(index,0);//一行ずつ格納?しているつもりです。
AfxGetApp()->WriteProfile("Reg","拡張子",str_ed1);//str_ed1にはEDIT箱で入力した文字列が入っている。
}
これでやると何回入力しても最後の行に表示されている値str_ed1しか保存されません。
おそらく1回1回更新されつづけてるのだとは思います。対策を教えて下さい。
Re:レジストリ
Posted: 2009年3月06日(金) 15:50
by バグ
質問の意味がよくわかりません。
>>エデットボックス入力した値をリストビューに貼り付けます。
>>それを複数回やります。その値をレジストリに格納します。
レジストリに格納したいのは、リストビューのアイテムなのか、エディットボックスに書き込まれたテキストなのか判断できません。
>>while((index=m_list.GetNextItem(index,LVNI_ALL))!=-1){
>>str_index=m_list.GetItemText(index,0);//一行ずつ格納?しているつもりです。
>>AfxGetApp()->WriteProfile("Reg","拡張子",str_ed1);//str_ed1にはEDIT箱で入力した文字列が入っている。
>>}
そもそも、このループはどのタイミングで呼ばれるのですか?
仮に、リストビューへアイテムが追加されるたびに呼ばれ、格納するのはエディットボックス内の文字列だと仮定すると、キーとセクションを毎回違うものに変更してやらなければ、毎回同じ場所へ書き込み更新されるだけです。
Re:レジストリ
Posted: 2009年3月06日(金) 15:52
by YuO
> おそらく1回1回更新されつづけてるのだとは思います。
レジストリの同一キーの同一名の項目への出力は,最後に書き込んだ物が残ります。
> 対策を教えて下さい
出力する段階で,出力したい物を作り出してしまえばよいです。
具体的な方法は,「何があって何をしたいのか」がきっちりと説明されていないので示せませんが。
Re:レジストリ
Posted: 2009年3月06日(金) 15:59
by ざこ
エデットボックスに書かれたテキストがリストビューのアイテムなので中身自体は同じ物だと思います。
この場合メインのダイアログボックスのクラス内にあるリストビューのアイテムを格納しようとしています。
ループのタイミングはウィンドウが閉じたときですつまりOnDestroy関数の中で呼ばれています。
Re:レジストリ
Posted: 2009年3月06日(金) 16:08
by バグ
>>エデットボックスに書かれたテキストがリストビューのアイテムなので中身自体は同じ物だと思います。
これは違うんじゃないですか?
>>エデットボックス入力した値をリストビューに貼り付けます。
>>それを複数回やります。その値をレジストリに格納します。
最初にこう書いているのですから、エディットボックスに書かれた文字列は、最後に入力された文字列であって、リストビューの中身と同じではありませんよね?
>>この場合メインのダイアログボックスのクラス内にあるリストビューのアイテムを格納しようとしています。
>>ループのタイミングはウィンドウが閉じたときですつまりOnDestroy関数の中で呼ばれています。
ということは、エディットボックスの中身ではなく、リストビューのアイテムをレジストリに格納するという事ですよね?
Re:レジストリ
Posted: 2009年3月06日(金) 16:12
by ざこ
>>出力する段階で,出力したい物を作り出してしまえばよいです。
しかしどれくらいの行かもわからないのに全て用意できるものですか?
それとも予め10個までと決めといて10個作ってそれ以上は不可とかでしょうか
確かにエデットボデックスの中身はリストビューでは最後の行のものですね。
レジストリはまだ不慣れですが、1回入力するごとにレジストリを別々で保存は無理なようですね。
エデットボックスに文字を打ち度に内容が保存される と思っていました。
保存するのはリストビューの内容で構いません。上記の画像では4行ですが何行かは決まっておりません。
※このプログラムはドラッグ&ドロップしたファイルを拡張子別にそれぞれのフォルダに移動させるという
ものです。
Re:レジストリ
Posted: 2009年3月06日(金) 16:54
by SooA
現在のリスト行数は取得できますよね?
でしたら、
1.リストに変更が加えられた。
2.レジストリキーの有無をチェック
3.あれば削除、無ければ作成
4.リスト内容で行数の分だけ新たに書き直す。
5.戻る
最も単純にするとこうなります。
これが出来たらレジストリの内容と
リストの内容を比較して必要なら書き込むといった
処理に変更してみましょう。
Re:レジストリ
Posted: 2009年3月06日(金) 17:56
by ざこ
レジストリに保存
int reg=0;
if(reg==0){
AfxGetApp()->WriteProfileString("Reg_Drop1","拡張子",str_ed1)
m_list.InsertItem(0,(LPCSTR)str_ed1);
reg++;
}
else if(reg==1){
AfxGetApp()->WriteProfileString("Reg_Drop2","拡張子",str_ed1)
m_list.InsertItem(1,(LPCSTR)str_ed1);
reg++;
}
else if(reg==2){
AfxGetApp()->WriteProfileString("Reg_Drop3","拡張子",str_ed1)
m_list.InsertItem(2,(LPCSTR)str_ed1);
reg++;
}
としました。ややグダグダな書き方になってしまいましたが、一応ちゃんと登録はできています。
1回リストビューに書き込むごとにレジストリに保存し、変数を使って調節しています。
レジストリを読み込む
CString expand;
int R=0;
if(R==0){
espand=AfxGetApp()->GetProfileString("Reg_Drop1","拡張子",NULL);
R++;
m_list.InsertItem(0,(LPCTSTR)expand);
}
else if(R==1){
espand=AfxGetApp()->GetProfileString("Reg_Drop2","拡張子",NULL);
R++;
m_list.InsertItem(1,(LPCTSTR)expand);
}
else if(R==2){
espand=AfxGetApp()->GetProfileString("Reg_Drop3","拡張子",NULL);
R++;
m_list.InsertItem(2,(LPCTSTR)expand);
}
としましたがこちらは問題があります。3つ分レジストリを保存したはずですが最初のレジストリの分しか
表示されないです。やや強引ですかね? 何かおかしい所あればご指摘ください
Re:レジストリ
Posted: 2009年3月06日(金) 20:06
by SooA
サンプル
void CMyView::OnButton1()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
CListBox *List = (CListBox*)GetDlgItem( IDC_LIST2 );
if( List->GetCount() != 4 )
{
List->InsertString( -1, "AAA") ;
}
}
void CMyView::OnButton2()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
CListBox *List = (CListBox*)GetDlgItem( IDC_LIST2 );
if( List->GetCurSel() != LB_ERR )
{
List->DeleteString( List->GetCurSel() ) ;
}
}
ボタン1でリストに AAA という項目を追加し、
ボタン2で選択項目を削除しています。
リストは現在の行数を調べて4行までしか追加できないようにしています。
あとは、各ボタンの処理の後に
レジストリキー(親)の有無をチェックし、
あれば削除、無ければ作成し、(もしくは子のデータを全て削除)
リスト内容で行数の分だけ新たに書き直す関数を
追加してやればいいわけです。
Re:レジストリ
Posted: 2009年3月06日(金) 22:03
by SooA
最初に書いた
1.リストに変更が加えられた。
2.レジストリキーの有無をチェック
3.あれば削除、無ければ作成
4.リスト内容で行数の分だけ新たに書き直す。
5.戻る
をプログラムにするとこんな感じになります。
自分はデフォで Win32API 使ってるんで置き換えて考えてください。
取りあえず Code と String の二つの仮データを保存しています。
Code と String のデータを HKEY_CURRENT_USER 下の
"Software\\ListTest" に作成します。
サンプル2
void CListTest2View::RegWrite()
{
HKEY HKey ;
int n ;
char Code[3][256] = { "txt", "exe", "dat" } ;
char String[3][256] = { "AAA", "BBB", "CCC" } ;
// 既にレジストリがあれば削除
RegDeleteKeyA( HKEY_CURRENT_USER, "Software\\ListTest" );
// レジストリを作成
if( RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\ListTest", 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &HKey, NULL ) == ERROR_SUCCESS )
{
for( n=0; n < 3; n++ )
RegSetValueExA( HKey, Code[n], NULL, REG_SZ, (LPBYTE)&String[n], sizeof( String[n] ) ) ;
RegCloseKey( HKey ) ;
}
}
void CListTest2View::OnButton1()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
CListBox *List = (CListBox*)GetDlgItem( IDC_LIST1 ) ;
if( List->GetCount() != 4 )
{
List->InsertString( -1, "AAA") ;
}
RegWrite();
}
void CListTest2View::OnButton2()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
CListBox *List = (CListBox*)GetDlgItem( IDC_LIST1 ) ;
if( List->GetCurSel() != LB_ERR )
{
List->DeleteString( List->GetCurSel() ) ;
}
RegWrite();
}