137 lines
4.7 KiB
C++
137 lines
4.7 KiB
C++
/* paint.cpp — Deshab 画板(GUI PE64 工具)
|
||||
|
|
*
|
|||
|
|
* 顶栏:色板(10 色)+ 笔刷(2/6/12px)+ Clear。
|
|||
|
|
* 客户区:左键拖拽画线(独立持久层,UI 每帧叠加)。
|
|||
|
|
* 键盘:C = 清空;Esc 关闭。
|
|||
|
|
* 无文件 IO(shim CreateFileA → PE-E05),本工具为纯画布。
|
|||
|
|
*/
|
|||
|
|
#include "pe_tool.h"
|
|||
|
|
|
|||
|
|
#define TB_H 52
|
|||
|
|
#define SWATCH_N 10
|
|||
|
|
#define SWATCH_S 24
|
|||
|
|
|
|||
|
|
static const u32 g_swatches[SWATCH_N] = {
|
|||
|
|
PTCOL(0x1A, 0x1A, 0x1A), PTCOL(0xFF, 0xFF, 0xFF),
|
|||
|
|
PTCOL(0xC4, 0x2B, 0x1C), PTCOL(0xF7, 0x63, 0x16),
|
|||
|
|
PTCOL(0xFF, 0xB9, 0x00), PTCOL(0x0F, 0x7B, 0x0F),
|
|||
|
|
PTCOL(0x00, 0x67, 0xC0), PTCOL(0x8B, 0x5C, 0xF6),
|
|||
|
|
PTCOL(0xE3, 0x00, 0x8B), PTCOL(0x8A, 0x8A, 0x8A),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
static u32 *g_layer; /* 持久绘画层(画布区) */
|
|||
|
|
static int g_layer_w, g_layer_h;
|
|||
|
|
static int g_cvw; /* 实际画布宽(窗口可能被 surface 钳位) */
|
|||
|
|
static int g_color = 6; /* 默认 Win11 蓝 */
|
|||
|
|
static int g_brush = 2; /* 笔刷索引:0=2px 1=6px 2=12px */
|
|||
|
|
static const int g_brush_px[3] = { 2, 6, 12 };
|
|||
|
|
static int g_drawing;
|
|||
|
|
static int g_last_x, g_last_y;
|
|||
|
|
|
|||
|
|
static void layer_alloc(int w, int h) {
|
|||
|
|
g_layer_w = w;
|
|||
|
|
g_layer_h = h;
|
|||
|
|
for (long i = 0; i < (long)w * h; i++) g_layer[i] = PTCOL(0xFF, 0xFF, 0xFF);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void stroke_to(int x, int y) {
|
|||
|
|
int px = g_brush_px[g_brush];
|
|||
|
|
/* 持久层画线(构造视图 canvas) */
|
|||
|
|
PT_Canvas cv;
|
|||
|
|
cv.w = g_layer_w; cv.h = g_layer_h; cv.bits = g_layer;
|
|||
|
|
pt_line(&cv, g_last_x, g_last_y, x, y, px, g_swatches[g_color]);
|
|||
|
|
pt_disc(&cv, x, y, px / 2, g_swatches[g_color]);
|
|||
|
|
g_last_x = x; g_last_y = y;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void mouse(int x, int y, int buttons, int edge) {
|
|||
|
|
int cw = g_cvw;
|
|||
|
|
|
|||
|
|
/* 顶栏命中 */
|
|||
|
|
if (edge & 1) { /* 左键按下 */
|
|||
|
|
if (y < TB_H) {
|
|||
|
|
/* 色板 */
|
|||
|
|
for (int i = 0; i < SWATCH_N; i++) {
|
|||
|
|
int sx = 10 + i * (SWATCH_S + 6);
|
|||
|
|
if (x >= sx && x < sx + SWATCH_S &&
|
|||
|
|
y >= (TB_H - SWATCH_S) / 2 && y < (TB_H - SWATCH_S) / 2 + SWATCH_S) {
|
|||
|
|
g_color = i;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/* 笔刷 */
|
|||
|
|
for (int i = 0; i < 3; i++) {
|
|||
|
|
int bx = 10 + SWATCH_N * (SWATCH_S + 6) + 12 + i * 40;
|
|||
|
|
if (x >= bx && x < bx + 36 && y >= 8 && y < TB_H - 8) {
|
|||
|
|
g_brush = i;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/* Clear */
|
|||
|
|
int cx = cw - 80;
|
|||
|
|
if (x >= cx && x < cx + 72 && y >= 12 && y < TB_H - 12) {
|
|||
|
|
layer_alloc(g_layer_w, g_layer_h);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* 画布起笔 */
|
|||
|
|
g_drawing = 1;
|
|||
|
|
g_last_x = x; g_last_y = y - TB_H;
|
|||
|
|
stroke_to(x, y - TB_H);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (edge & 2) g_drawing = 0;
|
|||
|
|
if (buttons & 1 && g_drawing && y >= TB_H)
|
|||
|
|
stroke_to(x, y - TB_H);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void key(unsigned vk, unsigned ch) {
|
|||
|
|
if (ch == 'c' || ch == 'C') layer_alloc(g_layer_w, g_layer_h);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void frame(PT_Canvas *cv) {
|
|||
|
|
g_cvw = cv->w;
|
|||
|
|
/* 画布层 → DIB */
|
|||
|
|
for (int r = 0; r < g_layer_h && r + TB_H < cv->h; r++)
|
|||
|
|
for (int q = 0; q < g_layer_w && q < cv->w; q++)
|
|||
|
|
cv->bits[(long)(r + TB_H) * cv->w + q] = g_layer[(long)r * g_layer_w + q];
|
|||
|
|
|
|||
|
|
/* 顶栏 */
|
|||
|
|
pt_fill(cv, 0, 0, cv->w, TB_H, PT_BG);
|
|||
|
|
pt_fill(cv, 0, TB_H - 1, cv->w, 1, PT_STROKE);
|
|||
|
|
for (int i = 0; i < SWATCH_N; i++) {
|
|||
|
|
int sx = 10 + i * (SWATCH_S + 6);
|
|||
|
|
int sy = (TB_H - SWATCH_S) / 2;
|
|||
|
|
pt_round_fill(cv, sx, sy, SWATCH_S, SWATCH_S, g_swatches[i], 6);
|
|||
|
|
if (g_color == i)
|
|||
|
|
pt_rect(cv, sx - 2, sy - 2, SWATCH_S + 4, SWATCH_S + 4, PT_ACCENT);
|
|||
|
|
}
|
|||
|
|
for (int i = 0; i < 3; i++) {
|
|||
|
|
int bx = 10 + SWATCH_N * (SWATCH_S + 6) + 12 + i * 40;
|
|||
|
|
int bc = g_brush == i ? PT_ACCENT : PT_TEXT2;
|
|||
|
|
pt_disc(cv, bx + 18, TB_H / 2, g_brush_px[i] / 2 + 1, bc);
|
|||
|
|
if (g_brush == i)
|
|||
|
|
pt_rect(cv, bx, 8, 36, TB_H - 16, PT_ACCENT);
|
|||
|
|
}
|
|||
|
|
pt_round_fill(cv, cv->w - 80, 12, 72, TB_H - 24, PT_CARD, 4);
|
|||
|
|
pt_rect(cv, cv->w - 80, 12, 72, TB_H - 24, PT_STROKE);
|
|||
|
|
pt_text_center(cv, "Clear", cv->w - 44, TB_H / 2 - 9, PT_TEXT);
|
|||
|
|
|
|||
|
|
pt_text(cv, "C = clear Esc = close", 10, cv->h - 24, PT_TEXT_DIM);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int main(void) {
|
|||
|
|
static u32 layer_mem[900 * 700]; /* 静态层:msvcrt malloc shim 可用,但静态最稳 */
|
|||
|
|
g_layer = layer_mem;
|
|||
|
|
PT_Desc d;
|
|||
|
|
d.w = 700; d.h = 560;
|
|||
|
|
d.title = L"Paint";
|
|||
|
|
d.frame = frame;
|
|||
|
|
d.key = key;
|
|||
|
|
d.mouse = mouse;
|
|||
|
|
/* 层尺寸按期望值预分配;pt_run 钳位后窗口只会更小(绘制有界) */
|
|||
|
|
layer_alloc(700, 560 - TB_H);
|
|||
|
|
return pt_run(&d);
|
|||
|
|
}
|