ページ 11

MFC

Posted: 2009年1月21日(水) 18:53
by ざこ
MFCのダイアログサイズの変更の仕方がわかりません。
プログラムのときには端っこドラッグして引っ張れば大きくなったら小さくなったりできますが
ビルド→実行してからだとサイズが変更できないです。ウィンドウの大きさにあわせてダイアログ内のアイテムの位置が変わるようにしたいのですが調べてもわかりません。教えて下さい。

Re:MFC

Posted: 2009年1月21日(水) 18:59
by Mist
ググる先生を有効活用しましょう。

http://7ujm.net/vc.html

の真ん中くらい。

Re:MFC

Posted: 2009年1月21日(水) 19:04
by ま~く
ちょっと意味がわからないのですが、ダイアログのリソースでボーダーを「サイズ変更枠」にするのではなく、動的にサイズ変更可能にしたいのですか?

*リース作成時に変更可能とする場合
ダイアログのプロパティにボーダー属性があるので、それを「サイズ変更枠」にする

*動的に変更可能とする場合
ModifyStyle で WS_THICKFRAMEを指定
ただし、システムメニューに「サイズ変更」がない状態なので、必要であればメニューに
SC_SIZEを追加する。


ダイアログ内のコントロールを再配置する場合は、WM_SIZE等のメッセージハンドラ内で
コントロールを移動すればよいと思います。
MoveWindow、SetWindowPosなどで

Re:MFC

Posted: 2009年1月21日(水) 20:29
by ざこ
まだその辺の単語うまく理解できてないんですが
ダイアログベースとかでプログラムを組みビルドして実行するとダイアログでてきますよね。
そのときにサイズ変更したいんです。プログラム内でサイズ変えるのではなくて実行してから画面の
端っこをひっぱりして変更したいのですができないのかな?もしかして。その可能性を考えてませんでした。
ModifyStyle で WS_THICKFRAMEはやってみたいんですけどどうもうまくいかなかったですね。
Mistさんの張られているHPも見たんですけどわからなかったです。

Re:MFC

Posted: 2009年1月21日(水) 21:01
by ま~く
とりあえず、リソースで設定しておきたいと判断します^^;

ダイアログのリソース編集ってわかりますか?
ダイアログにコントロールをぺたぺた貼り付けられる画面のことです。
(VCの中に出てくるやつです)

あ・・VCのバージョンはいくつですか?

Re:MFC

Posted: 2009年1月21日(水) 21:08
by Mist
あ~、言いたいことが理解できた。

出来るダイアログボックスと、できないダイアログボックスがあるみたい。

http://www.relief.jp/itnote/archives/001030.php

試してないけど、やり方はこれかしら。

http://mcn.oops.jp/wiki/index.php?%B2%B ... A%EE%C0%AE(MFC)

Re:MFC

Posted: 2009年1月21日(水) 21:10
by Mist
あ、下のアドレスは(MFC)というところまでアドレスに含まれていないと表示できません。

Re:MFC

Posted: 2009年1月21日(水) 21:26
by ざこ
多分mistさんのが正解だと思います。ちょっと試せる環境にないので明日試してみますね。
バージョンはVC++6.0です
そのペタペタのほうじゃなくて実際に動かしてみる時ですね。ペタペタはるときにダイアログを伸ばしたり
縮めたりするのはできるんですけどね。プログラムではなく手動です。
ありがとうございました。

Re:MFC

Posted: 2009年1月21日(水) 22:31
by ま~く
うわ><まだ理解できない僕って・・・

Mistさんの提示したURLを確認したんですけど、コモンダイアログの事ですか?
下のURLは最初にぼくが説明した感じだし・・・

Re:MFC

Posted: 2009年1月21日(水) 23:29
by ざこ
いや私の説明が悪いんです。御二方共わかりずらそうでしたのでそうだと思います。
ま~くさんに教えていただいたのとmistさんに教えていただいたのを検証して取り組んで見ます。
普通のダイアログの方かなとは思います。下の方のURLだったと思うのでま~くさんに説明していただいたとおりかな?まぁ明日試してわからなかったら最後質問させていただきます。

Re:MFC

Posted: 2009年1月22日(木) 07:02
by toyo
「サイズ枠変更」はこれのことですよ

Re:MFC

Posted: 2009年1月22日(木) 09:11
by ざこ
上記のやり方でできました。ありがとうございました。
後はサイズ変更に伴ってボタンの位置も移動する方法ですがま~くさんの意見やmistさんに貼り付けていただいたサイトがまさにこれっぽいので試して見ます。

