トップページ⇒tech
1001コメント323KB

■MFC相談室 mfc14d.dll■

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2005/07/13(水) 05:28:44
Microsoft Foundation Classライブラリ専用スレです。

■MFC相談室 mfc13d.dll■
http://pc8.2ch.net/test/read.cgi/tech/1110179996/
■ MFC相談室 MFC12.dll■
http://pc5.2ch.net/test/read.cgi/tech/1096848771/
■MFC相談室 mfc11.dll■
http://pc5.2ch.net/test/read.cgi/tech/1088084875/
■ VisualC++(MFC限定)相談室 MFC10.dll■
http://pc5.2ch.net/test/read.cgi/tech/1074104008/
■ VisualC++(MFC限定)相談室 MFC9.dll■
http://pc5.2ch.net/test/read.cgi/tech/1062098350/
■ VisualC++(MFC限定)相談室 MFC8.dll■ (スレタイ壊れているけど前スレ)
http://pc5.2ch.net/test/read.cgi/tech/1056584836/
■ VisualC++(MFC限定)相談室 MFC7.dll■
http://pc5.2ch.net/test/read.cgi/tech/1047949606/l50
■ VisualC++(MFC限定)相談室 MFC6.dll■
http://pc5.2ch.net/test/read.cgi/tech/1039607377/
■ VisualC++(MFC限定)相談室 5■
http://pc3.2ch.net/tech/kako/1028/10285/1028553308.html
■ VisualC++(MFC限定)相談室 4■
http://pc3.2ch.net/tech/kako/1021/10216/1021620974.html
■ VisualC++(MFC限定)相談室 3■
http://pc.2ch.net/tech/kako/1014/10140/1014057520.html
■ VisualC++(MFC限定)相談室 2■
http://pc.2ch.net/tech/kako/1008/10080/1008031675.html
■ VisualC++(MFC限定)相談室 ■
http://pc.2ch.net/tech/kako/989/989902845.html
0002デフォルトの名無しさん2005/07/13(水) 10:42:13
では、早速質問でつ。

CParentDialog::OnShowWindow(BOOL bShow, UINT nStatus)
{
 ChildDialog.Create(IDD_CHILD, this);
 ChildDialog.ShowWindow(true);
}
として動作していました。

が、ChildDialogに値を渡したいので、
ChildDialog.Create処理だけをParentDialog.DoModal()の前に移動して、
ChildDialogのプロパティを参照するようにしました。

そうしたところ、ChildDialog.ShowWindow(true)でエラーになりました。

回避方法教えて下さいでつ。
000322005/07/13(水) 10:47:26
事故解決しました。

処理変えなきゃ良いんでつね。
>ChildDialog.Create(IDD_CHILD, this);
これがnewだと勘違いしてます他。
0004デフォルトの名無しさん2005/07/13(水) 15:15:44
DoDataExchangeの動くタイミングを教えて下さい。
非表示では動作しませんか?
0005デフォルトの名無しさん2005/07/13(水) 15:27:39
>4
非表示でも動きます。
UpdateData(TRUE);
UpdateData(FALSE);
が実行されれば。
000642005/07/13(水) 15:59:26
サンクツ>>5

ただ、CWnd::UpdateDataの中の1行目「ASSERT(::IsWindow(m_hWnd));」でコケまつ。
0007デフォルトの名無しさん2005/07/13(水) 16:19:00
>>6
アプリがどういう作りかわからんが、
ウィンドウが作られる前にUpdateData動かしてるからだろ。たぶん。

ダイアログのコンストラクタでUpdateData呼び出したら、
同じエラーになるぞ。
000842005/07/13(水) 16:38:19
サンクツ>>7

Dlg.DestroyWindow();
Dlg.Create(IDD_DLG, this);

でウィンドウ作るようにしてみましたが、
今度は、
CDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
の出だしの、
「ASSERT(HIWORD(lpszTemplateName) == 0 || AfxIsValidString(lpszTemplateName));」
でこけてまつ。

変な記述してるわけじゃないんだけどな...
000942005/07/13(水) 16:45:08
>Dlg.Create(IDD_DLG, this);
>CDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd)

