SplitterWndでの分割バー無効にしたい

[戻る]
Nao 2007/06/27(水) 15:40:29
Naoと申します。

ただ今、VisualStudio2005のMFCにおいてSDIプログラムを作成しています。

CSplitterWndを使用して、4分割いたしました。
現在は4分割という事で、分割バーは3つあるのですが、その内の一本は固定したいのです。

その分割バーに対してWM_LBUTTONDOWNを無効にするやり方で出来そうなのですが、
その分割バーだけを無効にする方法はどのようにすればいいのでしょうか?

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

Blue 2007/06/27(水) 16:16:39
4分割しているということなので、
CMainFrameクラスでCSplitterWnd型のメンバ変数を3つ用意しているのではないでしょう
か?

その中のひとつを(WM_LBUTTONDOWN,WM_MOUSEMOVEをインプリメントした)CSplitterWndを
派生したクラスに変更してあげればいいだけでうまくいくと思います。

たいちう 2007/06/27(水) 16:25:30
方法1
WM_LBUTTONDOWNが来た時に、カーソルの座標とペインの幅や高さを元に、
計算すればどのバーか判断できそう。

方法2
CSplitterWndをサブクラス化して、バーが必ず無効になるクラスを作る。
そのペインに通常のCSplitterWndを入れてやれば、一本だけ固定された
バーが得られるでしょう。私だったらこの方法でやります。

ご参考
http://athomejp.com/goldfish/mfc/cobject/3viewwindow.asp
http://athomejp.com/goldfish/mfc/cobject/nomove.asp

Nao 2007/06/27(水) 16:46:06
Blueさん たいちうさん 
回答してくださってありがとうございます。

Blueさん

>4分割しているということなのでCMainFrameクラスでCSplitterWnd型のメンバ変数を3つ
用意しているのではないでしょうか?

はい。Blueさんのおっしゃる通りです。MainFrame.hの中において、

CSplitterWnd m_wndSplitter1,m_wndSplitter2,m_wndSplitter3

とメンバ変数を用意しております。

>その中のひとつを(WM_LBUTTONDOWN,WM_MOUSEMOVEをインプリメントした)CSplitterWndを
派生したクラスに変更してあげればいいだけでうまくいくと思います。

すみません。間違っているかも知れませんが、自分が思った事を記載します。

CSplitterWnd m_wndSplitter1,m_wndSplitter2
CSplitterWnd1(カスタム)m_wndSpliter3

このようにするという事でしょうか?

たいちうさん

方法2の
>CSplitterWndをサブクラス化して

この部分ですが、Blueさんのおっしゃっている[インプリメントした]という意味で
しょうか?
勉強不足ですみません。もし同じでしたらこの方法を試してみます。

Blue 2007/06/27(水) 16:49:37
> このようにするという事でしょうか?
そうです。
一度試してだめだったら質問してください。
やらないで質問は無駄が多くなりますので。

Nao 2007/06/27(水) 18:13:41
>一度試してだめだったら質問してください。
やらないで質問は無駄が多くなりますので。

申し訳ありませんでした。以後気をつけます。

上手く行きませんでした。やった手順を記載します。

@新しいクラスとしてCSplitterWnd1というクラスを追加しました。

ACSplitterWnd1のメンバ変数として、m_wndSplitter2を追加しました。

BCSplitterWnd1のイベントとして、WM_LBUTTONDOWNを追加して、この関数の中の
記述をコメントアウトしました。

たいちうさんの参考リンクではこのような感じだったので、真似をしてみました。
でも分割バーは動いてしまいます。

このように記述しました。

MainFrame.h内

CSplitterWnd    m_wndSplitter,m_wndSplitter1;  ///変更前m_wndSplitter2があった
CSplitterWnd1   m_wndSplitter2; ///追記した部分

MainFrame.cpp内


BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
if(!m_wndSplitter.CreateStatic(this,1,2))
        return FALSE;

if(!m_wndSplitter1.CreateStatic(&m_wndSplitter,2,1,WS_CHILD | WS_VISIBLE |   
   WS_BORDER,m_wndSplitter.IdFromRowCol(0,1)))
    return FALSE;

if(!m_wndSplitter2.CreateStatic(&m_wndSplitter1,2,1,WS_CHILD | WS_VISIBLE |   
  WS_BORDER,m_wndSplitter1.IdFromRowCol(1,0)))
    return FALSE;

    if(!m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(C***lView),CSize(120,100),pContext)
||
!m_wndSplitter1.CreateView(0,0,RUNTIME_CLASS(C***View),CSize(100,200),pContext) ||
    !m_wndSplitter2.CreateView(0,0,RUNTIME_CLASS(C***View),CSize(100,40),pContext) ||
    !m_wndSplitter2.CreateView(1,0,RUNTIME_CLASS(C***View),CSize(100,150),pContext))
    {
        m_wndSplitter.DestroyWindow();
        return FALSE;
    }

    return TRUE;
}

このような感じになっているのですが、分割バーを固定したい部分は
!m_wndSplitter2.CreateView(1,0,RUNTIME_CLASS(C***View),CSize(100,150),pContext)
のペインなのですが、普通に動いてしまいます。

どのようにすれば、いいのでしょうか?
長くなってしまいましたが、宜しくお願いいたします。

たいちう 2007/06/27(水) 18:30:36
私の方法2はBlueさんの方法とかぶってしまいましたね。同じ意味です。

> たいちうさんの参考リンクではこのような感じだったので、真似をしてみました。
> でも分割バーは動いてしまいます。

とりあえず、入れ子にしないで(CSplitterWnd1のみで)、
動かないようにはできましたか?

> CSplitterWnd1のメンバ変数として、m_wndSplitter2を追加しました。

CSplitterWndとそのサブクラスのインスタンスは、
CMainFrameのメンバ変数にするのが良いと思います。

# 入れ子のSplitter Windowを1つのクラスと考えて設計すると、
# 内側は外側のメンバ変数とすべきかもしれませんが、
# まず、サンプルに近い形で完成させて、
# 余力があれば、カプセル化を進めましょう。

Nao 2007/06/27(水) 22:09:11
たいちうさんご回答ありがとうございます。

たいちうさんの前の回答に2番目に貼ってあったリンク(2分割でもバー無効)
も出来ませんでした。

一度プロジェクトを作成し直してシンプルにそのリンクの内容を実行しましたけど、
分割バーは固定されませんでした。

/////////////2分割ソース///////////////////////////

〜CMainFrame.h内〜

CSplitterWnd      m_wndSplitter1;

〜CMainFrame.cpp内〜

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
   if (!m_wndSplitter1.CreateStatic(this, 1, 2)) return FALSE;

   
   if (!m_wndSplitter1.CreateView(
      0,0,
      RUNTIME_CLASS(CSplitter1View),
      CSize(100,100), pContext)) return FALSE;

      if (!m_wndSplitter1.CreateView(
      0, 1,
      RUNTIME_CLASS(CSplitter1View),
      CSize(0,0), pContext)) return FALSE;

   return TRUE;
}
////////////////////////////ここまで//////////////////////////

///////////////////リンク先の作業////////////////////////////

@新しいクラスを作成しました。作成したクラスCSplitterWndOrgに対して

〜SplitterWndOrg.h内〜

class CSplitterWndOrg : public CSplitterWnd /////CWndをCSplitterWndに変更

〜SplitterWndOrg.cpp内〜

BEGIN_MESSAGE_MAP(COrgSplitterWnd,CSplitterWnd); 上記と同じ変更

ACSplitterWndOrgのイベントにWM_LBUTTONDOWNを追加しました。

void COrgSplitterWnd::OnLButtonDown(
                    UINT nFlags, CPoint point)
{
    
    //CSplitterWnd ::OnLButtonDown(nFlags, point);  ///コメントアウトしました。
}

これで一応バーは動かなくなると記載されているのですが、動いてしまいます。

  なにか記述が足りないのでしょうか?
  ご教授していただけますでしょうか?宜しくお願いいたします。

Blue 2007/06/27(水) 23:18:56
>これで一応バーは動かなくなると記載されているのですが、動いてしまいます。

>CSplitterWnd      m_wndSplitter1;
を
CSplitterWndOrg  m_wndSplitter1;
に書き換えていますか?

Nao 2007/06/28(木) 10:44:59
>CSplitterWndOrg  m_wndSplitter1;
に書き換えていますか?

この部分を書き換えていませんでした。

MainFrm.h内の
CSplitterWnd   m_wndSplitter1を  CSplitterWndOrg   m_wndSplitter1に変更した
所、エラーが発生しました。

mainfrm.h(42) : error C2146 構文エラー ';'が識別子'm_wndSplitter1'の前に必要です。
mainfrm.h(42) : error C4430 型指定子がありません -intと仮定しました。
mainfrm.h(112) : error C2065 'm_wndSplitter1': 定義されていない識別子です。


mainfrm.h(42)  CSplitterWndOrg m_wndSplitter1 //// この場所

mainfrm.h(112) if(!m_wndSplitter1.CreateStatic(this,1,2)) return FALSE //この場所

こんな感じのエラーが出てしまいヘッダファイルのインクルードし忘れかと思い、
新しく作ったクラスとMainFrm.h内に新しく作成したクラスのヘッダファイルをインク
ルードしたのですが、エラーが増減しませんでした。

宜しくお願いいたします。

Blue 2007/06/28(木) 10:56:00
>エラーが発生しました。
ヘッダファイル(SplitterWndOrg.h)をインクルードしていますか?

インクルードしないと、CSplitterWndOrgが何者かはCMainFrameで
理解できないので当然エラーになります。
# ちゅうか、基本なのでは?

Blue 2007/06/28(木) 10:59:04
すみません、読み落としていたようです。
>こんな感じのエラーが出てしまいヘッダファイルのインクルードし忘れかと思い、
>新しく作ったクラスとMainFrm.h内に新しく作成したクラスのヘッダファイルをインク
>ルードしたのですが、エラーが増減しませんでした。
本当にそうですか?
リビルドしても同じですか?
インクルードしているファイルは正しいですか?
(SplitterWndOrgの定義の書かれていないヘッダファイルではないか?)

Nao 2007/06/28(木) 12:44:36
Blueさん

多分

〜SplitterWndorg.h内〜


IMPLEMENT_DYNAMIC(CSplitterWndOrg,CWnd)

CSplitterWndOrg::CSplitterWndOrg()
{
}

CSplitterWndOrg::~CSplitterWndOrg()
{
}

BEGIN_MESSAGE_MAP(CSplitterWndOrg,CSplitterWnd)
                 ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

void CSplitterWndOrg::OnLButtonDown(UINT nFlags,CPoint point);
{

     //CSplitterWnd::OnLButtonDown(nFlags,point);

}

このような感じになっているCSplitterWndOrg.hをMainFrm.cppにインクルード
しているのですが、何か間違っているでしょうか?
宜しくお願いいたします。

Blue 2007/06/28(木) 13:01:13
>〜SplitterWndorg.h内〜
ってSplitterWndorg.cppではないでしょうか?

class CSplitterWndOrg : public CSplitterWnd

と記述があるファイルをインクルードしないとだめですよ?

たいちう 2007/06/28(木) 13:04:54
class CSplitterWndOrg : public CSplitterWnd となっているのなら、
1つ間違い見っけ。

× IMPLEMENT_DYNAMIC(CSplitterWndOrg,CWnd)
○ IMPLEMENT_DYNAMIC(CSplitterWndOrg,CSplitterWnd)

その他のマクロも、チェックしてください。

Nao 2007/06/28(木) 13:22:43
Blueさん たいちうさん

ご回答ありがとうございます。

Blueさん

 すみません。先ほど記述したファイルはcppファイルでした。ヘッダファイルの中身は

 #pragma once

 class CSplitterWndOrg : public CSplitterWnd
{
    DECLARE_DYNAMIC(CSplitterWndOrg)

   public:
         CSplitterWndOrg();
         virtual ~CSplitterWndOrg();

  protected:
         DECLARE_MESSAGE_MAP()
  public:
         afx_msg void OnLButtonDown(UINT nFlags,CPoint point);
};
 
  このようになっております。何かおかしいでしょうか?
 宜しくお願いいたします。

たいちうさん

先ほどのcppファイルの中身のIMPLEMENT_DYNAMIC(CSplitterWndOrg,CWnd)
のところをIMPLEMENT_DYNAMIC(CSplitterWndOrg,CSplitterWnd)
に変更いたしました。

エラーの数と内容はまったく変わりませんでした。

どうすればいいでしょうか?宜しくお願いいたします。
 

ITO 2007/06/28(木) 13:25:46
VCについている「編集」→「置換」の機能を使うと便利です。
CDialog→CDialogBarにかえる時など使っています。

#「CSplitterWnd」を使ったサンプルを比べると間違えも見つかると思います。
# 付属のMSDN CDにもあります。
# わざわざネットで検索しなくても大丈夫です。

たいちう 2007/06/28(木) 13:31:49
今、VS2003で試してみましたが、IMPLEMENT_DYNAMICが間違っていても、
バーは固定されていました。

>> すみません。先ほど記述したファイルはcppファイルでした。ヘッダファイルの中身は

ヘッダファイル は、SpliterWndOrg.hで間違いないですか?

MainFrm.h の内容は、以下のようになっていますか?

#pragma once
#include "SpliterWndOrg.h"
class CMainFrame : public CFrameWnd
{
    CSplitterWndOrg m_wndSplitter1;
    ...

ファイル名などに間違いがないか、もう一度落ち着いて確認してください。

Nao 2007/06/28(木) 13:42:13
ITOさん たいちうさん

ご回答ありがとうございます。

ITOさん

>VCについている「編集」→「置換」の機能を使うと便利です。
CDialog→CDialogBarにかえる時など使っています。

次回から間違えの無いように、そのようにやりたいと思います。
アドバイスありがとうございます。

たいちうさん

>ファイル名などに間違いがないか、もう一度落ち着いて確認してください。
MainFrm.h内で

    #include "SplitterWndOrg.h"をインクルードし忘れてしました。

  きちんと分割バーは固定させました。すみません。
  アドバイスありがとうございました。

これで、ネスト前の分割バーの固定は終了したのですが、本来の質問のネストした
分割バーはまだ解決していませんので、このまま続けて宜しいのでしょうか?

たいちう 2007/06/28(木) 13:50:42
> このような感じになっているCSplitterWndOrg.hをMainFrm.cppにインクルード
> しているのですが、何か間違っているでしょうか?
> 宜しくお願いいたします。

やっと状況がわかった。↑のときは、MainFrm.cppで、
MainFrm.hの後に、CSplitterWndOrg.hをインクルードしていたんだね。

// MainFrm.cpp

#include "MainFrm.h"
#include "CSplitterWndOrg.h"

の順だと、コンパイラがMainFrm.cppをコンパイルする時には、
CSplitterWndOrgの宣言の前に、CMainFrameの宣言でCSplitterWndOrgが
使われてしまう。

ヘッダファイルでインクルードしないのならば、
ソースファイルのインクルード順も気をつけましょう。

> これで、ネスト前の分割バーの固定は終了したのですが、本来の質問のネストした
> 分割バーはまだ解決していませんので、このまま続けて宜しいのでしょうか?

宜しいのではないのでしょうか。

Nao 2007/06/28(木) 14:16:17
[[解決]]
たいちうさん

>#include "MainFrm.h"
>#include "CSplitterWndOrg.h"

たしかにお恥ずかしいですがこのように記述していました。

今気づいたのですが、VisualStudioなどでは

#include "C***.h"
#include "C****.h"
#include "C*****.h"
                      /////ここの領域をわざわざあけているのはこの間にインクルード
              しなさいという事だったんすね・・。
#include "MainFrm.h"

以後、気をつけます。

ネスト分割の方なのですが、たいちうさん Blueさんのおかげで基礎のネストなし分割
の方法を落ち着いてやってみたら出来ました。

すごく長い間、ご教授してくださりありがとうございました。
また何かありました時は、宜しくお願いいたします。

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