CScrollBarクラスのインスタンスができない?

[戻る]
ソイレントグリーン 2008/02/17(日) 10:16:14
いつもお世話になっています。
申し訳ございません、連投になりますが宜しくお願いします。

【環境】
Windows  XP SP2 / VisualStudio2005 MFC使用(スタテックライブラリ使用、SJIS)

【実装手順】
・MFC新しいプロジェクトより、ダイアログベースのアプリケーションを作成
・ダイアログのプロパティーの設定よりHorizontal ScrollBarを追加
・同じくOnHScrollを追加
・MSDNを参考に、スクロールバーを移動するために下記のように実装
http://msdn2.microsoft.com/ja-jp/library/e14hhbe6(VS.80).aspx

【問題点】
CScrollBarクラスから作ったpScrollBarインスタンスを操作すると未定義のエラーが発生
します。
Scroll.exe の 0x0051f61a でハンドルされていない例外が発生しました: 0xC0000005: 
場所 0x00000020 を読み込み中にアクセス違反が発生しました。

【確認したこと】
デバッガーでpScrollBarを確認すると、{CWnd hwnd=???}となっていてインスタンスが生
成されていない
(pScrollBarが NULLの状態)のではないかと思われる?

【やりたいこと】
スクロールバーをクリックしたら、スクロールバーを移動したい

【実装】
void CScrollDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
  // TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出しま
す。
  // Get the minimum and maximum scroll-bar positions.
  int minpos;
  int maxpos;
  pScrollBar->GetScrollRange(&minpos, &maxpos);  // ここでアクセスバイオレーショ
ン
  maxpos = pScrollBar->GetScrollLimit();

  // Get the current position of scroll box.
  int curpos = pScrollBar->GetScrollPos();

  // Determine the new position of scroll box.
  switch (nSBCode)
  {
  case SB_LEFT:      // Scroll to far left.
    curpos = minpos;
    break;

  case SB_RIGHT:      // Scroll to far right.
    curpos = maxpos;
    break;

  case SB_ENDSCROLL:  // End scroll.
    break;

  case SB_LINELEFT:    // Scroll left.
    if (curpos > minpos)
       curpos--;
    break;

  case SB_LINERIGHT:   // Scroll right.
    if (curpos < maxpos)
       curpos++;
    break;

  case SB_PAGELEFT:    // Scroll one page left.
  {
    // Get the page size. 
    SCROLLINFO   info;
    pScrollBar->GetScrollInfo(&info, SIF_ALL);
  
    if (curpos > minpos)
    curpos = max(minpos, curpos - (int) info.nPage);
  }
    break;

  case SB_PAGERIGHT:    // Scroll one page right.
  {
    // Get the page size. 
    SCROLLINFO   info;
    pScrollBar->GetScrollInfo(&info, SIF_ALL);

    if (curpos < maxpos)
       curpos = min(maxpos, curpos + (int) info.nPage);
  }
    break;

  case SB_THUMBPOSITION: // Scroll to absolute position. nPos is the position
    curpos = nPos;       // of the scroll box at the end of the drag operation.
    break;

  case SB_THUMBTRACK:    // Drag scroll box to specified position. nPos is the
    curpos = nPos;       // position that the scroll box has been dragged to.
    break;
  }

  // Set the new position of the thumb (scroll box).
  pScrollBar->SetScrollPos(curpos);
  CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}

瀬戸っぷ [E-Mail] 2008/02/17(日) 14:26:22
>デバッガーでpScrollBarを確認すると、{CWnd hwnd=???}となっていてインスタンスが生
>成されていない(pScrollBarが NULLの状態)のではないかと思われる?

MSDNには

 pScrollBar
    スクロール バー コントロールからメッセージが送られた場合は、コントロールへの
ポインタになります。ユーザーがウィンドウのスクロール バーをクリックした場合は、
このパラメータは NULL になります。このポインタは一時的である場合があるので、後で
使用するために保持しておくことはできません。

と書かれています。
Windwsメッセージのハンドラを用意しただけで、CScrollBarを構築する処理はどこにもあ
りませんから
インスタンスが精製されないのも致し方ないかと。

CScrollBarは使用できませんが、CWnd::GetScrollRange()等が利用できるかと思います。

ソイレントグリーン 2008/02/17(日) 17:28:24
瀬戸っぷさん。いつもお世話になります。

>ユーザーがウィンドウのスクロール バーをクリックした場合は、
>このパラメータは NULL になります。このポインタは一時的である場合があるので、後>使用するために保持しておくことはできません。
今回のケースでは、NULLステータスが仕様通りの動作になるわけですね (ノ_・。)クス
ン 

調べるのに苦労しましたがなんとか、解決できたと思います
MFCにおいて組み込みのスクロールバーと標準のスクロールバーとでは
多少実装方法が異なっているようです。
調べた結果標準のスクロールバーの場合
OnHScroll()関数の第三引数へ飛び込んでくる
pScrollBarがNULLステータスというのは、瀬戸っぷさんがご教示してくださった通りです
むしろ今回のケースとは異なりますが、組み込みのスクロールバーと、標準のスクロール
バーが
同じダイアログに存在する場合、NULLステータスを用いて識別する実装例も見かけまし
た。
ということで解決方法が出ましたが
今回のような、標準のスクロールバーをコントロールする場合
CScrollBar* pScrollBarは関係なく

//SCROLLINFO構造体を宣言
//C***Dlg.h

protected:
  SCROLLINFO scinfo;

//SCROLLINFO構造体のインスタンス初期化・設定
//C***Dlg.cpp
BOOL C***Dlg::OnInitDialog()関数の
// TODO: 初期化をここに追加します。以下に
  scinfo.cbSize=sizeof(SCROLLINFO);
  scinfo.fMask = SIF_RANGE;
  scinfo.nMin=0;
  scinfo.nMax=100;
  SetScrollInfo(SB_HORZ,&scinfo,0);
  xPos =100;
  return TRUE;  // フォーカスをコントロールに設定した場合を除き、TRUE を返しま
す。

//でもって、OnHScroll()メンバー関数内で実装を行い
その最期でCScrollBarクラスのSetScrollInfo()関数を用いて
SCROLLINFO 構造体がスクロール バーについて保持する情報を設定してやると
期待する動作が行えました
当然これが全てという訳ではないと思います、他の方法や私の勘違い等あればご指摘して
ください。

ソイレントグリーン 2008/02/19(火) 16:02:02
[[解決]]
解決とさせていただきます。
ありがとうございました。

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