#pragma float_control(precise, off)
#pragma optimize( "gt", on )
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
static HWND _fullHwnd = nullptr;
static HBITMAP _bitmap = nullptr;
static HDC _bitmapHdc = nullptr;
static int _screenWidth = 0;
static int _screenHeight = 0;
void updateScreen()
{
HDC hdc = GetDC(_fullHwnd);
BitBlt(hdc, 0, 0, _screenWidth, _screenHeight, _bitmapHdc, 0, 0, SRCCOPY);
ReleaseDC(_fullHwnd, hdc);
}
bool drawLine = false;
POINT previousPoint;
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_PAINT:
updateScreen();
break;
case WM_KEYDOWN:
if (VK_ESCAPE == wParam)
{
PostQuitMessage(0);
return 0;
}
break;
// Quit when this window is closed
case WM_DESTROY:
PostQuitMessage(0);
return 0;
// Handle drawing with mouse
case WM_LBUTTONDOWN:
drawLine = true;
previousPoint.x = LOWORD(lParam);
previousPoint.y = HIWORD(lParam);
return 0;
case WM_LBUTTONUP:
if (drawLine)
{
MoveToEx(_bitmapHdc, previousPoint.x, previousPoint.y, nullptr);
LineTo(_bitmapHdc, LOWORD(lParam), HIWORD(lParam));
}
drawLine = false;
return 0;
case WM_MOUSEMOVE:
if (drawLine)
{
MoveToEx(_bitmapHdc, previousPoint.x, previousPoint.y, nullptr);
LineTo(_bitmapHdc, previousPoint.x = LOWORD(lParam),
previousPoint.y = HIWORD(lParam));
}
return 0;
}
// Default message processing
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
// Get screen dimensions
_screenWidth = GetSystemMetrics(SM_CXSCREEN);
_screenHeight = GetSystemMetrics(SM_CYSCREEN);
// Register window class
const char* myWindowName = "MyWindowName";
const char* myClassName = "MyWindowClass";
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(wc));
wc.cbSize = sizeof(wc);
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.lpfnWndProc = MsgProc;
wc.lpszClassName = myClassName;
RegisterClassEx(&wc);
// Create a full screen window
_fullHwnd = CreateWindowA(
myClassName,
myWindowName,
WS_POPUP,
0, 0, _screenWidth, _screenHeight,
GetDesktopWindow(),
nullptr, 0, nullptr);
// Create a writable bitmap
void* pData = nullptr;
BITMAPINFO bmInfo;
ZeroMemory(&bmInfo, sizeof(bmInfo));
BITMAPINFOHEADER& header = bmInfo.bmiHeader;
header.biSize = sizeof(header);
header.biBitCount = 32;
header.biPlanes = 1;
header.biHeight = -_screenHeight;
header.biWidth = _screenWidth;
header.biSizeImage = 0;
header.biCompression = BI_RGB;
HDC screenHdc = GetDC(nullptr);
_bitmap = CreateDIBSection(
screenHdc,
&bmInfo,
DIB_RGB_COLORS,
&pData,
nullptr, 0);
_bitmapHdc = CreateCompatibleDC(screenHdc);
HBITMAP hOldBitmap = (HBITMAP)SelectObject(_bitmapHdc, _bitmap);
ReleaseDC(nullptr, screenHdc);
// Clear the bitmap buffer and show the window
const unsigned totalPixels = _screenHeight * _screenWidth;
{
unsigned* pPixel = (unsigned*)pData;
for (unsigned i = 0; i < totalPixels; ++i)
{
*pPixel++ = 0;
}
}
ShowWindow(_fullHwnd, SW_MAXIMIZE);
updateScreen();
// Paint a Mandelbrot background
{
const int HALF_WIDTH = _screenWidth / 2;
const int HALF_HEIGHT = _screenHeight / 2;
const double ZOOM = 200, OFFSETX = -0.55, OFFSETY = 0.50;
const double ZOOM_FACTOR = 1.0 / (ZOOM * HALF_WIDTH);
const int MAX_ITERATIONS = 255;
int x, y, i;
double zr, zi, ozr, ozi, nzr, nzi;
unsigned* pPixel = (unsigned*)pData;
for (y = -HALF_HEIGHT; y < HALF_HEIGHT; ++y)
{
zi = y * ZOOM_FACTOR + OFFSETY;
for (x = -HALF_WIDTH; x < HALF_WIDTH; ++x)
{
zr = x * ZOOM_FACTOR + OFFSETX;
nzr = nzi = ozr = ozi = i = 0;
do
{
ozr = nzr;
ozi = nzi;
nzr = ozr * ozr - ozi * ozi + zr;
nzi = 2.0 * ozr * ozi + zi;
// abs must be below 2.0
if ((nzr * nzr + nzi * nzi) > 4.0) break;
}
while (++i < MAX_ITERATIONS);
*pPixel++ = (i << 16) | (0xFF00 & -!(i < MAX_ITERATIONS));
}
}
}
bool messageLoopRunning = true;
MSG msg;
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
frequency.QuadPart /= 60;
LARGE_INTEGER newtime, oldtime;
oldtime.QuadPart = 0;
while (messageLoopRunning)
{
// Update the background colors
QueryPerformanceCounter(&newtime);
if (newtime.QuadPart > oldtime.QuadPart + frequency.QuadPart)
{
unsigned* pPixel = (unsigned*)pData;
for (unsigned i = 0; i < totalPixels; ++i)
{
*pPixel++ += 0x01ff01;
}
updateScreen();
oldtime = newtime;
}
// Process messages
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (WM_QUIT == msg.message)
{
messageLoopRunning = false;
break;
}
DispatchMessage(&msg);
}
// Avoid a busy loop
Sleep(1);
}
// Cleanup
SelectObject(_bitmapHdc, hOldBitmap);
DeleteDC(_bitmapHdc);
DeleteObject(_bitmap);
UnregisterClass(myClassName, hInstance);
return 0;
}