いつもお世話になっています。
申し訳ございません、連投になりますが宜しくお願いします。
【環境】
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);
}
>デバッガーでpScrollBarを確認すると、{CWnd hwnd=???}となっていてインスタンスが生
>成されていない(pScrollBarが NULLの状態)のではないかと思われる?
MSDNには
pScrollBar
スクロール バー コントロールからメッセージが送られた場合は、コントロールへの
ポインタになります。ユーザーがウィンドウのスクロール バーをクリックした場合は、
このパラメータは NULL になります。このポインタは一時的である場合があるので、後で
使用するために保持しておくことはできません。
と書かれています。
Windwsメッセージのハンドラを用意しただけで、CScrollBarを構築する処理はどこにもあ
りませんから
インスタンスが精製されないのも致し方ないかと。
CScrollBarは使用できませんが、CWnd::GetScrollRange()等が利用できるかと思います。
瀬戸っぷさん。いつもお世話になります。
>ユーザーがウィンドウのスクロール バーをクリックした場合は、
>このパラメータは NULL になります。このポインタは一時的である場合があるので、後
で
>使用するために保持しておくことはできません。
今回のケースでは、NULLステータスが仕様通りの動作になるわけですね (ノ_・。)クス
ン
調べるのに苦労しましたがなんとか、解決できたと思います
MFCにおいて組み込みのスクロールバーと標準のスクロールバーとでは
多少実装方法が異なっているようです。
調べた結果標準のスクロールバーの場合
OnHScroll()関数の第三引数へ飛び込んでくる
pScrollBarがNULLステータスというのは、瀬戸っぷさんがご教示してくださった通りです
むしろ今回のケースとは異なりますが、組み込みのスクロールバーと、標準のスクロール
バーが
同じダイアログに存在する場合、NULLステータスを用いて識別する実装例も見かけまし
た。
ということで解決方法が出ましたが
今回のような、標準のスクロールバーをコントロールする場合
CScrollBar* pScrollBarは関係なく
//SCROLLINFO構造体を宣言
//CDlg.h
protected:
SCROLLINFO scinfo;
//SCROLLINFO構造体のインスタンス初期化・設定
//CDlg.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 構造体がスクロール バーについて保持する情報を設定してやると
期待する動作が行えました
当然これが全てという訳ではないと思います、他の方法や私の勘違い等あればご指摘して
ください。
解決とさせていただきます。
ありがとうございました。