ついに夏本番!さぁ、家族でキャンプに行くぞ! >>

VC++6.0、Win32 APIを用いて作成しているダイアログボックスを表示するアプリについてです。

パターン(パターン1~3までの3種類)が格納される列と、文字列(最大256バイト)が
格納される列の2列からなるリストビューがあります。

そのリストビューに新しい情報(行)を追加するたびに、その該当行の情報を
別ファイル(設定ファイル)の構造体に格納し、リストビューの変更・削除があれば、
その都度構造体を更新し(?)反映させたいです。
メモリも無駄なく、効率的に使いたいです。

また次回以降そのアプリを起動させる際には、設定ファイルの内容を読み込んでリストビュー
の表示に反映させたいです。

正直、構造体は苦手なため解らないことだらけなのですが、パターンを格納するint型の変数と
文字列を格納する固定長256byteのchar型配列の変数が必要なのではと思っています。
後は、レコード数を格納するヘッダーも必要なのでしょうか・・・
メモリの取得、開放、移動方法はいまいち分かりません。

現在は、ラジオボタン(パターン用)とエディットボックス(文字列用)を用いて、
リストビューに登録するところまでは出来ています。
変更や削除の機能も実装出来ています。

上記の処理を実現させるための詳細な流れを教えてください。
サンプルコードも載せて頂けると幸いです。
分かりにくい文章で申し訳ありませんが、よろしくお願い致します。

このQ&Aに関連する最新のQ&A

A 回答 (16件中11~16件)

★追記。


・もう少しファイル構造を分かりやすく書いて見ました。
 なお、ファイルタイプは独自のバイナリ・データとします。

+------------+
|管理ヘッダ情報|←固定長ヘッダ
+------------+
|データ並び情報|←可変長データ
+------------+
|データ有無情報|←可変長データ
+------------+
|データNo.0000 |←固定長データ(先頭)
+------------+
|データNo.0001 |
+------------+
   :
+------------+
|データNo.1023 |←固定長データ(最後)
+------------+
※No.0000~No.1023 が実際の構造体データのブロックです。可変ブロックです。

解説:
・データファイルの構造は上から順に
 (1)管理ヘッダ情報(固定長ヘッダ)
 (2)データ並び情報(インデックス配列)
 (3)データ有無情報(有無フラグ配列)
 (4)データブロック(可変長データ)
 となります。
・1つのファイルにパックする場合はこんな感じですが (2)、(3)を別のファイルに
 分離する方法もあります。こちらはデータを拡張するときに別ファイルが増加する
 だけなのでデータ件数が多い場合は拡張しやすくなると思います。
・上記の『データ並び情報』がデータ(No.0000~No.1023)のインデックスになります。
 このインデックスからデータが実際のファイル内の何処に位置するのかが分かります。
 ディスク・システムで言うところの FAT にあたります。
・あと『データ有無情報』はデータ(No.0000~No.1023)が空きデータか、有効データかの
 フラグを管理しているテーブルです。このテーブルを用意したのは削除と登録(追加)
 するときに効率よく(高速に)空きデータを探せるためです。安全のためにデータブロック
 にも空きマーク(削除フラグ)をセットしておきます。これによりデータブロックより
 『データ有無情報』を正しく初期化できるようになります。

その他:
・ファイルのデータブロックがいったん拡張すると収縮することは出来ません。
 収縮する場合はデータブロックのデフラグを行ってファイル構造を再構築する必要が
 あります。これは別の処理やプログラムなどで組み込めば良いでしょう。
・以上。
    • good
    • 0
この回答へのお礼

この度は突然の図々しいお願いにも関わらず、詳細に渡る解説・アドバイスを、
ご丁寧に分かりやすくしていただき誠にありがとうございました。

しかしながら、今の自分では理解できない部分が多すぎるため、これだけのヒントを提示して頂きながら、
このままでは先に進めない状況です。大変情けなく感じております。

例えば、「idString…データのファイル形式を識別するための文字列」がどういうものなのか分かりません。
ファイル形式とは、「テキスト」とか「バイナリ」とかいうことでしょうか?(多分違うと思いますが・・・)

何から何まで教えていただくことは、丸投げしていることと同じですし大変心苦しいのですが、
主要な部分のソースコードだけでも提示していただけると幸いです。
もしそれが無理なようでしたら、この課題をやるにあたって参考になるサイトなどを紹介していただければと思います。

何から何までお世話になりっぱなしで本当に申し訳ないですが、どうぞよろしくお願いいたします。
(ちなみに、大したことではないのですが「データの構造体」の文字列は2つではなく1つです。
紛らわしい書き方ですみませんでした。)

お礼日時:2007/07/26 21:02

★ご要望どおりアドバイスします。


・最初にファイル構造をきちんと決めておきます。
 下記は私が考えているファイル構造です。
 参考に。

ファイル内容:
●ファイル構造の情報(head_t)
 ├データ並びの情報(order[])
 └データ有無の情報(exist[])
●データ内容の情報(data_t)
※構造体の型名は自由に決めてお使い下さい。

