update header comment email; sync bug fixes into 'mc' version
parent
08dc9c445d
commit
3638407c42
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
** Win32 Custom Window Example Program
|
** Win32 Custom Window Example Program
|
||||||
** v1.2 - April 30th 2020
|
** v1.3.1 - Jan 19th 2024
|
||||||
** by Allen Webster allenwebster@4coder.net
|
** by Allen Webster allenw@mr4th.com
|
||||||
**
|
**
|
||||||
** public domain example program
|
** public domain example program
|
||||||
** NO WARRANTY IMPLIED; USE AT YOUR OWN RISK
|
** NO WARRANTY IMPLIED; USE AT YOUR OWN RISK
|
||||||
|
@ -29,23 +29,23 @@ void ToggleMaximize(HWND hwnd);
|
||||||
void EmbeddedWidgetRect(RECT rect);
|
void EmbeddedWidgetRect(RECT rect);
|
||||||
|
|
||||||
typedef enum{
|
typedef enum{
|
||||||
InputEventKind_MouseLeftPress,
|
InputEventKind_MouseLeftPress,
|
||||||
InputEventKind_MouseLeftRelease,
|
InputEventKind_MouseLeftRelease,
|
||||||
} Input_Event_Kind;
|
} Input_Event_Kind;
|
||||||
|
|
||||||
typedef struct Input_Event Input_Event;
|
typedef struct Input_Event Input_Event;
|
||||||
struct Input_Event{
|
struct Input_Event{
|
||||||
Input_Event *next;
|
Input_Event *next;
|
||||||
Input_Event_Kind kind;
|
Input_Event_Kind kind;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Input Input;
|
typedef struct Input Input;
|
||||||
struct Input{
|
struct Input{
|
||||||
Input_Event *first_event;
|
Input_Event *first_event;
|
||||||
Input_Event *last_event;
|
Input_Event *last_event;
|
||||||
int mouse_x;
|
int mouse_x;
|
||||||
int mouse_y;
|
int mouse_y;
|
||||||
int left;
|
int left;
|
||||||
};
|
};
|
||||||
|
|
||||||
void UpdateAndRender(HWND hwnd, Input *input);
|
void UpdateAndRender(HWND hwnd, Input *input);
|
||||||
|
@ -54,7 +54,7 @@ void UpdateAndRender(HWND hwnd, Input *input);
|
||||||
|
|
||||||
int
|
int
|
||||||
HitTest(int x, int y, RECT rect){
|
HitTest(int x, int y, RECT rect){
|
||||||
return((rect.left <= x && x < rect.right) && (rect.top <= y && y < rect.bottom));
|
return((rect.left <= x && x < rect.right) && (rect.top <= y && y < rect.bottom));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
@ -67,19 +67,19 @@ int toggle_maximize_at_end_of_update = 0;
|
||||||
|
|
||||||
int
|
int
|
||||||
WindowIsActive(void){
|
WindowIsActive(void){
|
||||||
return(window_is_active);
|
return(window_is_active);
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
StopRunning(void){
|
StopRunning(void){
|
||||||
keep_running = 0;
|
keep_running = 0;
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
Minimize(HWND hwnd){
|
Minimize(HWND hwnd){
|
||||||
minimize_at_end_of_update = 1;
|
minimize_at_end_of_update = 1;
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
ToggleMaximize(HWND hwnd){
|
ToggleMaximize(HWND hwnd){
|
||||||
toggle_maximize_at_end_of_update = 1;
|
toggle_maximize_at_end_of_update = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_EMBEDDED_WIDGETS 128
|
#define MAX_EMBEDDED_WIDGETS 128
|
||||||
|
@ -87,10 +87,10 @@ int embedded_widget_count = 0;
|
||||||
RECT embedded_widget_rect[MAX_EMBEDDED_WIDGETS];
|
RECT embedded_widget_rect[MAX_EMBEDDED_WIDGETS];
|
||||||
void
|
void
|
||||||
EmbeddedWidgetRect(RECT rect){
|
EmbeddedWidgetRect(RECT rect){
|
||||||
if (embedded_widget_count < MAX_EMBEDDED_WIDGETS){
|
if (embedded_widget_count < MAX_EMBEDDED_WIDGETS){
|
||||||
embedded_widget_rect[embedded_widget_count] = rect;
|
embedded_widget_rect[embedded_widget_count] = rect;
|
||||||
embedded_widget_count += 1;
|
embedded_widget_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
@ -102,19 +102,19 @@ Input input;
|
||||||
|
|
||||||
Input_Event*
|
Input_Event*
|
||||||
PushEvent(void){
|
PushEvent(void){
|
||||||
Input_Event *result = 0;
|
Input_Event *result = 0;
|
||||||
if (input_event_cursor < MAX_INPUT_EVENT_COUNT){
|
if (input_event_cursor < MAX_INPUT_EVENT_COUNT){
|
||||||
result = &input_event_memory[input_event_cursor];
|
result = &input_event_memory[input_event_cursor];
|
||||||
input_event_cursor += 1;
|
input_event_cursor += 1;
|
||||||
if (input.first_event == 0){
|
if (input.first_event == 0){
|
||||||
input.first_event = result;
|
input.first_event = result;
|
||||||
}
|
|
||||||
if (input.last_event != 0){
|
|
||||||
input.last_event->next = result;
|
|
||||||
}
|
|
||||||
input.last_event = result;
|
|
||||||
}
|
}
|
||||||
return(result);
|
if (input.last_event != 0){
|
||||||
|
input.last_event->next = result;
|
||||||
|
}
|
||||||
|
input.last_event = result;
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT
|
LRESULT
|
||||||
|
@ -122,157 +122,157 @@ CustomBorderWindowProc(HWND hwnd,
|
||||||
UINT uMsg,
|
UINT uMsg,
|
||||||
WPARAM wParam,
|
WPARAM wParam,
|
||||||
LPARAM lParam){
|
LPARAM lParam){
|
||||||
LRESULT result = 0;
|
LRESULT result = 0;
|
||||||
switch (uMsg){
|
switch (uMsg){
|
||||||
case WM_NCCALCSIZE:
|
case WM_NCCALCSIZE:
|
||||||
{
|
{
|
||||||
RECT* r = (RECT*)lParam;
|
RECT* r = (RECT*)lParam;
|
||||||
if (IsZoomed(hwnd)){
|
if (IsZoomed(hwnd)){
|
||||||
int x_push_in = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
int x_push_in = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||||
int y_push_in = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
int y_push_in = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||||
r->top += x_push_in;
|
r->top += x_push_in;
|
||||||
r->left += y_push_in;
|
r->left += y_push_in;
|
||||||
r->right -= x_push_in;
|
r->right -= x_push_in;
|
||||||
r->bottom -= y_push_in;
|
r->bottom -= y_push_in;
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_NCACTIVATE:
|
||||||
|
{
|
||||||
|
result = 1;
|
||||||
|
window_is_active = wParam;
|
||||||
|
// A convenient function for checking if a window is minimized.
|
||||||
|
if (IsIconic(hwnd)){
|
||||||
|
result = DefWindowProcW(hwnd, uMsg, wParam, -1);
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_NCHITTEST:
|
||||||
|
{
|
||||||
|
POINT pos;
|
||||||
|
pos.x = GET_X_LPARAM(lParam);
|
||||||
|
pos.y = GET_Y_LPARAM(lParam);
|
||||||
|
|
||||||
|
RECT frame_rect;
|
||||||
|
GetWindowRect(hwnd, &frame_rect);
|
||||||
|
if (!HitTest(pos.x, pos.y, frame_rect)){
|
||||||
|
result = HTNOWHERE;
|
||||||
|
}
|
||||||
|
|
||||||
|
else{
|
||||||
|
|
||||||
|
RECT rect;
|
||||||
|
GetClientRect(hwnd, &rect);
|
||||||
|
ScreenToClient(hwnd, &pos);
|
||||||
|
|
||||||
|
// Borders
|
||||||
|
int l = 0;
|
||||||
|
int r = 0;
|
||||||
|
int b = 0;
|
||||||
|
int t = 0;
|
||||||
|
if (!IsZoomed(hwnd)){
|
||||||
|
if (rect.left <= pos.x && pos.x < rect.left + border_width){
|
||||||
|
l = 1;
|
||||||
|
}
|
||||||
|
if (rect.right - border_width <= pos.x && pos.x < rect.right){
|
||||||
|
r = 1;
|
||||||
|
}
|
||||||
|
if (rect.bottom - border_width <= pos.y && pos.y < rect.bottom){
|
||||||
|
b = 1;
|
||||||
|
}
|
||||||
|
if (rect.top <= pos.y && pos.y < rect.top + border_width){
|
||||||
|
t = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (l){
|
||||||
|
if (t){
|
||||||
|
result = HTTOPLEFT;
|
||||||
|
}
|
||||||
|
else if (b){
|
||||||
|
result = HTBOTTOMLEFT;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
result = HTLEFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (r){
|
||||||
|
if (t){
|
||||||
|
result = HTTOPRIGHT;
|
||||||
|
}
|
||||||
|
else if (b){
|
||||||
|
result = HTBOTTOMRIGHT;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
result = HTRIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (t){
|
||||||
|
result = HTTOP;
|
||||||
|
}
|
||||||
|
else if (b){
|
||||||
|
result = HTBOTTOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inside
|
||||||
|
else{
|
||||||
|
if (rect.top <= pos.y && pos.y < rect.top + caption_width){
|
||||||
|
result = HTCAPTION;
|
||||||
|
for (int i = 0; i < embedded_widget_count; i += 1){
|
||||||
|
if (HitTest(pos.x, pos.y, embedded_widget_rect[i])){
|
||||||
|
result = HTCLIENT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}break;
|
}
|
||||||
|
else{
|
||||||
|
result = HTCLIENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case WM_NCACTIVATE:
|
}break;
|
||||||
{
|
|
||||||
result = 1;
|
|
||||||
window_is_active = wParam;
|
|
||||||
// A convenient function for checking if a window is minimized.
|
|
||||||
if (IsIconic(hwnd)){
|
|
||||||
result = DefWindowProcW(hwnd, uMsg, wParam, -1);
|
|
||||||
}
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case WM_NCHITTEST:
|
case WM_CLOSE:
|
||||||
{
|
{
|
||||||
POINT pos;
|
keep_running = 0;
|
||||||
pos.x = GET_X_LPARAM(lParam);
|
}break;
|
||||||
pos.y = GET_Y_LPARAM(lParam);
|
|
||||||
|
|
||||||
RECT frame_rect;
|
case WM_SIZING:
|
||||||
GetWindowRect(hwnd, &frame_rect);
|
{
|
||||||
if (!HitTest(pos.x, pos.y, frame_rect)){
|
InvalidateRect(hwnd, 0, 0);
|
||||||
result = HTNOWHERE;
|
}break;
|
||||||
}
|
|
||||||
|
|
||||||
else{
|
case WM_PAINT:
|
||||||
|
{
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
BeginPaint(hwnd, &ps);
|
||||||
|
embedded_widget_count = 0;
|
||||||
|
UpdateAndRender(hwnd, 0);
|
||||||
|
EndPaint(hwnd, &ps);
|
||||||
|
}break;
|
||||||
|
|
||||||
RECT rect;
|
case WM_LBUTTONDOWN:
|
||||||
GetClientRect(hwnd, &rect);
|
{
|
||||||
ScreenToClient(hwnd, &pos);
|
Input_Event *event = PushEvent();
|
||||||
|
if (event != 0){
|
||||||
|
event->kind = InputEventKind_MouseLeftPress;
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
|
||||||
// Borders
|
case WM_LBUTTONUP:
|
||||||
int l = 0;
|
{
|
||||||
int r = 0;
|
Input_Event *event = PushEvent();
|
||||||
int b = 0;
|
if (event != 0){
|
||||||
int t = 0;
|
event->kind = InputEventKind_MouseLeftRelease;
|
||||||
if (!IsZoomed(hwnd)){
|
}
|
||||||
if (rect.left <= pos.x && pos.x < rect.left + border_width){
|
}break;
|
||||||
l = 1;
|
|
||||||
}
|
|
||||||
if (rect.right - border_width <= pos.x && pos.x < rect.right){
|
|
||||||
r = 1;
|
|
||||||
}
|
|
||||||
if (rect.bottom - border_width <= pos.y && pos.y < rect.bottom){
|
|
||||||
b = 1;
|
|
||||||
}
|
|
||||||
if (rect.top <= pos.y && pos.y < rect.top + border_width){
|
|
||||||
t = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (l){
|
|
||||||
if (t){
|
|
||||||
result = HTTOPLEFT;
|
|
||||||
}
|
|
||||||
else if (b){
|
|
||||||
result = HTBOTTOMLEFT;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
result = HTLEFT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (r){
|
|
||||||
if (t){
|
|
||||||
result = HTTOPRIGHT;
|
|
||||||
}
|
|
||||||
else if (b){
|
|
||||||
result = HTBOTTOMRIGHT;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
result = HTRIGHT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (t){
|
|
||||||
result = HTTOP;
|
|
||||||
}
|
|
||||||
else if (b){
|
|
||||||
result = HTBOTTOM;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inside
|
default:
|
||||||
else{
|
{
|
||||||
if (rect.top <= pos.y && pos.y < rect.top + caption_width){
|
result = DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||||
result = HTCAPTION;
|
}break;
|
||||||
for (int i = 0; i < embedded_widget_count; i += 1){
|
}
|
||||||
if (HitTest(pos.x, pos.y, embedded_widget_rect[i])){
|
return(result);
|
||||||
result = HTCLIENT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
result = HTCLIENT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case WM_CLOSE:
|
|
||||||
{
|
|
||||||
keep_running = 0;
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case WM_SIZING:
|
|
||||||
{
|
|
||||||
InvalidateRect(hwnd, 0, 0);
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case WM_PAINT:
|
|
||||||
{
|
|
||||||
PAINTSTRUCT ps;
|
|
||||||
BeginPaint(hwnd, &ps);
|
|
||||||
embedded_widget_count = 0;
|
|
||||||
UpdateAndRender(hwnd, 0);
|
|
||||||
EndPaint(hwnd, &ps);
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case WM_LBUTTONDOWN:
|
|
||||||
{
|
|
||||||
Input_Event *event = PushEvent();
|
|
||||||
if (event != 0){
|
|
||||||
event->kind = InputEventKind_MouseLeftPress;
|
|
||||||
}
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case WM_LBUTTONUP:
|
|
||||||
{
|
|
||||||
Input_Event *event = PushEvent();
|
|
||||||
if (event != 0){
|
|
||||||
event->kind = InputEventKind_MouseLeftRelease;
|
|
||||||
}
|
|
||||||
}break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
result = DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
|
||||||
}break;
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -283,134 +283,136 @@ WinMain(HINSTANCE hInstance,
|
||||||
|
|
||||||
#define WINDOW_CLASS L"MainWindow"
|
#define WINDOW_CLASS L"MainWindow"
|
||||||
|
|
||||||
WNDCLASSW window_class = {0};
|
WNDCLASSW window_class = {0};
|
||||||
window_class.style = 0;
|
window_class.style = 0;
|
||||||
window_class.lpfnWndProc = CustomBorderWindowProc;
|
window_class.lpfnWndProc = CustomBorderWindowProc;
|
||||||
window_class.hInstance = hInstance;
|
window_class.hInstance = hInstance;
|
||||||
window_class.hCursor = LoadCursorA(0, IDC_ARROW);
|
window_class.hCursor = LoadCursorA(0, IDC_ARROW);
|
||||||
window_class.lpszClassName = WINDOW_CLASS;
|
window_class.lpszClassName = WINDOW_CLASS;
|
||||||
|
|
||||||
ATOM atom = RegisterClassW(&window_class);
|
ATOM atom = RegisterClassW(&window_class);
|
||||||
if (atom == 0){
|
if (atom == 0){
|
||||||
fprintf(stderr, "RegisterClassW failed\n");
|
fprintf(stderr, "RegisterClassW failed\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD style = WS_OVERLAPPEDWINDOW;
|
||||||
|
HWND hwnd = CreateWindowW(WINDOW_CLASS,
|
||||||
|
L"Window Name",
|
||||||
|
style,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
hInstance,
|
||||||
|
0);
|
||||||
|
if (hwnd == 0){
|
||||||
|
fprintf(stderr, "CreateWindowExW failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowTheme(hwnd, L" ", L" ");
|
||||||
|
|
||||||
|
|
||||||
|
BOOL composition_enabled;
|
||||||
|
if (DwmIsCompositionEnabled(&composition_enabled) != S_OK){
|
||||||
|
fprintf(stderr, "DwmIsCompositionEnabled failed\n");
|
||||||
|
composition_enabled = 0;
|
||||||
|
}
|
||||||
|
fprintf(stdout, "Has compositor? %s\n", composition_enabled?"Yes":"No");
|
||||||
|
|
||||||
|
ShowWindow(hwnd, SW_SHOW);
|
||||||
|
|
||||||
|
keep_running = 1;
|
||||||
|
for (;keep_running;){
|
||||||
|
input.first_event = 0;
|
||||||
|
input.last_event = 0;
|
||||||
|
input_event_cursor = 0;
|
||||||
|
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
if (minimize_at_end_of_update){
|
||||||
|
ShowWindow(hwnd, SW_MINIMIZE);
|
||||||
|
}
|
||||||
|
else if (toggle_maximize_at_end_of_update){
|
||||||
|
if (IsZoomed(hwnd)){
|
||||||
|
ShowWindow(hwnd, SW_RESTORE);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ShowWindow(hwnd, SW_MAXIMIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
GetMessage(&msg, 0, 0, 0);
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD style = WS_OVERLAPPEDWINDOW;
|
for (;PeekMessageW(&msg, 0, 0, 0, PM_REMOVE);){
|
||||||
HWND hwnd = CreateWindowW(WINDOW_CLASS,
|
TranslateMessage(&msg);
|
||||||
L"Window Name",
|
DispatchMessage(&msg);
|
||||||
style,
|
|
||||||
CW_USEDEFAULT,
|
|
||||||
CW_USEDEFAULT,
|
|
||||||
CW_USEDEFAULT,
|
|
||||||
CW_USEDEFAULT,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
hInstance,
|
|
||||||
0);
|
|
||||||
if (hwnd == 0){
|
|
||||||
fprintf(stderr, "CreateWindowExW failed\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SetWindowTheme(hwnd, L" ", L" ");
|
POINT mpos;
|
||||||
|
GetCursorPos(&mpos);
|
||||||
|
ScreenToClient(hwnd, &mpos);
|
||||||
|
input.mouse_x = mpos.x;
|
||||||
|
input.mouse_y = mpos.y;
|
||||||
|
input.left = (GetKeyState(VK_LBUTTON)&(1 << 15));
|
||||||
|
|
||||||
|
minimize_at_end_of_update = 0;
|
||||||
|
toggle_maximize_at_end_of_update = 0;
|
||||||
|
embedded_widget_count = 0;
|
||||||
|
UpdateAndRender(hwnd, &input);
|
||||||
|
|
||||||
BOOL composition_enabled;
|
if (composition_enabled){
|
||||||
if (DwmIsCompositionEnabled(&composition_enabled) != S_OK){
|
DwmFlush();
|
||||||
fprintf(stderr, "DwmIsCompositionEnabled failed\n");
|
|
||||||
composition_enabled = 0;
|
|
||||||
}
|
}
|
||||||
fprintf(stdout, "Has compositor? %s\n", composition_enabled?"Yes":"No");
|
else{
|
||||||
|
Sleep(33);
|
||||||
ShowWindow(hwnd, SW_SHOW);
|
|
||||||
|
|
||||||
keep_running = 1;
|
|
||||||
for (;keep_running;){
|
|
||||||
input.first_event = 0;
|
|
||||||
input.last_event = 0;
|
|
||||||
input_event_cursor = 0;
|
|
||||||
|
|
||||||
MSG msg;
|
|
||||||
|
|
||||||
if (minimize_at_end_of_update){
|
|
||||||
ShowWindow(hwnd, SW_MINIMIZE);
|
|
||||||
}
|
|
||||||
else if (toggle_maximize_at_end_of_update){
|
|
||||||
if (IsZoomed(hwnd)){
|
|
||||||
ShowWindow(hwnd, SW_RESTORE);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
ShowWindow(hwnd, SW_MAXIMIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
GetMessage(&msg, 0, 0, 0);
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;PeekMessageW(&msg, 0, 0, 0, PM_REMOVE);){
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
POINT mpos;
|
|
||||||
GetCursorPos(&mpos);
|
|
||||||
ScreenToClient(hwnd, &mpos);
|
|
||||||
input.mouse_x = mpos.x;
|
|
||||||
input.mouse_y = mpos.y;
|
|
||||||
input.left = (GetKeyState(VK_LBUTTON)&(1 << 15));
|
|
||||||
|
|
||||||
minimize_at_end_of_update = 0;
|
|
||||||
toggle_maximize_at_end_of_update = 0;
|
|
||||||
embedded_widget_count = 0;
|
|
||||||
UpdateAndRender(hwnd, &input);
|
|
||||||
|
|
||||||
if (composition_enabled){
|
|
||||||
DwmFlush();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
Sleep(33);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
int
|
int
|
||||||
HasEvent(Input *input, Input_Event_Kind kind){
|
HasEvent(Input *input, Input_Event_Kind kind){
|
||||||
int result = 0;
|
int result = 0;
|
||||||
if (input != 0){
|
if (input != 0){
|
||||||
Input_Event **ptr_to = &input->first_event;
|
Input_Event **ptr_to = &input->first_event;
|
||||||
Input_Event *last = 0;
|
Input_Event *last = 0;
|
||||||
for (Input_Event *event = input->first_event, *next = 0;
|
for (Input_Event *event = input->first_event, *next = 0;
|
||||||
event != 0;
|
event != 0;
|
||||||
event = next){
|
event = next){
|
||||||
next = event->next;
|
next = event->next;
|
||||||
if (event->kind == kind){
|
if (event->kind == kind){
|
||||||
result = 1;
|
result = 1;
|
||||||
*ptr_to = next;
|
*ptr_to = next;
|
||||||
break;
|
if (event == input->last_event){
|
||||||
}
|
input->last_event = last;
|
||||||
else{
|
|
||||||
ptr_to = &event->next;
|
|
||||||
last = event;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
input->last_event = last;
|
break;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ptr_to = &event->next;
|
||||||
|
last = event;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return(result);
|
}
|
||||||
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum{
|
typedef enum{
|
||||||
Widget_None,
|
Widget_None,
|
||||||
Widget_Close,
|
Widget_Close,
|
||||||
Widget_Minimize,
|
Widget_Minimize,
|
||||||
Widget_Maximize,
|
Widget_Maximize,
|
||||||
Widget_Slider,
|
Widget_Slider,
|
||||||
} Widget;
|
} Widget;
|
||||||
|
|
||||||
Widget click_started = Widget_None;
|
Widget click_started = Widget_None;
|
||||||
|
@ -419,166 +421,166 @@ int delta_from_mouse_x = 0;
|
||||||
|
|
||||||
void
|
void
|
||||||
UpdateAndRender(HWND hwnd, Input *input){
|
UpdateAndRender(HWND hwnd, Input *input){
|
||||||
RECT window_rect;
|
RECT window_rect;
|
||||||
GetClientRect(hwnd, &window_rect);
|
GetClientRect(hwnd, &window_rect);
|
||||||
|
|
||||||
RECT inside_rect;
|
RECT inside_rect;
|
||||||
inside_rect.top = window_rect.top + caption_width;
|
inside_rect.top = window_rect.top + caption_width;
|
||||||
if (!IsZoomed(hwnd)){
|
if (!IsZoomed(hwnd)){
|
||||||
inside_rect.left = window_rect.left + border_width;
|
inside_rect.left = window_rect.left + border_width;
|
||||||
inside_rect.right = window_rect.right - border_width;
|
inside_rect.right = window_rect.right - border_width;
|
||||||
inside_rect.bottom = window_rect.bottom - border_width;
|
inside_rect.bottom = window_rect.bottom - border_width;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
inside_rect.left = window_rect.left;
|
inside_rect.left = window_rect.left;
|
||||||
inside_rect.right = window_rect.right;
|
inside_rect.right = window_rect.right;
|
||||||
inside_rect.bottom = window_rect.bottom;
|
inside_rect.bottom = window_rect.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
HDC dc = GetDC(hwnd);
|
HDC dc = GetDC(hwnd);
|
||||||
|
{
|
||||||
|
SelectObject(dc, GetStockObject(DC_PEN));
|
||||||
|
SelectObject(dc, GetStockObject(DC_BRUSH));
|
||||||
|
|
||||||
|
// Window border
|
||||||
{
|
{
|
||||||
SelectObject(dc, GetStockObject(DC_PEN));
|
if (WindowIsActive()){
|
||||||
SelectObject(dc, GetStockObject(DC_BRUSH));
|
SetDCPenColor(dc, RGB(255, 200, 0));
|
||||||
|
SetDCBrushColor(dc, RGB(255, 200, 0));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
SetDCPenColor(dc, RGB(128, 100, 0));
|
||||||
|
SetDCBrushColor(dc, RGB(128, 100, 0));
|
||||||
|
}
|
||||||
|
|
||||||
// Window border
|
Rectangle(dc, window_rect.left, window_rect.top, window_rect.right, inside_rect.top);
|
||||||
{
|
Rectangle(dc, window_rect.left, inside_rect.bottom, window_rect.right, window_rect.bottom);
|
||||||
if (WindowIsActive()){
|
Rectangle(dc, window_rect.left, inside_rect.top, inside_rect.left, inside_rect.bottom);
|
||||||
SetDCPenColor(dc, RGB(255, 200, 0));
|
Rectangle(dc, inside_rect.right, inside_rect.top, window_rect.right, inside_rect.bottom);
|
||||||
SetDCBrushColor(dc, RGB(255, 200, 0));
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
SetDCPenColor(dc, RGB(128, 100, 0));
|
|
||||||
SetDCBrushColor(dc, RGB(128, 100, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle(dc, window_rect.left, window_rect.top, window_rect.right, inside_rect.top);
|
|
||||||
Rectangle(dc, window_rect.left, inside_rect.bottom, window_rect.right, window_rect.bottom);
|
|
||||||
Rectangle(dc, window_rect.left, inside_rect.top, inside_rect.left, inside_rect.bottom);
|
|
||||||
Rectangle(dc, inside_rect.right, inside_rect.top, window_rect.right, inside_rect.bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close button
|
|
||||||
if (window_rect.right > 20){
|
|
||||||
RECT button;
|
|
||||||
button.left = window_rect.right - 20;
|
|
||||||
button.top = window_rect.top + 10;
|
|
||||||
button.right = window_rect.right - 10;
|
|
||||||
button.bottom = window_rect.top + 20;
|
|
||||||
|
|
||||||
SetDCPenColor(dc, RGB(180, 0, 0));
|
|
||||||
SetDCBrushColor(dc, RGB(180, 0, 0));
|
|
||||||
|
|
||||||
EmbeddedWidgetRect(button);
|
|
||||||
Rectangle(dc, button.left, button.top, button.right, button.bottom);
|
|
||||||
if (input != 0 && HitTest(input->mouse_x, input->mouse_y, button)){
|
|
||||||
if (HasEvent(input, InputEventKind_MouseLeftPress)){
|
|
||||||
click_started = Widget_Close;
|
|
||||||
}
|
|
||||||
if (click_started == Widget_Close && HasEvent(input, InputEventKind_MouseLeftRelease)){
|
|
||||||
StopRunning();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Minimize button
|
|
||||||
if (window_rect.right > 40){
|
|
||||||
RECT button;
|
|
||||||
button.left = window_rect.right - 40;
|
|
||||||
button.top = window_rect.top + 10;
|
|
||||||
button.right = window_rect.right - 30;
|
|
||||||
button.bottom = window_rect.top + 20;
|
|
||||||
|
|
||||||
SetDCPenColor(dc, RGB(0, 0, 180));
|
|
||||||
SetDCBrushColor(dc, RGB(0, 0, 180));
|
|
||||||
|
|
||||||
EmbeddedWidgetRect(button);
|
|
||||||
Rectangle(dc, button.left, button.top, button.right, button.bottom);
|
|
||||||
if (input != 0 && HitTest(input->mouse_x, input->mouse_y, button)){
|
|
||||||
if (HasEvent(input, InputEventKind_MouseLeftPress)){
|
|
||||||
click_started = Widget_Minimize;
|
|
||||||
}
|
|
||||||
if (click_started == Widget_Minimize && HasEvent(input, InputEventKind_MouseLeftRelease)){
|
|
||||||
Minimize(hwnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maximize button
|
|
||||||
if (window_rect.right > 60){
|
|
||||||
RECT button;
|
|
||||||
button.left = window_rect.right - 60;
|
|
||||||
button.top = window_rect.top + 10;
|
|
||||||
button.right = window_rect.right - 50;
|
|
||||||
button.bottom = window_rect.top + 20;
|
|
||||||
|
|
||||||
SetDCPenColor(dc, RGB(0, 180, 0));
|
|
||||||
SetDCBrushColor(dc, RGB(0, 180, 0));
|
|
||||||
|
|
||||||
EmbeddedWidgetRect(button);
|
|
||||||
Rectangle(dc, button.left, button.top, button.right, button.bottom);
|
|
||||||
if (input != 0 && HitTest(input->mouse_x, input->mouse_y, button)){
|
|
||||||
if (HasEvent(input, InputEventKind_MouseLeftPress)){
|
|
||||||
click_started = Widget_Maximize;
|
|
||||||
}
|
|
||||||
if (click_started == Widget_Maximize && HasEvent(input, InputEventKind_MouseLeftRelease)){
|
|
||||||
ToggleMaximize(hwnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Slider
|
|
||||||
if (window_rect.right > 200){
|
|
||||||
RECT track;
|
|
||||||
track.left = window_rect.right - 195;
|
|
||||||
track.top = window_rect.top + 14;
|
|
||||||
track.right = window_rect.right - 95;
|
|
||||||
track.bottom = window_rect.top + 16;
|
|
||||||
|
|
||||||
SetDCPenColor(dc, RGB(0, 0, 0));
|
|
||||||
SetDCBrushColor(dc, RGB(0, 0, 0));
|
|
||||||
Rectangle(dc, track.left, track.top, track.right, track.bottom);
|
|
||||||
|
|
||||||
RECT button;
|
|
||||||
button.left = window_rect.right - 200 + slider_x;
|
|
||||||
button.top = window_rect.top + 10;
|
|
||||||
button.right = window_rect.right - 190 + slider_x;
|
|
||||||
button.bottom = window_rect.top + 20;
|
|
||||||
|
|
||||||
SetDCPenColor(dc, RGB(100, 200, 200));
|
|
||||||
SetDCBrushColor(dc, RGB(100, 200, 200));
|
|
||||||
|
|
||||||
EmbeddedWidgetRect(button);
|
|
||||||
Rectangle(dc, button.left, button.top, button.right, button.bottom);
|
|
||||||
if (input != 0){
|
|
||||||
if (HitTest(input->mouse_x, input->mouse_y, button)){
|
|
||||||
if (HasEvent(input, InputEventKind_MouseLeftPress)){
|
|
||||||
click_started = Widget_Slider;
|
|
||||||
delta_from_mouse_x = slider_x - input->mouse_x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (click_started == Widget_Slider){
|
|
||||||
slider_x = delta_from_mouse_x + input->mouse_x;
|
|
||||||
if (slider_x < 0){
|
|
||||||
slider_x = 0;
|
|
||||||
}
|
|
||||||
if (slider_x > 100){
|
|
||||||
slider_x = 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input != 0 && !input->left){
|
|
||||||
click_started = Widget_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inside area
|
|
||||||
{
|
|
||||||
SetDCPenColor(dc, RGB(127, 127, 127));
|
|
||||||
SetDCBrushColor(dc, RGB(127, 127, 127));
|
|
||||||
Rectangle(dc, inside_rect.left, inside_rect.top, inside_rect.right, inside_rect.bottom);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ReleaseDC(hwnd, dc);
|
|
||||||
|
// Close button
|
||||||
|
if (window_rect.right > 20){
|
||||||
|
RECT button;
|
||||||
|
button.left = window_rect.right - 20;
|
||||||
|
button.top = window_rect.top + 10;
|
||||||
|
button.right = window_rect.right - 10;
|
||||||
|
button.bottom = window_rect.top + 20;
|
||||||
|
|
||||||
|
SetDCPenColor(dc, RGB(180, 0, 0));
|
||||||
|
SetDCBrushColor(dc, RGB(180, 0, 0));
|
||||||
|
|
||||||
|
EmbeddedWidgetRect(button);
|
||||||
|
Rectangle(dc, button.left, button.top, button.right, button.bottom);
|
||||||
|
if (input != 0 && HitTest(input->mouse_x, input->mouse_y, button)){
|
||||||
|
if (HasEvent(input, InputEventKind_MouseLeftPress)){
|
||||||
|
click_started = Widget_Close;
|
||||||
|
}
|
||||||
|
if (click_started == Widget_Close && HasEvent(input, InputEventKind_MouseLeftRelease)){
|
||||||
|
StopRunning();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minimize button
|
||||||
|
if (window_rect.right > 40){
|
||||||
|
RECT button;
|
||||||
|
button.left = window_rect.right - 40;
|
||||||
|
button.top = window_rect.top + 10;
|
||||||
|
button.right = window_rect.right - 30;
|
||||||
|
button.bottom = window_rect.top + 20;
|
||||||
|
|
||||||
|
SetDCPenColor(dc, RGB(0, 0, 180));
|
||||||
|
SetDCBrushColor(dc, RGB(0, 0, 180));
|
||||||
|
|
||||||
|
EmbeddedWidgetRect(button);
|
||||||
|
Rectangle(dc, button.left, button.top, button.right, button.bottom);
|
||||||
|
if (input != 0 && HitTest(input->mouse_x, input->mouse_y, button)){
|
||||||
|
if (HasEvent(input, InputEventKind_MouseLeftPress)){
|
||||||
|
click_started = Widget_Minimize;
|
||||||
|
}
|
||||||
|
if (click_started == Widget_Minimize && HasEvent(input, InputEventKind_MouseLeftRelease)){
|
||||||
|
Minimize(hwnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maximize button
|
||||||
|
if (window_rect.right > 60){
|
||||||
|
RECT button;
|
||||||
|
button.left = window_rect.right - 60;
|
||||||
|
button.top = window_rect.top + 10;
|
||||||
|
button.right = window_rect.right - 50;
|
||||||
|
button.bottom = window_rect.top + 20;
|
||||||
|
|
||||||
|
SetDCPenColor(dc, RGB(0, 180, 0));
|
||||||
|
SetDCBrushColor(dc, RGB(0, 180, 0));
|
||||||
|
|
||||||
|
EmbeddedWidgetRect(button);
|
||||||
|
Rectangle(dc, button.left, button.top, button.right, button.bottom);
|
||||||
|
if (input != 0 && HitTest(input->mouse_x, input->mouse_y, button)){
|
||||||
|
if (HasEvent(input, InputEventKind_MouseLeftPress)){
|
||||||
|
click_started = Widget_Maximize;
|
||||||
|
}
|
||||||
|
if (click_started == Widget_Maximize && HasEvent(input, InputEventKind_MouseLeftRelease)){
|
||||||
|
ToggleMaximize(hwnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slider
|
||||||
|
if (window_rect.right > 200){
|
||||||
|
RECT track;
|
||||||
|
track.left = window_rect.right - 195;
|
||||||
|
track.top = window_rect.top + 14;
|
||||||
|
track.right = window_rect.right - 95;
|
||||||
|
track.bottom = window_rect.top + 16;
|
||||||
|
|
||||||
|
SetDCPenColor(dc, RGB(0, 0, 0));
|
||||||
|
SetDCBrushColor(dc, RGB(0, 0, 0));
|
||||||
|
Rectangle(dc, track.left, track.top, track.right, track.bottom);
|
||||||
|
|
||||||
|
RECT button;
|
||||||
|
button.left = window_rect.right - 200 + slider_x;
|
||||||
|
button.top = window_rect.top + 10;
|
||||||
|
button.right = window_rect.right - 190 + slider_x;
|
||||||
|
button.bottom = window_rect.top + 20;
|
||||||
|
|
||||||
|
SetDCPenColor(dc, RGB(100, 200, 200));
|
||||||
|
SetDCBrushColor(dc, RGB(100, 200, 200));
|
||||||
|
|
||||||
|
EmbeddedWidgetRect(button);
|
||||||
|
Rectangle(dc, button.left, button.top, button.right, button.bottom);
|
||||||
|
if (input != 0){
|
||||||
|
if (HitTest(input->mouse_x, input->mouse_y, button)){
|
||||||
|
if (HasEvent(input, InputEventKind_MouseLeftPress)){
|
||||||
|
click_started = Widget_Slider;
|
||||||
|
delta_from_mouse_x = slider_x - input->mouse_x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (click_started == Widget_Slider){
|
||||||
|
slider_x = delta_from_mouse_x + input->mouse_x;
|
||||||
|
if (slider_x < 0){
|
||||||
|
slider_x = 0;
|
||||||
|
}
|
||||||
|
if (slider_x > 100){
|
||||||
|
slider_x = 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input != 0 && !input->left){
|
||||||
|
click_started = Widget_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inside area
|
||||||
|
{
|
||||||
|
SetDCPenColor(dc, RGB(127, 127, 127));
|
||||||
|
SetDCBrushColor(dc, RGB(127, 127, 127));
|
||||||
|
Rectangle(dc, inside_rect.left, inside_rect.top, inside_rect.right, inside_rect.bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ReleaseDC(hwnd, dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue