antenn-a
company profile

MFC航海日記 五十六日目(ステータスバーにプログレスバー表示)


今回作っているPicture Album(仮称)で、実際問題時間がかかるのはサムネイルを作成する所だったりするのだけども、そこをプログレスバーで「どれぐらい終わったよ」表示をしようかなと思った。
で、まあSDIにダイアログを貼り付けているので、そこの上に単純にプログレスバーを付けても良いんだけど、それじゃ詰まらんよねって事で少し遊んでみた。
タイトルに有るとおり、ステータスバーにプログレスバーを付けて見ようという事。

prev


さて、色々試しましたよ。でも、どうも上手く行かない。
ダイアログのOnInitDialog()の中でプログレスバーを作ろうとすると、怒られてしまう。
どうも、まだステータスバーが作られて居ないみたいなのだ。
はーてどうすっぺ。一時は諦めて、SetTimer で1秒後とかにCreateしてたりしたけど、猛烈に格好悪い(トホホ)
で、仕方ないので、少々荒っぽいやり方で実装しちゃいました。
本当にこんなんで良いのかなあ。動いてるけどね。

prev


まずは、CMainFrm.cpp の上の方にグローバル宣言します。
// MainFrm.cpp : CMainFrame クラスの実装
//

#include "stdafx.h"
#include "PictureAlbum.h"

#include "MainFrm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// 他クラスで使用する為のグローバル宣言
CProgressCtrl*	g_pProgressCtrl;

// CMainFrame

IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
						
既に怪しさ満点!
で、CMainFrame::OnCreate() の中で
	if (!m_wndStatusBar.Create(this) ||
		!m_wndStatusBar.SetIndicators(indicators,
		  sizeof(indicators)/sizeof(UINT)))
	{
		TRACE0("ステータス バーの作成に失敗しました。\n");
		return -1;      // 作成できませんでした。
	}

	// ProgressBarの作成
	CRect	rctProg;

	m_wndStatusBar.SetPaneInfo( 0, m_wndStatusBar.GetItemID( 0 ), m_wndStatusBar.GetPaneStyle( 0 ), 50 );
	m_wndStatusBar.SetPaneInfo( 1, m_wndStatusBar.GetItemID( 1 ), m_wndStatusBar.GetPaneStyle( 1 ), 580 );
	//m_wndStatusBar.GetItemRect( 1, &rctProg );
	rctProg.top = 2;
	rctProg.left = 130;
	rctProg.right = 700;
	rctProg.bottom = 18;

	g_pProgressCtrl = new CProgressCtrl;
	g_pProgressCtrl->Create( PBS_SMOOTH | WS_CHILD | WS_VISIBLE, rctProg, &m_wndStatusBar, 1 );
	
	//プログレスバー設定
	g_pProgressCtrl->SetRange( 0, 100 );
	g_pProgressCtrl->SetPos(0);
						
こんな感じでCreateしてます。
謎1)コメントアウトされてるけど、SetPaneInfo()した直後にGetItemRect() すると、Rectが取れない!
謎2)スタイルにPBS_SMOOTH を追加してるけど、SMOOTHにならない!
謎!
で、まあ、これで一応宣言出来たので、このコントロールを弄りたいソース、今は EMainDialog なので、EMainDialog.cpp に外部宣言を加えます。
// EMainDialog.cpp : 実装ファイル
//

#include "stdafx.h"
#include "PictureAlbum.h"
#include "EMainDialog.h"


// ステータスバーのポインタ(MainFrm.cpp内に記述)
extern CProgressCtrl *g_pProgressCtrl;
						

で、使いたい関数内で g_pProgressCtrl->SetPos() とか何とかやればOKです。
はっきり言って美しく無い!
やっぱ止めよう(ビビリ)
もう少し美しい形で実装するとなると、やっぱりApp Classにグローバル宣言するのが良かろう。
ちょ、、っとマシ? Extern とか使わないしね!(あんまり説得力無い)

prev


上のと似ているが、まずはApp Classに変数を追加する。今回の場合は PictureAlbum.h に相当する。
class CPictureAlbumApp : public CWinApp
{
public:
	CPictureAlbumApp();


// オーバーライド
public:
	virtual BOOL InitInstance();

// グローバル変数
public:
	CProgressCtrl*	g_pProgressCtrl;
// 実装
	afx_msg void OnAppAbout();
	DECLARE_MESSAGE_MAP()
};
						

次に、初期化をする為に MainFrm.cpp を開き、上と同じ様に CMainFrame::OnCreate() で
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	if (!m_wndStatusBar.Create(this) ||
		!m_wndStatusBar.SetIndicators(indicators,
		  sizeof(indicators)/sizeof(UINT)))
	{
		TRACE0("ステータス バーの作成に失敗しました。\n");
		return -1;      // 作成できませんでした。
	}

	// ProgressBarの作成
	CRect	rctProg;
	CPictureAlbumApp* m_pMyApp = (CPictureAlbumApp*)AfxGetApp();

	m_wndStatusBar.SetPaneInfo( 0, m_wndStatusBar.GetItemID( 0 ), m_wndStatusBar.GetPaneStyle( 0 ), 50 );
	m_wndStatusBar.SetPaneInfo( 1, m_wndStatusBar.GetItemID( 1 ), m_wndStatusBar.GetPaneStyle( 1 ), 580 );
	//m_wndStatusBar.GetItemRect( 1, &rctProg );
	rctProg.top = 2;
	rctProg.left = 130;
	rctProg.right = 700;
	rctProg.bottom = 18;

	m_pMyApp->g_pProgressCtrl = new CProgressCtrl;
	m_pMyApp->g_pProgressCtrl->Create( PBS_SMOOTH | WS_CHILD | WS_VISIBLE, rctProg, &m_wndStatusBar, 1 );
	
	//プログレスバー設定
	m_pMyApp->g_pProgressCtrl->SetRange( 0, 100 );
	m_pMyApp->g_pProgressCtrl->SetPos(0);
	
	return 0;
}
						

後は、CMainDialog.h の中に普通に変数宣言をして、OnInitDialog()かOnCreate()の中か何かで、同じ様に
m_pMyApp = (CPictureAlbumApp*)AfxGetApp();
等として、後は m_pMyApp->g_pProgressCtrl->SetPos() 等と使えばOKかな。
こっちの方が(少しだけ)綺麗かも。


antenn-a

prev next


antenn-a