ホーム ATL/WTL
パレット
ドキュメント種別 ATL/WTL に関する文書
最終更新日 2003/12/17
PR
 WTLではGDIオブジェクトのパレットをCPaletteTというテンプレートクラスでカプセル化しています。 テンプレート引数はbool値で、trueの場合はデストラクタでDeleteObject()を呼び出し、 falseの場合は呼び出しません。atlgdi.hヘッダではtypedefによって次のように宣言されています。

// atlgdi.h内
typedef CPaletteT<false>  CPaletteHandle;
typedef CPaletteT<true>   CPalette;
			

 WTLのCPaletteクラスは、MFCの同名のクラスとほぼ同じメンバ関数を用意しています。 CPaletteT::CreatePalette()はカスタムパレットを作成します。 カスタムパレットは主に色の種類が少ない、微妙な階調が多用される画像のために使用されます。 CPaletteT::CreateHalftonePalette()はハーフトーンパレットを作成します。 ハーフトーンパレットは主に色の種類が多い画像のために使用されます。

以下に示すのは、CPaletteクラスを使用してクライアント領域に64階調の青いグラデーションを描画する例です。 グラデーションは微妙な階調で表現するので、カスタムパレットを使用します。 なお、パレットの影響を確認するために256色モードの画面で実行します。 次のスクリーンショットは、上がパレットを使用した場合で、下が使用していない場合の表示です。



CPalette m_palette;  // CPalette型のメンバ変数

// WM_PAINTメッセージハンドラ
void OnPaint(HDC /*hDC*/){
    CPaintDC dc(m_hWnd);

    // パレットを選択
    HPALETTE hOldPalette;
    if(!m_palette.IsNull()){
        hOldPalette = dc.SelectPalette(m_palette, FALSE);
        dc.RealizePalette();
    }

    // ブラシ作成
    CBrush brush[64];
    for(int i=0; i<64; i++)
        brush[i].CreateSolidBrush(PALETTERGB(0, 0, 255 - (i * 4)));

    // クライアント矩形を取得し、グラデーションを描画
    CRect rect, rcLine;
    GetClientRect(rect);
    for(i=0; i<rect.Height(); i++){
        rcLine.SetRect(0, i, rect.Width(), i + 1);
        dc.FillRect(rcLine, brush[(i * 63) / rect.Height()]);
    }

    // 元のパレットを選択
    if(!m_palette.IsNull())
        dc.SelectPalette(hOldPalette, FALSE);
}

// WM_CREATEメッセージハンドラ
LRESULT OnCreate(LPCREATESTRUCT lpcs){
    CClientDC dc(m_hWnd);
    if(dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE){
        // カスタムパレットを作成
        struct{
            LOGPALETTE lp;
            PALETTEENTRY ape[63];
        }pal;

        LOGPALETTE* pLP = (LOGPALETTE*)&pal;
        pLP->palVersion = 0x300;
        pLP->palNumEntries = 64;

        for(int i=0; i<64; i++){
            pLP->palPalEntry[i].peRed = 0;
            pLP->palPalEntry[i].peGreen = 0;
            pLP->palPalEntry[i].peBlue = 255 - (i * 4);
            pLP->palPalEntry[i].peFlags = 0;
        }

        m_palette.CreatePalette(pLP);
    }

    return 0;
}
			

 まず、先頭でCPaletteクラスのインスタンスであるm_paletteをメンバ変数として宣言します。 この変数は、CPaletteクラスのコンストラクタでNULLに初期化されています。

 次に、WM_CREATEメッセージハンドラを見ます。 WM_CREATEメッセージハンドラでは始めに、パレットが必要かどうかをチェックしています。 チェックするには、ディスプレイが256色モードかどうかを判定します。

// dcはデバイスコンテキストクラスのインスタンス
if(dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE){
    // 256色モードなのでパレットが必要
}
			

パレットが必要な場合はカスタムパレットを作成します。

 次に、WM_PAINTメッセージハンドラでは、 m_paletteがNULLではない場合(=パレットが必要な場合)、 作成したパレットオブジェクトをSelectPalette()で現在のパレットとして選択し、 RealizePalette()でリアライズします。 SelectPalette()は引数にHPALETTE型の変数を受け取りますが、 CPaletteTクラスはHPALETTE変換演算子を持っているのでそのまま渡すことができます。 SelectPalette()は以前のパレットハンドルを返すので、 これをhOldPaletteという変数に保存しておきます。

次に、ブラシを使ってグラデーションを描画します。 明るい青から黒に近い青まで64階調で描画されます。

最後に、先ほど保存しておいた元のパレットハンドルに戻すため、 再度SelectPalette()を呼び出して元のパレットハンドルを選択します。

 ところで、WTLはストックパレットもサポートしています。 以下に示すのは、ストックパレットによって描画する例です。

// WM_PAINTメッセージハンドラ
void OnPaint(HDC /*hDC*/){
    CPaintDC dc(m_hWnd);

    // パレットを選択
    HPALETTE hOldPalette = dc.SelectStockPalette(DEFAULT_PALETTE, FALSE);

    // 描画
    ...
    ...

    // 元のパレットを選択
    dc.SelectPalette(hOldPalette, FALSE);
}
			

また、atlmisc.hヘッダに定義されているAtlGetStockPalette()というグローバル関数を使えば、 ストックパレットのハンドルを取得することができます。

// ストックパレットのハンドルを取得
HPALETTE hStockPalette = AtlGetStockPalette(DEFAULT_PALETTE);