Last active
September 6, 2023 03:08
-
-
Save kinjalkishor/739b6edcc5bbb8d17ccb1f71db2602a9 to your computer and use it in GitHub Desktop.
Simple WinApi window with functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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