// ヘッダの構造体(40バイト)
typedef struct head_t {
 char idString[ 12 ]; // ファイル形式のID文字列(ASCIIZ文字列)
 long headSize; // ヘッダのサイズ(head_t,order[],exit[]の合計)
 long allSize; // 全データのサイズ(oneSize×管理データ数)
 long oneSize; // 1データのサイズ(int,256,256=516バイト)
 long nowData; // 登録データの個数(現在個数)
 long maxData; // 最大データの個数(1024単位)
 long *order; // データの並び順配列(通し番号)
 char *exist; // データの有無用配列(0=無効[データ空き],1=有効[データあり])
} head_t;

// データの構造体(516バイト)
typedef struct data_t {
 int pattern; // パターン番号(1-3,0=無効とか削除用)
 char str1[ 256 ]; // 固定長文字列1
 char str2[ 256 ]; // 固定長文字列2
} data_t;
※構造体のメンバ名も自由に決めてお使い下さい。

解説(head_t):
・この構造体で全データの有効(データあり)、無効(データなし,空き,削除)を管理します。
 データはある決まった数(1024個分)を1つの単位としてディスクのクラスタとFATの様に
 管理されます。これは例え1つのデータでも1つの単位(1024個分)の管理領域がヘッダに
 作られて管理されるという事です。よって1つのデータサイズは 516 バイトですが1つの
 単位分(1024個分)なので516×1024=516キロバイトになります。今回は1つの単位として
 1024個分にしていますが256個分とか、64個分とかを1つの単位にしても良いでしょう。
 数が少なければファイルのサイズが無駄なく抑えられますが、データを追加するたびに
 管理領域を拡張する必要があります。一度にたくさんのデータを追加登録する場合は
 管理領域を一度に拡張させる工夫が必要です。
 (1)idString…データのファイル形式を識別するための文字列(自由に決めること)
  ID文字列が "kenkenpo" ならば char 型配列に[k][e][n][k][e][n][p][o][\0][\0][\0][\x1a]
  となるように格納します。[\0]はNULL文字、[\x1a]は制御文字です。この文字列は最低1個の
  [\0]と[\x1a]を含むようにします。こうするとコマンド・プロンプトの TYPE コマンドで
  ID文字列だけが表示できたり、C 言語で使う文字列なので idString[] をそのまま strncmp で
  比較が出来ます。チェック用に1つの[\0]を入れるということです。
 (2)headSize…ヘッダ情報、データ並び情報、データ有無情報の合計サイズです。
  ファイルの先頭よりhead_t(40バイト)、データ並び情報(4096バイト)、データ有無情報(128バイト)
  の順番に格納されています。その合計サイズ(4264バイト)です。
  なお、データ並び情報はsizeof(long)×maxData個分のサイズです。
  さらにデータ有無情報はsizeof(char)×maxData÷8のサイズです。
 (3)allSize…管理データの全サイズです。つまりsizeof(data_t)×maxData=516 KB
 (4)oneSize…管理データの1つサイズです。つまりsizeof(data_t)
 (5)nowData…管理データの有効な登録データ個数です。最初は0個。最大maxData個。
 (6)maxData…管理データの最大データ個数です。これが単位数。今回は1024個分。
 (7)order…データの並び順です。データ位置を入れ替えたり、ソートしたときに対応するため追加。
  中身はlong型の変数にファイルのデータ構造の通し番号で管理しています。
  よって、リストビューに読み込むときは order[0]~order[nowData-1] までの内容を読み込み、
  この変数値である通し番号を頼りにファイルからランダムアクセスしてデータ追加します。
 (8)exist…データの有効/無効のフラグです。このフラグで管理データの登録/削除を管理。
  フラグ内容は登録(追加)すると『1』、削除や空きデータにするには『0』とします。
  このフラグはファイルのデータ構造の通し番号と同じく順番に対応付けられています。

解説(data_t):
・これがリストビューの1行データの構造体です。
 (1)pattern…パターン番号の情報です。
  1~3が有効値。
  0 は空きデータまたは削除データを表す。
  データを削除する時はファイルの構造体に pattern=0 として書き込み、
  さらにデータ並び順から削除詰めとデータ有無フラグを 0 とする必要があります。
 (2)str1…固定長文字列1です。
 (3)str2…固定長文字列2です。

その他:
・上記の構造体やファイル構造は私が考えたものです。
 こんな感じならリストビューとファイルの構造体がメモリを無駄なく関連付けられると
 思います。メモリを無駄なくするためはリストビューにデータの実体(パターン番号と
 文字列1、文字列2)を管理させてプログラムではリストビューとファイル内の追加、削除
 更新(変更)のやり取りだけを面倒みればいいと思います。
・VTClient さんの4つの回答(アドバイス)をよく読むとリストビューと同じデータを
 独自にリスト構造で管理しています。同じ内容のデータを独自に管理した分だけメモリが
 無駄になっています。また、リストビューとの対応を取るのが面倒だったり、ずれが生じる
 可能性があります。
・よって管理する情報はファイル構造のデータ有無やデータ並びだけを管理してデータの内容
 (実体)はリストビューに任せます。変更する時にリストビューよりデータを取得して書き換え
 このときにリストビューとファイルを同時に更新する操作関数をしっかりと作ります。
・操作関数をはっきりと用意しておけば1つの登録用関数を呼び出すだけでリストビューと
 ファイル内の構造を同時に対応して処理できます。追加、更新、削除、移動、ソートなど。
・以上。一度読み今後の方針をお聞かせ下さい。
    • good
    • 0

対応内容です。



