メルマガ:あゆしゃのC言語プログラミング
タイトル:あゆしゃのC言語プログラミング(Vol.586) CE6 CCEPaletクラス  2005/07/13


/*========================================================*/
    <<<あゆしゃのC言語プログラミング>>>
/*========================================================*/
 第586回 CE6 CCEPaletクラス
 発行    2005年7月13日(水曜日)
 発行数   約2600

{magclick}
/*========================================================*/
 はじめに ( 決り文句 )
/*========================================================*/
・このメールマガジンは、主にまぐまぐさんから発行しています。
・ジャンルは、マルチメディアのプログラム、C言語です。
・横60文字で作成し、インデントは大抵半角スペース4つです。
・ここで扱うプログラムは、C言語と半光年以内のものです。
・登録解除は、メルマガのホームページでお願いします。
・過去ログはバックナンバー(下欄参照)を活用して下さい。
・内容は私が感じたもので、最新の技術も、へたれもあります。
・わかりやすさを優先させる為、たまに嘘があるかもしれません。
・セキュリティ突破のため、暗号化された単語があります。

/*========================================================*/
 ご挨拶
/*========================================================*/

 こんにちは。あゆしゃです。

 今週は、最悪な日々です。

 。。。ワンピースのないジャンプなんて。。。

 ねぇ?

{magclick}
/*========================================================*/
 今回のお題  << CE6 CCEPaletクラス >>
/*========================================================*/

 気を取り直して、CCEPaletクラスの作成です。

 前回のCCEImageクラスを継承し、パレット処理を作成します。

class CCEPalet : public CCEImage
{
protected:
    enum { PAL_SIZE = 16 };
    enum { PAL_HEIGHT = 32 };
    COLORREF pal[ PAL_SIZE ];
public:
    virtual BOOL CheckResize( int width, int height );
    virtual int HitCheck( POINT& pos );
    virtual void DrawBack( void );
    virtual void EraseSelect( void );
    virtual void DrawSelect( void );
};

 。。。なんだかバーチャルばっかりですが。。。

 各パーツごとよりも、CCEImageとして扱えたほうが便利かと
思い、仮想関数をいっぱい作ってみました。

/*========================================================*/

 CheckResizeは、CCEImageの関数としちゃいましたが、パーツ
ごとにサイズが違うということを忘れていました。

BOOL CCEPalet::CheckResize( int width, int height )
{
    // 幅は最大、縦の大きさは固定
    return CCEImage::CheckResize( width, PAL_HEIGHT );
}

/*========================================================*/

 ヒットチェックは、マウスの位置と画像の位置から、現在の
選択位置を判定します。

 忘れていましたが、スクリーン上に描画する位置とサイズは、
CCEImageが持っています、ということにします。

 イメージそのものに合わさっているかどうかは、CCEImageのほう
で大雑把に判定することにしましょう。

void CCEImage::CheckSelect( POINT& pos )
{
    if( pos.x > m_dx &&     // 始点より大きく、
        pos.y > m_dy &&
        pos.x < m_dx2 &&    // 終点より小さく、
        pos.y < m_dy2 )
    {
        int sel = HitCheck( pos );
        if( sel != m_sel ) {
            m_selold = sel;
            m_sel = sel;
        }
    }
}

int CCEPalet::HitCheck( POINT& pos )
{
    const int m = 2;        // マージン
    int x = pos.x - m_dx;   // クライアント座標に変換
    int y = pos.y - m_dy;
    int s = x / PAL_SIZE;   // 選択位置に変換
    int x1 = m_dx + GetPalX1( s ) + m;      // 選択開始位置
    int x2 = m_dx + GetPalX2( s ) - m;      // 選択終了位置
    if( x < x1 &&
        x > y2 &&
        y < m_dy + m &&
        y > m_dy2 - m )     // 範囲外だったら、
    {
        s = m_sel;          // 現在と同じ値を返す
    }
    return s;
}

 1つのパレットの範囲は描画処理でも使用する計算なので、
別関数にしました。

int CCEPalet::GetPalX1( int no )
{
    return no * m_dw / PAL_SIZE;
}
int CCEPalet::GetPalX2( int no )
{
    return ( no + 1 ) * m_dw / PAL_SIZE - 1;
}

 境界線のところの判定がシビアだと不便になるので、少し
マージンを入れています。

