Skip to content

Instantly share code, notes, and snippets.

@kinjalkishor
Last active September 6, 2023 03:08
Show Gist options
  • Save kinjalkishor/739b6edcc5bbb8d17ccb1f71db2602a9 to your computer and use it in GitHub Desktop.
Save kinjalkishor/739b6edcc5bbb8d17ccb1f71db2602a9 to your computer and use it in GitHub Desktop.
Simple WinApi window with functions
#if defined(_MSC_VER)
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")
#endif
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <stdio.h>
using int64 = signed long long int;
using uint = unsigned int;
using uint64 = unsigned long long int;
using isz = ptrdiff_t;
#define scast static_cast
namespace sdf2
{
template <class T, ptrdiff_t N>
inline constexpr ptrdiff_t arr_cap(const T (&)[N]) noexcept {
return N;
}
// For null terminated char arrays, returns size without null char.
template <class T, ptrdiff_t N>
inline constexpr ptrdiff_t strz_cap(const T (&)[N]) noexcept {
return N-1;
}
inline void truncate_len_to_capacity(isz& copy_len, isz src_len, isz capacity) {
copy_len = src_len;
if (copy_len > capacity) {
copy_len = capacity;
}
}
inline int mb_wcs_from_mbs(wchar_t* dest, int dest_num_chars, const char* src, int src_len) {
const int dest_size_with_null_char = dest_num_chars+1;
//mbstowcs(dest, src, copy_len);
int result = MultiByteToWideChar(CP_UTF8, 0, src, src_len, dest, dest_size_with_null_char);
return result;
}
// dest_num_chars is dest capacity to hold chars without null char.
isz strz_wcs_from_mbs(wchar_t* dest, isz dest_num_chars, const char* src, isz src_len) {
isz copy_len = 0;
sdf2::truncate_len_to_capacity(copy_len, src_len, dest_num_chars);
mb_wcs_from_mbs(dest, dest_num_chars, src, copy_len);
dest[copy_len] = L'\0'; //k_null_char<wchar_t>();
return copy_len;
}
template<class T>
inline isz strz_len(const T* src);
template<>
inline isz strz_len(const char* src) {
return strlen(src);
}
template<>
inline isz strz_len(const wchar_t* src) {
return wcslen(src);
}
}
#include <format>
namespace sdf2
{
template <class... _Types>
_NODISCARD inline void print(const std::string_view _Fmt, const _Types&... _Args) {
std::printf("%s", std::vformat(_Fmt, std::make_format_args(_Args...)).c_str());
}
template <class... _Types>
_NODISCARD inline void println(const std::string_view _Fmt, const _Types&... _Args) {
std::printf("%s\n", std::vformat(_Fmt, std::make_format_args(_Args...)).c_str());
}
template <class... _Types>
_NODISCARD inline void wprint(const std::wstring_view _Fmt, const _Types&... _Args) {
std::wprintf(L"%s", std::vformat(_Fmt, std::make_format_args<std::wformat_context>(_Args...)).c_str());
}
template <class... _Types>
_NODISCARD inline void wprintln(const std::wstring_view _Fmt, const _Types&... _Args) {
std::wprintf(L"%s\n", std::vformat(_Fmt, std::make_format_args<std::wformat_context>(_Args...)).c_str());
}
}
namespace sdf2
{
class std_console {
private:
void* hconsole = nullptr;
const uint color_yellow = 6;
public:
std_console() {}
~std_console() {
FreeConsole();
//check if(hconsole)
}
bool create_window(const char* window_title, int xpos, int ypos, int width, int height) {
if (!AllocConsole()) {
MessageBoxW(nullptr, L"Couldn't create output console", L"Error", 0);
return false;
}
HWND console_window = GetConsoleWindow();
MoveWindow(console_window, xpos, ypos, width, height, TRUE);
wchar_t wconsole_title[256] = {};
sdf2::strz_wcs_from_mbs(wconsole_title, sdf2::strz_cap(wconsole_title), window_title, sdf2::strz_len(window_title));
SetWindowTextW(console_window, wconsole_title);
// The freopen_s function closes the file currently associated with stream and reassigns stream to the file specified by path.
freopen("conin$", "r", stdin);
freopen("conout$", "w", stdout);
freopen("conout$", "w", stderr);
hconsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hconsole, color_yellow);
return true;
}
};
//#include <thread>
//#include <chrono>
void sys_sleep(uint dwMilliseconds) {
Sleep(dwMilliseconds);
//std::this_thread::sleep_for(std::chrono::milliseconds(dwMilliseconds));
}
class game_timer_qpc {
public:
float period() {
int64 cnts_per_sec = 0;
QueryPerformanceFrequency((LARGE_INTEGER*)&cnts_per_sec);
// secs_per_cnt_qpc is 0.0000001f, 1e-07;
float secs_per_cnt_qpc = 1.0f / scast<float>(cnts_per_sec);
//printfln("{}", secs_per_cnt_qpc);
return secs_per_cnt_qpc;
}
int64 get_time() {
// Retrieves the current value of the performance counter,
// which is a high resolution (<1 micro second) time stamp.
int64 prev_time_qpc = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&prev_time_qpc);
return prev_time_qpc;
}
};
}
using namespace sdf2;
//-------------------------
namespace wm_wnd2
{
class app_vars {
public:
bool app_quit = false;
bool app_active = true;
bool app_minimized = false;
};
app_vars g_av;
bool winapp_init(WNDPROC m_wnd_proc, HINSTANCE m_hInstance, const wchar_t* m_app_class_name) {
// register window class
WNDCLASSEX wcex = {};
wcex.cbSize = sizeof(wcex);
wcex.style = CS_OWNDC; //CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = m_wnd_proc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = m_hInstance;
wcex.hIcon = LoadIconW(nullptr, IDI_APPLICATION);
wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW);
//wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcex.hbrBackground = CreateSolidBrush(RGB(25, 25, 112));
wcex.lpszMenuName = nullptr;
wcex.lpszClassName = m_app_class_name;
wcex.hIconSm = LoadIconW(nullptr, IDI_APPLICATION);
if (!RegisterClassExW(&wcex)) {
printf("Cannot Register WinApi Class.\n");
return false;
}
return true;
}
bool winapp_create_window(HWND& m_hwnd, const char* wnd_title, int xpos, int ypos, int width, int height,
HINSTANCE m_hInstance, const wchar_t* m_app_class_name) {
uint dwStyle = 0;
uint dwExStyle = 0;
dwStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS|WS_CLIPCHILDREN;
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
int x, y, w, h;
RECT window_rect = {0, 0, width, height};
AdjustWindowRectEx(&window_rect, dwStyle, false, dwExStyle);
x = xpos + window_rect.left;
y = ypos + window_rect.top;
w = window_rect.right - window_rect.left;
h = window_rect.bottom - window_rect.top;
wchar_t wstr_wnd_title[256] = {};
sdf2::strz_wcs_from_mbs(wstr_wnd_title, sdf2::strz_cap(wstr_wnd_title), wnd_title, sdf2::strz_len(wnd_title));
HWND handle_wnd = CreateWindowExW(dwExStyle,
m_app_class_name,
wstr_wnd_title,
dwStyle,
x, y, w, h,
nullptr, nullptr, m_hInstance, nullptr);
if (!handle_wnd) {
printf("Cannot Create Window.\n");
return false;
}
//ShowWindow(handle_wnd, iCmdShow);
ShowWindow(handle_wnd, SW_SHOW);
UpdateWindow(handle_wnd);
SetForegroundWindow(handle_wnd);
SetFocus(handle_wnd);
m_hwnd = handle_wnd;
return true;
}
void winapp_poll_events(MSG& m_msg) {
if(PeekMessageW(&m_msg, nullptr, 0, 0, PM_REMOVE)) {
TranslateMessage(&m_msg);
DispatchMessageW(&m_msg);
}
}
bool winapp_is_quit_msg(const MSG& m_msg) {
return (m_msg.message == WM_QUIT);
}
void winapp_deinit(HWND m_hwnd, HINSTANCE m_hInstance, const wchar_t* m_app_class_name) {
DestroyWindow(m_hwnd);
UnregisterClassW(m_app_class_name, m_hInstance);
}
}
using namespace wm_wnd2;
//---------------------------------------------
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//======================================
// WinMain
//======================================
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
std_console gconstd;
gconstd.create_window("Std Console", 864, 0, 640, 640);
printf("SysConsole Initialized.\n");
println("Sample program");
//-------------------------
int xpos = 10;
int ypos = 50;
int width = 800;
int height = 450;
const char* wnd_title = "Sample window";
const wchar_t* APP_CLASS_NAME = L"SAMPLE_APP_CLASS";
HWND m_hwnd = nullptr;
MSG m_msg = {};
winapp_init(MainWndProc, hInstance, APP_CLASS_NAME);
winapp_create_window(m_hwnd, wnd_title, xpos, ypos, width, height, hInstance, APP_CLASS_NAME);
//rs->init_r(hInstance, wnd1.hwnd, wnd1.width, wnd1.height, wnd1.fullscreen);
//rs->setup();
//---
game_timer_qpc nw_timer;
int64 prev_time_qpc = nw_timer.get_time();
// program main loop
while (!g_av.app_quit) {
//nw_app.poll_events();
winapp_poll_events(m_msg);
//if (nw_app.is_quit_msg()) { g_av.sys_quit(); }
if (winapp_is_quit_msg(m_msg)) { g_av.app_quit = true; }
if (g_av.app_active && !g_av.app_minimized) {
int64 curr_time_qpc = nw_timer.get_time();
float delta_time_qpc = (curr_time_qpc - prev_time_qpc)*nw_timer.period();
//process_input();
//calculate_frame_stats();
//rs->render(delta_time_qpc);
//rs->swap_buffers();
prev_time_qpc = curr_time_qpc;
} else {
sys_sleep(1);
continue;
}
} // while: not app_quit
//rs->cleanup();
//rs->deinit_r();
winapp_deinit(m_hwnd, hInstance, APP_CLASS_NAME);
return scast<int>(m_msg.wParam);
}
//======================================
// Window Procedure
//======================================
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_ACTIVATE:
g_av.app_active = scast<bool>(LOWORD(wParam) != WA_INACTIVE);
g_av.app_minimized = scast<bool>(HIWORD(wParam));
return 0;
case WM_CREATE:
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
case WM_QUIT:
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
//gkeys[wParam] = true;
switch (wParam) {
case VK_ESCAPE:
PostQuitMessage(0);
return 0;
}
return 0;
case WM_KEYUP:
//gkeys[wParam] = false;
return 0;
default: break;
}
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment