ホーム WTL Mobile
プログレスバー
ドキュメント種別 ATL/WTL に関する文書
最終更新日 2009/10/21
PR
 WTLではコモンコントロールのプログレスバーコントロールをCProgressBarCtrlT というクラステンプレートでカプセル化しています。 テンプレート引数にはクラスを指定しますが、 そのクラスはCProgressBarCtrlTの基底クラスとして使用されます。 atlctrls.hヘッダではtypedefによって次のように宣言されています。

// atlctrls.h
typedef CProgressBarCtrlT<ATL::CWindow>   CProgressBarCtrl;
			

これは、CProgressBarCtrlクラスはCWindowクラスの派生クラスであることを意味します。

 WTLのCProgressBarCtrlクラスは、MFCのCProgressCtrlクラスと同等の機能を備えています。 以下に示すのは、CProgressBarCtrlクラスを使用する例です。 [開始]ボタンを押すと100ミリ秒毎に1/10ずつバーを進めます。


プロジェクトファイル ダウンロード
// stdafx.h
#pragma once

#define WINVER 0x0420
#include <atlbase.h>
#if _ATL_VER == 0x900
#define _SECURE_ATL 1
#endif

#define _WTL_USE_CSTRING
#include <atlapp.h>
extern CAppModule _Module;
#include <atlwin.h>

#include <tpcshell.h>
#include <aygshell.h>
#pragma comment(lib, "aygshell.lib")

#include <atlcrack.h>
#include <atlmisc.h>
#include <atlframe.h>
#include <atlctrls.h>
#define _WTL_CE_NO_ZOOMSCROLL
#define _WTL_CE_NO_FULLSCREEN
#include <atlwince.h>
			

// SampleProjectDialog.h
#pragma once

class CSampleProjectDialog : 
    public CAppStdDialogImpl<CSampleProjectDialog>,
    public CUpdateUI<CSampleProjectDialog>,
    public CMessageFilter, public CIdleHandler
{
public:
    DECLARE_APP_DLG_CLASS(NULL, IDR_MAINFRAME, L"Software\\WTL")

    enum { IDD = IDD_MAINDLG };

    CProgressBarCtrl m_progress_sec;
    CButton m_button_start;

    virtual BOOL PreTranslateMessage(MSG* pMsg){
        return CWindow::IsDialogMessage(pMsg);
    }

    virtual BOOL OnIdle(){
        return FALSE;
    }

    BEGIN_UPDATE_UI_MAP(CSampleProjectDialog)
    END_UPDATE_UI_MAP()

    BEGIN_MSG_MAP(CSampleProjectDialog)
        MSG_WM_TIMER(OnTimer)
        MSG_WM_INITDIALOG(OnInitDialog)
        MSG_WM_DESTROY(OnDestroy)
        COMMAND_ID_HANDLER_EX(IDC_BUTTON_START, OnButtonStart)
        CHAIN_MSG_MAP(CUpdateUI<CSampleProjectDialog>)
        CHAIN_MSG_MAP(CAppStdDialogImpl<CSampleProjectDialog>)
    END_MSG_MAP()

    void OnTimer(UINT_PTR nIDEvent){
        UINT pos = m_progress_sec.GetPos();
        pos++;
        m_progress_sec.SetPos(pos);
        if(10 <= pos){
            KillTimer(nIDEvent);
            m_button_start.EnableWindow(TRUE);
        }
    }

    BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam){
        AtlCreateEmptyMenuBar(m_hWnd);

        // コントロール設定
        m_progress_sec = GetDlgItem(IDC_PROGRESS_SEC);
        m_button_start = GetDlgItem(IDC_BUTTON_START);

        m_progress_sec.SetRange(0, 10);
        m_progress_sec.SetPos(0);

        // メッセージループにメッセージフィルタとアイドルハンドラを追加
        CMessageLoop* pLoop = _Module.GetMessageLoop();
        pLoop->AddMessageFilter(this);
        pLoop->AddIdleHandler(this);

        SetMsgHandled(false);

        return TRUE;
    }

    void OnDestroy(){
        // メッセージループからメッセージフィルタとアイドルハンドラを削除
        CMessageLoop* pLoop = _Module.GetMessageLoop();
        pLoop->RemoveMessageFilter(this);
        pLoop->RemoveIdleHandler(this);
    }

    void OnButtonStart(UINT uNotifyCode, int nID, CWindow wndCtl){
        m_progress_sec.SetPos(0);
        m_button_start.EnableWindow(FALSE);
        SetTimer(1, 100, NULL); 
    }
};
			

