ダイアログのスクロールについて

[戻る]
りこ 2010/01/08(金) 11:59:33
環境:WinXP,VC++6.0 MFC ダイアログベースです。

こちら↓
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200808/08080015.txt

に私と全く同じ質問があるのですが、bunさんが「参考に」と
http://aventech.hp.infoseek.co.jp/Test.zip

とURLの記載をされておられるのですが、なくなっていて取得出来ません・・・。

基本的に行いたいことは上記記載の別質問の方と同じなのですが、参考になるサイトや
サンプルコードがございましたらご教授お願いいたしますm(__)m

りこ 2010/01/08(金) 12:17:39
追加質問すいません、同じ質問ページ内で仲澤@失業者さんが

「
こういったケースの一般的な方法は、

  親DLGのクライアントに「全てのコントロールを持つ、親より大きい子DLG」
  を配置して「子DLG」ごとスクロールする

が一般的です。この方法の良いところは
 1.実装が簡単。コードが少ない。
 2.子DLGの変更が親の仕様に(強く)影響しない(ように実装できる)。
 3.縦横スクロール自由自在。
 4.親がDLGでなくても良い。
 5.スクロールしたくないコントロールは親に配置すればよい。
 6.数回程度なら、この仕組みをネストできる。

ではがんばってください。
」
と記載されておられる方法で行ってみようと思うのですが、
リソースは親DLGと子DLGを作成して、
親DLGの表示時に子DLGも表示するのでしょうか?
DLGをDLGに「配置する」というのがよく分からないです・・・。

PATIO 2010/01/08(金) 13:36:41
参考にされているスレッドに実装イメージが説明されていますが、
それでは分からないでしょうか?

> CTestDlg::OnInitDialog()から
> スクロールビュー(CTestScrollView)を作成し、
> 
> CTestScrollView::OnCreate()から
> 内部ダイアログ(CInnerDlg)を作成しています。

CTestDlgが土台のダイアログ、その上にCTestScrollViewを生成して
CTestScrollViewのOnCreateでCInnerDlg(コントロールが載った物)を
作成すると書いてあります。
この場合、CInnerDlgはタイトルバーもウインドウ枠も無い物になるでしょう。

わからないのであれば、どの部分が分からないのかを説明した方が
レスもつきやすいと思います。

りこ 2010/01/08(金) 13:46:29
ご回答ありがとうございます。

分からないのは
>CTestDlgが土台のダイアログ、その上にCTestScrollViewを生成して
>CTestScrollViewのOnCreateでCInnerDlg(コントロールが載った物)を
>作成すると書いてあります。

この具体的な方法が分からないです。



リソースは
・親ダイアログ(CDialog)
・子ダイアログ(CScrollView)

の2つ作成する、という事で正しいでしょうか?

また、親ダイアログのCTestDlg::OnInitDialog()から
どうやって「スクロールビュー(CTestScrollView)を作成」するのでしょうか?

細かい作法などを含め思いっきり初心者なので、サンプルコードが欲しかった
という思いがあります・・・。

りこ 2010/01/08(金) 13:56:52
あ・・・あと、環境についてなんですが、VC++6.0ではなくてVC++2005でした><
すいません、訂正させていただきます。

PATIO 2010/01/08(金) 14:04:11
あー、そういう状況だとウインドウを自分で起こす所から
勉強しないと駄目ですね。
ウィザード等では出来ないので自分でコードを書かないといけません。
あと、サンプルソースをもらっても一つ一つのコードが何をしているのか、
何の為にそこに記述されているのかと言った事が理解できないと
応用が利かないので結構厳しいです。

ちなみにですが、リソースを作成する必要があるのはダイアログの場合だけです。
スクロールビューはダイアログでは有りません。
ダイアログもビューもウインドウの一種ですが、
使用する場面が全く違います。

親ダイアログの上にスクロールを処理する為のウインドウをのっけて
そのスクロールを処理するウインドウの中に実際のコントロールが
のっかったダイアログがはまり込むイメージです。
単純にダイアログの上にダイアログを載せてもそれだけではスクロールできません。

で、ある程度は試行錯誤するとしてまずはダイアログの上にスクロールビューを
載せると言う部分のコードにチャレンジして見てはどうでしょう。
親ダイアログを親にしてスクロールビューをCreateする流れになります。

基本的なWindowsの知識がある程度あれば良いのですけれど、
いきなりサンプルで何とかしようとするとハマル事が多いので
基本形に関してはちゃんとやって見てからの方がいいカナと思います。

りこ 2010/01/08(金) 14:10:00
PATIOさん
ありがとうございます。

>あー、そういう状況だとウインドウを自分で起こす所から
>勉強しないと駄目ですね。

重々承知しておりますが、ゆっくり勉強している時間がないもので・・・
サンプルがあれば、細かく何をしているかが分からなくても何とかなるかと
思っているのですが・・・。

>親ダイアログを親にしてスクロールビューをCreateする流れになります。
イメージは大体分かりましたが、いざ実装しようと思うとサッパリな状況です。

とにかく試行錯誤してみます・・・・

maru 2010/01/08(金) 14:26:54
> サンプルがあれば、細かく何をしているかが分からなくても何とかなるかと
> 思っているのですが・・・。
サンプルがあっても、そのサンプルの大体の動作が理解できて、どの部分を自分の
アプリケーションに持ってくればよいかを理解する力がなければ、何ともなりません。
つまり、
> あと、サンプルソースをもらっても一つ一つのコードが何をしているのか、
> 何の為にそこに記述されているのかと言った事が理解できないと
> 応用が利かないので結構厳しいです。
という状態に陥るはめになります。

> 細かい作法などを含め思いっきり初心者なので、サンプルコードが欲しかった
> という思いがあります・・・。
という状態では、まずマイクロソフトのサンプルプログラムから勉強した方がよいで
しょう。
http://msdn.microsoft.com/ja-jp/library/hyds2fy1(VS.80).aspx
に色々なサンプルプログラムがあります。
まずはここでWindowsプログラムの基本からかな。

PATIO 2010/01/08(金) 14:56:46
時間が無いのは皆同じだと考えた方が良いかもしれません。
あと、基礎知識だけでも勉強される事をお勧めします。
結果的には勉強したおいた方が最終的に短時間で対応できたと
言う事になるような気がするので。
サンプルコードの継ぎ接ぎでやってしまうと
結局自分でメンテできないコードになりかねません。
結果的に勉強した場合よりもトータルで時間が掛かると言う事にもなりかねません。

ここから先はご自身の判断になると思いますので
強要は出来ないと思いますが、私個人としては多少回り道に見えても
勉強する事をお勧めします。

仲澤@失業者 2010/01/08(金) 15:07:56
親を win_Parent 子をwin_Child とすると

1.win_Parent をCreate()
2.win_ParentのOnCreate()でwin_Parentを親にしてwin_Child を作成する

のが、最初です。
win_Child を作るときはWS_CHILDスタイルを指定しなければなりません。
とりあえずここまでできなければ始まりませんね。

親はクライアントエリアを持つものを指定、子は何でも良いですが、
面倒ならばCButtonでも良いですよ。
あとで、最終的な物に差し替えればよいのです。

>サンプルがあれば、細かく何をしているかが分からなくても何とかなるかと
>思っているのですが・・・。

なんか「ググるな危険」のようですね(vv;)。

りこ 2010/01/08(金) 16:28:53
とりあえず、親をCDialogで、子をFormViewで作成することにしました。


親ダイアログをcreateしました。(これのみで確認しました)

親ダイアログのOnInitDialog内でCFormViewをCreateすると、
「viewform.cpp」の
    // dialog template must exist and be invisible with WS_CHILD set
    if (!_AfxCheckDialogTemplate(m_lpszTemplateName, TRUE))
    {
        ASSERT(FALSE);          // invalid dialog template name
        PostNcDestroy();        // cleanup if Create fails too soon
        return FALSE;
    }
にひっかかってしまい、ASEERT(FALSE)の箇所で例外にされてしまいます・・・。

ダイアログのテンプレート名というのは、子のリソースIDの事?だと思うのですが、
子をCreateする際には

    m_pChildView->Create(NULL,NULL, 
        WS_VISIBLE|WS_CHILD|WS_EX_CLIENTEDGE|WS_BORDER |
        WS_HSCROLL| WS_VSCROLL ,rect,this,nID,&context);

の「nID」にリソースIDが入れています。
(他にも変数がありますが・・・)

何がおかしいのか不明です・・・

りこ 2010/01/08(金) 16:37:35
自己解決しました。

子のリソースプロパティでstyleを「子」にしていなかったからでした。

とりあえず画面に出るようにはなったのですが、
スクロールバーが出てきません・・・。

この方法は間違っているのでしょうか???

maru 2010/01/08(金) 17:12:45
> とりあえず画面に出るようにはなったのですが、
「何が」画面に出るようになったのでしょうか?
親ダイアログの中にFormViewが出るようになったってこと?

> スクロールバーが出てきません・・・。
期待しているのは親ダイアログにスクロールバーを出すことですよね?
この子はCFormViewから作成されていて、CFormViewはCScrollViewから派生しているの
で、CScrollView::SetScrollSizes()を使用して適切な引数を渡せばスクロールバーが
表示されますが、それは子のほうで、親ではありません。

> CTestDlg::OnInitDialog()から
> スクロールビュー(CTestScrollView)を作成し、
> 
> CTestScrollView::OnCreate()から
> 内部ダイアログ(CInnerDlg)を作成しています。
をよく読んでください。これは
> ・親ダイアログ(CDialog)
> ・子ダイアログ(CScrollView)
の他に孫ダイアログであるCInnerDlgがあるのです。ここでCTestDlgはスクロールバー
を持つ親として使用しているのでなく、目的とするダイアログボックスのテストドラ
イバになっているのです。どこにスクロールバーがほしいのか、その為にはどのクラ
スを使用するのが良いかを考えないと何をやっているのか分からなくなります。
試行錯誤も良いですが、自分のコードが何をやっているのか理解しないと時間がかか
るだけですよ。

りこ 2010/01/08(金) 17:39:49
>「何が」画面に出るようになったのでしょうか?
>親ダイアログの中にFormViewが出るようになったってこと?

はい、そうです。

>期待しているのは親ダイアログにスクロールバーを出すことですよね?
>この子はCFormViewから作成されていて、CFormViewはCScrollViewから派生しているの
>で、CScrollView::SetScrollSizes()を使用して適切な引数を渡せばスクロールバーが
>表示されますが、それは子のほうで、親ではありません。

子でも構わないです^^

行いたいのは、スクロール機能を持つ画面に複数(40個くらい)のコントロールを配
置して、縦スクロールで表示させる、といった事です。

りこ 2010/01/08(金) 18:23:36
子のFormViewを触る(viewの範囲をクリック等)と落ちてしまいます・・・。

VIEWCORE.CPPの249行目↓

