////////////////////////////////////
//ImageListサンプル−ToolBar Editor
////////////////////////////////////
//☆ツールバービットマップのサイズ定数
#define NAME		"ToolBar Editor"
#define CX_IMAGE	16
#define CY_IMAGE	15
#define CW			16
#define NONE		0
#define DRAG1		1
#define DRAG2		2
#define DRAW		3

//☆グローバル変数(2003年1月2日BaseDirを追加）
char BaseDir[MAX_PATH];		//TBEditorのあるフォールだーの下のSampleBMPフォールダー
CBMP cvsbmp;				//Canvas内のビットマップ取込用CBMPクラス変数
char* g_FileName;			//最後に読みこんだファイル名
bool g_FileGiven = FALSE;	//起動時のファイルパラメーターの有無
int g_x, g_y;				//クライアント領域の描画有効範囲
int g_Width, g_Height;		//描画有効範囲サイズ
RECT g_DispArea;			//ツールバー表示矩形
RECT g_DrawArea;			//描画領域
RECT g_SampArea;			//描画領域のサンプル表示領域
RECT g_ColArea;				//描画色選択の表示領域
RECT g_SampColArea;			//選択描画色の表示領域
int g_Busy = NONE;					//作業中フラッグ
int g_Drawx;				//描画開始ｘ座標
int g_Drawy;				//描画開始ｙ座標
int g_Color = 0;			//描画色
int g_Selected = IDM_DOT;	//選択された描画図形メニューID

//☆サイズ関係のグローバル変数を取得
void GetSize(LPARAM lParam) {

	RECT Trec, Srec;
	GetWindowRect(TBar.m_hWnd, &Trec);
	GetWindowRect(SBar.m_hWnd, &Srec);
	g_x = 0;
	g_y = Trec.bottom - Trec.top;
	g_Width = LOWORD(lParam);
	g_Height = HIWORD(lParam) - Trec.bottom + Trec.top - Srec.bottom + Srec.top;
	//ツールバービットマップ表示領域の位置設定
	g_DispArea.left = g_x + 1;
	g_DispArea.top = g_y + 1;
	g_DispArea.right = g_DispArea.left + CX_IMAGE * 32;
	g_DispArea.bottom = g_DispArea.top + CY_IMAGE;
	//描画領域の位置設定
	g_DrawArea.left = g_x + 1;
	g_DrawArea.top = g_DispArea.bottom + 1;
	g_DrawArea.right = g_DrawArea.left + CW * 16;
	g_DrawArea.bottom = g_DrawArea.top + CW * 15;
	//描画領域のサンプル表示領域
	g_SampArea.left = (g_Width + g_DrawArea.right - CX_IMAGE) / 2;
	g_SampArea.top = g_y + (g_Height + g_DispArea.bottom - CY_IMAGE) / 2;
	g_SampArea.right = g_SampArea.left + CX_IMAGE;
	g_SampArea.bottom = g_SampArea.top + CY_IMAGE;
	//描画色選択の表示領域
	g_ColArea.left = (g_Width + g_DrawArea.right - CX_IMAGE * 8) / 2;
	g_ColArea.top = g_SampArea.bottom + CW * 3;
	g_ColArea.right = g_ColArea.left + CW * 8;
	g_ColArea.bottom = g_ColArea.top + CW * 2;
	//選択描画色の表示領域
	g_SampColArea.left = (g_ColArea.left + g_DrawArea.right - CW) / 2;
	g_SampColArea.top = g_ColArea.top + CW / 2;
	g_SampColArea.right = g_SampColArea.left + CW;
	g_SampColArea.bottom = g_SampColArea.top + CW;
}

//☆イメージリストの初期化と初期表示
void InitClientArea() {

	COLORREF c = cvs.m_Color;	//描画色を退避、保存
	ImgList.DeleteImage(-1);	//全てのイメージを消去
	cvs.Color(15);
	cvs.Clear();
	cvs.Color(0);
	//ツールバービットマップ表示領域の表示
	cvs.Box(g_DispArea.left - 1, g_DispArea.top - 1, g_DispArea.right + 1, g_DispArea.bottom + 1, 0);
	//その他領域の表示
	cvs.Color(7);
	cvs.Box(g_DrawArea.right + 1, g_DrawArea.top, g_x + g_Width, g_y + g_Height, 1);
	//描画領域のサンプル表示領域の表示
	cvs.Color(15);
	cvs.Box(g_SampArea.left - 1, g_SampArea.top - 1, g_SampArea.right + 1, g_SampArea.bottom + 1, 1);
	cvs.Color(0);
	cvs.Box(g_SampArea.left - 1, g_SampArea.top - 1, g_SampArea.right + 1, g_SampArea.bottom + 1, 0);
	//描画領域の表示
	cvs.Box(g_DrawArea.left - 1, g_DrawArea.top - 1, g_DrawArea.right + 1, g_DrawArea.bottom + 1, 0);
	for(int i = 1; i < CX_IMAGE; i++)
		cvs.Line(g_DrawArea.left + i * CW, g_DrawArea.top, g_DrawArea.left + i * CW, g_DrawArea.bottom);
	for(int i = 1; i < CY_IMAGE; i++)
		cvs.Line(g_DrawArea.left, g_DrawArea.top + i * CW, g_DrawArea.right, g_DrawArea.top + i * CW);
	//描画色選択の表示領域の表示
	for(int i = 0; i < 8; i++) {
		cvs.Color(i);
		cvs.Box(g_ColArea.left + i * CW, g_ColArea.top, g_ColArea.left + (i + 1) * CW, g_ColArea.top + CW, 1);
	}
	for(int i = 0; i < 8; i++) {
		cvs.Color(i + 8);
		cvs.Box(g_ColArea.left + i * CW, g_ColArea.top + CW, g_ColArea.left + (i + 1) * CW, g_ColArea.top + CW * 2, 1);
	}
	cvs.Color(0);
	cvs.Box(g_ColArea.left - 1, g_ColArea.top - 1, g_ColArea.right + 1, g_ColArea.bottom + 1, 0);
	//選択描画色の表示領域
	cvs.m_Color = c;
	cvs.Box(g_SampColArea.left, g_SampColArea.top, g_SampColArea.right, g_SampColArea.bottom, 1);
	cvs.Color(0);
	cvs.Box(g_SampColArea.left - 1, g_SampColArea.top - 1, g_SampColArea.right + 1, g_SampColArea.bottom + 1, 0);
	cvs.m_Color = c;
}

////////////////////////////////////////
//スキャンラインシードフィルアルゴリズム
//を使った塗潰しルーチン−著作者 Fuzzy氏
////////////////////////////////////////
#define MAXSIZE	1024				//バッファサイズは1024
#define MINX	g_SampArea.left		//画面サイズ
#define MINY	g_SampArea.top
#define MAXX	g_SampArea.right - 1
#define MAXY	g_SampArea.bottom - 1

struct BUFSTR {
	int buf_lx;	//領域左端のX座標
	int buf_rx;	//領域右端のX座標
	int buf_y;	//領域のY座標
	int buf_oy;	//親ラインのY座標
};
struct BUFSTR Buffer[MAXSIZE];
struct BUFSTR *Start_Idx, *End_Idx;

void Scan_Line(int lx, int rx, int y, int oy, COLORREF col) {

	while (lx <= rx) {
		//非領域色を飛ばす
		for (; lx < rx ; lx++)
			if(GetPixel(cvs.hDC(), lx, y) == col) break;
		if(GetPixel(cvs.hDC(), lx, y) != col) break;
		End_Idx->buf_lx = lx;
		//領域色を飛ばす
		for(; lx <= rx ; lx++)
			if(GetPixel(cvs.hDC(), lx, y) != col) break;
		End_Idx->buf_rx = lx - 1;
		End_Idx->buf_y = y;
		End_Idx->buf_oy = oy;
		if(++End_Idx == &Buffer[MAXSIZE]) End_Idx = Buffer;
	}
}

void Paint(int x, int y, COLORREF paint_color) {

	int lx, rx, uy, dy, oy;
	int lxsav, rxsav;
	int i;
	COLORREF col;

	Start_Idx = Buffer;
	End_Idx = Buffer + 1;
	Start_Idx->buf_lx = Start_Idx->buf_rx = x;
	Start_Idx->buf_y = Start_Idx->buf_oy = y;
	col = GetPixel(cvs.hDC(), x, y);

	do {
		lx = Start_Idx->buf_lx;
		rx = Start_Idx->buf_rx;
		uy = Start_Idx->buf_y;
		dy = Start_Idx->buf_y;
		oy = Start_Idx->buf_oy;
		lxsav = lx - 1;
		rxsav = rx + 1;
		if(++Start_Idx == &Buffer[MAXSIZE]) Start_Idx = Buffer;
		//処理済のシードなら無視
		if (GetPixel(cvs.hDC(), lx, uy) == paint_color) continue;
		//右方向の境界を探す
		while(rx < MAXX) {
			if(GetPixel(cvs.hDC(), rx + 1, uy) != col) break;
			rx++;
		}
		//左方向の境界を探す
		while(lx > MINX) {
			if(GetPixel(cvs.hDC(), lx - 1, uy) != col ) break;
			lx--;
		}
		//lx-rxの線分を描画
//		cvs.m_Color = paint_color;	//既になっている
		for (i = lx; i <= rx; i++)	cvs.Dot(i, uy);
		//真上のスキャンラインを走査する
		if(--uy >= MINY) {
			if(uy == oy) {
				Scan_Line(lx, lxsav, uy, uy + 1, col);
				Scan_Line(rxsav, rx, uy, uy + 1, col);
			}
			else {
				Scan_Line(lx, rx, uy, uy + 1, col);
			}
		}
		//真下のスキャンラインを走査する
		if(++dy <= MAXY) {
			if(dy == oy) {
				Scan_Line(lx, lxsav, dy, dy - 1, col);
				Scan_Line(rxsav, rx, dy, dy - 1, col);
			}
			else {
				Scan_Line(lx, rx, dy, dy - 1, col);
			}
		}
	} while(Start_Idx != End_Idx);
}

//☆サンプル表示領域描画関数
void DrawSample(int x, int y) {

	//始点座標(sx, sy)と終点座標(ex, ey)を定める
	int sx = g_SampArea.left + g_Drawx;
	int sy = g_SampArea.top + g_Drawy;
	int ex = g_SampArea.left + x;
	int ey = g_SampArea.top + y;

	//色の決定
	if(g_Color < 16)				cvs.Color(g_Color);
	//点を打つ
	if(g_Selected == IDM_DOT)		cvs.Dot(ex, ey);
	//線を引く
	if(g_Selected == IDM_LINE) {	cvs.Line(sx, sy, ex, ey);
									cvs.Dot(ex, ey);}
	if(g_Selected == IDM_PAINT)		Paint(ex, ey, cvs.m_Color);
	//終了位置の修正
	if(sx < ex)			ex++;
	else if(sx > ex)	sx++;
	if(sy < ey)			ey++;
	else if(sy > ey)	sy++;
	//矩形を描く
	if(g_Selected == IDM_BOX)		cvs.Box(sx, sy, ex, ey, 0);
	//楕円を描く
	if(g_Selected == IDM_ELLIPSE)	cvs.Ellipsed(sx, sy, ex, ey, 0);
	//塗潰矩形を描く
	if(g_Selected == IDM_BOXF)		cvs.Box(sx, sy, ex, ey, 1);
	//塗潰楕円を描く
	if(g_Selected == IDM_ELLIPSEF)	cvs.Ellipsed(sx, sy, ex, ey, 1);
}

//☆サンプル表示領域を描画領域へ拡大転送
void SampToDraw() {

	cvs.GetBMP(g_SampArea.left, g_SampArea.top, CX_IMAGE, CY_IMAGE);
	cvs.FitBMP(g_DrawArea.left, g_DrawArea.top, g_DrawArea.right - g_DrawArea.left, g_DrawArea.bottom -  g_DrawArea.top, 0);
	//グリッドを描く
	COLORREF c = cvs.m_Color;	//描画色を退避、保存
	cvs.Color(0);
	for(int i = 1; i < CX_IMAGE; i++)
		cvs.Line(g_DrawArea.left + i * CW, g_DrawArea.top, g_DrawArea.left + i * CW, g_DrawArea.bottom);
	for(int i = 1; i < CY_IMAGE; i++)
		cvs.Line(g_DrawArea.left, g_DrawArea.top + i * CW, g_DrawArea.right, g_DrawArea.top + i * CW);
	cvs.m_Color = c;
}

