MFCで現在 View-Documentの存在を知った程度の知識でプログラムを書いています。

MDI?形式でドキュメントにstrというCString型のメンバ変数を持たせています。
ViewからはGetDocumentで簡単にアクセスできますが、自作したダイアログボックス(例えばAbortのようなもの)の中にエディトボックスがあり、ここに入力された内容をドキュメントのメンバ変数strに代入したいのですが、どうすればよいのか分からず困っています。

あと、SDIやダイアログ形式でも同じように自作したダイアログのエディトボックスに入力した内容を設定したいです。

VBのInputBoxのようなことをしようとしていると想像してください。

A 回答 (4件)

SDIの場合の手順を示します


1) AfxGetMainWnd()でメインウィンドウのポインタを取得します。
2)メインウィンドウのポインタをキャストしてCFrameWndのポインタを
  入手します。
3)CFrameWndのポインタを使ってCFrameWndクラスのGetActiveDocument()
を呼び出します。戻り値をキャストし、ドキュメントのメンバ変数strに
  代入します。

これでSDI形式の場合なら、ダイアログからでもアクセスできます。

MDI形式では、若干手順が異なります
1) AfxGetMainWnd()でメインウィンドウのポインタを取得します。
2)メインウィンドウのポインタをキャストしてCFrameWndのポインタを
  入手します。

ここまでは同じなのですが
3)CFrameWndのポインタを使ってCFrameWndクラスのGetActiveFrame()
を呼び出します。戻り値をキャストしてCMDIChildWndのポインタを得ます。
4)CMDIChildWndのGetActiveDocument()
を呼び出します。
  戻り値をキャストし、ドキュメントのメンバ変数strに
  代入します。

以上の手順でよかったと思います。
(未確認です)

なお、上記手順にはエラー処理が一切考慮されていません。
また、特にMDI形式の場合
ターゲットとなるドキュメントがアクティブであることが前提とされています。

アクティブでないドキュメントにアクセスするには
さらに複雑な手順が必要です。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
GetActiveDocument()でドキュメントを取得し、データをセットすることができましたが、Viewの画面では反映されず一度、最小化し元のサイズや最大化すると、セットした内容の結果になりました。
ダイアログを閉じた?(値をセットした時点)で直にviewにも反映させたいのですが、DDX/DDVでいうところのUpdateDataのようなものはドキュメントであるのでしょうか?

お礼日時:2009/05/14 11:03

#1です


>GetActiveDocument()でドキュメントを取得し、
>データをセットすることができましたが、
>Viewの画面では反映されず一度、
>最小化し元のサイズや最大化すると、セットした内容の結果になりました。

>DDX/DDVでいうところのUpdateDataのようなものは
>ドキュメントであるのでしょうか?

CDocument::UpdateAllViews()を呼び出してください。

http://msdn.microsoft.com/ja-jp/library/eys41xfw(vs.80).aspx
    • good
    • 0

#1です


>VBのInputBoxのようなことをしようとしていると想像してください。

これを見落としておりました。

>ViewからはGetDocumentで簡単にアクセスできますが、
>自作したダイアログボックス(例えばAbortのようなもの)の中に
>エディトボックスがあり、
>ここに入力された内容を
>ドキュメントのメンバ変数strに代入したいのですが、
>どうすればよいのか分からず困っています。

ダイアログボックスの中からドキュメントに設定するわけではなくて、
ダイアログボックスが消えてからドキュメントに設定するわけですね。

それなら,DDX/DDVを使えば簡単です

まず、ダイアログ・クラスをCInputDialogとします。
(別になんでもいいわけですが...)
ここにメンバ変数m_Textを追加します。
m_Textはコントロール変数のCString型、カテゴリはValueにします。

操作方法についてはこちらが詳しいです
http://www.g-ishihara.com/mfc_dx_02.htm

あとは、必要な個所で呼ぶだけです
呼び方は

CInputDialog dlg;
if (dlg.DoModal() ==IDOK)
{
GetDocument()->str = dlg.m_Text;
}

これでOKです
    • good
    • 0

>例えばAbortのようなもの


ということはモーダルダイアログでしょうか。

だとしたら、モーダルダイアログから返ってきた時点で、Documentに代入すればいいのでは。
モーダルダイアログに入力した値の取得方法はヘルプに詳しく書いてあるはずです。
    • good
    • 0

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

このQ&Aを見た人はこんなQ&Aも見ています

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

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

QCStringからchar*への型変換について教えてください。

