一个曼德勃罗特集探器/缩放器,带有朱利亚集漫游






4.33/5 (5投票s)
一个曼德勃罗特集探器/缩放器,带有朱利亚集漫游
- 下载源代码 - 10.25 KB (Visual C++ 6.0 项目文件)

引言
这个简单的应用程序和文章演示了 Windows 消息处理和在 Win32 设备上下文中进行绘制。设备上下文是一个结构体,它定义了一组图形对象及其相关属性,以及影响输出的图形模式。
图形对象包括用于绘制线条的画笔、用于绘画和填充的刷子、用于复制或滚动屏幕部分的位图、用于定义可用颜色集的调色板、用于剪切和其他操作的区域。
我们将首先声明我们的变量。
//*********************************************************************
//* Defines *
//*********************************************************************
#define pi 3.1415926
#define WIDTH 400
#define HEIGHT 400
#define WEXT 380
#define HEXT 210
#define MAGNITUDE_CUTOFF 100
#define NUMCOLOURS 256
#define ID_TIMER 1
#define DIVFACTOR 1
#define XMin -1.4
#define XMax 1.4
#define YMin -1.4
#define YMax 1.4
#define Iter 32
#define Scal 32767
#define ResX 150
#define ResY 150
// **************************************************************************
// ** Global Variables **
// **************************************************************************
bool xorDone=false;
char title[]="MandelZoom / Julia Walkabout by Topcoder",buffer[80],String[40];
int max_iterations,mousex,mousey,xorEx=0,xorEy=0,MouseX,MouseY;
double xmin = -2.10, xmax = 0.75, ymin = -1.5 , ymax = 1.5;
double width_fact, height_fact;
double midx,midy,dx,dy;
double dxx,dyy,px,py,zsx,zsy,zex,zey;
int xp,yp,random=0;
float jdx=0,jdy=0,r=0,theta=0,jx=0,jy=0,tempx,tempy;
rektangel rekt;
POINT start,end;
HDC hdc;
HWND Button[2],Edit,StatusBar;
HDC hdcMem;
HBITMAP hbmMem;
HANDLE hOld;
RECT rect;
HBRUSH hbrush = CreateSolidBrush(RGB(0,0,128));
然后我们使用 RegisterClassEx()
注册我们的窗口。
int WINAPI WinMain (HINSTANCE hinst, HINSTANCE hprevinst, LPSTR lpCmdLine,int cmdShow)
{
if (hprevinst == NULL)
{
WNDCLASSEX wclass;
wclass.cbSize = sizeof(WNDCLASSEX);
wclass.hInstance = hinst;
wclass.lpfnWndProc = (WNDPROC)WndProc;
wclass.style = CS_HREDRAW | CS_VREDRAW;
wclass.hIcon = LoadIcon(hinst, IDC_ARROW);
wclass.hIconSm = NULL;
wclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wclass.lpszMenuName = NULL;
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
wclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wclass.lpszClassName = "BASIC2";
if(!RegisterClassEx(&wclass)) return 0;
然后我们使用 CreateWindowEx()
和 ShowWindow()
创建实际的窗口并显示它。
HWND hwnd = CreateWindowEx(
WS_EX_WINDOWEDGE, // extended window style
"BASIC2", // registered class name
title, // window name
WS_OVERLAPPEDWINDOW,// window style
CW_USEDEFAULT, // horizontal position of window
CW_USEDEFAULT, // vertical position of window
WIDTH+WEXT, // window width
HEIGHT+32, // window height
NULL, // handle to parent or owner window
NULL, // menu handle or child identifier
hinst, // handle to application instance
NULL); // window-creation data
ShowWindow(hwnd, cmdShow);
UpdateWindow(hwnd);
现在,我们使用以下代码启动 Win32 消息循环。Windows 应用程序处理来自操作系统的消息,并且大多数 Win32 应用程序必须能够转换和分派窗口消息。
现在我们可以使用 TranslateMessage()
和 DispatchMessage()
发送和接收窗口消息。
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage(&msg); // send the message to the window proc
}
return msg.wParam;
}// End int WINAPI WinMain (
WM_CREATE 消息
当应用程序正在创建和实例化时,会调用 WM_CREATE 消息
。在此代码部分,使用 CreateWindow()
函数创建控件,例如按钮、列表框和组合框。
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_CREATE:
Button[0] = CreateWindow (
"button",
"reset",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
WIDTH+5, //Button position x
HEIGHT-48, //Button position y
WIDTH/2, //Button Dimension x
30, //Button Dimension y
hwnd,
(HMENU) 5 ,
((LPCREATESTRUCT) lparam)->hInstance,
NULL);
Button[1] = CreateWindow (
"button",
"Exit",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
WIDTH+(WIDTH/2)+5, //Button position x
HEIGHT-48, //Button position y
(WIDTH/2)-48, //Button Dimension x
30, //Button Dimension y
hwnd,
(HMENU) 6,
((LPCREATESTRUCT) lparam)->hInstance,
NULL);
SetTimer(hwnd,ID_TIMER,1,NULL);
break;
WM_PAINT 消息
如果应用程序的某个区域需要更新,则会调用 WM_PAINT 消息
。
我们将把我们的绘制和更新函数放在这个代码部分。
case WM_PAINT:
Paint(hwnd);
initWalk();
putCursor();
walkabout();
break;
WM_LBUTTONDOWN 消息
当按下左键时,会调用 WM_LBUTTONDOWN 消息
。当用户按下左鼠标按钮时,我们的应用程序将鼠标的当前 x 和 y 坐标存储在变量 start.x
和 start.y
中。当用户拖动鼠标时,会绘制一个矩形,它定义了要缩放的曼德勃罗特集区域的大小。
case WM_LBUTTONDOWN:
{
if (mouse_x>=0 && mouse_x<=WIDTH && mouse_y>=0 && mouse_y<=HEIGHT)
{
rekt.visa = true;
rekt.sx = (float)mouse_x;
rekt.sy = (float)mouse_y;
rekt.ex = (float)mouse_x;
rekt.ey = (float)mouse_y;
xorEx=(int)rekt.sx+100;
xorEy=(int)rekt.sy+100;
end.x=0;
end.y=0;
start.x=mouse_x;
start.y=mouse_y;
MoveToEx (hdc, start.x, start.y, NULL) ;
zsx=(xmin+(xmax-xmin)*((mousex)-px)/(WIDTH-1));
zsy=(ymin+(ymax-ymin)*((mousey)-py)/(HEIGHT-1));
zex=(xmin+(xmax-xmin)*((mousex)-px)/(WIDTH-1));
zey=(ymin+(ymax-ymin)*((mousey)-py)/(HEIGHT-1));
tempx=xmin;
tempy=ymin;
xmin=zsx;
ymin=zsy;
textout();
}
} break;
WM_MOUSEMOVE 消息
当用户拖动鼠标时,会调用 WM_MOUSEMOVE 消息
。当鼠标被拖动时,会绘制一个矩形框以显示下一个缩放区域将在哪里。
case WM_MOUSEMOVE:
{
if (mouse_x>=0 && mouse_x<=WIDTH && mouse_y>=0 && mouse_y<=HEIGHT)
{
if (mouse_x>=rekt.sx && mouse_y >=rekt.sy )
{
rekt.ex = (float)mouse_x;
rekt.ey = (float)mouse_y;
dx=zex-zsx;
dy=zey-zsy;
}
if (rekt.visa )
{
BitBlt(hdc, 0, 0, WIDTH, HEIGHT, hdcMem, 0, 0, SRCCOPY);
SetROP2(hdc,R2_NOTXORPEN);
int DrawMode = GetROP2(hdc);
MoveToEx (hdc, (int)rekt.sx, (int)rekt.sy, NULL) ;
LineTo (hdc, (int)rekt.ex ,(int)rekt.sy) ;
LineTo (hdc, (int)rekt.ex ,(int)rekt.ey) ;
LineTo (hdc, (int)rekt.sx ,(int)rekt.ey) ;
LineTo (hdc, (int)rekt.sx ,(int)rekt.sy) ;
SetROP2(hdc,R2_COPYPEN);
}
mousex=mouse_x;
mousey=mouse_y;
textout();
}
} break;
WM_LBUTTONUP 消息
当释放左键时,会调用 WM_LBUTTONUP 消息
。一旦用户释放左鼠标按钮,我们的应用程序会将鼠标的当前 x 和 y 坐标存储在变量 end.x
和 end.y
中。我们的应用程序现在计算用于计算曼德勃罗特集的新插值。
case WM_LBUTTONUP:
{
if (mouse_x>=0 && mouse_x<=WIDTH && mouse_y>=0 && mouse_y<=HEIGHT)
{
rekt.visa = false;
end.x=mouse_x;
end.y=mouse_y;
rekt.ex =(float)mousex;
rekt.ey =(float)mousey;
if (end.x >start.x+5 && end.y >start.y +5)
{
// Free-up the off-screen DC
initWalk();
MouseX=WIDTH/2;
MouseY=HEIGHT/2;
SelectObject(hdcMem, hOld);
DeleteObject(hbmMem);
DeleteDC(hdcMem);
dx=zex-zsx;
dy=zey-zsy;
if (mouse_x>=rekt.sx && mouse_y >=rekt.sy )
{
zex=(xmin+(xmax-xmin)*((mousex)-px)/(WIDTH-1));
zey=(ymin+(ymax-ymin)*((mousey)-py)/(HEIGHT-1));
xmax=zex;
ymax=zey;
dx=zex-zsx;
dy=zey-zsy;
textout();
//if (rekt.sx!=rekt.ex && rekt.sy!=rekt.ey)
fract(/*hdc*/);
putCursor();
walkabout();
}
}
else
{
BitBlt(hdc, 0, 0, WIDTH,
HEIGHT, hdcMem, 0, 0, SRCCOPY);
xmin=tempx;
ymin=tempy;
}
}
} break;
WM_KEYDOWN 消息
当按下键时,会调用 WM_KEYDOWN 消息
。
case WM_KEYDOWN:
{
int virtual_code = (int) wparam;
int key_bits = (int) lparam;
switch (virtual_code)
{
case 27: {
PostQuitMessage(0); //<esc> quits
} break;
case 13: {
//<enter>
resetFrac();
fract(/*hdc*/);
} break;
case 32:{
}break;
case VK_RIGHT: { } break;
case VK_LEFT: { } break;
default: break;
}
} break;
WM_QUIT 和 WM_DESTROY 消息
当应用程序发出想要退出的信号时,会调用 WM_QUIT
和 WM_DESTROY 消息
。
WM_QUIT:
case WM_DESTROY:
KillTimer(hwnd,ID_TIMER);
PostQuitMessage(0);
break;
return 0;
default:
return DefWindowProc(hwnd, msg, wparam, lparam);
}
ReleaseDC(hwnd, hdc);
return 0;
} // end LRESULT CALLBACK WndProc()
这就是创建在 Win32 设备上下文中绘制和缩放曼德勃罗特集的 Win32 应用程序所需的一切。
感谢阅读。
历史
- 2010-05-08 更新完成
- 2002-06-22 代码完成