先頭の引数は数値なのにLPCTSTRに入ってる時点で不思議。
なんか明示的に書いてやる必要があるのかな?
001042005/07/13(水) 16:47:27
UpdateData呼び出すのも難しいYO
0011デフォルトの名無しさん2005/07/13(水) 16:52:12
>4
つか、いったい何がしたいのか?
001242005/07/13(水) 16:56:23
Dlg.DestroyWindow();

>Dlg.m_Control.SetCaption("データ"); //////←これをやりたい!

Dlg.DoModal();

コントロールに文字列を設定したい。
なぜかというと、Dlgの中のメソッドの人に、
コントロールの文字列を使って動作する処理が入ってるから。

それを直すのも怖いし。
0013デフォルトの名無しさん2005/07/13(水) 17:01:20
>4
環境書いてくれい
VC6.0++とかか?

あと、Dlg.DestroyWindow();で
ダイアログを破棄してからセットするのか?ていうかできないんじゃ・・・

001442005/07/13(水) 17:04:42
Yes.>VC6.0++とかか?

>あと、Dlg.DestroyWindow();でダイアログを破棄してからセットするのか?ていうかできないんじゃ・・・

え”〜困ります。
既に出来てるDlgがグローバル変数になってて、一旦初期化しないと...
001542005/07/13(水) 17:12:22
Dlg.DestroyWindow();
Dlg.UpdateData(FALSE);
>Dlg.m_Control.SetCaption("データ"); //////←これをやりたい!
Dlg.DoModal();

でも、UpdataDataでエラーですね。。。
UpdateDataを外してもデータのセット時にエラーだし。
0016デフォルトの名無しさん2005/07/13(水) 17:14:26
>>15
CDialog::OnInitDialogの中で
UpdateData(TRUE)
0017162005/07/13(水) 17:15:50
上のは
UpdateData(TRUE)じゃなくてUpdateDate(FALSE)です
001842005/07/13(水) 17:20:18
>CDialog::OnInitDialogの中で
っていつコールされるんでしたっけ???
0019デフォルトの名無しさん2005/07/13(水) 17:21:02
dlg.Create(IDD_DIALOG1, NULL); //わざと作る
dlg.DestroyWindow(); //破棄する

dlg.Create(IDD_DIALOG1, NULL); //も一回作る
dlg.m_ctltext="aiueo";//ダイアログのメンバにセット
dlg.UpdateData(FALSE);//変数からコントロールに更新
dlg.ShowWindow(SW_SHOW);//表示

これなら動いたぞ

0020デフォルトの名無しさん2005/07/13(水) 17:25:49
dlg = new CNewDlg();
dlg->m_ctltext="aiueo";
dlg->DoModal();


dlgはCNewDlg*型
これならUpdateDataいらんな
0021162005/07/13(水) 17:31:53
>>18
>っていつコールされるんでしたっけ???

CreateまたはDoModalしたとき。
そのCDialog::OnInitDialogの中で
自動でUpdateData(FALSE)が呼ばれるようになってる
MFCのソース見てごらん。

19の書いてくれてるのは
dlg.m_ctltext="aiueo";//ダイアログのメンバにセット
dlg.Create(IDD_DIALOG1, NULL); //も一回作る
dlg.ShowWindow(SW_SHOW);//表示
としてもOKだと思うよ。
中でUpdateDataしてくれるはず。
002242005/07/13(水) 17:34:33
>これなら動いたぞ
>>19

ですよね?
自分もそれに近いコールで動いてる箇所もあるような気がするし、
今のフォームはASSERTにひっかかるし、キョドってる。
MFCのCDialogのASSERTってトラップっていうか邪魔。
0023192005/07/13(水) 17:37:42
>21
あ〜ほんとだ、動くね。
002442005/07/13(水) 17:48:25
>dlg.Create(IDD_DIALOG1, NULL); //わざと作る
>dlg.DestroyWindow(); //破棄する
>dlg.Create(IDD_DIALOG1, NULL); //も一回作る
19路線でやってみたいと思いましたが、
Createの中の、
BOOL CWnd::CreateDlgIndirect(LPCDLGTEMPLATE lpDialogTemplate,
CWnd* pParentWnd, HINSTANCE hInst)
の中の、
hWnd = ::CreateDialogIndirect(hInst, lpDialogTemplate,
pParentWnd->GetSafeHwnd(), AfxDlgProc);
この行でエラーダイアログが出ます。
002542005/07/13(水) 18:00:19
>dlg.Create(IDD_DIALOG1, NULL); //わざと作る
>dlg.DestroyWindow(); //破棄する
>dlg.Create(IDD_DIALOG1, NULL); //も一回作る

