|
|
// stb_wingraph.h v0.01 - public domain windows graphics programming
// wraps WinMain, ChoosePixelFormat, ChangeDisplayResolution, etc. for
// doing OpenGL graphics
//
// in ONE source file, put '#define STB_DEFINE' before including this
// OR put '#define STB_WINMAIN' to define a WinMain that calls stbwingraph_main(void)
//
// @TODO:
// 2d rendering interface (that can be done easily in software)
// STB_WINGRAPH_SOFTWARE -- 2d software rendering only
// STB_WINGRAPH_OPENGL -- OpenGL only
#ifndef INCLUDE_STB_WINGRAPH_H
#define INCLUDE_STB_WINGRAPH_H
#ifdef STB_WINMAIN
#ifndef STB_DEFINE
#define STB_DEFINE
#define STB_WINGRAPH_DISABLE_DEFINE_AT_END
#endif
#endif
#ifdef STB_DEFINE
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "user32.lib")
#endif
#ifdef __cplusplus
#define STB_EXTERN extern "C"
#else
#define STB_EXTERN
#endif
#ifdef STB_DEFINE
#ifndef _WINDOWS_
#ifdef APIENTRY
#undef APIENTRY
#endif
#ifdef WINGDIAPI
#undef WINGDIAPI
#endif
#define _WIN32_WINNT 0x0400 // WM_MOUSEWHEEL
#include <windows.h>
#endif
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#endif
typedef void * stbwingraph_hwnd; typedef void * stbwingraph_hinstance;
enum { STBWINGRAPH_unprocessed = -(1 << 24), STBWINGRAPH_do_not_show, STBWINGRAPH_winproc_exit, STBWINGRAPH_winproc_update, STBWINGRAPH_update_exit, STBWINGRAPH_update_pause, };
typedef enum { STBWGE__none=0,
STBWGE_create, STBWGE_create_postshow, STBWGE_draw, STBWGE_destroy, STBWGE_char, STBWGE_keydown, STBWGE_syskeydown, STBWGE_keyup, STBWGE_syskeyup, STBWGE_deactivate, STBWGE_activate, STBWGE_size,
STBWGE_mousemove , STBWGE_leftdown , STBWGE_leftup , STBWGE_middledown, STBWGE_middleup, STBWGE_rightdown , STBWGE_rightup , STBWGE_mousewheel, } stbwingraph_event_type;
typedef struct { stbwingraph_event_type type;
// for input events (mouse, keyboard)
int mx,my; // mouse x & y
int dx,dy; int shift, ctrl, alt;
// for keyboard events
int key;
// for STBWGE_size:
int width, height;
// for STBWGE_crate
int did_share_lists; // if true, wglShareLists succeeded
void *handle;
} stbwingraph_event;
typedef int (*stbwingraph_window_proc)(void *data, stbwingraph_event *event);
extern stbwingraph_hinstance stbwingraph_app; extern stbwingraph_hwnd stbwingraph_primary_window; extern int stbwingraph_request_fullscreen; extern int stbwingraph_request_windowed;
STB_EXTERN void stbwingraph_ods(char *str, ...); STB_EXTERN int stbwingraph_MessageBox(stbwingraph_hwnd win, unsigned int type, char *caption, char *text, ...); STB_EXTERN int stbwingraph_ChangeResolution(unsigned int w, unsigned int h, unsigned int bits, int use_message_box); STB_EXTERN int stbwingraph_SetPixelFormat(stbwingraph_hwnd win, int color_bits, int alpha_bits, int depth_bits, int stencil_bits, int accum_bits); STB_EXTERN int stbwingraph_DefineClass(void *hinstance, char *iconname); STB_EXTERN void stbwingraph_SwapBuffers(void *win); STB_EXTERN void stbwingraph_Priority(int n);
STB_EXTERN void stbwingraph_MakeFonts(void *window, int font_base); STB_EXTERN void stbwingraph_ShowWindow(void *window); STB_EXTERN void *stbwingraph_CreateWindow(int primary, stbwingraph_window_proc func, void *data, char *text, int width, int height, int fullscreen, int resizeable, int dest_alpha, int stencil); STB_EXTERN void *stbwingraph_CreateWindowSimple(stbwingraph_window_proc func, int width, int height); STB_EXTERN void *stbwingraph_CreateWindowSimpleFull(stbwingraph_window_proc func, int fullscreen, int ww, int wh, int fw, int fh); STB_EXTERN void stbwingraph_DestroyWindow(void *window); STB_EXTERN void stbwingraph_ShowCursor(void *window, int visible); STB_EXTERN float stbwingraph_GetTimestep(float minimum_time); STB_EXTERN void stbwingraph_SetGLWindow(void *win); typedef int (*stbwingraph_update)(float timestep, int real, int in_client); STB_EXTERN int stbwingraph_MainLoop(stbwingraph_update func, float mintime);
#ifdef STB_DEFINE
stbwingraph_hinstance stbwingraph_app; stbwingraph_hwnd stbwingraph_primary_window; int stbwingraph_request_fullscreen; int stbwingraph_request_windowed;
void stbwingraph_ods(char *str, ...) { char buffer[1024]; va_list v; va_start(v,str); vsprintf(buffer, str, v); va_end(v); OutputDebugString(buffer); }
int stbwingraph_MessageBox(stbwingraph_hwnd win, unsigned int type, char *caption, char *text, ...) { va_list v; char buffer[1024]; va_start(v, text); vsprintf(buffer, text, v); va_end(v); return MessageBox(win, buffer, caption, type); }
void stbwingraph_Priority(int n) { int p; switch (n) { case -1: p = THREAD_PRIORITY_BELOW_NORMAL; break; case 0: p = THREAD_PRIORITY_NORMAL; break; case 1: p = THREAD_PRIORITY_ABOVE_NORMAL; break; default: if (n < 0) p = THREAD_PRIORITY_LOWEST; else p = THREAD_PRIORITY_HIGHEST; } SetThreadPriority(GetCurrentThread(), p); }
static void stbwingraph_ResetResolution(void) { ChangeDisplaySettings(NULL, 0); }
static void stbwingraph_RegisterResetResolution(void) { static int done=0; if (!done) { done = 1; atexit(stbwingraph_ResetResolution); } }
int stbwingraph_ChangeResolution(unsigned int w, unsigned int h, unsigned int bits, int use_message_box) { DEVMODE mode; int res; int i, tries=0; for (i=0; ; ++i) { int success = EnumDisplaySettings(NULL, i, &mode); if (!success) break; if (mode.dmBitsPerPel == bits && mode.dmPelsWidth == w && mode.dmPelsHeight == h) { ++tries; success = ChangeDisplaySettings(&mode, CDS_FULLSCREEN); if (success == DISP_CHANGE_SUCCESSFUL) { stbwingraph_RegisterResetResolution(); return TRUE; } break; } }
if (!tries) { if (use_message_box) stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The resolution %d x %d x %d-bits is not supported.", w, h, bits); return FALSE; }
// we tried but failed, so try explicitly doing it without specifying refresh rate
// Win95 support logic
mode.dmBitsPerPel = bits; mode.dmPelsWidth = w; mode.dmPelsHeight = h; mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
res = ChangeDisplaySettings(&mode, CDS_FULLSCREEN);
switch (res) { case DISP_CHANGE_SUCCESSFUL: stbwingraph_RegisterResetResolution(); return TRUE;
case DISP_CHANGE_RESTART: if (use_message_box) stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "Please set your desktop to %d-bit color and then try again."); return FALSE;
case DISP_CHANGE_FAILED: if (use_message_box) stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The hardware failed to change modes."); return FALSE;
case DISP_CHANGE_BADMODE: if (use_message_box) stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The resolution %d x %d x %d-bits is not supported.", w, h, bits); return FALSE;
default: if (use_message_box) stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "An unknown error prevented a change to a %d x %d x %d-bit display.", w, h, bits); return FALSE; } }
int stbwingraph_SetPixelFormat(stbwingraph_hwnd win, int color_bits, int alpha_bits, int depth_bits, int stencil_bits, int accum_bits) { HDC dc = GetDC(win); PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd) }; int pixel_format;
pfd.nVersion = 1; pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; pfd.dwLayerMask = PFD_MAIN_PLANE; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = color_bits; pfd.cAlphaBits = alpha_bits; pfd.cDepthBits = depth_bits; pfd.cStencilBits = stencil_bits; pfd.cAccumBits = accum_bits;
pixel_format = ChoosePixelFormat(dc, &pfd); if (!pixel_format) return FALSE;
if (!DescribePixelFormat(dc, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) return FALSE; SetPixelFormat(dc, pixel_format, &pfd);
return TRUE; }
typedef struct { // app data
stbwingraph_window_proc func; void *data; // creation parameters
int color, alpha, depth, stencil, accum; HWND share_window; HWND window; // internal data
HGLRC rc; HDC dc; int hide_mouse; int in_client; int active; int did_share_lists; int mx,my; // last mouse positions
} stbwingraph__window;
static void stbwingraph__inclient(stbwingraph__window *win, int state) { if (state != win->in_client) { win->in_client = state; if (win->hide_mouse) ShowCursor(!state); } }
static void stbwingraph__key(stbwingraph_event *e, int type, int key, stbwingraph__window *z) { e->type = type; e->key = key; e->shift = (GetKeyState(VK_SHIFT) < 0); e->ctrl = (GetKeyState(VK_CONTROL) < 0); e->alt = (GetKeyState(VK_MENU) < 0); if (z) { e->mx = z->mx; e->my = z->my; } else { e->mx = e->my = 0; } e->dx = e->dy = 0; }
static void stbwingraph__mouse(stbwingraph_event *e, int type, WPARAM wparam, LPARAM lparam, int capture, void *wnd, stbwingraph__window *z) { static int captured = 0; e->type = type; e->mx = (short) LOWORD(lparam); e->my = (short) HIWORD(lparam); if (!z || z->mx == -(1 << 30)) { e->dx = e->dy = 0; } else { e->dx = e->mx - z->mx; e->dy = e->my - z->my; } e->shift = (wparam & MK_SHIFT) != 0; e->ctrl = (wparam & MK_CONTROL) != 0; e->alt = (wparam & MK_ALT) != 0; if (z) { z->mx = e->mx; z->my = e->my; } if (capture) { if (!captured && capture == 1) SetCapture(wnd); captured += capture; if (!captured && capture == -1) ReleaseCapture(); if (captured < 0) captured = 0; } }
static void stbwingraph__mousewheel(stbwingraph_event *e, int type, WPARAM wparam, LPARAM lparam, int capture, void *wnd, stbwingraph__window *z) { // lparam seems bogus!
static int captured = 0; e->type = type; if (z) { e->mx = z->mx; e->my = z->my; } e->dx = e->dy = 0; e->shift = (wparam & MK_SHIFT) != 0; e->ctrl = (wparam & MK_CONTROL) != 0; e->alt = (GetKeyState(VK_MENU) < 0); e->key = ((int) wparam >> 16); }
int stbwingraph_force_update; static int WINAPI stbwingraph_WinProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) { int allow_default = TRUE; stbwingraph_event e = { STBWGE__none }; // the following line is wrong for 64-bit windows, but VC6 doesn't have GetWindowLongPtr
stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(wnd, GWL_USERDATA);
switch (msg) {
case WM_CREATE: { LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lparam; assert(z == NULL); z = (stbwingraph__window *) lpcs->lpCreateParams; SetWindowLong(wnd, GWL_USERDATA, (LONG) z); z->dc = GetDC(wnd); if (stbwingraph_SetPixelFormat(wnd, z->color, z->alpha, z->depth, z->stencil, z->accum)) { z->rc = wglCreateContext(z->dc); if (z->rc) { e.type = STBWGE_create; z->did_share_lists = FALSE; if (z->share_window) { stbwingraph__window *y = (stbwingraph__window *) GetWindowLong(z->share_window, GWL_USERDATA); if (wglShareLists(z->rc, y->rc)) z->did_share_lists = TRUE; } wglMakeCurrent(z->dc, z->rc); return 0; } } return -1; }
case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(wnd, &ps); SelectObject(hdc, GetStockObject(NULL_BRUSH)); e.type = STBWGE_draw; e.handle = wnd; z->func(z->data, &e); EndPaint(wnd, &ps); return 0; }
case WM_DESTROY: e.type = STBWGE_destroy; e.handle = wnd; if (z && z->func) z->func(z->data, &e); wglMakeCurrent(NULL, NULL) ; if (z) { if (z->rc) wglDeleteContext(z->rc); z->dc = 0; z->rc = 0; } if (wnd == stbwingraph_primary_window) PostQuitMessage (0); return 0;
case WM_CHAR: stbwingraph__key(&e, STBWGE_char , wparam, z); break; case WM_KEYDOWN: stbwingraph__key(&e, STBWGE_keydown, wparam, z); break; case WM_KEYUP: stbwingraph__key(&e, STBWGE_keyup , wparam, z); break;
case WM_NCMOUSEMOVE: stbwingraph__inclient(z,0); break; case WM_MOUSEMOVE: stbwingraph__inclient(z,1); stbwingraph__mouse(&e, STBWGE_mousemove, wparam, lparam,0,wnd, z); break; case WM_LBUTTONDOWN: stbwingraph__mouse(&e, STBWGE_leftdown, wparam, lparam,1,wnd, z); break; case WM_MBUTTONDOWN: stbwingraph__mouse(&e, STBWGE_middledown, wparam, lparam,1,wnd, z); break; case WM_RBUTTONDOWN: stbwingraph__mouse(&e, STBWGE_rightdown, wparam, lparam,1,wnd, z); break; case WM_LBUTTONUP: stbwingraph__mouse(&e, STBWGE_leftup, wparam, lparam,-1,wnd, z); break; case WM_MBUTTONUP: stbwingraph__mouse(&e, STBWGE_middleup, wparam, lparam,-1,wnd, z); break; case WM_RBUTTONUP: stbwingraph__mouse(&e, STBWGE_rightup, wparam, lparam,-1,wnd, z); break; case WM_MOUSEWHEEL: stbwingraph__mousewheel(&e, STBWGE_mousewheel, wparam, lparam,0,wnd, z); break;
case WM_ACTIVATE: allow_default = FALSE; if (LOWORD(wparam)==WA_INACTIVE ) { wglMakeCurrent(z->dc, NULL); e.type = STBWGE_deactivate; z->active = FALSE; } else { wglMakeCurrent(z->dc, z->rc); e.type = STBWGE_activate; z->active = TRUE; } e.handle = wnd; z->func(z->data, &e); return 0;
case WM_SIZE: { RECT rect; allow_default = FALSE; GetClientRect(wnd, &rect); e.type = STBWGE_size; e.width = rect.right; e.height = rect.bottom; e.handle = wnd; z->func(z->data, &e); return 0; }
default: return DefWindowProc (wnd, msg, wparam, lparam); }
if (e.type != STBWGE__none) { int n; e.handle = wnd; n = z->func(z->data, &e); if (n == STBWINGRAPH_winproc_exit) { PostQuitMessage(0); n = 0; } if (n == STBWINGRAPH_winproc_update) { stbwingraph_force_update = TRUE; return 1; } if (n != STBWINGRAPH_unprocessed) return n; } return DefWindowProc (wnd, msg, wparam, lparam); }
int stbwingraph_DefineClass(HINSTANCE hInstance, char *iconname) { WNDCLASSEX wndclass;
stbwingraph_app = hInstance;
wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_OWNDC; wndclass.lpfnWndProc = (WNDPROC) stbwingraph_WinProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(hInstance, iconname); wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); wndclass.hbrBackground = GetStockObject(NULL_BRUSH); wndclass.lpszMenuName = "zwingraph"; wndclass.lpszClassName = "zwingraph"; wndclass.hIconSm = NULL;
if (!RegisterClassEx(&wndclass)) return FALSE; return TRUE; }
void stbwingraph_ShowWindow(void *window) { stbwingraph_event e = { STBWGE_create_postshow }; stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(window, GWL_USERDATA); ShowWindow(window, SW_SHOWNORMAL); InvalidateRect(window, NULL, TRUE); UpdateWindow(window); e.handle = window; z->func(z->data, &e); }
void *stbwingraph_CreateWindow(int primary, stbwingraph_window_proc func, void *data, char *text, int width, int height, int fullscreen, int resizeable, int dest_alpha, int stencil) { HWND win; DWORD dwstyle; stbwingraph__window *z = (stbwingraph__window *) malloc(sizeof(*z));
if (z == NULL) return NULL; memset(z, 0, sizeof(*z)); z->color = 24; z->depth = 24; z->alpha = dest_alpha; z->stencil = stencil; z->func = func; z->data = data; z->mx = -(1 << 30); z->my = 0;
if (primary) { if (stbwingraph_request_windowed) fullscreen = FALSE; else if (stbwingraph_request_fullscreen) fullscreen = TRUE; }
if (fullscreen) { #ifdef STB_SIMPLE
stbwingraph_ChangeResolution(width, height, 32, 1); #else
if (!stbwingraph_ChangeResolution(width, height, 32, 0)) return NULL; #endif
dwstyle = WS_POPUP | WS_CLIPSIBLINGS; } else { RECT rect; dwstyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; if (resizeable) dwstyle |= WS_SIZEBOX | WS_MAXIMIZEBOX; rect.top = 0; rect.left = 0; rect.right = width; rect.bottom = height; AdjustWindowRect(&rect, dwstyle, FALSE); width = rect.right - rect.left; height = rect.bottom - rect.top; }
win = CreateWindow("zwingraph", text ? text : "sample", dwstyle, CW_USEDEFAULT,0, width, height, NULL, NULL, stbwingraph_app, z);
if (win == NULL) return win;
if (primary) { if (stbwingraph_primary_window) stbwingraph_DestroyWindow(stbwingraph_primary_window); stbwingraph_primary_window = win; }
{ stbwingraph_event e = { STBWGE_create }; stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA); z->window = win; e.did_share_lists = z->did_share_lists; e.handle = win; if (z->func(z->data, &e) != STBWINGRAPH_do_not_show) stbwingraph_ShowWindow(win); }
return win; }
void *stbwingraph_CreateWindowSimple(stbwingraph_window_proc func, int width, int height) { int fullscreen = 0; #ifndef _DEBUG
if (width == 640 && height == 480) fullscreen = 1; if (width == 800 && height == 600) fullscreen = 1; if (width == 1024 && height == 768) fullscreen = 1; if (width == 1280 && height == 1024) fullscreen = 1; if (width == 1600 && height == 1200) fullscreen = 1; //@TODO: widescreen widths
#endif
return stbwingraph_CreateWindow(1, func, NULL, NULL, width, height, fullscreen, 1, 0, 0); }
void *stbwingraph_CreateWindowSimpleFull(stbwingraph_window_proc func, int fullscreen, int ww, int wh, int fw, int fh) { if (fullscreen == -1) { #ifdef _DEBUG
fullscreen = 0; #else
fullscreen = 1; #endif
}
if (fullscreen) { if (fw) ww = fw; if (fh) wh = fh; } return stbwingraph_CreateWindow(1, func, NULL, NULL, ww, wh, fullscreen, 1, 0, 0); }
void stbwingraph_DestroyWindow(void *window) { stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(window, GWL_USERDATA); DestroyWindow(window); free(z); if (stbwingraph_primary_window == window) stbwingraph_primary_window = NULL; }
void stbwingraph_ShowCursor(void *window, int visible) { int hide; stbwingraph__window *win; if (!window) window = stbwingraph_primary_window; win = (stbwingraph__window *) GetWindowLong((HWND) window, GWL_USERDATA); hide = !visible; if (hide != win->hide_mouse) { win->hide_mouse = hide; if (!hide) ShowCursor(TRUE); else if (win->in_client) ShowCursor(FALSE); } }
float stbwingraph_GetTimestep(float minimum_time) { float elapsedTime; double thisTime; static double lastTime = -1; if (lastTime == -1) lastTime = timeGetTime() / 1000.0 - minimum_time;
for(;;) { thisTime = timeGetTime() / 1000.0; elapsedTime = (float) (thisTime - lastTime); if (elapsedTime >= minimum_time) { lastTime = thisTime; return elapsedTime; } #if 1
Sleep(2); #endif
} }
void stbwingraph_SetGLWindow(void *win) { stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA); if (z) wglMakeCurrent(z->dc, z->rc); }
void stbwingraph_MakeFonts(void *window, int font_base) { wglUseFontBitmaps(GetDC(window ? window : stbwingraph_primary_window), 0, 256, font_base); }
// returns 1 if WM_QUIT, 0 if 'func' returned 0
int stbwingraph_MainLoop(stbwingraph_update func, float mintime) { int needs_drawing = FALSE; MSG msg;
int is_animating = TRUE; if (mintime <= 0) mintime = 0.01f;
for(;;) { int n;
is_animating = TRUE; // wait for a message if: (a) we're animating and there's already a message
// or (b) we're not animating
if (!is_animating || PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { stbwingraph_force_update = FALSE; if (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { return 1; // WM_QUIT
}
// only force a draw for certain messages...
// if I don't do this, we peg at 50% for some reason... must
// be a bug somewhere, because we peg at 100% when rendering...
// very weird... looks like NVIDIA is pumping some messages
// through our pipeline? well, ok, I guess if we can get
// non-user-generated messages we have to do this
if (!stbwingraph_force_update) { switch (msg.message) { case WM_MOUSEMOVE: case WM_NCMOUSEMOVE: break; case WM_CHAR: case WM_KEYDOWN: case WM_KEYUP: case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: case WM_TIMER: case WM_SIZE: case WM_ACTIVATE: needs_drawing = TRUE; break; } } else needs_drawing = TRUE; }
// if another message, process that first
// @TODO: i don't think this is working, because I can't key ahead
// in the SVT demo app
if (PeekMessage(&msg, NULL, 0,0, PM_NOREMOVE)) continue;
// and now call update
if (needs_drawing || is_animating) { int real=1, in_client=1; if (stbwingraph_primary_window) { stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(stbwingraph_primary_window, GWL_USERDATA); if (z && !z->active) { real = 0; } if (z) in_client = z->in_client; }
if (stbwingraph_primary_window) stbwingraph_SetGLWindow(stbwingraph_primary_window); n = func(stbwingraph_GetTimestep(mintime), real, in_client); if (n == STBWINGRAPH_update_exit) return 0; // update_quit
is_animating = (n != STBWINGRAPH_update_pause);
needs_drawing = FALSE; } } }
void stbwingraph_SwapBuffers(void *win) { stbwingraph__window *z; if (win == NULL) win = stbwingraph_primary_window; z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA); if (z && z->dc) SwapBuffers(z->dc); } #endif
#ifdef STB_WINMAIN
void stbwingraph_main(void);
char *stb_wingraph_commandline;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { { char buffer[1024]; // add spaces to either side of the string
buffer[0] = ' '; strcpy(buffer+1, lpCmdLine); strcat(buffer, " "); if (strstr(buffer, " -reset ")) { ChangeDisplaySettings(NULL, 0); exit(0); } if (strstr(buffer, " -window ") || strstr(buffer, " -windowed ")) stbwingraph_request_windowed = TRUE; else if (strstr(buffer, " -full ") || strstr(buffer, " -fullscreen ")) stbwingraph_request_fullscreen = TRUE; } stb_wingraph_commandline = lpCmdLine;
stbwingraph_DefineClass(hInstance, "appicon"); stbwingraph_main();
return 0; } #endif
#undef STB_EXTERN
#ifdef STB_WINGRAPH_DISABLE_DEFINE_AT_END
#undef STB_DEFINE
#endif
#endif // INCLUDE_STB_WINGRAPH_H
|