// SampleProject.cpp
#include "stdafx.h"
#include "resourceppc.h"
#include "SampleProjectDialog.h"

CAppModule _Module;

int WINAPI _tWinMain(HINSTANCE hInstance,
    HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
    HRESULT hRes =
        CSampleProjectDialog::ActivatePreviousInstance(hInstance, lpstrCmdLine);

    if(FAILED(hRes) || S_FALSE == hRes){
        return hRes;
    }

    hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
    ATLASSERT(SUCCEEDED(hRes));

    AtlInitCommonControls(ICC_PROGRESS_CLASS);
    SHInitExtraControls();

    hRes = _Module.Init(NULL, hInstance);
    ATLASSERT(SUCCEEDED(hRes));

    int nRet = CSampleProjectDialog::AppRun(lpstrCmdLine, nCmdShow);

    _Module.Term();
    ::CoUninitialize();

    return nRet;
}
			

 まず、リソースを作成します。ダイアログにプログレスバーコントロールとボタンコントロールを配置し、 それぞれの[ID]と[Caption]を次のように設定します。 なお、プログレスバーコントロールの[プロパティ]では[Smooth]を[True]に設定します。

コントロール名 ID Caption
プログレスバー IDC_PROGRESS_SEC -
ボタン IDC_BUTTON_START 開始

 次に、stdafx.hヘッダでは、CProgressBarCtrlクラスとCButtonクラスを使用するためにatlctrls.hヘッダをインクルードします。

 CSampleProjectDialogクラスでは、まず、プログレスバーコントロールとボタンコントロール用にそれぞれCProgressBarCtrlクラスとCButtonクラスのインスタンスをメンバ変数として宣言します。 これらを使うためには、WM_INITDIALOGメッセージハンドラでコントロールのハンドルを代入する必要があります。

 次に、WM_INITDIALOGメッセージハンドラでSetRange()SetPos()を呼び出して プログレスバーコントロールの範囲と初期位置を設定します。

 次に、リソースIDがIDC_BUTTON_STARTWM_COMMANDメッセージハンドラとしてOnButtonStart()を追加します。 このハンドラ関数ではSetTimer()を呼び出して100ミリ秒毎のタイマーを設定します。

 次に、100ミリ秒毎に呼び出されるWM_TIMERメッセージハンドラでSetPos()を呼び出してバーを1/10ずつ進めます。 バーが最後まで到達した場合はタイマーを止めます。

 最後に_tWinMain()で、引数にICC_PROGRESS_CLASSを指定してAtlInitCommonControls()を呼び出します。

 今回の例ではバーを進めるためにSetPos()を使用しましたが、 CProgressBarCtrlクラスは、バーを進めるために別の2つの方法を用意しています。

 1番目の方法は、OffsetPos()を使用する方法です。 OffsetPos()はバーの位置を現在の位置から相対的に設定します。

void OnTimer(UINT_PTR nIDEvent){
    m_progress_sec.OffsetPos(1);
    UINT pos = m_progress_sec.GetPos();
    if(10 <= pos){
        KillTimer(nIDEvent);
        m_button_start.EnableWindow(TRUE);
    }
}
			

 2番目の方法は、StepIt()を使用する方法です。 StepIt()を使用する場合は、 あらかじめSetStep()で増分値を設定します。 その後StepIt()を呼び出すたびに増分値ずつバーが進みます。

// OnInitDialog() で m_progress_sec.SetStep(1); を呼び出しておく
void OnTimer(UINT_PTR nIDEvent){
    m_progress_sec.StepIt();
    UINT pos = m_progress_sec.GetPos();
    if(10 <= pos){
        KillTimer(nIDEvent);
        m_button_start.EnableWindow(TRUE);
    }
}