ステータスバーにプログレスコントロールを表示する

IEでファイルをダウンロードする時等にステータスバーに表示されるアレは
プログレスコントロールをステータスバーの子ウィンドウとして動的に作成し表示しています。
CProgressCtrlをメンバに持った新しいCStatusBarくらすを作成すると
汎用になって何かと便利なのでそうすると良いです。
という訳で、CStatusBarを基本クラスに持ったクラスを作成します。
ここでは仮にCProgressStatusBarと名付ける事にします。

ではまず、プログレスコントロールと表示する位置を保存するメンバ変数を定義します。
ここではそれぞれ、m_progressm_nIndexとしておきます。
そしてm_nIndexはコンストラクタで非表示を意味する-1に初期化しておいてください。


// ProgressStatusBar.h

protected:
    int m_nIndex;
    CProgressCtrl m_progress;


// ProgressStatusBar.cpp

CProgressStatusBar::CProgressStatusBar()
{
    m_nIndex = -1;
}

そして、ステータスバーを作成した時にプログレスバーも作成します。
WM_CREATEが送られてきた時に作成するのが適当でしょう。


int CProgressStatusBar::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
    if (CStatusBar::OnCreate(lpCreateStruct) == -1)
        return -1;

    // プログレスコントロールを作成
    RECT rc = { 0 };
    m_progress.Create(WS_CHILD | PBS_SMOOTH, rc, this, 1);
    
    return 0;
}

これでまずはプログレスコントロールを非表示のまま作成できました。
表示するには、その為のメンバ関数を作成します。
この関数は表示位置を変えたり非表示にしたりも出来るようにします。


// プログレスコントロールを指定したペインに表示
UINT CProgressStatusBar::ShowProgressBar(int nIndex)
{
    RECT rc;
    int nOldIndex = m_nIndex;
    m_nIndex = nIndex;
    GetItemRect(nIndex, &rc);
    m_progress.MoveWindow(&rc);
    m_progress.ShowWindow((nIndex == -1) ? SW_HIDE : SW_SHOWNA);
    return nOldIndex;
}

引数のnIndexは何番目のペインに表示するか設定するものです。
それから特に必要はありませんが直前の表示位置を返すようにしておくと
便利かもしれないので戻り値で返すようにしています。
この関数で行う処理はまずペインの座標をGetItemRect()で取得し
取得した座標にMoveWindow()でプログレスコントロールの位置を移動させ
ShowWindow()で表示(nIndexが-1の時は非表示)しています。

それからウィンドウサイズが変更された時にプログレスコントロールの位置等を修正する必要があります。
これはWM_SIZEが送られてきた時に修正すればいいでしょう。
例によってメッセージハンドラの追加で以下を実装してください。


void CProgressStatusBar::OnSize(UINT nType, int cx, int cy) 
{
    CStatusBar::OnSize(nType, cx, cy);

    if (!::IsWindow(m_progress.m_hWnd) || m_nIndex == -1)
        return;

    // 位置を修正
    RECT rc;
    GetItemRect(m_nIndex, &rc);
    m_progress.MoveWindow(&rc, FALSE);
}

ステータスバーが作成されていない場合はGetItemRect()を使うとエラーになるので
IsWindow()で作成されているかチェックし作成されていなければ処理しないで戻るようにします。
それからプログレスコントロールが非表示の時も処理した所で意味が無いのでそのままリターン。
その後GetItemRect()MoveWindow()で位置を調整しています。

あとはプログレスコントロールと同じように使う為にCProgressCtrlのメンバ関数をラッパさせます。
これらの関数はCProgressCtrlのメンバ関数を呼び出すだけなのでヘッダファイルに定義して
インライン関数にしておくと速度も出ますしいいでしょう。
それと内蔵したプログレスコントロールのポインタを返す関数もあると便利かもしれません。
# CProgressStatusBar.GetWindow(GW_CHILD)ででも取得できますが。


class CProgressStatusBar : public CStatusBar
{
        :
        :
// インプリメンテーション
public:
    // 内蔵プログレスコントロールのポインタを取得
    CProgressCtrl* GetProgressCtrl()          { return &m_progress;                    }

    // CProgressCtrlメンバ関数
    void SetRange(short nLower, short nUpper) { m_progress.SetRange(nLower, nUpper);   }
    void SetRange32(int nLower, int nUpper)   { m_progress.SetRange32(nLower, nUpper); }
    void GetRange(int& nLower, int& nUpper)   { m_progress.GetRange(nLower, nUpper);   }
    int  GetPos()                             { return m_progress.GetPos();            }
    int  SetPos(int nPos)                     { return m_progress.SetPos(nPos);        }
    int  OffsetPos(int nPos)                  { return m_progress.OffsetPos(nPos);     }
    int  SetStep(int nStep)                   { return m_progress.SetStep(nStep);      }
    int  StepIt()                             { return m_progress.StepIt();            }
        :
        :
};

以上で全て終わりです。

以下はこのクラスのソースをです。
参考にするなりそのままクラスに追加してお使いください。

ProgressStatusBar.cpp
ProgressStatusBar.h

< 戻る << HOME ©1999-2002 by Akky, All right reserved.