/*========================================================*/

 前回はDrawBallと書きましたが、選択を描画する前の処理全般、
ということにしてみました。

void CCEPalet::DrawBack( void )
{
    CCEImage::DrawBack();   // 背景色を黒で塗りつぶし
    CDC& dc = *CDC::FromHandle( img.GetDC() );  // DC取得
    for( int i = 0; i < PAL_SIZE; i++ )
    {
        DrawBall( dc, i );                      // 描画処理
    }
    img.ReleaseDC();                            // DC開放
}

 円を描く処理はEeraseSelectでも使用するので、別関数に
しました。

void CCEPalet::DrawBall( CDC& dc, int palno )
{
    int x1 = palno * m_dw / PAL_SIZE;       // 描画位置
    int x2 = ( palno + 1 ) * m_dw / PAL_SIZE - 1;
    int cx = ( x2 + x1 ) / 2;
    int dx1 = cx - cr;
    int dx2 = cx + cr;
    int dy1 = m_dh / 4;                     // 描画位置
    int dy2 = m_dh * 3 / 4;
    int cr = ( y2 - y1 ) / 2;               // 円の半径
    CBrush b( pal[ i ] );
    CBrush* pb = dc.SelectObject( &b );     // 色指定
    dc.Ellipse( dx1, dy1, dx2, dy2 );       // 描画実行
    dc.SelectObject( pb );
}

/*========================================================*/

 選択を消す処理は、その範囲を背景色で消して、丸を再描画
します。

void CCEPalet::EraseSelect( void )
{
    CDC& dc = *CDC::FromHandle( img.GetDC() );  // DC取得
    int x1 = GetPalX1( m_selold );
    int x2 = GetPalX2( m_selold );
    dc.FillSolidRect( x1, 0, x2 - x1, PAL_HEIGHT,
        GetBackColor() );
    DrawBall( dc, m_selold );
    img.ReleaseDC();                            // DC開放
}

 選択は、現在位置を四角で囲いましょう。

void CCEPalet::DrawSelect( void )
{
    CDC& dc = *CDC::FromHandle( img.GetDC() );  // DC取得
    int x1 = GetPalX1( m_selold );
    int x2 = GetPalX2( m_selold );
    dc.FillSolidRect( x1, 0, x2 - x1, PAL_HEIGHT,
        GetSelColor() );
    img.ReleaseDC();                            // DC開放
}

{magclick}
/*========================================================*/
 さいごに
/*========================================================*/

 雨も降るし、中途半端に。。

{magclick}
/*========================================================*/
 次回予告
/*========================================================*/

 次回は7月15日(金曜日)に、第587回をお送りします。
 お題は「CE7 キャラエディッタ1」

 とりあえず、パレットの選択のできるバージョンを固めましょ
う。

 お楽しみに!

/*========================================================*/
 最後の決り文句
/*========================================================*/
 このメールマガジンは、まぐまぐさんから発行しています。
 このメールマガジンを解除したい場合は、まぐまぐさんをご利用
ください。このメルマガのまぐまぐアイディーは最後にあります。
 このメールマガジンには広告が挿入されていますか?
 このメールマガジンの内容に文面の引用はありませんか?
 めーらっくすの場合はめーらっくすの利用方に従ってください。
 このメールマガジンの内容の、転用、流用、宣伝、リンク、
次回は金曜日ですよ! なんて大歓迎です。

{magclick}
/*========================================================*/
 
/*========================================================*/

発行者 あゆしゃ

ホームページ::あゆしゃの世界
http://ayusya.hp.infoseek.co.jp/

ご意見・ご感想・ご質問メール
mailto:ayusya@flamenco.plala.or.jp

まぐまぐ::アイディー
0000020674

まぐまぐ::登録と解除
http://www.mag2.com/m/0000020674.htm

まぐまぐ::バックナンバー
http://jazz.tegami.com/backnumber/frame.cgi?id=0000020674

めーらっくす::アイディー
MM3E1AEE285AB4F

めーらっくす::登録と解除
http://www.mailux.com/mm_dsp.php?mm_id=MM3E1AEE285AB4F 

めーらっくす::バックナンバー★最近のものならこちらが便利★
http://www.mailux.com/mm_bno_list.php?mm_id=MM3E1AEE285AB4F

ブラウザの閉じるボタンで閉じてください。