Re:MFC

Posted: 2009年1月22日(木) 10:00
by ざこ
お二方の意見を参考にしてとあるhpに
フォームのリサイズと同じ比率でコントロールをリサイズします

bool flg = false;//起動時にイベントが発生してサイズを変えると落ちるため、回避のためのフラグ
void CtestDlg::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	
	// TODO: この位置にメッセージ ハンドラ用のコードを追加してください

	if(flg) GetDlgItem(IDC_STATIC)->MoveWindow(cx/10,cy/10, cx/2,cy/2);//動的なサイズの変更
	flg = true;
}
とやり方が載ってました。これかなと思って試した結果サイズを変更しようと端をドラッグすると
問題が発生しました。作業を終了します
となります。やり方がおかしいのでしょうか?
※上記のソースはdialogのクラスでWM_SIZEのメッセージを使ってます。

Re:MFC

Posted: 2009年1月22日(木) 10:19
by ま~く
できてよかったですね^^

問題はIDC_STATICにあると思います。
IDC_STATICではコントロールを特定できないので、
たとえば IDC_LABEL1 のように 別のIDをつけてみてください。

ちなみに flg による判定はうまくいくと思いますが、見た感じが微妙ですね^^;

Re:MFC

Posted: 2009年1月22日(木) 10:28
by ざこ
とんでもないことに気づきました。そのままパクッて貼り付けたんですがSTATICをダイアログ内で使用してませんでした・・
それでif(flg) GetDlgItem(IDC_STATIC)->MoveWindow(cx/10,cy/10, cx/2,cy/2);//動的なサイズの変更を

if(flg) GetDlgItem(IDC_IDOK)->MoveWindow(cx/10,cy/10, cx/2,cy/2);//動的なサイズの変更
if(flg) GetDlgItem(IDC_CANCEL)->MoveWindow(cx/10,cy/10, cx/2,cy/2);//動的なサイズの変更
if(flg) GetDlgItem(IDC_LIST1)->MoveWindow(cx/10,cy/10, cx/2,cy/2);//動的なサイズの変更

にすると今度はドラッグする前、
詳しくは今SDIベースでメニューのとある欄を押すとダイアログが表示され、そのダイアログをいじくったりの作業を
今しています。それでメニューの所を押した時点で問題が発生しました。作業を終了します
とでます。何が問題なのかさっぱりです。

Re:MFC

Posted: 2009年1月22日(木) 10:33
by バグ
flg変数は、OnSize関数の中で毎回trueにしなくても、OnInitDialog関数の中で一度だけtrueにしてやればいいと思いますよ(^-^)

OnInitDialog関数の中でButtonやStaticなんかのコントロールの初期化を行っているようなので、この初期化が終了してしまわない内に、コントロールに対して何か操作しようとするとエラーが出るようです。

Re:MFC

Posted: 2009年1月22日(木) 10:37
by バグ
あ、追記です。
前述のflg変数ですが、Dialogクラスにメンバ変数として追加しておいた方がよいですよ。
グローバル変数でも構わないといえばそうなのですが、Dialog内でしか使わないものですから、Dialog内でしか使えないようにしておいた方が、可読性の向上を考えると良いと思います。

Re:MFC

Posted: 2009年1月22日(木) 13:55
by ざこ
なんとかできました。最後の作業なんですが1度起動してダイアログのサイズを変更して終了します。
次また起動したときに終了したサイズで始める。というプログラム取り入れたいんです。最初は一定の値いれといて終了時にウィンドウのサイズをどっかに入れ次回起動時にそのサイズではじめる という感じかなとは思いますが
プログラムって1回終了したらデータ失われますよね。失われず続きからできるなら上記の作業いらないのかな
とは思います。お手数ですが教えて下さい。

Re:MFC

Posted: 2009年1月22日(木) 14:04
by バグ
ファイルにTop, Bottom, Left, Rightの値を保存しておくのがいいかと思います。
で、ダイアログを閉じる際のイベントハンドラ内(OnCloseとかOnDestroyかな?)で、値を更新保存する…というのでいけるんではないでしょうか?

Re:MFC

Posted: 2009年1月22日(木) 14:29
by ざこ
どうやらレジストリというものを使うっぽいのでちょっと勉強してみます。

Re:MFC

Posted: 2009年1月22日(木) 15:08
by Mist
勉強のために作られているソフトだったらいいんですけど、完成後他の人に使ってもらうことを考えておられるのであればなるべくレジストリは使わないほうがいいと思います。
(テキストファイルやバイナリファイルで十分な気もします)

