たびたびお世話になります。yellowです。
ダイアログベースのアプリケーションで、ダイアログにステータスバー
をつけています。
表示までは(不自然ながらも)何とかできたのですが、ステータスバー
に文字を表示する時に失敗してしまいます。
ビルドは通りますが実行時にエラーが出る状態で、原因が思い当たりません。
どなたか、お知恵をお貸しいただけませんでしょうか。
【やりたい事】
ダイアログのボタンクリック時にステータスバー左端に文字を表示する。
【現状:ステータスバー自体の表示方法】
1.プロジェクトをダイアログベースで作成し、普通にダイアログを編集しました。
2.ダイアログのクラスにメンバ変数「m_statusBar」を追加しました。
------------------------------------------------------------
public:
CStatusBar m_statusBar; // ステータスバーの変数
------------------------------------------------------------
3.ダイアログのクラスの OnInitDialog メソッドに、以下のコードを追加しました。
------------------------------------------------------------
// ダイアログウィンドウの下部にステータスバーを作成
RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
------------------------------------------------------------
4.ダイアログのサイズ変更時にステータスバーを再配置するため、
OnSizeメソッドにも以下のコードを追加しました。
------------------------------------------------------------
RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
------------------------------------------------------------
このコードにより、ダイアログ下部にステータスバーが表示されます。
ステータスバーは、SDIなどで通常表示されるものと異なっており、
複数ペインには分かれておらず初期表示の「レディ」文字列も表示されません。
ダイアログのサイズをマウスで変更した場合、ステータスバーはちゃんと
画面下部に表示しなおされます。
【問題点】
5.ダイアログにボタン「Button1」を追加しました。
6.「Button1」のクリック時にステータスバーに文字列 aaa を表示させるため、
「Button1」に対して以下のメソッドを作成しました。
------------------------------------------------------------
void CXXXDlg::OnBnClickedButton1()
{
// メインフレームウィンドウのポインタを取得
CFrameWnd* pWnd = (CFrameWnd*)AfxGetApp()->m_pMainWnd;
// ステータスバーのポインタを取得
CStatusBar* pStatusBar = (CStatusBar*)pWnd->GetMessageBar();
// ステータスバーの一つ目のペインに文字を出力
pStatusBar->SetPaneText(0, _T(aaa));
}
------------------------------------------------------------
このコードでは、ビルドには成功しました。
ところが、アプリケーションを実行し、「Button1」をクリックすると
以下のような、VisualStudioのエラーダイアログが表示されます。
メッセージ内容:
------------------------------------------------------------
XXX.exeの○○でハンドルされていない例外が発生しました。
場所○○を読み込み中にアクセス違反が発生しました。
------------------------------------------------------------
(文中「○○」にはアドレス?が書いてありました...)
エラーが発生する行は、OnBnClickedButton1関数の
pStatusBar->SetPaneText(0, _T(aaa));
の行のようなのですが、これ以上の原因が特定できず、行き詰まってしまいました。
ビルドはできているので、文法上の問題はクリアしていると思うのですが、
なぜ実行時にエラーとなるのか見当がつきかねています。
CStatusBar自体の仕様を勘違いしているのでは?とも思いましたが、
MFCのリファレンスを見ても自分では原因を特定できませんでした。
よろしくお願いいたします。
> メッセージ内容:
> ------------------------------------------------------------
> XXX.exeの○○でハンドルされていない例外が発生しました。
> 場所○○を読み込み中にアクセス違反が発生しました。
> ------------------------------------------------------------
> (文中「○○」にはアドレス?が書いてありました...)
>
> エラーが発生する行は、OnBnClickedButton1関数の
> pStatusBar->SetPaneText(0, _T(aaa));
> の行のようなのですが、これ以上の原因が特定できず、行き詰まってしまいました。
MFCもステータスバーも使っていませんが…
お約束として、
pStatusBarの取得に成功していますか?
失敗していてNULL(あるいは不定値)だったりしませんか?
MSDNで「CStatusBar」を見ましたか?
表示するのに手順が必要みたいですね。
ペインの文字も更新は出来ても割付は作成時にしないといけないみたいですね。
追伸、
わざわざ、MSDNホームページで検索しなくてもVC付属のCDで十分です。
ちょっと自分の勉強の為、調べてみました。
手順としては
1.CStatusBar オブジェクトを構築します。
2.Create (または CreateEx) 関数を呼び出してステータス バー ウィンドウを作成
し、それを CStatusBar オブジェクトに結び付けます。
3.SetIndicators を呼び出して各インジケータに文字列 ID を関連付けます。
ここまでで初期処理。
以下4か5を使ってテキストの表示のようですね。
4.CWnd::SetWindowText を使って、ペイン 0 のテキストのみを更新します。
5.SetPaneText 関数を使って任意のペインのテキストを更新します。
項目3番、意味が分かりませんでした^^;
どうやらステータスバーにペインを何個設定するかのようです。
その時に、ペイン毎にIDを必要とし、そのID配列を設定する必要があります。
このあたりの設定が丸ごと抜けている気がします。
凍結しちゃいそうなので、テスト的に作成したものをアップしておきます。
VC++6.0ダイアログベースで作成しました。
機能
・初期表示時に左側のペインに「aaa」を表示する。
・画面上に配置したボタンを押下すると右側のペインに「bbb」を表示する。
その他はWM_SIZE受信時にサイズを変更しているだけです。
(OnSizeのソースはアップしてません。)
--------------------------------------------------------------------------
OnInitDialog()内
// インスタンス生成
m_poStatusBar = new CStatusBar;
m_poStatusBar->Create(this, WS_CHILD | WS_VISIBLE | CBRS_BOTTOM,
AFX_IDW_STATUS_BAR);
// 表示領域設定
CRect rect;
CRect rect_st;
m_poStatusBar->GetWindowRect( rect_st);
this->GetClientRect(&rect);
int nwork = rect_st.bottom;
rect_st.top = rect.bottom - (nwork);
rect_st.bottom = rect_st.top + nwork;
rect_st.left = rect.left;
rect_st.right = rect.right;
// ステータスバーをペイン2つに設定
m_poStatusBar->SetIndicators(&indicators[0], 2);
// ペイン1、2の設定(とりあえず半分づつで表示)
m_poStatusBar->SetPaneInfo(0, 0, SBPS_STRETCH, (rect_st.right -
rect_st.left) / 2); // ペイン1の設定
m_poStatusBar->SetPaneInfo(1, 1, SBPS_STRETCH, (rect_st.right -
rect_st.left) / 2); // ペイン2の設定
m_poStatusBar->MoveWindow( rect_st);
m_poStatusBar->SetPaneText(0, aaa);
--------------------------------------------------------------------------
OnButtonDown()内
// ペイン2にbbbを表示
m_poStatusBar->SetPaneText(1, bbb);
--------------------------------------------------------------------------
インジケータ用配列
static UINT indicators[] =
{
ID_PANE1,
ID_PANE2,
};
--------------------------------------------------------------------------
すみません、質問を投稿させていただいてからしばらくアクセスせず
大変申し訳ありません。
体調を崩しておりました・・・
ご意見をくださった皆様、ありがとうございます。
ためしてみて、結果を報告いたします。
大変遅くなりまして申し訳ありません。
皆様からのご意見を参考に、試してみました。
以下の方法にて、解決できました。
基本的には、Fly様にお教えいただいた方法のとおりです。
ご親切に、大変わかりやすいソースコードを掲載くださいまして、
本当にありがとうございました。
---------------------------------------------------------------
OnInitDialog内:
if (m_statusBar.Create(this))
{
// インディケータの配列。
// リソースファイルのStringTableに「ID_PANE1」のIDの文字列を用意しておく。
static UINT indicators[] =
{
ID_PANE1,
};
// ペインを一つ用意。
m_statusBar.SetIndicators(&indicators[0], 1);
// ペインの幅は100。三つ目の引き数は、ペインのスタイルをあらわす。
m_statusBar.SetPaneInfo(0, 0, SBPS_NORMAL , 100);
}
RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
---------------------------------------------------------------
OnSize内:
if( ::IsWindow( this->GetSafeHwnd()) == TRUE &&
this->IsWindowVisible() == TRUE)
{
RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
}
---------------------------------------------------------------
ペインに文字列を表示したいメソッド内:
m_statusBar.SetPaneText(0, aaa); // これだけでOK.
---------------------------------------------------------------
本件、仕組みがきちんと理解できていない部分もありますので、もう少し
研究してみたいと思っていますが、
まずは欲しい機能が満たせましたので、[解決]とさせて頂きます。
本当にありがとうございました。