以前の質問に

int型 → CString型/char型

がありましたが、

CString型をchar*型に変換する方法を
教えていただければありがたいです。

MSDNで「LPCTSTRキャスト」が説明されていましたが、
例が載ってないのでよくわかりませんでした。

よろしくお願いします。

Aベストアンサー

目的にもよりますが一時的にchar配列として使いたいならCString::GetBuffer()が利用できます。
char配列としての利用が終わったらCString::ReleaseBuffer()する必要がありますが。

直接CString内の文字列を扱う必要があるならCString::operator LPCTSTRで文字列ポインタが得られます。
ただし、CStringオブジェクトをいじると無効ポインタなる可能性があるので気をつけてください。

MSDNのMicrosoft Foundation Classリファレンス→CString→クラスメンバで確認してください。

QCString型からdouble型への変換

C++は初心者です。VC4.0を使っていますがMFCなどは使っていません。

CString型の変数をint型やlong型への変換はなんとかできたのですが、double型へ変換することができずに困っています。atofを使えばいいのだと思い下記のように記述したのですが、コンパイルするとエラーがでます。

  CString sample = "0.234";
  double i;
  i = atof((const char*)sample);

error C2440: 'type cast' : cannot convert from 'class CString' to 'const char *'

どう直せば無事にdouble i に0.234を格納できるのでしょうか?よろしくお願いします。

Aベストアンサー

i = atof( (const char*)sample.GetBuffer(0) );

Qエディットボックスの入力制限について

いつもお世話になっております。
VS2005でC++を使ってWindowsプログラミングの作成を行っています。

エディットボックスに半角数字のみ入力するような制限はできますが、
この制限をもっと詳しくし、例えば数字の0~60までしか入力できないようにすることは可能でしょうか。

ご教授お願いいたします。

Aベストアンサー

Win32 APIを使っていて、入力があるたびに値のチェックをするのであれば、WM_COMMANDの処理で通知コードがEN_UPDATEまたはEN_CHANGEの場合を扱えば実現できます。
たとえば、エディットボックスのあるダイアログボックスのメッセージハンドラをに以下のような文を挿入すれば、エディットボックスの入力値が変わるごとに入力チェックをしてくれます(半角スペース*2を全角スペースに変換しています)。

case WM_COMMAND:
(挿入ここから)
 if (HIWORD(wParam) == EN_UPDATE/* 表示の変更前にチェックするならEN_CHANGE */ && LOWORD(wParam) == IDC_EDIT/* チェックを行うエディットボックスのコントロールID */)
 {
  char buf[256]; /* 文字列処理用バッファ */
  int value; /* 入力値 */

  GetWindowText((HWND)lParam, buf, 255); /* エディットボックスの文字列取得 */
  value = atoi(buf);
  if (value < 0 || 60 < value) /* 入力値チェック */
  {
   /* 入力値が範囲外であることをユーザーに通知する */
   MessageBox(hDlg, "0から60までの間の数を入力してください。", "入力エラー", MB_OK);
  }
 }
(以下、他のWM_COMMANDメッセージ処理)

ただし、入力値チェックを1からにして動かしてみればわかりますが、入力があるたび値のチェックをすると使う側からすればウザいです。

このような場合、自分ならば、値を入力ではなく選択させる(コンボボックスやスピンコントロールなどを使って)か、入力チェックを入力した値を利用/取得する時点で行うようにします。

Win32 APIを使っていて、入力があるたびに値のチェックをするのであれば、WM_COMMANDの処理で通知コードがEN_UPDATEまたはEN_CHANGEの場合を扱えば実現できます。
たとえば、エディットボックスのあるダイアログボックスのメッセージハンドラをに以下のような文を挿入すれば、エディットボックスの入力値が変わるごとに入力チェックをしてくれます(半角スペース*2を全角スペースに変換しています)。