char szPattern[16]→構造体->txBuf
char szBuff[256]→構造体->txBuf

構造体->txBufが重複してますが、パターンが何かは、
nPatternの値を参照してリストビューに反映させればいいのです。
ですから、パターン用文字列は不要と見ています。(節約化)

static LV_COLUMN lvcol→LVCOLUMN(名前違いで、中身まったく同じ)
static LV_ITEM item→LVITEM(名前違いで、中身まったく同じ)
static int nItem→登録ではindex
(static?)int nIndex→変更、削除はindex
static HWND hList→list
static int nPattern→state

エラーについてですが、おそらく「登録」だけでませんか?
私が載せた処理は「常にリストの最後に追加」
の処理にしています。
(1)もし質問者さんが「任意選択位置に“挿入”」しているのであれば IDC_BUTTON1: だけは、nItemを参照させて
常に最後の末尾に追加にすれば直るはずです。
(2)あと、リストビューの自動ソートのスタイルは“なし”
にしてください。

(1)、(2)が気に入らず、どうしても自由位置挿入や
自動ソートにしたいのなら、さらに重い処理追加になりますから
特に(1)は割愛してはどうでしょうか…。
これ以上の追加はリストが非常に長くなり載せられません…。

この回答への補足

<続きです。>
case WM_COMMAND:
switch(LOWORD(wp)){
/* 登録ボタンが押されたときの処理 */
case IDC_BUTTON_ENTRY:
// ラジオグループの状態をチェック
if(Button_GetCheck(hRadio_Pattern1) == BST_CHECKED){
省略
}

GetWindowText(hEdit, szBuff, sizeof(szBuff));
SetWindowText(hEdit, ""); // エディットボックスを空欄にする
nItem = ListView_GetItemCount(hList); // 項目数を取得
item.mask = LVIF_TEXT;
item.pszText = szPattern;
item.iItem = nItem;
item.iSubItem = 0;
ListView_InsertItem(hList, &item);

item.mask = LVIF_TEXT;
item.pszText = szBuff;
item.iItem = nItem;
item.iSubItem = 1;
ListView_SetItem(hList, &item);

// 『変更』ボタンを無効にする
省略
// 『削除』ボタンを無効にする
省略
// エディットボックスにフォーカスを合わせる
省略
return TRUE;

/* 『変更』ボタンが押されたときの処理 */
case IDC_BUTTON_CHANGE:
// ラジオグループの状態をチェック
if(Button_GetCheck(hRadio_Pattern1) == BST_CHECKED){
省略
}
// 選択中の行を知る
nIndex = ListView_GetNextItem(hList, -1, LVNI_ALL | LVNI_SELECTED);
// エディットボックスに表示中の文字列を取得する
GetWindowText(hEdit, szBuff, sizeof(szBuff));
// 選択中の行の表示を変更する
ListView_SetItemText(hList, nIndex, 0, szPattern);
ListView_SetItemText(hList, nIndex, 1, szBuff);
// エディットボックスを空欄にする
省略
// 『変更』ボタンを無効にする
省略
// 『削除』ボタンを無効にする
省略
// エディットボックスにフォーカスを合わせる
省略
return TRUE;

/* 『削除』ボタンが押されたときの処理 */
case IDC_BUTTON_DELETE:
// 選択中の行を知る
nIndex = ListView_GetNextItem(hList, -1, LVNI_ALL | LVNI_SELECTED);
// 選択中の行を削除する
ListView_DeleteItem(hList, nIndex);
// エディットボックスを空欄にする
省略
// 『変更』ボタンを無効にする
省略
// 『削除』ボタンを無効にする
省略
// エディットボックスにフォーカスを合わせる
省略
return TRUE;

以下は、各コントロールが選択されたときなどの、
ラジオボタンやプッシュボタンの有効・無効、
ラジオボタンのチェックの有無に関するコードですので、
省略させていただきます。

補足日時:2007/07/26 10:40
    • good
    • 0
この回答へのお礼

ご返答が遅くなってしまい、申し訳ありません。
対応箇所を詳しく提示していただきありがとうございました。
再び質問で申し訳ないのですが、今回場合物理的なファイルというものは存在しないのでしょうか?
例えば、fopenしてfread、fwriteするようなことはできますでしょうか。
ちなみに、エラーについてですが、まだ解消することができません。
追加は常に末尾にしておりますし、
ソートは”しない”にしております。
元々のソースの一部を載せさせていただきますので、間違っている部分(たくさんあるとは思うのですが・・・)
を指摘していただけると幸いです。
このソースに、VTClientさんのソースを移植することはできますでしょうか。
大変見にくいかとは思いますが、何卒よろしくお願いいたします。

switch(msg){
/* ダイアログ初期化処理 */
case WM_INITDIALOG:
InitCommonControls();
/* 各コントロールのハンドルを取得 */
// ラジオボタン
省略
// エディットボックス
省略
// プッシュボタン
省略
// リストビュー
省略

// リストビューの列の設定
lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvcol.fmt = LVCFMT_LEFT;
lvcol.cx = 70;
lvcol.pszText = "パターン";
lvcol.iSubItem = 0;
ListView_InsertColumn(hList, 0, &lvcol);

lvcol.cx = 600;
lvcol.pszText = "検索文字列";
lvcol.iSubItem = 1;
ListView_InsertColumn(hList, 1, &lvcol);
// 拡張スタイル(行全体選択, グリッド線, 列ドラッグ)
省略
// エディットボックスに入力できる最大文字数を制限する
省略
// ラジオボックスの初期の状態(パターン1にチェック)
省略

return TRUE;
<補足の方に続けさせて頂きます。>

お礼日時:2007/07/26 10:38

FileList構造体は、No.1 参照で修正済みリストです


書き込み/読み込みは、wsprintf関数を使えば簡単です

BOOL CALLBACK DlgProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)
{
static HWND list=0;
static int state=1,index=0;
// state=0:未使用 / 1~3:各パターン
switch (msg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_RADIO1:
state=1;
return 1;
case IDC_RADIO2:
state=2;
return 1;
case IDC_RADIO3:
state=3;
return 1;
case IDC_BUTTON1: // 登録
{
LVITEM cell;
FileList *p,*p2;
int cur,cur2;
char txBuf[15];

cell.mask=LVIF_TEXT;
index=ListView_GetItemCount(list);// 最後の列の次
cell.iItem=index;
cell.iSubItem=0;
cell.pszText=txBuf;
switch (state)
{
case 1:
strcpy(txBuf,"パターンA");
break;
case 2:
strcpy(txBuf,"パターンB");
break;
case 3:
strcpy(txBuf,"パターンC");
}
ListView_InsertItem(list,&cell);
cell.iSubItem=1;
GetDlgItemText(hDlg,IDC_EDIT1,txBuf,sizeof(txBuf));// txBuf=登録文字列
for (cur=0;FList[cur].cur!=index;cur++);// cur=最後の行
for (cur2=0;FList[cur2].type;cur2++); // cur2=挿入用未使用位置
p=&FList[cur];// 対応構造体アドレス代入
p2=&FList[cur2];// 同上
p2->back=(p=p->back);//
p->next=p2;//
p2->cur=index;//
p2->type=state;//上記4行で前後ポインタ更新
for (++cur2;FList[cur2].type;cur2++); // cur2=次回用未使用位置
p2->next=&FList[cur2];//
FList[cur2].cur=index+1;//
FList[cur2].back=p2;//上記3行で次回用調整
p2->txBuf=(char*)malloc(p2->size=strlen(txBuf)+1);// 節約のため可変長文字列は動的確保
strcpy(p2->txBuf,txBuf);//文字列コピー
ListView_SetItem(list,&cell);
SetFocus(list);
return 1;
}
case IDC_BUTTON2:// 変更
{
LVITEM cell;
FileList *p;
int cur;
char txBuf[15];

cell.mask=LVIF_TEXT;
index=ListView_GetSelectionMark(list);// 選択位置
if (index<0) return 1;// 非選択時は終了
cell.iItem=index;
cell.iSubItem=0;
cell.pszText=txBuf;
switch (state)
{
case 1:
strcpy(txBuf,"パターンA");
break;
case 2:
strcpy(txBuf,"パターンB");
break;
case 3:
strcpy(txBuf,"パターンC");
}
ListView_SetItem(list,&cell);
cell.iSubItem=1;
GetDlgItemText(hDlg,IDC_EDIT1,txBuf,sizeof(txBuf));
for (cur=0;FList[cur].cur!=index;cur++); // cur=最後の行
p=&FList[cur];
p->type=state; //更新
if (p->size) free(p->txBuf);
p->txBuf=(char*)malloc(p->size=strlen(txBuf)+1);// 文字列再確保
strcpy(p->txBuf,txBuf);
ListView_SetItem(list,&cell);
SetFocus(list);
return 1;
}
case IDC_BUTTON3:
{
FileList *pf,*p;
int cur;

index=ListView_GetSelectionMark(list);
if (index<0) return 1;
ListView_DeleteItem(list,index);
for (cur=0;FList[cur].cur;cur++);// インデックス先頭検索
for (pf=&FList[cur];pf->cur!=index;pf=pf->next); // 選択位置の対応インデックス
for (p=pf->next;p->type;p=p->next) p->cur--;p->cur--; // 対応インデックス切り詰め
pf->type=0;// 更新
pf->next->back=pf->back;// 更新
pf->back->next=pf->next;// 更新
if (pf->size) free(pf->txBuf);// 不要文字列排除
pf->size=0,pf->cur=0;// 更新
SetFocus(list);
return 1;
}
case WM_INITDIALOG:
for (int i=0;i<100;i++)// 初期化
{
FList[i].size=FList[i].type=0;
if (i) FList[i].back=&FList[i-1]; else FList[i].back=&FList[i];
if (i<99) FList[i].next=&FList[i+1]; else FList[i].next=&FList[i];
}
list=GetDlgItem(hDlg,IDC_LIST1);
・・・

この回答への補足

重ねての質問で申し訳ありません。

今自分のソースに、VTClientさんに教えて頂いたソースを加えている途中なのですが(変数が多少違いますので、所々変更を加えながらやっています)、ビルドは通るのですがダイアログから登録ボタンを押すと画面が落ちてしまいます。

デバッグをしてみると該当行はcase IDC_BUTTON1の中の、
p->next = p2;
の様です。
「CxC0000005:Access Violation」とのダイアログが表示されました。
pの中のそれぞれの値は、「CXX0030: Eroor: 式を評価できません」となっています。

考えられる原因があれば教えて頂ければと思います。
よろしくお願い致します。

補足日時:2007/07/23 13:10
    • good
    • 0
この回答へのお礼

詳細なコードとコメント、本当にありがとうございます。
大変助かります。

この質問をさせていただく前、自分は元々以下のような変数を用意していましたが、
VTClientさんに書いていただいたコードの中に重なるものはありますでしょうか。

LPNMHDR lpnmhdr;

char szPattern[16];// パターン文字列
char szBuff[256]; // 検索文字列(エディットボックス・リストビュー兼用)

static LV_COLUMN lvcol;// リストビューの列に関する構造体
static LV_ITEM item;// リストビューのアイテムに関する構造体
static DWORD dwStyle;// リストビューの拡張スタイルを格納する変数
static int nItem;// リストビューの項目数
int nIndex;// リストビューで選択されている行番号 0,1,2,・・・
static HWND hRadio_Pattern1, hRadio_Pattern2, hRadio_Pattern3,// パターン1, パターン2, パターン3
static HWND hEdit;
static HWND hButton_Entry, hButton_Change, hButton_Delete, hButton_Replace;// 登録, 変更, 削除, 編集(置換)開始
static HWND hList;
static int nPattern; // ラジオボタンの状態を表す変数

また、LV_ITEMとLVITEMは違うものなのでしょうか。

度々申し訳ありませんが、よろしくお願い致します。

お礼日時:2007/07/23 10:14

載せたソースは即興で作成したデバッグ不足のため


誤動作、メモリエラーなどもたまにでますが、
「こんな感じ」という概念だけ観て下さい。

下記のリスト解説ですが抜粋でいきます。
(汚いので理解しない方が良いと思いますが…)

(BUTTON1=ここでは追加)
GetDlgItemText(hDlg,IDC_EDIT1,txBuf,sizeof(txBuf));
エディットフィールドからテキスト内容を取得
while (FList[cur].type) cur++;
ラジオボタン状態が0=空の配列要素インデックスをサーチ
strcpy(FList[cur].txBuf=(char*)malloc(FList[cur].size=strlen(txBuf)+1),txBuf);
テキスト内容はメモリ節約のため動的割り当て
FList[cur].type=state;
状態格納
FList[cur].cur=index;
インデックス格納
pre=cur;
while (FList[cur].type) cur++;
FList[cur].back=&FList[pre];
FList[pre].next=&FList[cur];
入れ替え
(BUTTON2…削除)
for (cur=0;!FList[cur].type&&cur<100;cur++);
for (pFile=&FList[cur];pFile->cur!=index;pFile=pFile->next);
pFile->type=0;
pFile->back->next=pFile->next;
pFile->next->back=pFile->back; … ここまで削除と切り詰め
free(pFile->txBuf); … メモリ開放
for (pFile=pFile->next;pFile->type;pFile=pFile->next) pFile->cur--; … 切り詰め

すみません、解かりにくいですね…。

書き込み/読み込み 処理は例えば...

 配列要素,対応インデックス,バッファ,バッファサイズ,前ポインタ,
 先ポインタ\r\n

のようにするのが無難かと思います。
    • good
    • 0

まず、冒頭で、(ここではリストビュー項目100個にしています)



struct FileList{
int cur;
char* txBuf;
int size;
int type;
FileList *back;
FileList *next;
} FList[100];

のようにして、

BOOL CALLBACK DlgProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)
{
static HWND list=0;
static int state=1,index=0;
・・・
case IDC_BUTTON1:
{
LVITEM cell;
char txBuf[256];
int pre=0,cur=0;

cell.mask=LVIF_TEXT;
index=cell.iItem=ListView_GetSelectionMark(list)+1;
cell.iSubItem=0;
cell.pszText=txBuf;
switch (state)
{
case 1:
strcpy(txBuf,"パターンA");
break;
case 2:
strcpy(txBuf,"パターンB");
break;
case 3:
strcpy(txBuf,"パターンC");
}
ListView_InsertItem(list,&cell);
cell.iSubItem=1;
GetDlgItemText(hDlg,IDC_EDIT1,txBuf,sizeof(txBuf));
while (FList[cur].type) cur++;
strcpy(FList[cur].txBuf=(char*)malloc(FList[cur].size=strlen(txBuf)+1),txBuf);
FList[cur].type=state;
FList[cur].cur=index;
pre=cur;
while (FList[cur].type) cur++;
FList[cur].back=&FList[pre];
FList[pre].next=&FList[cur];
ListView_SetItem(list,&cell);
ListView_SetSelectionMark(list,cell.iItem);
SetFocus(list);
}
return 1;
case IDC_BUTTON2:
{
int cur;
FileList *pFile;

ListView_DeleteItem(list,index=ListView_GetSelectionMark(list));
for (cur=0;!FList[cur].type&&cur<100;cur++);
for (pFile=&FList[cur];pFile->cur!=index;pFile=pFile->next);
pFile->type=0;
pFile->back->next=pFile->next;
pFile->next->back=pFile->back;
free(pFile->txBuf);
for (pFile=pFile->next;pFile->type;pFile=pFile->next) pFile->cur--;
SetFocus(list);
return 1;
}
・・・
と動的更新して、ファイル書き込みはFList[0]~FList[100]の内容を
FList[0].各項目+改行、FList[1].各項目+改行・・・
のようにして読み込みで先頭オフセットから読み込んでいき、
FList[0].各項目に格納、改行ごとに、
FileList* pIndex;
for (index=0;!FList[index].type;index++);
for (pIndex=&FList[index];pIndex->type;pIndex=pIndex->next){
pIndex->txBuf=(char*)malloc(pIndex->size)・・・

といった感じかと思いますが、汚くてすみません(汗)。
    • good
    • 0
この回答へのお礼

具体的なコードを書いて頂き、ありがとうございます<(_ _)>

しかし、自分の知識不足のため今のところあまり理解できていないのが正直な所です。
これから、頑張って解読しようと思います。

そこで、図々しいお願いだとは思いますが、もし宜しければソースにコメントを
入れて頂けないでしょうか。
何度もご面倒お掛けしてしまい大変申し訳ないのですが、よろしくお願い致します。

ちなみに、ダイアログボックス画面構成は、ラジオボタンが3つのラジオグループ、
エディットボックス、『登録』・『変更』・『追加』の3つのボタン、そしてリストビューです。
普通に登録、変更、削除をすることは出来ています。

リストビューの内容を登録したファイルは、別のアプリからも使いたいと思っています。
具体的には、パターンごとに用意された3つの関数にそれぞれの文字列を引数として
与えるというものです。

今現在その「別アプリ」は、ただパターンごとの文字列配列(今回は3つ)を用意して、
対応する関数に渡しているだけです。
現在作成中の設定アプリから、その文字列の登録・変更・削除をしたいというのが
今回の目的です。

何卒、よろしくお願い致します。

お礼日時:2007/07/21 23:27

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QUpdateData( FALSE); による文字列データの表示更新(VC++6.0)

VC++の超初心者です.

UpdateData( FALSE );
を用いてエディットボックスの文字列の表示の更新を
試みているのですが,たとえば,以下のコードのようにボタンをクリックした際に文字列表示の更新を複数回行おうとするとうまくいきません.
具体的には一回目のUpdateData( FALSE );が反映されず二回目のUpdateData( FALSE );のみ反映されるという症状です.

なおm_mojiretsuはCstring型でエディットボックスのDDX用の変数です.

void CMyDlg::OnButton1()
{
DWORD p;

m_mojiretsu=_T("mojirstu1");
UpdateData( FALSE );

/*5秒の待ち*/
p=timeGetTime();
while(1){if((timeGetTime()-p)>5000) break;}

m_mojiretsu=_T("mojirstu1\r\nmojirstu2");
UpdateData( FALSE );

}


何か別の処理を行わなければいけないのでしょうか.
どこかに根本的なミスがあるのでしょうか.

VC歴3日程度で,右も左も分からず大変困っております.よろしくお願いします.

VC++の超初心者です.

UpdateData( FALSE );
を用いてエディットボックスの文字列の表示の更新を
試みているのですが,たとえば,以下のコードのようにボタンをクリックした際に文字列表示の更新を複数回行おうとするとうまくいきません.
具体的には一回目のUpdateData( FALSE );が反映されず二回目のUpdateData( FALSE );のみ反映されるという症状です.

なおm_mojiretsuはCstring型でエディットボックスのDDX用の変数です.

void CMyDlg::OnButton1()
{
DWORD p;

m_mojiretsu=_T("mojirst...続きを読む

Aベストアンサー

m_mojiretsu=_T("mojiretsu1");
UpdateData(FALSE);
UpdateWindow(); // <- これを追加

/*5秒の待ち*/
...

とすれば、ひとまず期待どおりの動作になると思います。

# こうするよりは、OnButton1() では変数を書き換えるべしと言う
# 自前のコマンドメッセージを投げるだけで、すぐに戻った方が
# お行儀は良いのですが...
# そこいらへんは追々調べたり試したりしてみて下さい。

QGetPrivateProfileStringでiniファイル読込む処理を詳しく知りたいのですが・・・

お世話になっています。

iniファイルを読込み、各変数に代入するC言語のDLLを作成したいのです。
このサイトの投稿や、MSDNなどにも載っていたのですが、
少し理解に苦しみます。

現在まで、理解した点がwindows.hのインクルードを
記述するところ辺りです。
iniファイルは下記のようなレイアウトです。

---<mst.ini>----------------------------
[user]
name=username
ID=userid
[pc]
pcname=FMV
----------------------------------------

#include<windows.h>は記述することまでは
分かりましたが、以下から進みません。。。

GetPrivateProfileString("")

初心者で申し訳ありませんが、お助け願います。

Aベストアンサー

こんにちは。itohhといいます。

サンプルを載せておきます。

mst.iniファイル内の[user]セクションのnameキーの値を取得する。
DWORD dwLen=0;
char strBuf[100];
dwLen = GetPrivateProfileString("user",       // セクション名
                "name",       // キー名
                "soushi_ni",     // デフォルト値
                strBuf,       // 読み込んだ値を格納するエリア
                sizeof(strBuf),   // 上記のエリアのサイズ
                "mst.ini" );     // iniファイル名

解説:
iniファイル名をフルパスで指定しないとWindowsのディレクトリにあるものと判断されます。
Win9xなら「c:\windows」、WinNT系なら「c:\WinNT」。

[user]セクションのnameキーがないときは、デフォルト値で指定した値が設定させます。

復帰値「dwLen」は実際に設定した値(文字列)の長さが返されます。

こんにちは。itohhといいます。

サンプルを載せておきます。

mst.iniファイル内の[user]セクションのnameキーの値を取得する。
DWORD dwLen=0;
char strBuf[100];
dwLen = GetPrivateProfileString("user",       // セクション名
                "name",       // キー名
                "soushi_ni",     // デフォルト値
                strBuf,       // 読み込んだ値を格納するエリア
             ...続きを読む

QビジュアルC++でボタンの有効/無効

ビジュアルC++でプログラミングをしているのですが、ツールから貼り付けたボタンの有効/無効を操作したのですが、何度やっても成功しません><、


ネットで検索した結果
CWnd* myWnd = GetDlgItem(IDC_MYEDIT);
myWnd->EnableWindow(TRUE);

でできると書いてあるのですが、どのサイトの物を使用してもビルドできませんでした(;ロ;)

どなたか原因がわかるかた、ご教授くださいm(__)m

Aベストアンサー

みているサンプルは
「Windows フォームアプリケーション」
で作成したプロジェクト用のものではありません。

どのタイミングで有効・無効を切り替えるかわかりませんが、
Enabledプロパティで変更できませんか?

this->button1->Enabled = false; // 無効

Control::Enabled プロパティ
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.control.enabled.aspx

QC# リストビューの値を取得

foreach (ListViewItem item in ListView1.SelectedItems)
{
MessageBox.Show(item.Text);
}

上記の書き方だと1カラム目しか取得できないのですが、これを2カラム目3カラム目と順番に表示するにはどうしたらよいでしょうか?

Aベストアンサー

foreach (ListViewItem item in ListView1.SelectedItems)
foreach (ListViewItem.ListViewSubItem subItem in item.SubItems)
{
MessageBox.Show(subItem.Text);
}
}

かな? .NET はよく知らないけど。

Qint型からchar型への変換

タイトル通り、int型からchar型への変換の仕方がわかりません!><
どうしたらいいのでしょうか?

Aベストアンサー

#include <stdio.h>


char buf[5];
int no;

no = 10;
sprintf(buf, "%d", no);

QListViewにて行追加

Visual C# 2005初心者です。
ListViewを使用して、データを表示するのに、

listView1.Items.Add("1111111", 3);
listView1.Items.Add("2222222", 3);
listView1.Items.Add("3333333", 3);

と書くと、列が追加されます。
行を追加するには、どうすればよいのでしょうか?

どうか、教えてください。

Aベストアンサー

listViewのViewプロパティをDetailsに設定した上で、Items.Add()メソッドを呼び出せば行方向にアイテムが追加されます。ただしそのままではアイテムが表示されないので、listView.Columns.Add()メソッドで列ヘッダにコレクションを追加します。

Qエディットボックスのフォントを変えたい

MFCで作ったダイアログ上の他のコントロールはいじらずに、
エディットボックスのフォントだけを大きく変えたいのですが、
行間が変わらない為か、文字の下のほうが切れてしまいます。

色々試してみていますが、どうしても出来ません。

元のダイアログのフォントは12ptです。

OnInitDialog関数内で、
CFont m_font;(メンバ変数)に以下を設定し、
m_font.CreateFont( 20, 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, 0, SHIFTJIS_CHARSET, OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,DEFAULT_PITCH | FF_DONTCARE, "MS P ゴシック" );

OnCtlColor関数内で、該当エディットボックスの場合だけ
pDC->SelectObject( &m_font );
しています。

CreateFontのパラメータが間違っているのでしょうか?

それとも、これら関数を呼び出す場所が間違っているのでしょうか?

ご回答お待ちしております。

MFCで作ったダイアログ上の他のコントロールはいじらずに、
エディットボックスのフォントだけを大きく変えたいのですが、
行間が変わらない為か、文字の下のほうが切れてしまいます。

色々試してみていますが、どうしても出来ません。

元のダイアログのフォントは12ptです。

OnInitDialog関数内で、
CFont m_font;(メンバ変数)に以下を設定し、
m_font.CreateFont( 20, 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, 0, SHIFTJIS_CHARSET, OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,DEFAULT_PIT...続きを読む

Aベストアンサー

こんにちは。

Senna_FFさんの回答とかぶりますが、SetFontで出来ます。
CreateFontの下に下記の一行を追加してみてください。
質問のCreatoFontは正しく動作していました。
IDC_EDITはフォントを変更したいエディットボックスのIDを入れてください。


GetDlgItem(IDC_EDIT)->SetFont(&m_font);

QDWORDの実際の型は何でしょうか

VC++.NETの環境です。
DOWRD dw1 = 1;
int i = 2; と定義し
ここで
if ( i > dw1 ){
何かの処理;
}
とコーディングすると
warning C4018: '>' : signed と unsigned の数値を比較しようとしました。
のワーニングがでます。
これは、DWORDがint型でなくunsigned int型のようにも見えます。
ある本によれば(VC++.V.NET逆引き大全500の極意)
DWORD はint型であると記述されています。
もし、int型ならこのワーニングはでないはずなのですが、
なぜでるのでしょうか。又、DWORDの実際の型は何なのでしょうか。ご存じのかたおりましたら、教えていただけませんでしょうか。

Aベストアンサー

型定義が知りたいのならば、宣言ファイルを見れば疑問を挟む余地もありません。
DWORD型はwindef.hで
"typedef unsigned long DWORD;"
と宣言されています。

Visual Studioを使っているのならば、知りたい型の上にマウスポインタを置いて右クリック、ポップアップメニューの「定義へ移動」または「宣言へ移動」で簡単に知ることが出来ます。

Qiniファイルのキーと値を取得するにはどうすれば?

こんばんわ、マッイィーです。

毎度のことながらお助けを。

iniファイルのキーと値をとるために必要な関数は
何か教えてください。

その取得したキーと値を配列に格納したいのですが、
いい方法ありませんか?

分かっちゃった!って人、おもいっきり教えてください。

もんどりもっさりに教えてください。

Aベストアンサー

★キーの『値』だけを取得して配列に取得したいのですね。
・szBuff バッファ領域の文字列から=文字を検索して配列に格納すればよい。
 ちなみに配列には文字列でセットしますか?
 それとも整数値に変換した値をセットしますか?
 どっち。
・とりあえず、下にサンプルを載せておくので使い分けて下さい。

サンプル:
TCHAR szBuff[ 32768 ];
LPTSTR lpSeek;
LPTSTR lpFind;
LPTSTR *s[ 100 ]; ←文字列として格納
INT n[ 100 ]; ←整数として格納
INT i = 0; ←カウンタ

GetPrivateProfileSection( TEXT("セクション名"), szBuff, sizeof(szBuff), TEXT("INIファイル名") );

for ( lpSeek = szBuff ; *lpSeek != '\0' ; lpSeek++ ){
 if ( (lpFind = strchr(lpSeek,'=')) != NULL ){ ←=文字を検索
  s[ i ] = lpFind + 1;
  n[ i ] = atol( lpFind + 1 );
  i++;
 }
 while ( *lpSeek != '\0' ){ ←次のキーデータに移動するための処理
  lpSeek++;
 }
}
printf( "max=%d\n", i ); ←i カウンタがそのままキーデータの個数になる。

解説:
・前回のサンプルに文字列や整数値を配列にセットする部分を追加しただけ。
 lpSeek に1つ1つのキーデータの文字列になるので、=文字を strchr 関数で
 検索して=文字の次の1文字目がデータ(値)になります。
・あとは文字列の配列(s)や、整数の配列(n)にセットしているだけです。
 配列の要素数は 100 個にしています。セクション内にいくつのキーデータがあるか
 不明ですので多めに宣言しておくか、最初に個数をカウントしてから malloc 関数で
 確保してからセットして下さい。

最後に:
・ここは 2チャンネルのような掲示板ではありませんよ。
 質問、補足、お礼などの文章をもう少し『品』がある文章にすると読みやすくなります。
 ここの辺も気をつけて下さい。
・以上。今後の参考に!

★キーの『値』だけを取得して配列に取得したいのですね。
・szBuff バッファ領域の文字列から=文字を検索して配列に格納すればよい。
 ちなみに配列には文字列でセットしますか?
 それとも整数値に変換した値をセットしますか?
 どっち。
・とりあえず、下にサンプルを載せておくので使い分けて下さい。

サンプル:
TCHAR szBuff[ 32768 ];
LPTSTR lpSeek;
LPTSTR lpFind;
LPTSTR *s[ 100 ]; ←文字列として格納
INT n[ 100 ]; ←整数として格納
INT i = 0; ←カウンタ

GetPrivateProfileS...続きを読む

QVC++から引数付きexeファイルの実行

タイトルの通り、VC++から外部ファイルを実行したいのですがどのような関数を使えばよいのでしょうか?
exeファイルを実行中は親プロセスであるVCのプログラムの方を止めておきたいのです。
出来ればexeファイルは引数付きで実行したいと思いますので、よろしくお願いします。
開発環境はVisualStudio2005です。

Aベストアンサー

#1です。こちらで作成したサンプルです。
呼び出し側
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
intret;
printf("system試験開始\n");
ret = system("C:\\VCSTUDY\\printarg\\Debug\\printarg.exe XXX YYY ZZZ");
if (ret == 0){
printf("system成功\n");
}else{
printf("system失敗\n");
}
return 0;
}
----------------------

呼び出される側(c:\\test.exeに相当)
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
inti;
for (i = 0; i < argc; i++){
printf("ARGV[%d]=%s\n",i,argv[i]);
}
return 0;
}
以下、実行結果です。
コマンドプロンプト画面に下記の文字が出力されます。
------------------------
system試験開始
ARGV[0]=C:\VCSTUDY\printarg\Debug\printarg.exe
ARGV[1]=XXX
ARGV[2]=YYY
ARGV[3]=ZZZ
system成功
Press any key to continue
---------------------------

#1です。こちらで作成したサンプルです。
呼び出し側
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
intret;
printf("system試験開始\n");
ret = system("C:\\VCSTUDY\\printarg\\Debug\\printarg.exe XXX YYY ZZZ");
if (ret == 0){
printf("system成功\n");
}else{
printf("system失敗\n");
}
return 0;
}
----------------------

呼び出される側(c:\\test.exeに相当)
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
inti;
for (i = 0; i < argc; i++){
p...続きを読む


人気Q&Aランキング