GoFのCommandパターンにヒントを得て作成。
描画した履歴を文字列型配列変数に記録しておき、必要に応じて取り出します。
今回は単純な文字列型配列変数ではなく、スタックのモジュールを用意してみました。
bregexp.dll(bregonig.dll)および月影ともさんのbregexp.hspが必要です。// 文字列用スタック
#module string_stack stack, max
#modinit
max = 0
sdim stack, 32, 10
return
#deffunc new_sstack array v
newmod v, string_stack@
return
#modfunc push str s
stack(max) = s
max++
return
#defcfunc pop modvar string_stack@
if max == 0 {
logmes "引数の値が異常です。"
return ""
}
max--
return stack(max)
#defcfunc get_length modvar string_stack@
return max
#defcfunc get_last modvar string_stack@
return stack(max-1)
#defcfunc get_at modvar string_stack@, int index
if index < 0 || max <= index {
logmes "引数の値が異常です。"
return ""
}
return stack(index)
#modfunc clear_stack
max = 0
return
#global
// 矩形の塗りつぶし
// http://rpen.blogspot.com/2007/11/blog-post.html
#include "gdi32.as"
#module
#const FLOODFILLSURFACE 1
#deffunc fill int x, int y
current_color = ginfo_r, ginfo_g, ginfo_b
CreateSolidBrush (ginfo_b << 16) | (ginfo_g << 8) | ginfo_r
if stat {
hBrush = stat
} else {
dialog "ブラシの生成に失敗しました。プログラムを終了します。", 1
end
}
SelectObject hDC, hBrush
pget x, y
ExtFloodFill hdc, x, y, (ginfo_b << 16) | (ginfo_g << 8) | ginfo_r, FLOODFILLSURFACE
DeleteObject hBrush
color current_color(0), current_color(1), current_color(2)
return
#global
// 命令を解析して描画するモジュール
#include "bregexp.hsp"
#module drawer
#define ctype result(%1) int(_result(%1))
#deffunc draw str _cmd
cmd = _cmd
BSplit _result, cmd, "m/[ ,]+/"
switch _result(0)
case "moveTo" : pos result(1), result(2) : swbreak
case "lineTo" : line result(1), result(2) : swbreak
case "color" : color result(1), result(2), result(3) : swbreak
case "fill" : fill result(1), result(2) : redraw 1 : swbreak
default : logmes "未知の命令です" : swbreak
swend
return
#deffunc draw_all array cmds, int wait_time
redraw 0
color 255, 255, 255 : boxf
color
repeat get_length(cmds)
draw get_at(cmds, cnt)
if wait_time {
redraw 1
wait wait_time
redraw 0
}
loop
redraw 1
return
#global
#define push_and_do(%1,%2) push %1, %2 : draw %2
#define WM_MOUSEMOVE $00000200
#define WM_LBUTTONDOWN $00000201
#define WM_LBUTTONUP $00000202
#define WM_RBUTTONDOWN $00000204
*init
title "左ドラッグで線を描画 / 右クリックで塗りつぶし"
oncmd gosub *onLButtonDown, WM_LBUTTONDOWN
oncmd gosub *onRButtonDown, WM_RBUTTONDOWN
oncmd gosub *onLButtonUp, WM_LBUTTONUP
oncmd gosub *onMouseMove, WM_MOUSEMOVE
objsize 80
button gosub "color change", *color_change
button gosub "redraw slowly", *all_draw_slowly
button gosub "clear", *clear
button gosub "undo", *undo
new_sstack cmds
stop
// 色の変更
*color_change
hsvcolor rnd(192), 255, 255
push_and_do cmds, "color " + ginfo_r + "," + ginfo_g + "," + ginfo_b
return
// 全消去
*clear
clear_stack cmds
draw_all cmds, 0
return
// アンドゥ
*undo
tmp = pop(cmds)
draw_all cmds, 0
return
// すべて描画
*all_draw
draw_all cmds, 0
return
// ゆっくりとすべて描画
*all_draw_slowly
oncmd 0
gosub *invalidate_buttons
draw_all cmds, 4
gosub *validate_buttons
oncmd 1
return
// 左ドラッグ開始
*onLButtonDown
dragging = 1
push_and_do cmds, "moveTo " + mousex + "," + mousey
return
// 左ドラッグ終了
*onLButtonUp
dragging = 0
return
// 左ドラッグ中
*onMouseMove
if dragging {
push_and_do cmds, "lineTo " + mousex + "," + mousey
}
return
// 右クリック
*onRButtonDown
if dragging == 0 {
push_and_do cmds, "fill " + mousex + "," + mousey
}
return
#include "obj.as"
*invalidate_buttons
repeat 4
objgray cnt, 0
loop
return
*validate_buttons
repeat 4
objgray cnt, 1
loop
return
2008年2月12日火曜日
アンドゥや再生ができるペイントツール
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