## This example show how to have real time pixie using win32 API. import pixie, winim/lean let w: int32 = 256 h: int32 = 256 var screen = newImage(w, h) ctx = newContext(screen) frameCount = 0 hwnd: HWND running = true proc draw() = # draw shiny sphere on gradient background let linerGradient = newPaint(pkGradientLinear) linerGradient.gradientHandlePositions.add(vec2(0, 0)) linerGradient.gradientHandlePositions.add(vec2(0, 256)) linerGradient.gradientStops.add( ColorStop(color: color(0, 0, 0, 1), position: 0)) linerGradient.gradientStops.add( ColorStop(color: color(1, 1, 1, 1), position: 1)) ctx.fillStyle = linerGradient ctx.fillRect(0, 0, 256, 256) let radialGradient = newPaint(pkGradientRadial) radialGradient.gradientHandlePositions.add(vec2(128, 128)) radialGradient.gradientHandlePositions.add(vec2(256, 128)) radialGradient.gradientHandlePositions.add(vec2(128, 256)) radialGradient.gradientStops.add( ColorStop(color: color(1, 1, 1, 1), position: 0)) radialGradient.gradientStops.add( ColorStop(color: color(0, 0, 0, 1), position: 1)) ctx.fillStyle = radialGradient ctx.fillCircle(circle( vec2(128.0, 128.0 + sin(float32(frameCount)/10.0) * 20), 76.8 )) inc frameCount # Draw image pixels onto win32 window. let w = screen.width.int32 h = screen.height.int32 dc = GetDC(hwnd) var info = BITMAPINFO() info.bmiHeader.biBitCount = 32 info.bmiHeader.biWidth = w info.bmiHeader.biHeight = h info.bmiHeader.biPlanes = 1 info.bmiHeader.biSize = DWORD sizeof(BITMAPINFOHEADER) info.bmiHeader.biSizeImage = w * h * 4 info.bmiHeader.biCompression = BI_RGB var bgrBuffer = newSeq[uint8](screen.data.len * 4) # Convert to BGRA. for i, c in screen.data: bgrBuffer[i*4+0] = c.b bgrBuffer[i*4+1] = c.g bgrBuffer[i*4+2] = c.r discard StretchDIBits( dc, 0, h - 1, w, -h, 0, 0, w, h, bgrBuffer[0].addr, info, DIB_RGB_COLORS, SRCCOPY ) discard ReleaseDC(hwnd, dc) proc windowProc(hwnd: HWND, message: UINT, wParam: WPARAM, lParam: LPARAM): LRESULT {.stdcall.} = case message of WM_DESTROY: PostQuitMessage(0) running = false return 0 else: return DefWindowProc(hwnd, message, wParam, lParam) proc main() = var hInstance = GetModuleHandle(nil) appName = "Win32/Pixie" msg: MSG wndclass: WNDCLASS wndclass.style = CS_HREDRAW or CS_VREDRAW wndclass.lpfnWndProc = windowProc wndclass.cbClsExtra = 0 wndclass.cbWndExtra = 0 wndclass.hInstance = hInstance wndclass.hIcon = LoadIcon(0, IDI_APPLICATION) wndclass.hCursor = LoadCursor(0, IDC_ARROW) wndclass.hbrBackground = GetStockObject(WHITE_BRUSH) wndclass.lpszMenuName = nil wndclass.lpszClassName = appName if RegisterClass(wndclass) == 0: MessageBox(0, "This program requires Windows NT!", appName, MB_ICONERROR) return # Figure out the right size of the window we want. var rect: lean.RECT rect.left = 0 rect.top = 0 rect.right = w rect.bottom = h AdjustWindowRectEx(cast[LPRECT](rect.addr), WS_OVERLAPPEDWINDOW, 0, 0) # Open the window. hwnd = CreateWindow( appName, "Win32/Pixie", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, 0, 0, hInstance, nil ) ShowWindow(hwnd, SW_SHOW) UpdateWindow(hwnd) while running: draw() PeekMessage(msg, 0, 0, 0, PM_REMOVE) TranslateMessage(msg) DispatchMessage(msg) main()