/**==========================================================================
Copyright (C) 2018 Nick Currie, Copyleft.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
==========================================================================**/
#include
#include
/*============================================================================
Licensed under the MIT License .
Copyright (c) 2013-2018 Niels Lohmann .
See MIT license text in nlohmann_json.h
============================================================================*/
#include "src/json.h"
//#include "src/json_old.h"
//============================================================================
//============================================================================================================================================
// Pre-define headers.
//============================================================================================================================================
LRESULT CALLBACK MainProc(HWND, UINT, WPARAM, LPARAM);
//============================================================================================================================================
#define _NULL_RECT {0,0,0,0}
//-------------------------------------------
const long transparency = 0x000000; // use full black as the window transparency "colour".
static const std::string emptystring = "";
static const std::string undefined = "Undefined";
static const std::string unknown = "Unknown";
//============================================================================================================================================
class WindowClass
{
HWND _hwnd = nullptr;
HDC _hdc = nullptr;
PAINTSTRUCT _ps;
HDC _buffHDC = nullptr;
HBITMAP _buffCCB;
HBITMAP _buffBMP;
union
{
uint32_t Clicks;
POINT Click;
};
public:
// Variables
WINDOWINFO info = {sizeof(WINDOWINFO), _NULL_RECT, _NULL_RECT, 0,0,0,0,0,0,0};
// Functions
inline int32_t clickx(void) { return Click.x; }
inline int32_t clicky(void) { return Click.y; }
inline void click(uint32_t thisXY) {Click.x = int16_t(thisXY & 0xFFFF); Click.y = int16_t((thisXY >> 16) & 0xFFFF); }
inline HWND hwnd() {return _hwnd;}
inline void sethwnd(HWND hwnd) {_hwnd = hwnd;}
inline HDC hdc() {return _hdc;}
inline void getDC() {_hdc = GetDC(_hwnd);}
inline void sethdc(HDC hdc) {_hdc = hdc;}
inline void releaseDC() {ReleaseDC(_hwnd, _hdc); _hdc = nullptr;}
inline void buffrect(RECT* thisRect) { Rectangle(_buffHDC, thisRect->left, thisRect->top, thisRect->right, thisRect->bottom); }
inline void beginpaint() {_hdc = BeginPaint(_hwnd, &_ps);}
inline void endpaint() {EndPaint(_hwnd, &_ps); ReleaseDC(_hwnd,_hdc); _hdc = nullptr;}
inline void createcompatibledc() {_buffHDC = CreateCompatibleDC(_hdc);} // create the offscreen DC;
inline HDC buffHDC() {return _buffHDC;}
inline void createcompatiblebitmap()
{
_buffCCB = CreateCompatibleBitmap(_hdc, cwidth(), cheight());
} // create bitmap with the window DC;)
inline void selectbitmap() {_buffBMP = (HBITMAP)SelectObject(_buffHDC, _buffCCB);} // put the bitmap in the DC
inline void deleteCCB() {DeleteObject(_buffCCB);}
inline void deletecompatibledc() {DeleteDC(_buffHDC);}
inline void createbuffer()
{
_buffHDC = CreateCompatibleDC(_hdc);
_buffCCB = CreateCompatibleBitmap(_hdc, wwidth(), wheight());
_buffBMP = (HBITMAP)SelectObject(_buffHDC, _buffCCB);
}
inline void bitblt()
{
BitBlt(_hdc, 0, 0, cwidth(), cheight(), _buffHDC, 0, 0, SRCCOPY);
}
inline void deletebuffer()
{
_buffBMP = (HBITMAP)SelectObject(_buffHDC, _buffCCB);
DeleteObject(_buffCCB);
DeleteDC(_buffHDC);
}
inline long cwidth() {return info.rcClient.right - info.rcClient.left;}
inline long cheight() {return info.rcClient.bottom - info.rcClient.top;}
inline long wwidth() {return info.rcWindow.right - info.rcWindow.left;}
inline long wheight() {return info.rcWindow.bottom - info.rcWindow.top;}
inline bool getwindowinfo() {return GetWindowInfo(_hwnd, &info);}
inline void invalidateclientrect(bool xx = true)
{
GetClientRect(_hwnd, &info.rcClient);
InvalidateRect(_hwnd, &info.rcClient, xx);
}
} Main;
//============================================================================================================================================
// Inlines.
//============================================================================================================================================
template inline std::string NumToStr(T number)
{
std::ostringstream ss;
ss << number;
return ss.str();
}
//============================================================================================================================================
// Main Window Procedures.
//============================================================================================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int32_t iCmdShow)
{
static TCHAR szAppName[] = TEXT("ThisProgram");
WNDCLASS wndclass = {CS_HREDRAW | CS_VREDRAW, MainProc, 0, 0, hInstance, LoadIcon(nullptr, IDI_APPLICATION), LoadCursor(nullptr, IDC_ARROW), (HBRUSH) CreateSolidBrush(transparency), nullptr, szAppName};
if (!RegisterClass(&wndclass))
{
MessageBox(nullptr, TEXT("Program requires Windows NT or later!"), szAppName, MB_ICONERROR);
return 0;
}
if (hPrevInstance != nullptr)
{
MessageBox(nullptr, TEXT("Odd previous instance behaviour detected"), szCmdLine, MB_ICONERROR);
return 0;
}
Main.sethwnd(CreateWindowEx(WS_EX_LAYERED, szAppName, TEXT(szAppName), DS_3DLOOK | DS_MODALFRAME | WS_POPUP | WS_CLIPCHILDREN, 20, 20, 90, 90, nullptr, nullptr, hInstance, nullptr));
ShowWindow(Main.hwnd(), iCmdShow);
UpdateWindow(Main.hwnd());
MSG msg = {};
while(GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//============================================================================================================================================
LRESULT CALLBACK MainProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
Main.getwindowinfo();
switch(Message)
{
case WM_CREATE:
{
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
SetLayeredWindowAttributes(hwnd, transparency, (255 * 100)/100, LWA_ALPHA | LWA_COLORKEY);
}
break;
case WM_ERASEBKGND:
{
return(LRESULT)true;
}
break;
case WM_LBUTTONDOWN:
{
SetCapture(hwnd);
Main.click(lParam);
}
break;
case WM_LBUTTONUP:
{
ReleaseCapture();
}
break;
case WM_MOUSEMOVE:
{
if (GetCapture() == hwnd) //Check if this window has mouse input
{
//Get the window's position.
Main.getwindowinfo();
//Get the current mouse coordinates
POINT Mouse;
Mouse.x = int16_t(LOWORD(lParam));
Mouse.y = int16_t(HIWORD(lParam));
//Calculate the new window coordinates
int32_t xWindow = Main.info.rcWindow.left + Mouse.x - Main.clickx();
int32_t yWindow = Main.info.rcWindow.top + Mouse.y - Main.clicky();
//Set the window's new screen position(don't resize or change z-order)
SetWindowPos(hwnd, nullptr, xWindow, yWindow, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
}
}
break;
case WM_PAINT:
{
SetWindowPos(hwnd, nullptr, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
Main.getwindowinfo();
Main.beginpaint();
Main.createbuffer(); // <- create the offscreen DC
SelectObject(Main.buffHDC(), GetStockObject(DC_PEN));
SelectObject(Main.buffHDC(), GetStockObject(DC_BRUSH));
// "Blank" buffered window with transparent colour.
SetDCPenColor(Main.buffHDC(), transparency);
SetDCBrushColor(Main.buffHDC(), transparency);
Rectangle(Main.buffHDC(), 0, 0, 300, 300);
// Draw surrounding border.
SetDCPenColor(Main.buffHDC(), 0x00808080);
SetDCBrushColor(Main.buffHDC(), 0x00808080);
RoundRect(Main.buffHDC(), 0, 0, 300, 300, 60, 60);
Main.bitblt(); // copy contents of buffered window to window.
Main.deletebuffer(); // tidy up after buffering window draw.
Main.endpaint();
}
break;
case WM_SIZE:
{
Main.invalidateclientrect(true);
}
break;
case WM_SETFOCUS:
{
SetLayeredWindowAttributes(hwnd, transparency, 255, LWA_ALPHA | LWA_COLORKEY);
Main.invalidateclientrect();
}
break;
case WM_SYSKEYDOWN:
{
if ((lParam && 0x1000000) && (wParam == 0x51)) // Alt-Q
{
PostMessage(Main.hwnd(), WM_CLOSE, 0, 0);
}
}
break;
case WM_KILLFOCUS:
{
SetLayeredWindowAttributes(hwnd, transparency, (255 * 0.5), LWA_ALPHA | LWA_COLORKEY);
Main.invalidateclientrect();
}
break;
case WM_COMMAND:
{
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
case WM_CLOSE:
{
DestroyWindow(hwnd);
}
break;
default:
return true;
}
return DefWindowProc(hwnd, Message, wParam, lParam);
}
//============================================================================================================================================