理由は
1.レジストリに設定を残す(=レジストリを汚す)ソフトは嫌われる傾向にある
  このソフトがレジストリを使用していることの銘記は必要になる
  よほどのことがない限り大丈夫と思いますが、レジストリを破壊するようなことがあるとOS再インストールということになる
2.アンインストール時に、レジストリから情報を消す手段が必要になる
  アンインストーラが必要になる
  レジストリを使用していなければ実行ファイルのフォルダ丸ごと削除だけですむ
3.他のPCで同じソフトを使用したい場合に設定を引き継がせにくい

特にVistaだとUACの影響でレジストリが使えなかったり、仮想化されてXPとは違う動きになったりしますしね。

Re:MFC

Posted: 2009年1月22日(木) 16:03
by ざこ
.iniファイルに保存する形式にしました。まず初期サイズ作ってたんです。
DialongクラスにOnInitDailog関数作ってそこで
CRect WinRect;
WinRect.left=AfxGetApp()->GetProfileInt("memo","left",200);
WinRect.top=AfxGetApp()->GetProfileInt("memo","top",200);
WinRect.left=AfxGetApp()->GetProfileInt("memo","right",622);
WinRect.bottom=AfxGetApp()->GetProfileInt("memo","bottom",310);
MoveWindow(WinRect);
としてたんです。これで初期設定は出来ていました。

それでその後にです。ダイアログが閉じるときにそのサイズを保存しようとして
ダイアログのクラスにOnDestroy関数つくりそこに
CRect WinRect;
WinRect.left=AfxGetApp()->WriteProfileInt("memo","left",WinRect.left);
WinRect.top=AfxGetApp()->WriteProfileInt("memo","top",WinRect.top);
WinRect.left=AfxGetApp()->WriteProfileInt("memo","right",WinRect.right);
WinRect.bottom=AfxGetApp()->WriteProfileInt("memo","bottom",WinRect.bottom);
MoveWindow(WinRect);


としたんです。すると意味不明なことに
メニューから【ダイアログ】←※メニューからダイアログを呼びだす場所
押すとプログラムが動かなく閉じることもできなくなります。再起動してDestroy関数を消去しても同じ結果になり
InitDialogの方消せば動かなくなるのは止まりました。何が悪いのでしょうか?

Re:MFC

Posted: 2009年1月22日(木) 16:12
by バグ
ちなみに、WinRectに数値は入っているんですよね?

Re:MFC

Posted: 2009年1月22日(木) 16:25
by ざこ
動かなくなるのは私のミスだと思います。ただ間違いはDestoy関数なはずなのに何故消去してもなるのかと・・
>>CRect WinRect;
WinRect.left=AfxGetApp()->WriteProfileInt("memo","left",WinRect.left);
WinRect.top=AfxGetApp()->WriteProfileInt("memo","top",WinRect.top);
WinRect.left=AfxGetApp()->WriteProfileInt("memo","right",WinRect.right);
WinRect.bottom=AfxGetApp()->WriteProfileInt("memo","bottom",WinRect.bottom);
MoveWindow(WinRect);

の部分を

CRect WinRect;
GetWindowRect(&WinRect);
AfxGetApp()->WriteProfileInt("memo","left",WinRect.left);
AfxGetApp()->WriteProfileInt("memo","top",WinRect.top);
AfxGetApp()->WriteProfileInt("memo","right",WinRect.right);
AfxGetApp()->WriteProfileInt("memo","bottom",WinRect.bottom);
にしました。するととりあえずおかしくなることはなくなりました。

>>WinRectに数値は入っているんですよね?
Destroyの中のWinRectの中を見るとちゃんとサイズ変更した値が入っていました。
ちゃんと起動しました。ありがとうございました。

Re:MFC

Posted: 2009年1月22日(木) 16:42
by バグ
ソースの全体を見ていないので推測ですが、OnDestroyの中でMoveWindowを呼び出していたのが原因ではないかと思います。既に破棄されたWindowに対して、なんらかの処理を行おうとしたために暴走してしまったのではないでしょうか?

Re:MFC

Posted: 2009年1月22日(木) 16:57
by バグ
あと1つ気になったんですが、iniファイルに書き込むのって、WriteProfileIntでいいんでしたっけ?
WritePrivateProfileStringじゃなかったっかな?違ってたらすみません(^_^;)

Re:MFC

Posted: 2009年1月22日(木) 17:17
by ざこ
これは"新VisualC++6.0 入門シニア偏"に載っていました。
その方法でもできるかもしれませんね。ありがとうございました。