case WM_COMMAND:
(挿入ここから)
 if (HIWORD(wParam) == EN_UPDATE/* 表示の変更前にチェックするな...続きを読む

Q特定のビューへのポインタ取得方法について

MFCプログラミング(MDI)について教えてください。

1つのドキュメントに
複数の子ウィンドウ+子ビューのセットがあるとき、
特定のビューへのポインタの取得方法を教えてください。

ちなみに、ビューの種類は、

1.CViewの派生クラス
2.CFormViewの派生クラス

です。

MSDNを調べ回っった結果、

ドキュメントクラスのポインタから、
GetNextView(pos)を使って順番にビューを使うところまで来たのですが、その後が分かりませんし、
この方法の方向性自体の是非も良く分かりません。

ご指導よろしくお願いします。

POSITION pos = pDoc->GetFirstViewPosition();
while(pos != NULL)
{
CView* tmpView = pDoc->GetNextView(pos);
if(tmpView == ???????)........?????
}

Aベストアンサー

1つのドキュメントにそのクラスのビューは1つだけ、という前提でよければ

CView* tmpView = pDoc->GetNextView( pos );
if ( tmpView->IsKindOf( RUNTIME_CLASS ( CTargetView ) ) {
...
}

QMFCでSDIからダイアログの呼び出し

現在MFCでプログラムを作っているのですが、

SDIベースで作成しており、
MENUバーからMENUを選択したときに
新規(リソースに作成済み)のダイアログを
表示したいのですが、どのようにしたら
よろしいのでしょうか?

ヒントだけでもお願いいたします。

DoModal()とか、newを使ったら、良いのではないかという
見当だけはつけてみたのですが。

よろしくお願いいたします。

Aベストアンサー

1.まず作成したダイアログに対応したクラスを作成します。
  これをCSampleDlgとします。
  (クラスウィザードを使えば楽でしょう)
2.メニューが選択されたとき、以下の処理を入れればモーダルで
  ダイアログが表示されます。
  {
    CSampleDlg dlg;
    dlg.DoModal();
  }

QVC++におけるCStringの変換

 VisualC++6.0において、CStringというオブジェクトがありますよね。
 たとえば、Edit->GetWindowText(str);
 などで、strにEditのさす文字列を入れたりして、そのあとにstrを使って算術演算をするときにどうしてもstrをintかlong型に直したいのです。
 キャストの仕方がよくわからないので、知っている方教えてください。よろしくお願いします。

Aベストアンサー

LPCSTR で中身をアクセスし、strtol() のような C の関数で処理しましょう。例えば、

CString cstr;
long l;

l = strtol((LPCSTR)cstr, NULL, 0);

この使い方だと、先に紹介されている atol() と同じですが、strtol() では、数字とみなせない
文字列を渡したときに、エラーの起きている位置を知ることができるので、真剣なプログラムには、
atol() よりは、strtol() の方が向いています。

QVisual Studioでのbmpファイルの背景透明化

Visual Studioで自作したC++プログラムのための
ビットマップアイコンを作っているのですが、背景の透明化の
仕方が分かりません。こういう機能ってついていないので
しょうか・・?

使用しているのはVisual Studio 2002と2005のアカデミック版です。

Aベストアンサー

見当違いであればすみません。
背景と同化したい部分を灰色にしたビットマップを用意して、LoadImage関数を呼ぶ方法で可能かもしれません。3Dカラーと同化するというLoadImage関数の引数 LR_LOADMAP3DCOLORS があります。
以下、MFCのCButtonオブジェクトに貼り付ける場合の例です。

m_hBmp = (HBITMAP)::LoadImage( AfxGetApp()->m_hInstance,
(ビットマップのID), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS );
m_Button.SetBitmap(m_hBmp);

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

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

Qカンマ区切りのデータを配列に読み込みたい

趣味でゲームを製作しているのですが、その中で、
マップデータのテキストファイルを二次元配列に読み込むようにしています。
データファイルは、カンマ区切りで、例えば、
1,2,3,4,5
5,4,3,2,1
1,2,3,4,5
というようになっています。

fp=fopen(path,"r");
for(j=0; j<3; j++)
{
for(i=0; i<5; i++)
{
char c;
do{c=(getc(fp));}
while(c==','||c=='\n'||c=='\r');
map[j][i] = c-'0';
}
}

配列の各要素に読み込む中身が、0~9など1文字に限られている場合、このgetc()を使う方法で問題ないのですが、0~255など、文字数がまちまちになると、1文字を取り出すgetc()ではできなくなってしまいます。

これがどうすれば可能になるのか、情けないのですがちょっと思いつかないので、アドバイスを頂ければ幸いです。

Aベストアンサー

少し手を入れたらできそうですね。


{
char c;
do{c=(getc(fp));}
while(c==','||c=='\n'||c=='\r');
//-----------追加-----ここから
// int calc; の宣言要
calc = 0;
do { calc = (c - '0') + (calc*10);}
while(isdigit(c=getc(fp)));
//-----------追加-----ここまで
map[j][i] = calc;
}


人気Q&Aランキング

おすすめ情報