int CView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
    int nResult = CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
    if (nResult == MA_NOACTIVATE || nResult == MA_NOACTIVATEANDEAT)
        return nResult;   // frame does not want to activate

    CFrameWnd* pParentFrame = GetParentFrame();
    if (pParentFrame != NULL)
    {
        // eat it if this will cause activation
        ASSERT(pParentFrame == pDesktopWnd || pDesktopWnd->IsChild
(pParentFrame));

        // either re-activate the current view, or set this view to 
be active



ASSERTの箇所みたいですが、原因が分かりません・・・

maru 2010/01/08(金) 18:48:00
> 子でも構わないです^^
話がごちゃごちゃですよ。

ダイアログにコントロールがいっぱいあってスクロールしないといけない
->ダイアログボックスをスクロールバー付きにして、スクロールイベントに対して
コントロールを移動させればよい。
->コントロールが多く、移動させるのが面倒。
->大きなダイアログ(子)を作って、それを別のスクロールバーつきダイアログ
(親)に乗せて、親のスクロールイベントに対して、その子を移動する。
という関係で親子の話をしているんだと思っていましたが。

そもそもスクロールしなければならないほどコントロールがいっぱいあるダイアログ
なんて設計を疑うべきです。コントロールのグループを分けてプロパティシートにす
るとか、ダイアログを小さくする手段はいくらでもあります。
わざわざ実装を難しくして悩む必要が本当にあるんですか?
(本当に実装が難しいかはやってみていないのでよくわかりませんが。)

ユーザインターフェースを考え直すことをお勧めいたします。

りこ 2010/01/08(金) 19:02:13
>話がごちゃごちゃですよ。

すいません・・・。

>ダイアログにコントロールがいっぱいあってスクロールしないといけない
>->ダイアログボックスをスクロールバー付きにして、スクロールイベントに対して
>コントロールを移動させればよい。

これで十分かもしれないです。
この方法で参考になるサイト等ご存知でしたら教えてくださいm(__)m

設計というか要望なのでどうしようもないんです・・・。

りこ 2010/01/08(金) 20:09:14
まとめます。

「触ると落ちる」というのは解決しました。
ここで言っている「親」というのも実は子で、プロパティで「子」を設定すれば大丈夫
でした。

現在、CDialog(親)をCreateして、そのOnInitDialog()の中でさらに子をCreateしてい
ます。

子はFormViewです。

Create後に子のOnInitialUpdate()を呼び、そこで
    CRect rect;
    SIZE sz;

    GetClientRect( rect );

    sz.cy = rect.bottom -rect.top;
    sz.cx = rect.right -rect.left;

    SetScrollSizes(MM_HIMETRIC,sz);

このようにしているのですが、スクロールが表示されないという所で詰まっています。

FormViewであればSetScrollSizesでスクロールが表示されると思ったのですが・・・。
(もちろん、リソースのプロパティでスクロールもONにしております)

何か不備がありそうな箇所がございましたらご指摘お願いいたします。

ITO 2010/01/09(土) 10:42:17
うーん、
何か話が難しくなってきますね。
このままうまくいっても、基本をうまく設計しておかないと、
何らかのタイミングで「HWND == NULL」等の例外で異常終了する可能性
がありますね。

もう少し単純に考えて、ウインドウをFormViewのSDI一つにしてそこに
スクロールバーを配置してそれに連動して動くようにすればいいと思いますが....
maruさんが先に提案していましたね。

> 設計というか要望なのでどうしようもないんです・・・。
もし、顧客かやの仕様でなく要望ならまだ相談の余地が残っていると思います。

PATIO 2010/01/18(月) 10:54:57
どういう事がしたくて一画面のスクロールで無いと困ると
言われているのかを考えないと説得するにしても説得のしようが無いかなと。

一画面のスクロールで対応したいと言うからには
そういう画面で無いと困る理由があるのではないかと思います。
ところが、実際にはこう言うレイアウトにした方が見やすいし、
使いやすいですよと言う提案をする余地もあると思うので
そういう提案が出来てお客さんもハッピーになれるなら
必ずしも要望と全く同じ方法である必要は無いのではないかなと思います。

逆にどうしても一画面に全て載せてスクロールで何とかしないと
不可能な理由があれば、何とか知恵を絞ってでも対応してあげないと
いけないという事になると思うのですけれど。

りこ 2010/01/18(月) 11:14:16
[[解決]]
スクロールは、SetScrollSizesの引数のサイズで表示できました。
また、ダイアログのプロパティでStyleを「オーバーラップ」にすることで触れるように
なりました。

ITO 2010/01/19(火) 09:38:17
> また、ダイアログのプロパティでStyleを「オーバーラップ」にすることで触れる
> ようになりました。
解決したようですが、いろいろな操作をしてデバッグすることを薦めます。
複雑なウインドウの処理を行なうと思いがけないところで例外の異常終了が起きて
しまうので注意が必要だと思います。

古いスレッドには追加発言できません。