//☆図形メニューとツールバーのチェック変更
void CheckChange(HWND hWnd, WORD Sel) {

	SendMessage(TBar.GetHandle(), TB_SETSTATE, g_Selected,
				(LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
	CheckMenuItem(GetSubMenu(GetSubMenu(GetMenu(hWnd), 1), 2), g_Selected,
				MF_UNCHECKED | MF_BYCOMMAND);
	g_Selected = Sel;
	SendMessage(TBar.GetHandle(), TB_SETSTATE, Sel,
				(LPARAM)MAKELONG(TBSTATE_ENABLED | TBSTATE_PRESSED, 0));
	CheckMenuItem(GetSubMenu(GetSubMenu(GetMenu(hWnd), 1), 2), g_Selected,
				MF_CHECKED | MF_BYCOMMAND);
}

//☆色メニューのチェック変更
void CheckColor(HWND hWnd, int Col) {
	CheckMenuItem(GetSubMenu(GetSubMenu(GetMenu(hWnd), 1), 4), g_Color,
				MF_UNCHECKED | MF_BYPOSITION);
	g_Color = Col;
	cvs.Color(g_Color);
	cvs.Box(g_SampColArea.left, g_SampColArea.top, g_SampColArea.right, g_SampColArea.bottom, 1);
	CheckMenuItem(GetSubMenu(GetSubMenu(GetMenu(hWnd), 1), 4), g_Color,
				MF_CHECKED | MF_BYPOSITION);
}

//メニュー、ビットマップボタンの状態を変える
void ChangeStatus(bool flag) {

	UINT state = flag ? MF_ENABLED : MF_DISABLED;
	//☆ファイルの保存メニューを変更にする
	EnableMenuItem(GetSubMenu(GetMenu(TBEditor.m_hWnd), 0), 2, MF_BYPOSITION | state);
	EnableMenuItem(GetSubMenu(GetMenu(TBEditor.m_hWnd), 0), 3, MF_BYPOSITION | state);
	//☆ビットマップの編集メニューを変更にする
	EnableMenuItem(GetMenu(TBEditor.m_hWnd), 1, MF_BYPOSITION | state);
	DrawMenuBar(TBEditor.m_hWnd);
	//☆ビットマップのボタン状態を変更にする
	SendMessage(TBar.m_hWnd, TB_ENABLEBUTTON, IDM_SAVE, MAKELONG(flag, 0));
	SendMessage(TBar.m_hWnd, TB_ENABLEBUTTON, IDM_ADDBMP, MAKELONG(flag, 0));
	SendMessage(TBar.m_hWnd, TB_ENABLEBUTTON, IDM_DOT, MAKELONG(flag, 0));
	SendMessage(TBar.m_hWnd, TB_ENABLEBUTTON, IDM_LINE, MAKELONG(flag, 0));
	SendMessage(TBar.m_hWnd, TB_ENABLEBUTTON, IDM_BOX, MAKELONG(flag, 0));
	SendMessage(TBar.m_hWnd, TB_ENABLEBUTTON, IDM_ELLIPSE, MAKELONG(flag, 0));
	SendMessage(TBar.m_hWnd, TB_ENABLEBUTTON, IDM_BOXF, MAKELONG(flag, 0));
	SendMessage(TBar.m_hWnd, TB_ENABLEBUTTON, IDM_ELLIPSEF, MAKELONG(flag, 0));
	SendMessage(TBar.m_hWnd, TB_ENABLEBUTTON, IDM_PAINT, MAKELONG(flag, 0));
	SendMessage(TBar.m_hWnd, TB_ENABLEBUTTON, IDM_SELEC, MAKELONG(flag, 0));
}