/////////////////////////////////////////////////
// 主函数
/////////////////////////////////////////////////
int main()
{
//////// 窗口配置
// 初始化绘图窗口及颜色
initgraph(640, 480);
InitColor();
// 主窗口画布
IMAGE* imgWnd = GetWorkingImage();
//////// 数学参数
// 初始化 Mandelbrot Set(曼德布洛特集)座标系
double fromx, fromy, tox, toy;
fromx = -2.1; tox = 1.1;
fromy = -1.2; toy = 1.2;
//////// 界面 UI
RECT rctHelpBtn = { 2, 480 - 20, 50, 478 }; // 帮助按钮区域
//////// 鼠标消息
// 捕获鼠标操作,实现放大鼠标选中区域
ExMessage m;
bool isLDown = false;
int selfx, selfy, seltx, selty; // 定义选区
// 计算鼠标位置对应的 Mandelbrot Set 座标
COMPLEX z = { 0, 0 };
// 计算对比模式的 C 值换算到屏幕座标的位置
POINT comparePt;
//////// 对比模式
bool isInCompareMode = false; // 是否在对比模式中
COMPLEX compareC = { 0, 0 }; // 用于存储 Julia Set 的 c 值
//////// 窗口绘制
// 窗口图像记录,用于刷新背景,快速绘制不同的表层内容
IMAGE imgLeftWnd(640, 480);
IMAGE imgRightWnd(640, 480);
// 重绘左侧窗口的函数
auto RedrawLeftWnd = [&]()
{
DrawMandelbrot(fromx, fromy, tox, toy);
DrawHelpButton(rctHelpBtn);
WCHAR buf[128] = L"Mandelbrot Set";
outtextxy(0, 0, buf);
getimage(&imgLeftWnd, 0, 0, 640, 480);
};
// 重绘右侧窗口的函数
auto RedrawRightWnd = [&]()
{
// 绘制 Julia Set
if (isInCompareMode)
{
// 绘制 Julia Set (茱莉亚集)
double fromx, fromy, tox, toy;
fromx = -2.1; tox = 1.1;
fromy = -1.2; toy = 1.2;
setorigin(640, 0); // 设置原点到右侧
DrawJulia(fromx, fromy, tox, toy, compareC);
setorigin(0, 0); // 恢复原点到左侧
flushmessage(EX_MOUSE); // 清空在绘制过程中缓冲的鼠标消息
}
else
{
// 未定义行为
}
WCHAR buf[128] = { 0 };
swprintf(buf, 127, L"Julia Set | c = %.3f %+.3fi", compareC.re, compareC.im);
outtextxy(640, 0, buf);
getimage(&imgRightWnd, 640, 0, 640 * 2, 480);
};
RedrawLeftWnd();
//////// 主循环
do
{
//////// 获取鼠标消息,进行一些坐标的计算
getmessage(&m, EM_MOUSE | EM_KEY); // 获取一条鼠标消息
z.re = fromx + (tox - fromx) * (m.x / 640.0);
z.im = fromy + (toy - fromy) * (m.y / 480.0);
comparePt.x = (int)((compareC.re - fromx) * 640 / (tox - fromx));
comparePt.y = (int)((compareC.im - fromy) * 480 / (toy - fromy));
switch (m.message)
{
case WM_KEYDOWN:
break;
// 按鼠标中键恢复原图形座标系
case WM_MBUTTONUP:
// 在 Juila 集右键,退出对比模式
if (m.x > 640)
{
Resize(nullptr, 640, 480); // 恢复窗口大小
isInCompareMode = false; // 退出对比模式
}
else
{
fromx = -2.1; tox = 1.1;
fromy = -1.2; toy = 1.2;
RedrawLeftWnd(); // 重绘左侧窗口
}
break;
// 按鼠标左键并拖动,选择区域
case WM_MOUSEMOVE:
{
putimage(0, 0, &imgLeftWnd);
if (isInCompareMode)
{
putimage(640, 0, &imgRightWnd);
DrawSelCircle(comparePt.x, comparePt.y, 5);
}
// 只在左侧 Mandelbrot 区域显示复平面坐标
if (m.x < 640)
{
WCHAR buf[64] = { 0 };
swprintf(buf, 63, L"%.3f + %.3fi", z.re, z.im);
outtextxy(m.x, m.y - 10, buf);
}
if (isLDown)
{
seltx = m.x;
selty = m.y;
rectangle(selfx, selfy, seltx, selty);
}
}
break;
// 按鼠标左键并拖动,选择区域
case WM_LBUTTONDOWN:
setlinecolor(WHITE);
//setrop2(R2_XORPEN);
isLDown = true;
selfx = seltx = m.x;
selfy = selty = m.y;
rectangle(selfx, selfy, seltx, selty);
break;
// 按鼠标左键并拖动,选择区域
case WM_LBUTTONUP:
isLDown = false;
// 检测帮助按钮
if (m.x >= rctHelpBtn.left && m.x <= rctHelpBtn.right &&
m.y >= rctHelpBtn.top && m.y <= rctHelpBtn.bottom)
{
HelpMsgBox();
break;
}
// 选择区域
//rectangle(selfx, selfy, seltx, selty);
//setrop2(R2_COPYPEN);
seltx = m.x;
selty = m.y;
if (selfx == seltx || selfy == selty) break;
// 修正选区为 4:3
int tmp;
if (selfx > seltx) { tmp = selfx; selfx = seltx; seltx = tmp; }
if (selfy > selty) { tmp = selfy; selfy = selty; selty = tmp; }
if ((seltx - selfx) * 0.75 < (selty - selfy))
{
selty += (3 - (selty - selfy) % 3);
selfx -= (selty - selfy) / 3 * 4 / 2 - (seltx - selfx) / 2;
seltx = selfx + (selty - selfy) / 3 * 4;
}
else
{
seltx += (4 - (seltx - selfx) % 4);
selfy -= (seltx - selfx) * 3 / 4 / 2 - (selty - selfy) / 2;
selty = selfy + (seltx - selfx) * 3 / 4;
}
// 更新座标系
double f, t;
f = fromx + (tox - fromx) * selfx / 640;
t = fromx + (tox - fromx) * seltx / 640;
fromx = f;
tox = t;
f = fromy + (toy - fromy) * selfy / 480;
t = fromy + (toy - fromy) * selty / 480;
fromy = f;
toy = t;
// 画图形
RedrawLeftWnd();
break;
// 保持按下右键时,只有按下瞬间会触发 WM_RBUTTONDOWN 事件,因此作为进入对比模式的入口
case WM_RBUTTONDOWN:
if (m.x < 640)
{
isInCompareMode = true;
Resize(nullptr, 640 * 2, 480); // 将窗口宽度扩展到 1280 像素
}
break;
}
// 按鼠标右键,显示 Julia Set(茱莉亚集)
// 按住右键可以连续查看不同位置的 Julia Set
if (isInCompareMode && m.rbutton && m.x < 640)
{
// 设置对比模式的 c 值为当前鼠标位置对应的 Mandelbrot Set 座标
compareC = z;
RedrawRightWnd();
}
} while (m.message != WM_KEYDOWN);
closegraph();
return 0;
}
2025年06月09日 11点06分
8