●オーディオプレイヤ開発記 その7
それでは、CStatic クラスにラベルの文字ぴったりにウィンドウのサイズを合わせてくれるような機能をつけてみます。その過程で必要となる関数がいくつかあるのでそれも追加しておきます。まず、CWnd クラスに、
virtual std::string GetCaption() const {
int nCaptionLength = GetWindowTextLength(m_hWnd) + 1;
TCHAR * pszCaption = new TCHAR[nCaptionLength];
GetWindowText(m_hWnd, pszCaption, nCaptionLength);
std::string strCaption = pszCaption;
delete [] pszCaption;
return strCaption;
}
を追加します。そして、CStatic クラスに、
virtual std::string GetText() const { return GetCaption(); }
virtual int GetTextLength() const { return GetCaptionLength(); }
virtual int GetTextHeight() const {
if(!m_hWnd) return -1;
HDC hdc = GetDC(m_hWnd);
SIZE size;
GetTextExtentPoint32(hdc, GetText().c_str(), GetText().length(), &size);
ReleaseDC(m_hWnd, hdc);
return size.cy;
}
virtual int GetTextWidth() const {
if(!m_hWnd) return -1;
HDC hdc = GetDC(m_hWnd);
SIZE size;
GetTextExtentPoint32(hdc, GetText().c_str(), GetText().length, &size);
ReleaseDC(m_hWnd, hdc);
return size.cx;
}
virtual void SetSizeToTextSize() {
SetSize(GetTextWidth(), GetTextHeight());
}
を追加します。これで、MainWnd.h から Static.h をインクルードし、CMainWnd クラスのメンバ変数に CStatic m_label; と追加しておき、OnCreate 関数を、
LRESULT CMainWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
SetMainWnd(true); // メインウィンドウに設定
SetStyle(WS_OVERLAPPEDWINDOW);
SetCaption(TEXT("サウンドプレイヤー"));
SetSize(320, 240);
// 再生時間表示用ラベルの作成
m_label.Create();
m_label.SetParent(m_hWnd);
m_label.SetText(TEXT("00:00:00 / 00:00:00"));
m_label.SetSizeToTextSize();
m_label.Show(SW_SHOW);
Show(m_rApp.GetNCmdShow());
Update();
return CFrameWnd::OnCreate(lpCreateStruct);
}
などとすることにより、テキストのサイズぴったりにウィンドウサイズが調整されたラベルが表示されるようになりました。ただ、CStatic::GetTextHeight, CStatic::GetTextWidth 関数ですが、HDC ( デバイスコンテキストハンドル ) を手動で、GetDC / ReleaseDC するってのがイマイチですね。折角なのでこれまた MFC に習って、CDC, CClientDC クラスとして管理するようにしておきましょう。
まずは、CDC クラスです。
//----------------------------------------------------------------------------
// DC.h : デバイスコンテキストの管理を行う
//----------------------------------------------------------------------------
#ifndef DCH
#define DCH
//----------------------------------------------------------------------------
// デバイスコンテキストの管理を行うクラス
//----------------------------------------------------------------------------
class CDC
{
public: // 関数
CDC(): m_hDC(0) { }
virtual ~CDC() { Destroy(); }
virtual void Destroy() { if(m_hDC) DeleteDC(m_hDC), m_hDC = 0; }
virtual int GetTextHeight(const std::string & str) const {
SIZE size;
GetTextExtentPoint32(m_hDC, str.c_str(), str.length(), &size);
return size.cy;
}
virtual int GetTextWidth(const std::string & str) const {
SIZE size;
GetTextExtentPoint32(m_hDC, str.c_str(), str.length(), &size);
return size.cx;
}
protected: // メンバ変数
HDC m_hDC;
public: // メンバ変数の取得・設定
operator HDC() const { return m_hDC; }
};
//----------------------------------------------------------------------------
#endif
GetTextHeight, GetTextWidth も追加しておきました。続いて、CDC クラスを継承した CClientDC クラスです。
//----------------------------------------------------------------------------
// ClientDC.h : ウィンドウのクライアント領域用デバイスコンテキストの管理を行う
//----------------------------------------------------------------------------
#ifndef ClientDCH
#define ClientDCH
#include "DC.h"
//----------------------------------------------------------------------------
// ウィンドウのクライアント領域用デバイスコンテキストの管理を行うクラス
//----------------------------------------------------------------------------
class CClientDC : public CDC
{
public: // 関数
CClientDC(HWND hWnd) {
m_hWnd = hWnd;
m_hDC = GetDC(m_hWnd);
}
virtual ~CClientDC() { }
virtual void Destroy() {
if(m_hDC) ReleaseDC(m_hWnd, m_hDC), m_hWnd = 0, m_hDC = 0;
}
protected: // メンバ変数v
HWND m_hWnd;
};
//----------------------------------------------------------------------------
#endif
これで、先ほどの CStatic::GetTextHeight, CStatic::GetTextWidth は、
virtual int GetTextHeight() const {
if(!m_hWnd) return -1;
CClientDC dc(m_hWnd);
return dc.GetTextHeight(GetText());
}
virtual int GetTextWidth() const {
if(!m_hWnd) return -1;
CClientDC dc(m_hWnd);
return dc.GetTextWidth(GetText());
}
と書けるようになりました。ここまでのソースコードはこちら ( Hayaemon20060207_src.lzh ) 。