📄 mandel.cpp
字号:
// mandel.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#include "mandel.h"
#include <math.h>
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
char WindowName[] = "Windows";
char WindowTitle[] = "基于牛顿求根法的分形";
BYTE ColorRGB[256][3];
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_MANDEL, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MANDEL);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage is only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_MANDEL);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (LPCSTR)IDC_MANDEL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
class Drawer
{
HBITMAP m_bitmap;
HDC m_hdc;
bool redraw;
PQ_PARAM pq;
public:
RECT m_rect;
int m_times;
double m_deep;
double m_rotate;
double p,q;
public:
void Enlarge(RECT rt);
void Reset();
void Resize(HDC hdc,RECT rect);
Drawer(HDC hdc);
~Drawer();
void DrawMandel(HDC hdc);
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
BYTE R, G, B;
double deltax, deltay, x, y, tmp, xx, yy, d;
int maxcol, maxrow;
int color, row, col, count;
};
Drawer::Drawer(HDC hdc):redraw(true),m_times(500),m_deep(50.0)
{
m_rect.left = 100;
m_rect.top = 50;
m_rect.right = 740;
m_rect.bottom = 530;
pq.pmax = 1.5;
pq.pmin = -1.5;
pq.qmax = 1.5;
pq.qmin = -1.5;
p = 0.32; q = 0.043;
m_hdc = CreateCompatibleDC(hdc);
m_bitmap = CreateCompatibleBitmap(hdc, 640, 480);
SelectObject(m_hdc, m_bitmap);
}
Drawer::~Drawer()
{
DeleteDC(m_hdc);
DeleteObject(m_bitmap);
m_hdc = NULL;
m_bitmap = NULL;
}
void Drawer::DrawMandel(HDC hdc)
{
if (!redraw)
{
BitBlt(hdc, m_rect.left, m_rect.top, m_rect.right-m_rect.left,
m_rect.bottom-m_rect.top, m_hdc, 0, 0,SRCCOPY);
return;
}
PQTYPE x=0.0, y=0.0,r=0.0,dp,dq;
int i=m_rect.left, j=m_rect.top, k=0,i1=0,j1=0, i2=0,j2=0;
dp = (pq.pmax - pq.pmin)/(m_rect.right-m_rect.left);
dq = (pq.qmax - pq.qmin)/(m_rect.bottom-m_rect.top);
for(i1=0; i<m_rect.right; i++,i1++)
{
for(j1=0,j = m_rect.top; j<m_rect.bottom; j++,j1++)
{
x = pq.pmin + dp*i1;
y = pq.qmin + dq*j1;
count=0;
while (count<2048)
{
xx = x*x;
yy = y*y;
d = 3.0*((xx - yy)*(xx - yy) + 4.0*xx*yy);
if (d == 0.0)
d = 0.000001;
tmp=x;
x = (2.0/3.0)*x + (xx - yy)/d;
y = (2.0/3.0)*y - 2.0*tmp*y/d;
count+=1;
}
if (x>0.0)
color = count%100;
else
{
if ((x<-0.3) && (y>0.0))
color = (count%100) + 100;
else
color = (count%100) + 155;
}
if (k >= m_times) k = int(r*100);
k *= 0x1111ff;
SetPixelV(hdc, i, j, color);
SetPixelV(m_hdc, (i-m_rect.left), (j-m_rect.top), color);
}
}
redraw = false;
}
class Box
{
RECT last_rect;
bool hasbox;
void OverPreDraw(HDC hdc);
HPEN hpen;
COLORREF m_color;
public:
void Reset();
Box(COLORREF color=RGB(0xFF, 0xFF, 0XFF));
void Draw(HDC hdc, RECT rect);
void SetColor(COLORREF color);
~Box();
};
Box::Box(COLORREF color)
{
hasbox = false;
last_rect.left = last_rect.right = last_rect.top = last_rect.bottom = 0;
m_color = color;
hpen = CreatePen(PS_SOLID, 2, color);
}
Box::~Box()
{
if (hpen != NULL)
DeleteObject(hpen);
}
#define MKPOINT(p,x1,y1) p.x = x1;p.y=y1
void m_Rectangle(HDC hdc, int left, int top, int right, int bottom)
{
POINT p[5];
MKPOINT(p[0], left, top);
MKPOINT(p[1],right, top);
MKPOINT(p[2],right, bottom);
MKPOINT(p[3],left, bottom);
MKPOINT(p[4], left, top);
Polyline(hdc, p, 5);
}
void Box::OverPreDraw(HDC hdc)
{
if(hasbox)
{
m_Rectangle(hdc, last_rect.left, last_rect.top, last_rect.right,\
last_rect.bottom);
hasbox = false;
}
}
void Box::Draw(HDC hdc, RECT rect)
{
SelectObject(hdc, hpen);
SetROP2(hdc, R2_XORPEN);
if (hasbox) OverPreDraw(hdc);
m_Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
hasbox = true;
last_rect = rect;
}
void Box::SetColor(COLORREF color)
{
m_color = color;
if (hpen != NULL) DeleteObject(hpen);
hpen = CreatePen(PS_SOLID, 2, m_color);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
static RECT rt;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
static Drawer drawer(GetDC(hWnd));
static Box box;
static bool down=false, move=false;
static int i=0;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case IDM_RESET:
drawer.Reset();
InvalidateRect(hWnd, NULL, false);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_CREATE:
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
drawer.DrawMandel(hdc);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN:
down = true;
SetCapture(hWnd);
rt.left = LOWORD(lParam);
rt.top = HIWORD(lParam);
break;
case WM_MOUSEMOVE:
if (down)
{
i++;
move = true;
if (i>=2)
{
i = 0;
hdc = GetDC(hWnd);
rt.right = LOWORD(lParam);
rt.bottom = HIWORD(lParam);
box.Draw(hdc, rt);
ReleaseDC(hWnd, hdc);
}
}
break;
case WM_LBUTTONUP:
ReleaseCapture();
if(down && move)
{
drawer.Enlarge(rt);
box.Reset();
down = false;
move = false;
InvalidateRect(hWnd, NULL, false);
}
down = false;
move = false;
break;
case WM_LBUTTONDBLCLK:
down = false;
move = false;
rt.left = LOWORD(lParam) - 10;
rt.top = HIWORD(lParam) - 10;
rt.right = rt.left + 20;
rt.bottom = rt.top + 20;
drawer.Enlarge(rt);
InvalidateRect(hWnd, NULL, false);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
void Drawer::Resize(HDC hdc, RECT rect)
{
HBITMAP m_bitmap1=NULL;
m_bitmap1 = CreateCompatibleBitmap(hdc, rect.right-rect.left, rect.bottom-rect.top);
if (m_bitmap1 != NULL)
{
m_rect = rect;
DeleteObject(m_bitmap);
m_bitmap = m_bitmap1;
SelectObject(m_hdc, m_bitmap1);
redraw = true;
}
}
void Box::Reset()
{
hasbox = false;
}
void Drawer::Reset()
{
pq.pmax = 1.5;
pq.pmin = -1.5;
pq.qmax = 1.5;
pq.qmin = -1.5;
m_rotate = 0;
redraw = true;
}
void Drawer::Enlarge(RECT rt)
{
PQTYPE dp,dq,tmp;
int itmp;
if (rt.left > rt.right)
{
itmp = rt.left;
rt.left = rt.right;
rt.right = itmp;
}
if (rt.top > rt.bottom)
{
itmp = rt.top;
rt.top = rt.bottom;
rt.bottom = itmp;
}
if (rt.left < m_rect.left) return;
if (rt.right > m_rect.right) return;
if (rt.top < m_rect.top) return;
if (rt.bottom > m_rect.bottom) return;
dp = (pq.pmax - pq.pmin)/(m_rect.right-m_rect.left);
dq = (pq.qmax - pq.qmin)/(m_rect.bottom - m_rect.top);
tmp = pq.pmin;
pq.pmin = pq.pmin + dp*(rt.left-m_rect.left);
pq.pmax = tmp + dp*(rt.right-m_rect.left);
tmp = pq.qmin;
pq.qmin = pq.qmin + dq*(rt.top - m_rect.top);
pq.qmax = tmp + dq*(rt.bottom - m_rect.top);
redraw = true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -