aardio 文档
aardio 范例: 拼图
import fsys.dlg;
import fonts.fontAwesome;
import win.ui;
/*DSG{{*/
var winform = win.form(text='\uD83E\uDDE9 拼图 - 自绘小游戏';right=918;bottom=587;bgcolor=0xF0F0F0;border="thin";max=false)
winform.add(
btnOpen={cls="button";text='\uD83D\uDCC2 选择图片';left=718;top=11;right=809;bottom=39;z=1};
btnStart={cls="button";text='\u25B7 开始游戏';left=821;top=11;right=912;bottom=39;z=2};
cbDifficulty={cls="combobox";left=611;top=12;right=706;bottom=38;edge=1;items={"3 x 3","4 x 4","5 x 5","6 x 6"};mode="dropdown";z=3};
dragOrphan={cls="plus";left=664;top=723;right=823;bottom=889;clipBk=false;transparent=1;z=9};
gameCanvas={cls="plus";left=0;top=0;right=570;bottom=587;db=1;dl=1;dt=1;edge=1;notify=1;z=4};
lblStatus={cls="plus";text="请选择图片并开始计时";left=581;top=339;right=911;bottom=369;align="left";clip=1;color=0x666666;font=LOGFONT(h=-14);notify=1;z=7};
lblTime={cls="plus";text="时间: 0s";left=581;top=304;right=911;bottom=332;align="left";color=0x333333;font=LOGFONT(h=-16);z=6};
previewBox={cls="plus";left=582;top=51;right=912;bottom=291;border={color=0xFFCCCCCC;radius=4;width=1};z=5};
sideArea={cls="plus";left=581;top=376;right=911;bottom=584;bgcolor=0xE8E8E8;border={color=0xFFCCCCCC;radius=4;width=1};db=1;dl=1;dr=1;z=8}
)
/*}}*/
winform.cbDifficulty.selIndex = 1;
var gameState = {
imagePath = null;
srcBitmap = null;
blurBitmap = null;
gridN = 3;
cellW = 0;
cellH = 0;
boardX = 0;
boardY = 0;
boardW = 600;
boardH = 600;
knobRatio = 0.22;
pieces = {};
dragging = null;
dragOffX = 0;
dragOffY = 0;
gameStep = 0;
gameCompleted = false;
startTime = 0;
elapsedTime = 0;
placedCount = 0;
totalPieces = 0;
};
import sys.midiOut;
var midiOut = sys.midiOut();
var snapThreshold;
// 生成边信息表
var generateEdges = function(n) {
var edges = {};
for(row=1; n) {
edges[row] = {};
for(col=1; n) {
edges[row][col] = {top=0; right=0; bottom=0; left=0};
}
}
for(row=1; n) {
for(col=1; n) {
if(col < n) {
var v = (math.random(0,1) == 0) ? 1 : -1;
edges[row][col].right = v;
edges[row][col+1].left = -v;
}
if(row < n) {
var v = (math.random(0,1) == 0) ? 1 : -1;
edges[row][col].bottom = v;
edges[row+1][col].top = -v;
}
}
}
return edges;
};
// 生成边的路径点序列
var buildEdgePoints = function(x0, y0, x1, y1, edgeType, knobSize) {
if(edgeType == 0) {
return { {x=x1; y=y1} };
}
var dx = x1 - x0;
var dy = y1 - y0;
var len = math.sqrt(dx*dx + dy*dy);
if(len < 1) return { {x=x1; y=y1} };
var ux = dx / len;
var uy = dy / len;
var nx = -uy;
var ny = ux;
var dir = edgeType;
var ks = knobSize * len;
var t1 = 0.35;
var t2 = 0.65;
var neckW = 0.10 * len;
var headH = ks;
var p1x = x0 + dx * t1;
var p1y = y0 + dy * t1;
var p2x = p1x + nx * dir * neckW * 0.3;
var p2y = p1y + ny * dir * neckW * 0.3;
var p3x = x0 + dx * (t1 - 0.05) + nx * dir * headH;
var p3y = y0 + dy * (t1 - 0.05) + ny * dir * headH;
var p4x = x0 + dx * 0.5 + nx * dir * headH;
var p4y = y0 + dy * 0.5 + ny * dir * headH;
var p5x = x0 + dx * (t2 + 0.05) + nx * dir * headH;
var p5y = y0 + dy * (t2 + 0.05) + ny * dir * headH;
var p6x = x0 + dx * t2 + nx * dir * neckW * 0.3;
var p6y = y0 + dy * t2 + ny * dir * neckW * 0.3;
var p7x = x0 + dx * t2;
var p7y = y0 + dy * t2;
return {
{x=p1x; y=p1y}, {x=p2x; y=p2y}, {x=p3x; y=p3y}, {x=p4x; y=p4y},
{x=p5x; y=p5y}, {x=p6x; y=p6y}, {x=p7x; y=p7y}, {x=x1; y=y1}
};
};
// 构建拼图块路径
var buildPiecePath = function(row, col, cellW, cellH, edgeInfo, knobRatio) {
var x0, y0 = 0, 0;
var x1, y1 = cellW, cellH;
var path = gdip.path();
var topPts = buildEdgePoints(x0, y0, x1, y0, edgeInfo.top, knobRatio);
var rightPts = buildEdgePoints(x1, y0, x1, y1, edgeInfo.right, knobRatio);
var bottomPts = buildEdgePoints(x1, y1, x0, y1, edgeInfo.bottom, knobRatio);
var leftPts = buildEdgePoints(x0, y1, x0, y0, edgeInfo.left, knobRatio);
var addEdge = function(pts, startX, startY) {
if(#pts == 1) {
path.addLine(startX, startY, pts[1].x, pts[1].y);
}
else {
path.addLine(startX, startY, pts[1].x, pts[1].y);
path.addBezier(pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y, pts[4].x, pts[4].y);
path.addBezier(pts[4].x, pts[4].y, pts[5].x, pts[5].y, pts[6].x, pts[6].y, pts[7].x, pts[7].y);
path.addLine(pts[7].x, pts[7].y, pts[8].x, pts[8].y);
}
};
addEdge(topPts, x0, y0);
addEdge(rightPts, x1, y0);
addEdge(bottomPts, x1, y1);
addEdge(leftPts, x0, y1);
path.closeFigure();
return path;
};
// 切割拼图块位图
var cutPieceBitmap = function(srcBmp, row, col, cellW, cellH, piecePath, knobRatio) {
var margin = math.ceil(cellW * knobRatio * 1.2);
var marginH = math.ceil(cellH * knobRatio * 1.2);
if(marginH > margin) margin = marginH;
var bmpW = cellW + margin * 2;
var bmpH = cellH + margin * 2;
var pieceBmp = gdip.bitmap(bmpW, bmpH);
var g = gdip.graphics(pieceBmp);
g.smoothingMode = 4;
g.interpolationMode = 7;
g.pixelOffsetMode = 4;
g.translate(margin, margin);
g.setClipPath(piecePath);
var srcX = (col - 1) * cellW;
var srcY = (row - 1) * cellH;
g.drawImageRectRect(srcBmp, -margin, -margin, bmpW, bmpH, srcX - margin, srcY - margin, bmpW, bmpH);
g.resetClip();
g.resetTransform();
g.translate(margin, margin);
var pen = gdip.pen(0x80000000, 1.5);
g.drawPath(pen, piecePath);
pen.delete();
g.delete();
return pieceBmp, margin;
};
// 碰撞检测
var hitTestPiece = function(piece, mx, my) {
var p = piece;
var px = p.currentX - p.margin;
var py = p.currentY - p.margin;
return mx >= px && mx <= px + p.bmpW && my >= py && my <= py + p.bmpH;
};
// 吸附检测
var checkSnap = function(piece) {
if(piece.rotation % 360 != 0) return false;
var dx = math.abs(piece.currentX - piece.targetX);
var dy = math.abs(piece.currentY - piece.targetY);
if(!snapThreshold) snapThreshold = gameState.cellW * 0.25;
return dx < snapThreshold && dy < snapThreshold;
};
// 执行吸附并返回是否成功
var trySnapPiece = function(piece) {
if(checkSnap(piece)) {
piece.currentX = piece.targetX;
piece.currentY = piece.targetY;
piece.rotation = 0;
piece.placed = true;
gameState.placedCount++;
if(midiOut) {
midiOut.play("changeInstrument(14), 5_", "C5", 80);
}
if(gameState.placedCount >= gameState.totalPieces) {
gameState.gameCompleted = true;
gameState.elapsedTime = math.floor((time.tick() - gameState.startTime) / 1000);
winform.lblStatus.text = string.format("恭喜完成!用时 %d 秒", gameState.elapsedTime);
winform.btnStart.text = "▷ 开始游戏";
}
return true;
}
return false;
};
var constrainPiecePosition = function(piece) {
var gs = gameState;
var canvasRc = winform.gameCanvas.getClientRect();
var canvasW = canvasRc.right;
var canvasH = canvasRc.bottom;
// 确保至少有一部分图块在画布内可见
var minVisible = math.min(gs.cellW, gs.cellH) * 0.4;
// 左边界
if(piece.currentX + gs.cellW < minVisible) {
piece.currentX = minVisible - gs.cellW * 0.5;
}
// 右边界
if(piece.currentX > canvasW - minVisible) {
piece.currentX = canvasW - minVisible - gs.cellW * 0.5;
}
// 上边界
if(piece.currentY + gs.cellH < minVisible) {
piece.currentY = minVisible - gs.cellH * 0.5;
}
// 下边界
if(piece.currentY > canvasH - minVisible) {
piece.currentY = canvasH - minVisible - gs.cellH * 0.5;
}
};
// 绘制拼图块
var drawPieceOnGraphics = function(graphics, piece) {
var p = piece;
var drawX = p.currentX - p.margin;
var drawY = p.currentY - p.margin;
if(p.rotation % 360 == 0) {
graphics.drawImage(p.bitmap, drawX, drawY);
}
else {
var cx = drawX + p.bmpW / 2;
var cy = drawY + p.bmpH / 2;
graphics.save();
graphics.translate(cx, cy);
graphics.rotate(p.rotation);
graphics.translate(-cx, -cy);
graphics.drawImage(p.bitmap, drawX, drawY);
graphics.restore();
}
};
// 计算 dragOrphan 的精确屏幕位置
var calcDragOrphanPos = function(piece) {
var p = piece;
var size = math.max(p.bmpW, p.bmpH) + 20;
var bmpOffsetX = (size - p.bmpW) / 2;
var bmpOffsetY = (size - p.bmpH) / 2;
var canvasDrawX = p.currentX - p.margin;
var canvasDrawY = p.currentY - p.margin;
var screenX, screenY = win.toScreen(winform.gameCanvas.hwnd, canvasDrawX, canvasDrawY);
var dragX = screenX - bmpOffsetX;
var dragY = screenY - bmpOffsetY;
return dragX, dragY, size;
};
var updateDragWindow = function(piece) {
if(!piece) {
winform.dragOrphan.show(false);
return;
}
var p = piece;
var size = math.max(p.bmpW, p.bmpH) + 20;
var dragBmp = gdip.bitmap(size, size);
var g = gdip.graphics(dragBmp);
g.smoothingMode = 4;
g.interpolationMode = 7;
g.save();
g.translate(size / 2, size / 2);
if(p.rotation % 360 != 0) g.rotate(p.rotation);
g.translate(-p.bmpW / 2, -p.bmpH / 2);
g.drawImage(p.bitmap, 0, 0);
g.restore();
g.delete();
winform.dragOrphan.background = dragBmp;
var dragX, dragY, dragSize = calcDragOrphanPos(p);
winform.dragOrphan.setPos(dragX, dragY, dragSize, dragSize);
winform.dragOrphan.show(4/*_SW_SHOWNOACTIVATE*/);
};
// 随机散布拼图块
var scatterPieces = function() {
var gs = gameState;
var canvasRc = winform.gameCanvas.getClientRect();
var canvasW = canvasRc.right;
var canvasH = canvasRc.bottom;
for(i=1; #gs.pieces) {
var p = gs.pieces[i];
if(!p.placed) {
p.rotation = math.random(0, 3) * 90;
var maxX = canvasW - gs.cellW;
var maxY = canvasH - gs.cellH;
p.currentX = math.random(10, math.max(10, maxX));
p.currentY = math.random(10, math.max(10, maxY));
}
}
for(i=#gs.pieces; 1; -1) {
var j = math.random(1, i);
gs.pieces[i], gs.pieces[j] = gs.pieces[j], gs.pieces[i];
}
};
var cleanupPieces = function() {
var gs = gameState;
for(i=1; #gs.pieces) {
var p = gs.pieces[i];
if(p.bitmap) { p.bitmap.delete(); p.bitmap = null; }
if(p.path) { p.path.delete(); p.path = null; }
}
gs.pieces = {};
};
var initPuzzle = function() {
var gs = gameState;
cleanupPieces();
gs.placedCount = 0;
gs.gameCompleted = false;
gs.elapsedTime = 0;
gs.dragging = null;
if(!gs.srcBitmap) return;
var n = gs.gridN;
var canvasRc = winform.gameCanvas.getClientRect();
var canvasW = canvasRc.right;
var canvasH = canvasRc.bottom;
var boardMargin = 30;
var boardSize = math.min(canvasW, canvasH) - boardMargin * 2;
gs.boardW = boardSize;
gs.boardH = boardSize;
gs.boardX = (canvasW - boardSize) / 2;
gs.boardY = (canvasH - boardSize) / 2;
gs.cellW = boardSize / n;
gs.cellH = boardSize / n;
snapThreshold = gs.cellW * 0.25;
var scaledBmp = gdip.bitmap(boardSize, boardSize);
var sg = gdip.graphics(scaledBmp);
sg.interpolationMode = 7;
sg.drawImageRect(gs.srcBitmap, 0, 0, boardSize, boardSize);
sg.delete();
var edges = generateEdges(n);
gs.totalPieces = n * n;
var pieceIndex = 0;
for(row=1; n) {
for(col=1; n) {
pieceIndex++;
var edgeInfo = edges[row][col];
var pPath = buildPiecePath(row, col, gs.cellW, gs.cellH, edgeInfo, gs.knobRatio);
var pBmp, margin = cutPieceBitmap(scaledBmp, row, col, gs.cellW, gs.cellH, pPath, gs.knobRatio);
var targetX = gs.boardX + (col - 1) * gs.cellW;
var targetY = gs.boardY + (row - 1) * gs.cellH;
var piece = {
index = pieceIndex;
row = row;
col = col;
bitmap = pBmp;
path = pPath;
margin = margin;
bmpW = pBmp.width;
bmpH = pBmp.height;
targetX = targetX;
targetY = targetY;
currentX = 0;
currentY = 0;
rotation = 0;
placed = false;
};
table.push(gs.pieces, piece);
}
}
scaledBmp.delete();
scatterPieces();
};
winform.gameCanvas.onDrawBackground = function(graphics,rc,backgroundColor,foregroundColor){
var p1 = ::POINTF(0, 0);
var p2 = ::POINTF(rc.right, rc.bottom);
var brush = gdip.lineBrush(p1, p2, 0xFF2c3e50, 0xFF34495e);
graphics.fillRectangle(brush, rc);
brush.delete();
};
winform.gameCanvas.onDrawContent = function(graphics,rc,txtColor,rcContent,foregroundColor,font){
var gs = gameState;
if(gs.gameStep < 2 && #gs.pieces == 0) {
var font = gdip.font("Microsoft YaHei", 16, 0, 3);
var fmt = gdip.stringformat();
fmt.align = 1;
fmt.lineAlign = 1;
var brush = gdip.solidBrush(0x80FFFFFF);
var tip;
if(gs.gameStep) {
tip = "尽快记住图片,点这里「开始拼图」"
} else {
tip = gs.srcBitmap ? "图片已加载,点这里「开始游戏」" : "点这里「选择图片」"
}
graphics.drawString(tip, font, ::RECTF(0, 0, rc.right, rc.bottom), fmt, brush);
brush.delete(); fmt.delete(); font.delete();
return;
}
if(#gs.pieces == 0) return;
var boardBrush = gdip.solidBrush(0x20FFFFFF);
graphics.fillRectangle(boardBrush, ::RECTF(gs.boardX, gs.boardY, gs.boardW, gs.boardH));
boardBrush.delete();
// 绘制网格线
var gridPen = gdip.pen(0x40FFFFFF, 1);
gridPen.setDashStyle(2);
var n = gs.gridN;
for(i=0; n) {
var x = gs.boardX + i * gs.cellW;
graphics.drawLine(gridPen, x, gs.boardY, x, gs.boardY + gs.boardH);
}
for(i=0; n) {
var y = gs.boardY + i * gs.cellH;
graphics.drawLine(gridPen, gs.boardX, y, gs.boardX + gs.boardW, y);
}
gridPen.delete();
// 先绘制已放置的拼图块
for(i=1; #gs.pieces) {
var p = gs.pieces[i];
if(p.placed) {
drawPieceOnGraphics(graphics, p);
}
}
// 再绘制未放置的拼图块(不含正在拖拽的)
for(i=1; #gs.pieces) {
var p = gs.pieces[i];
if(!p.placed && !(gs.dragging && gs.dragging.index == p.index)) {
drawPieceOnGraphics(graphics, p);
}
}
var borderPen = gdip.pen(0x80FFFFFF, 2);
graphics.drawRectangle(borderPen, gs.boardX, gs.boardY, gs.boardW, gs.boardH);
borderPen.delete();
// 游戏结束提示
if(gs.gameCompleted) {
var maskBrush = gdip.solidBrush(0xA000b894);
graphics.fillRectangle(maskBrush, ::RECTF(0, rc.bottom * 0.35, rc.right, rc.bottom * 0.3));
maskBrush.delete();
var font = gdip.font("Microsoft YaHei", 22, 0, 3);
var fmt = gdip.stringformat();
fmt.align = 1;
fmt.lineAlign = 1;
var msg = string.format("恭喜完成!用时 %d 秒", gs.elapsedTime);
var msgBrush = gdip.solidBrush(0xFFFFFFFF);
graphics.drawString(msg, font, ::RECTF(0, rc.bottom * 0.35, rc.right, rc.bottom * 0.3), fmt, msgBrush);
msgBrush.delete(); fmt.delete(); font.delete();
winform.btnStart.text = "▷ 开始游戏";
winform.btnStart.disabled = false;
winform.btnOpen.disabled = false;
winform.previewBox.redraw();
winform.lblStatus.text = "已完成,点击「开始游戏」重新开始";
if(midiOut) midiOut.play("changeInstrument(10), 1_,3_,5_,1'__", "C4", 150);
}
};
winform.gameCanvas.onMouseDown = function(wParam, lParam) {
var gs = gameState;
if((gs.gameStep != 2) || gs.gameCompleted) {
if( !gs.gameSte ){
if(! gs.srcBitmap) return winform.btnOpen.oncommand();
return winform.btnStart.oncommand();
}
}
var mx, my = win.getMessagePos(lParam);
for(i=#gs.pieces; 1; -1) {
var p = gs.pieces[i];
if(!p.placed && hitTestPiece(p, mx, my)) {
gs.dragging = p;
gs.dragOffX = mx - p.currentX;
gs.dragOffY = my - p.currentY;
table.remove(gs.pieces, i);
table.push(gs.pieces, p);
win.setCapture(winform.gameCanvas.hwnd);
updateDragWindow(p);
owner.redraw();
return;
}
}
};
winform.gameCanvas.onMouseDrag = function(wParam, lParam) {
var gs = gameState;
if(!gs.dragging) return;
var mx, my = win.getMessagePos(lParam);
gs.dragging.currentX = mx - gs.dragOffX;
gs.dragging.currentY = my - gs.dragOffY;
// 只更新悬浮窗位置,不重绘画布
var p = gs.dragging;
var dragX, dragY, size = calcDragOrphanPos(p);
winform.dragOrphan.setPos(dragX, dragY, size, size);
};
winform.gameCanvas.onMouseUp = function(wParam, lParam) {
var gs = gameState;
win.releaseCapture();
if(!gs.dragging) return;
var p = gs.dragging;
var mx, my = win.getMessagePos(lParam);
p.currentX = mx - gs.dragOffX;
p.currentY = my - gs.dragOffY;
constrainPiecePosition(p);
trySnapPiece(p);
gs.dragging = null;
// 先隐藏悬浮窗再重绘画布
winform.dragOrphan.show(false);
owner.redraw();
};
winform.gameCanvas.onRightMouseDown = function(wParam, lParam) {
var gs = gameState;
if((gs.gameStep != 2) || gs.gameCompleted) return;
var mx, my = win.getMessagePos(lParam);
for(i=#gs.pieces; 1; -1) {
var p = gs.pieces[i];
if(!p.placed && hitTestPiece(p, mx, my)) {
p.rotation = (p.rotation + 90) % 360;
if(trySnapPiece(p)) {
owner.redraw();
return;
}
if(gs.dragging && gs.dragging.index == p.index) {
updateDragWindow(p);
}
owner.redraw();
if(midiOut) {
midiOut.play("changeInstrument(115), 3_", "C4", 60);
}
return;
}
}
};
winform.previewBox.onDrawContent = function(graphics, rc) {
graphics.smoothingMode = 4;
graphics.interpolationMode = 7;
var gs = gameState;
var img = (gs.gameStep == 1 || gs.gameCompleted) ? gs.srcBitmap : gs.blurBitmap;
if(!img) {
var font = gdip.font("Microsoft YaHei", 11, 0, 3);
var fmt = gdip.stringformat();
fmt.align = 1; fmt.lineAlign = 1;
var brush = gdip.solidBrush(0xFF999999);
graphics.drawString("预览图", font, ::RECTF(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top), fmt, brush);
brush.delete(); fmt.delete(); font.delete();
return;
}
graphics.drawImageScale(img, rc);
};
winform.setInterval(function() {
var gs = gameState;
if(gs.gameStep > 0 && !gs.gameCompleted) {
gs.elapsedTime = math.floor((time.tick() - gs.startTime) / 1000);
winform.lblTime.text = string.format("⏱ 时间: %d 秒", gs.elapsedTime);
if(gs.gameStep > 1) {
winform.lblStatus.text = string.format("已完成: %d / %d", gs.placedCount, gs.totalPieces);
} else {
winform.lblStatus.text = "记住图片并点击开始拼图";
}
}
}, 1000);
winform.btnOpen.oncommand = function() {
var path = fsys.dlg.open("图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif||",,"选择拼图图片");
if(!path) return;
if(gameState.srcBitmap) {
gameState.srcBitmap.delete();
gameState.srcBitmap = null;
}
if(gameState.blurBitmap) {
gameState.blurBitmap.delete();
gameState.blurBitmap = null;
}
gameState.imagePath = path;
gameState.srcBitmap = gdip.bitmap(path);
gameState.gameCompleted = false;
gameState.gameStep = 0;
if(!gameState.srcBitmap) {
winform.msgboxErr("无法加载图片文件");
return;
}
gameState.blurBitmap = gameState.srcBitmap.getThumbnailImage(
winform.previewBox.width * 0.02, winform.previewBox.height * 0.02, true);
winform.previewBox.redraw();
winform.lblStatus.text = "图片已加载,点击「开始游戏」";
winform.gameCanvas.redraw();
};
winform.btnStart.oncommand = function() {
var gs = gameState;
if(!gs.srcBitmap) {
winform.msgbox("请先选择一张图片", "提示");
return;
}
winform.btnOpen.disabled = true;
if(gs.gameStep == 0 || gs.gameCompleted) {
cleanupPieces();
gs.gameCompleted = false;
gs.placedCount = 0;
gs.dragging = null;
gs.gameStep = 1;
gs.startTime = time.tick();
gs.elapsedTime = 0;
winform.btnStart.text = "🧩 开始拼图";
winform.btnStart.disabled = false;
winform.gameCanvas.redraw();
winform.previewBox.redraw();
return;
}
// gameStep==1 时,开始拼图
if(gs.gameStep != 1) {
return;
}
var selIdx = winform.cbDifficulty.selIndex;
var difficulties = {3, 4, 5, 6};
gs.gridN = difficulties[selIdx] : 3;
snapThreshold = null;
initPuzzle();
gs.gameStep = 2;
winform.previewBox.redraw();
winform.btnStart.text = "🧩 正在拼图";
winform.btnStart.disabled = true;
winform.lblStatus.text = string.format("拼图进行中!%dx%d = %d 块", gs.gridN, gs.gridN, gs.totalPieces);
winform.gameCanvas.redraw();
if(midiOut) {
midiOut.play("changeInstrument(10), 1_,2_,3_,4_,5_", "C4", 80);
}
};
winform.sideArea.onDrawContent = function(graphics, rc) {
graphics.smoothingMode = 4;
var font = gdip.font("Segoe UI Emoji", 10, 0, 3);
var fmt = gdip.stringformat();
fmt.align = 1;
var brush = gdip.solidBrush(0xFF666666);
var tips = {
"🖱 左键拖拽拼图块";
"🔄 右键旋转拼图块";
"📌 靠近正确位置自动吸附";
"🎯 旋转角度正确才能吸附";
};
var dpiX, dpiY = winform.dpiScale(1, 1);
var lineHeight = 35 * dpiY;
var y = 20 * dpiY;
for(i=1; #tips) {
graphics.drawString(tips[i], font, ::RECTF(rc.left, y, rc.right - rc.left, 30 * dpiY), fmt, brush);
y += lineHeight;
}
brush.delete(); fmt.delete(); font.delete();
};
//winform.gameCanvas.dlgCode = 4/*_DLGC_WANTALLKEYS*/
winform.gameCanvas.cursor = ::User32.LoadCursor(null,32649/*_IDC_HAND*/);
winform.show();
//悬浮窗口,独立窗口,与所有者窗口(原来的父窗口)保持相对位置
winform.dragOrphan.orphanWindow(true/*转为透明分层窗口*/);
win.loopMessage();
Markdown 格式