ごめんなさい、ここまでOKでした。
間違いは、2回目のCreateのID間違いでした。

が、この後のDoModal()でエラー。
DoModal前にCreateは禁止だったかなぁ?????
002642005/07/13(水) 18:03:04
Createをやめて、UpdateDataに差し替えたところ、

BOOL CWnd::UpdateData(BOOL bSaveAndValidate)
{
ASSERT(::IsWindow(m_hWnd)); // calling UpdateData before DoModal?

の出だしのASSERTで爆発。

もっと自由にコールできるメソッドにして欲しぃ。
0027192005/07/13(水) 18:06:49
>4
Createの後でDoModalは俺もエラー
だからとりあえずShowWindowにした。

DoModalでなきゃヤダとか言うなら>>20の方法なら
問題なくDoModal出来る。
表示されるダイアログがクラス化されていればの話だが・・・

他に方法あったっけ?

002816&212005/07/13(水) 18:09:01
>>25-26
おいおい
モーダルとモードレスの違い分かってる?
002942005/07/13(水) 18:11:03
thx>>27
>DoModalでなきゃヤダとか言うなら>>20の方法なら
>表示されるダイアログがクラス化されていればの話だが・・・

Dlgがグローバル変数で、かつ、実体宣言されてるので、
こうするためには激しい書換えが発生しまつ。
一部のメンテなんで激しい書換えは予定外でつ。厳しい...
0030デフォルトの名無しさん2005/07/13(水) 18:14:23
>>28
そういうMFCでのモーダルとモードレスの制限が知りたいんじゃなく回避方法が必要なんでわ?
0031282005/07/13(水) 18:19:35
>>29
そういう問題じゃない。
Createの後で何でDoModalするんだよ。
モードレスダイアログなら19の書いてくれてるように
CreateしてShowWindowでいいの!

>>30
何を回避?
4がモーダルとモードレスを混同しているとしか思えないが。
0032デフォルトの名無しさん2005/07/13(水) 18:34:26
>4がモーダルとモードレスを混同しているとしか思えないが。
アタマワリー

別のライブラリなら、
TCustomForm *Form = new TForm(NULL);
Form->PropA = "aaa"; //値をセット
Form->ShowModal(); //モーダル
Form->Show(); //モードレス

という感じで自由にコールできるぞ。
0033312005/07/13(水) 18:46:01
>>32
意味不明。
このスレはMFCの話だろ。

Createするってことはモードレスを意図してるんだろ。
その後でDoModalする必要性は如何に?
0034192005/07/13(水) 18:54:14
>4
表示ダイアログの書き換えムリなら、

ShowWindowでモードレス表示して、
親ダイアログは制御を取らないように・・・って
なんか面倒なような気が・・・

俺なら問答無用に表示ダイアログ作り直すw
0035デフォルトの名無しさん2005/07/13(水) 18:54:17
>Createするってことはモードレスを意図してるんだろ。

これが読み間違いだろ。
このクリエイトの目的は値をセットするためであってモードレス意図じゃないだろ。
003642005/07/13(水) 18:56:55
>>34
やっぱ難しいんですね。
MFCのDoModalとそれ以前のコントロールの設定の組み合わせは。

ダイアログ直して、コントロールに依存しないようにしてみまつ。
0037192005/07/13(水) 19:00:31
ていうか、表示ダイアログの使い方って言うか、
仕様が変。

DoModalしたきゃ、表示ダイアログクラス化して、
パブリックなメンバ変数にアクセスして設定するとかしなきゃダメ。
そうすりゃ何でもあり。自由自在!!

003842005/07/13(水) 19:02:27
>>37
変なものをメンテしてるんだから、そんなこと言われても...

やっぱ、MFCのCDialogがもう少し使いやすくなるべきでわ。
ライブラリが色々強要してくると面倒。
0039332005/07/13(水) 19:04:50
>>35
値をセットしたいなら
[モーダル]
 dlg.m_hoge="abcde";
 dlg.DoModal(); ※
[モードレス]
 dlg.m_hoge="abcde";
 dlg.Create(); ※
 dlg.ShowWindow();
でいいだろ。(引数は省略)
UpdateData(FALSE)はそれぞれの※の後で、
CDialog::OnInitDialog()の中で自動で呼ばれる。

CreateとDoModalを一緒に呼び出す意図が分からないのだが。
004042005/07/13(水) 19:09:28
>>39
あるグローバルのダイアログが色んな用途に使われてて(←ここが破綻の元。せめて、1リソースに複数クラスにしといてくれたら何とかなったかも)、
モーダル/モードレスで開いたり閉じたりします。
で、
dlg.DestroyWindow(); //破棄する
が必要なんです。
で、破棄後に、
[モーダル]
 dlg.m_hoge="abcde";
するとエラーになる。
0041192005/07/13(水) 19:18:36
>4
ねぇ、そのグローバルのダイアログってクラス化されてないの?
dlg.DestroyWindow();のdlgってあくまでCDialogなのか?

宣言部教えて

004242005/07/13(水) 19:24:34
19はシツコイ。

何を言いたいのか分かっているというか、
ダイアログのコントロールに直接入出力するのがおかしいことくらい誰でも知っている。

とりあえず、自分は19を必要としてない。
004342005/07/13(水) 19:32:28
ごめんなさい42を取り消します。
19さんは色々教えて下さった方でした。
「モーダルとモードレスと知らないのか?」と煽った人と勘違いしました。
0044192005/07/13(水) 19:36:46
>4
うぇ〜あぶねぇ・・・
ムカついて煽りの一文書くとこだったw
0045192005/07/13(水) 19:40:59
>あるグローバルのダイアログが色んな用途に使われてて

どんな使い方してる?
DoModalで表示?それともShowWindowで表示?
必ずCreateしないと使えないの?
004642005/07/13(水) 20:01:03
>>45
今までずっとShowWindowでモードレスされてたウィンドウですが、
今回の修正でモーダルが必要になったんでdlg.DestroyWindow()しました。
ダイアログを別インスタンスにしようと思ったら、
グローバルなダイアログ同士が参照しあってて、
正直ガクブル
0047332005/07/13(水) 20:02:28
>>42
俺に対して言ってるんだろうなぁ。
16以降の俺の全レス読んで欲しい。それでも煽りと捉えられてしまうなら残念。

簡単なコードで試してみたが動いたことだけ報告しておくよ。
(ダイアログ作成と廃棄のタイミングまで細かく見てないので、これでは問題あるかも。
あと、それぞれの関数はボタンのコマンドハンドラでdlgはCDialog派生です)
void CTestApp::OnModal()
{
// TODO: この位置にコマンド ハンドラ用のコードを追加してください
dlg.DestroyWindow();
dlg.m_str = "Modal";
dlg.DoModal();
}
void CTestApp::OnModeless()
{
// TODO: この位置にコマンド ハンドラ用のコードを追加してください
dlg.DestroyWindow();
dlg.m_str = "Moeless";
dlg.Create(IDD_HOGE, NULL);
dlg.ShowWindow(SW_SHOW);
}
004842005/07/13(水) 20:06:24
thx>>47
煽りに対して憤ってるんじゃありません。
前スレで感じたんだけど、MFCスレは上手く会話を流さないとやヴぁい流れになるんで。


dlg.DestroyWindow();
dlg.m_str = "Modal";
dlg.DoModal();

この「m_str」はCStringだと思いますが、これをコントロールにするとエラーします。
でもまぁこれはMFCの制限と捕らえました。
0049デフォルトの名無しさん2005/07/13(水) 20:10:04
自演の悪寒
0050デフォルトの名無しさん2005/07/13(水) 20:10:54
二つのプログラムA,Bで双方向に非同期で通信したかったので、
A,BをそれぞれDDEサーバーかつDDEクライアントにして
プログラムを書いたら、どうにか動いたのですが、それをLinuxに
移植したいと考えています(できればWindowsでも動かしたいです)。
DDEの代わりになるお勧めの方法はありますか?
交換するデータ量は、たとえばAのプログラムでボタンをクリックした
ときに、数バイト程度の文字列をBに送るとか、その逆です。
よろしく。
0051472005/07/13(水) 20:13:28
>>48
dlg.m_ctrl.
dlg.Create(...)
こうすると確かにエラー
Createの段階ではコントロールウィンドウが作成されてないためでしょう

dlg.Create(...)
dlg.m_ctrl.
ならOKでしたよ。
0052デフォルトの名無しさん2005/07/13(水) 20:15:35
>>46
MFC の window = CWnd は、
Windows の window HWND のラッパ。

CWnd は C++ 的 object。そのまんまの lifetime。
HWND は Cretate から Destroy までの lifetime。
もしくは DoModal() の開始から終了までの lifetime。

dialog 上の control (dialog から見て child control) は HWND 的には
dialog (control から見て parent window) と lifetime を共にする。
0053192005/07/13(水) 20:26:26
>4
ちょーとまて
>この「m_str」はCStringだと思いますが、これをコントロールにするとエラーします。
って事は実はクラス化されているのか?DoDataExchangeも使ってるし・・・

dlg.DestroyWindow(); のdlgって
CDialogの派生でCXxxxDlgなのかな?


dlg.DestroyWindow(); //今までの削除
CXxxxDlg dlg2;//新しく宣言
dlg2.DoModal(); //表示

まずこれで動くか?


0054デフォルトの名無しさん2005/07/13(水) 20:27:27
>>46
ご愁傷様。そこで回避案。
class IInitDialogHandler
{
public:
0055デフォルトの名無しさん2005/07/13(水) 20:30:25
>>46
>今までずっとShowWindowでモードレスされてたウィンドウですが、
>今回の修正でモーダルが必要になったんでdlg.DestroyWindow()しました。

AfxGetMainWnd()->EnableWindow(FALSE); してから dlg.ShowWindow() すると
おおむねモーダル風になるよ。
0056デフォルトの名無しさん2005/07/13(水) 20:40:52
>>46
class IInitDialogHandler
{
virtual void Do() = 0;
};
class 問題のDialog
{
IInitDialogHandler* m_initDialogHandler;
void OnInitDialog()
{
if (m_initDialogHandler) {
m_initDialogHandler->Do();
}
}
};
問題のDialog dlg;
class 問題のDialogのClient : public IInitDialogHandler
{
virtual void Do()
{
dlg.m_control.SetWindowText("modal");
}
void OnModal()
{
dlg.DestroyWindow();
dlg.DoModal();
dlg.CreateWindow(...);
}
}
005747&512005/07/13(水) 22:30:54
>>51の補足
[モーダル]の場合
dlg.m_ctrl.・・・
dlg.DoModal();
とすると、DoModal前はコントロールのウィンドウが作成されておらず、HWNDが無効なため
m_ctrlにアクセスしようとするとエラーになる。(51のCreate前と同様の現象)

>>12を読む限り文字列さえ設定できれば良いようなので
新たにCString型のDDX変数を追加して>>47みたいにすればOK。
SetCaptionというのには標準のDDX_Textを使えないので
自前でDDX_,DDV_を実装すればよい。
関数を書いてもいいし、CHogeDialog::DoDataExchangeの中に書くのでもいい。
http://www.microsoft.com/japan/developer/library/vcmfc/_mfcnotes_tn026.htm
0058デフォルトの名無しさん2005/07/13(水) 22:52:44
ダイアログクラスのインスタンスを何度も使いまわすなら
CWnd : : Detach()でも使えないかね…
DestroyWindow()はなんか大げさな希ガス。
0059デフォルトの名無しさん2005/07/14(木) 08:29:58
実は>55が一番素直じゃないかって気もしないでもないな。
006042005/07/14(木) 08:42:33
>>53
あ、DoDataExchangeってそういう使い方するんですか。
コントロール生成の前に値を変数に入れとくわけですね。
って超基本を誤解してた悪寒。

>>51-59
各種破棄メソッドとlifetimeの関係、
このあたり、ずっと知りたいとこでした。¢(ーー;メモシトク・・・
0061デフォルトの名無しさん2005/07/14(木) 13:58:17
CDC dcWork,dcScreen;

dcWork に描画された内容を 指定したRGB値を透明色にして 全体を半透明に dcScrren にBitBltしたいのですが、
このようなことはできるのでしょうか?(自前でアルファブレンドや透明色のコードを書かないで)
CDC::AlphaBlendとCDC::TransparentBltの2つの機能をあわせたような処理を実現したいのです。

自前でピクセルを全て操作するような処理を実装すると、すこぶる遅くなるので、MFC(API)に任せたいのです。
(DirectXとかOpenGLとかは使いたくないです。)

賢者の方よろしくご教授下さい。お願いします。
0062デフォルトの名無しさん2005/07/14(木) 14:14:19
少なくともMFCにそんな機能は無い。
0063612005/07/14(木) 14:22:23
>>62 そうなんですかがっかり・・・・

他にこのAPIが使えそうとか、こういう風な実装をすれば、高速に処理できるとかヒントや参考になるリンクでも
知っている人がいましたら、ぜひお教え下さい。お願いします。

GDI+とかでもできなさそうでしょうか?Graphicsクラス?
0064デフォルトの名無しさん2005/07/14(木) 14:58:03
素直にDirectX使った方がいいかと
0065デフォルトの名無しさん2005/07/14(木) 15:09:53
MFCにDirectXのラッパ無いんでしたっけ?
0066デフォルトの名無しさん2005/07/14(木) 15:22:55
そんなの要らん
006716ほか2005/07/14(木) 19:19:35
>>60
今ごろになって何言ってんの?
まともにデバッガ使ってないだろ。

ついでに、俺の全レスは>>16>>21>>28>>31>>33>>39>>47>>51>>57。
それでも42-43のような発言をした挙句に撤回もせずに
すっとぼけて出てくる気が知れん。

-----------------------------------------------------
あまりにも目に余るので一言言わせてもらいました。
他の回答者&質問者の方々、スレ汚しになり申し訳ありません。
0068デフォルトの名無しさん2005/07/14(木) 19:21:13
CListCtrlを継承したクラスでカスタムドローを使って描画しています。
リストのアイテムを選択した際の描画をフックするためにOnCustomDrawの中で
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)pNMHDR;
switch( lplvcd->nmcd.dwDrawStage )
{
case CDDS_PREPAINT:
*pResult = (CDRF_NOTIFYSUBITEMDRAW | CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT);
break;
case CDDS_ITEMPREPAINT:
*pResult = (CDRF_NOTIFYSUBITEMDRAW | CDRF_NOTIFYPOSTPAINT);
break;
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
*pResult = (CDRF_NOTIFYSUBITEMDRAW | CDRF_NOTIFYPOSTPAINT);
break;
case CDDS_POSTPAINT:
break;
case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
case CDDS_ITEMPOSTPAINT:
if ( (lplvcd->nmcd.uItemState & CDIS_FOCUS) != 0 )
{
// ... (*)
}
break;
default:
*pResult = CDRF_DODEFAULT;
break;
}
としていまして、アイテムをマウスでピックした際には(*)に来るのですが、
プログラムの中から以下のようにアイテムを選択状態にしても来ません。
SetItemState( iIndexInVisible, CDIS_SELECTED | CDIS_FOCUS, CDIS_SELECTED | CDIS_FOCUS );
何が問題かわかりますでしょうか。。。
0069682005/07/14(木) 19:24:27
わかりにくくてすみません。>>68の(*)の位置で選択状態にあるアイテムの描画をしているのですが、
マウスでアイテムをピックした場合にはうまくいくものの、プログラム内の他の関数から
SetItemStateを読んでアイテムを選択状態にしても(*)の場所に処理が来ずに描画ができないという状況です。
0070デフォルトの名無しさん2005/07/14(木) 19:30:32
>>68
Listコントロール自体がフォーカスを持っていないからでは?
0071デフォルトの名無しさん2005/07/14(木) 19:33:16
>>69
 選択状態のアイテムの強調表示を常に行いたいのなら、ListViewのスタイルに
LVS_SHOWSELALWAYS を追加して、uItemState & CDIS_SELECTED を見るのが
正しげに思える。
0072デフォルトの名無しさん2005/07/14(木) 19:38:48
>>69
フォーカスと選択に関する例です。解っているなら無視してください。

例えば List Control の代表的な例としてエクスプローラでファイルがいくつか入った
フォルダを開いて、アイテムをクリックすると、リストコントロールとアイテムが選択され、
かつそのアイテムにフォーカスが移動する。

ここでCtrl+矢印でフォーカスだけ移動させてみると、フォーカスを示す点線の矩形が
ファイル名を囲むように表示される。他のウィンドウをクリックするなどして、リストコント
ロールがフォーカスを失うと、アイテムのフォーカスを示す矩形は非表示になる。
0073デフォルトの名無しさん2005/07/14(木) 19:55:46
>>68
SetItemStateの引数に渡すのはCDIS_じゃなくてLVIS_の方だと思う。
それぞれ以下のようにdefineされてるので、確認。

CommCtrl.h
#define LVIS_FOCUSED 0x0001
#define LVIS_SELECTED 0x0002
#define CDIS_SELECTED 0x0001
#define CDIS_FOCUS 0x0010
0074デフォルトの名無しさん2005/07/15(金) 00:05:26
エディットボックスがあってコントロール変数CString m_Editがあるとします。
そしてWM_USER_ADD_STRINGというメッセージを受けるとメッセージハンドらで
CXXXDlg::OnAddString(WPARAM wParam, LPARAM lParam)
{
 m_Edit += (LPCTSTR)lParam;
 UpdateData(FALSE);
}
とやってm_Editに文字列を追加していきます。
そしてたくさん追加するとスクロールバーが出てくるのですがこいつを一番したに自動で行かせたいのです。
つまり最後に追加した奴を見るのにいちいち人手でスクロールさせるのは面倒くさいので自動にしたいわけです。
いい方法はありませんか?
0075デフォルトの名無しさん2005/07/15(金) 00:14:31
あります。
0076デフォルトの名無しさん2005/07/15(金) 01:15:04
>>74
MSDNのCEditクラスメンバー辺りを矯めつ眇めつする。
0077デフォルトの名無しさん2005/07/15(金) 01:42:18
ちなみに
UpdateDataの次の行から

CEdit * pWnd = (CEdit *)GetDlgItem(IDC_EDIT);
int lines = pWnd->GetLineCount();
int pos = pWnd->LineIndex(lines - 1);
pWnd->SetSel(pos, pos, FALSE);

とかやってみるとそれっぽく動いたのですが、どうも落とし穴がありそうな気が。

さらにIDC_EDIT2を追加してこちらも同様にWM_USER_ADD_STRING2で
テキストを追加、行を最後に移動と言う処理をさせると
IDC_EDITとIDC_EDIT2のどちらかしかスクロールバーが最後に来てくれないのです。
なぜでしょうか?
0078デフォルトの名無しさん2005/07/15(金) 01:56:24
>>77
SetSel()は表示されることを保証しないからねぇ。
ちなみに私が使っている最終行を表示させる関数はこう。
void showLastLine(CEdit & edit)
{
edit.SetRedraw(false);
edit.LineScroll(edit.GetLineCount());
edit.LineScroll(-1);
edit.SetRedraw();
}
0079デフォルトの名無しさん2005/07/15(金) 02:07:15
>>78
ありがとうございます!!!
明日早速試してみます。
本当に夜分遅くありがとうございました!
0080612005/07/15(金) 06:21:33
>>61-64

ふぅ時間がかかりましたが自己解決しました。DirectXもOpenGLも使わずにすみました。
0081デフォルトの名無しさん2005/07/15(金) 13:40:58
質問です。
ViewのOnCreateでダイアログを作成してモードレスで表示しています。
ソフトが立ち上がったときにこのダイアログのエディットコントロールに
すでに入力フォーカスがあるようにしたいのですが、
OnInitDialogでSetFocusをやったけれどうまくいきませんでした。
どこでSetFocusをすればいいのでしょうか?
0082デフォルトの名無しさん2005/07/15(金) 13:43:07
質問です。
ViewのOnCreateでダイアログを作成してモードレスで表示しています。
ソフトが立ち上がったときにこのダイアログのエディットコントロールに
すでに入力フォーカスがあるようにしたいのですが、
OnInitDialogで
GetDlgItem(ID)->SetFocus()
をやったけれどうまくいきませんでした。
どこでSetFocusをすればいいのでしょうか?
0083デフォルトの名無しさん2005/07/15(金) 13:44:21
あっ、書き込めてないと思って2重カキコしてしまいました。すいません・・・
0084デフォルトの名無しさん2005/07/15(金) 14:57:53
>>82
OnInitDialog()のテンプレートにはコメントがついていると思うのだが、
そこには何と書いてあるかな?
0085デフォルトの名無しさん2005/07/15(金) 16:04:25
とりあえず自己解決策を見出してみたのですが、
>84さんのやり方のほうが簡単だとおもって
戻り値をFALSEに代えてみたけどちょっと動作が不安定なのです・・・
入力フォーカスが行ったり行かなかったりします。(大概いかない)
もしよければ詳しく教えてもらえませんか?

OnInitDialogで

GetDlgItem(ID)->SetFocus();
return FALSE;

とやると、一旦はフォーカスが行くようですが、
そのあとKillFocusが呼ばれ、フォーカスは目的の場所には行っていません。
当然SetFocusをやらなければKillFocusも呼ばれないのですが。
0086デフォルトの名無しさん2005/07/15(金) 17:40:26
viewのOnInitialUpdate()のタイミングでViewがアクティブになり
ダイアログからフォーカス奪うからだめでしょう。
そのタイミングでダイアログをアクティブにするため
PostMessageすればよろし。
0087デフォルトの名無しさん2005/07/15(金) 19:44:30
こんばんわ。

MFCで、リソースからダイアログを生成したのですが、
再描画がうまくされない不具合があります。

なぜなのでしょうか?

ちなみに、再描画されないリソースダイアログは、親のダイアログの子としてCreate生成しております。
0088デフォルトの名無しさん2005/07/15(金) 20:21:30
再描画がうまくされないとは?
0089872005/07/15(金) 20:26:31
かいけつしました
0090872005/07/15(金) 20:28:37
ありがとうございます。

具体的には、親のダイアログの子としてCreateすると、
子ダイアログの後ろにある、親の背景が透けて見えるという
感じです。コンパイルは成功するのですが、描画だけおかしくて。
問題点を教えてもらえればありがたいです。
0091デフォルトの名無しさん2005/07/15(金) 20:29:55
それは、ダイアログリソースの可視にチェックを入れている
せいだろう。チェックを外してみるが良し。
0092872005/07/15(金) 20:31:07
>>91さん
ビンゴでした。どうもありがとうございました。
0093872005/07/15(金) 20:58:52
可視を消したら全部消えちゃった
0094デフォルトの名無しさん2005/07/15(金) 21:09:23
>>93
当たり前だろ
0095デフォルトの名無しさん2005/07/15(金) 22:03:44
>>91は詐欺師
0096デフォルトの名無しさん2005/07/16(土) 01:04:36
強制的に対象ダイアログに対してInvalidate()なりUpdateWindow()なり
RedrawWindow()なりやってみる。
0097742005/07/16(土) 01:24:20
さっそくためさせていただきました。
結論から言うと>>77でも>>78さんのやり方でもできましたが、>>77で書いた問題はどちらもありました。
で、その問題はなぜ起きるかと言うと、UpdateDataの契機でIDC_EDITもIDC_EDIT2も
最初の行にスクロールして戻ってしまうからでした。
よって
CXXXDlg::OnAddString()
CXXXDlg::OnAddString2()
のいずれのハンドラでもIDC_EDIT、IDC_EDIT2の両方に対し、最後の行に移動する処理を書く必要があったみたいです。

もっとうまい方法がある気がしますが、自分はこの辺でやめときます。
(キャレットを最後に移動させておくとかするとUpdateDataで最初の行に戻らないのかも??)
0098782005/07/16(土) 01:47:39
>>97
あー、そりゃDDXで全てやろうとするからだ。
私の場合は処理速度の問題もあったからReplaceSel()で追加しているんで
UpdateData()までは気付かなかったよ。
0099デフォルトの名無しさん2005/07/16(土) 08:51:57
>>87
子ウィンドウをクリップにチェック
0100742005/07/16(土) 09:49:33
>>98
ReplaceSel()を使うのですか。またひとつ勉強になりました。
0101822005/07/16(土) 11:54:45
>86
そうか。PostMessageもありましたね。
自分の解決策は、Appのイニシャライズで無理矢理SetFocusをする方法でした。
なぜフォーカスを奪われてしまうところの解決策はなさそうですね。
とりあえず解決しております。分からないこともありますが・・・
ありがとうございました。
■ このスレッドは過去ログ倉庫に格納されています