Skip to content

Instantly share code, notes, and snippets.

@NoTimeForHero
Last active May 19, 2019 21:18
Show Gist options
  • Save NoTimeForHero/d3a66b0ef266925f821afe6c0ba88152 to your computer and use it in GitHub Desktop.
Save NoTimeForHero/d3a66b0ef266925f821afe6c0ba88152 to your computer and use it in GitHub Desktop.
Semi-transparent overlay to show user that window is blocked
#include <windows.h>
#include <hbapi.h>
#include <vector>
#include <map>
#include <cstdlib>
typedef std::vector<HWND> HWND_ARRAY;
std::map<HWND, HWND_ARRAY*> arrOverlays;
std::map<HWND, HBRUSH> overlaysBrushes;
HWND WIN32_CreateOverlay(HINSTANCE hInstance, HWND hwndParent, BYTE cRed, BYTE cGreen, BYTE cBlue, BYTE cAlpha);
void WIN32_VanishOverlay(HWND hWndParent, BOOL isShow);
void WIN32_UpdateOverlay(HWND hWndParent);
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
static void MakeWindowTransparent(HWND hWnd, BYTE level);
static void SetBackgroundColor(HWND hWnd, BYTE red, BYTE green, BYTE blue);
static RECT GetWorkingArea(HWND hwnd);
static void AdjustParentCords(HWND hWnd, HWND hwndParent);
HB_FUNC( OVERLAYCREATE ) // hWnd -> pDisp
{
HINSTANCE hInstance = GetModuleHandle(NULL);
HWND hWnd = (HWND) hb_parnl( 1 );
BYTE colRed = (BYTE) hb_parni( 2 );
BYTE colGreen = (BYTE) hb_parni( 3 );
BYTE colBlue = (BYTE) hb_parni( 4 );
BYTE alpha = (BYTE) hb_parni( 5 );
HWND hOverlay = WIN32_CreateOverlay(hInstance, hWnd, colRed, colGreen, colBlue, alpha);
if (!arrOverlays.count(hWnd)) arrOverlays[hWnd] = new HWND_ARRAY();
arrOverlays[hWnd]->push_back(hOverlay);
}
HB_FUNC( OVERLAYCLOSE )
{
HWND hWndParent = (HWND) hb_parnl( 1 );
if (!arrOverlays.count(hWndParent)) return;
HWND_ARRAY *array = arrOverlays[hWndParent];
for(std::vector<int>::size_type i = 0; i != array->size(); i++) {
HWND hWnd = array->at(i);
DestroyWindow( hWnd );
if (overlaysBrushes.count(hWnd) > 0) {
HBRUSH hBrush = overlaysBrushes[hWnd];
DeleteObject(hBrush);
}
}
array->clear();
delete arrOverlays[hWndParent];
arrOverlays.erase(hWndParent);
}
HB_FUNC ( OVERLAYWNDPROC)
{
HWND hWnd = (HWND) hb_parnl( 1 );
long message = hb_parnl( 2 );
long wParam = hb_parnl( 3 );
long lParam = hb_parnl( 4 );
switch (message) {
case WM_MOVE:
{
WIN32_UpdateOverlay(hWnd);
}
case WM_SIZE:
{
WIN32_UpdateOverlay(hWnd);
}
}
}
HB_FUNC( OVERLAYUPDATE )
{
HWND hWndParent = (HWND) hb_parnl( 1 );
WIN32_UpdateOverlay(hWndParent);
}
HB_FUNC( OVERLAYVANISH)
{
HWND hWndParent = (HWND) hb_parnl( 1 );
BOOL isShow = hb_parl( 2 );
WIN32_VanishOverlay(hWndParent, isShow);
}
void WIN32_UpdateOverlay(HWND hWndParent) {
if (!arrOverlays.count(hWndParent)) return;
HWND_ARRAY *array = arrOverlays[hWndParent];
for(std::vector<int>::size_type i = 0; i != array->size(); i++) {
AdjustParentCords( array->at(i), hWndParent );
}
}
void WIN32_VanishOverlay(HWND hWndParent, BOOL isShow) {
if (!arrOverlays.count(hWndParent)) return;
HWND_ARRAY *array = arrOverlays[hWndParent];
for(std::vector<int>::size_type i = 0; i != array->size(); i++) {
ShowWindow(array->at(i), isShow ? SW_SHOW : SW_HIDE );
}
}
HWND WIN32_CreateOverlay(HINSTANCE hInstance, HWND hwndParent, BYTE cRed, BYTE cGreen, BYTE cBlue, BYTE cAlpha)
{
WNDCLASS wc;
RECT lpRect;
int X, Y, Width, Height;
HWND hWnd;
char class_name[255];
sprintf(class_name, "OverlayWindow");
//sprintf(class_name, "OverlayWindow_%d", rand());
memset(&wc, 0, sizeof(WNDCLASS));
wc.lpszClassName = class_name;
wc.hInstance = hInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.lpfnWndProc = WndProc;
lpRect = GetWorkingArea(hwndParent);
X = lpRect.left;
Y = lpRect.top;
Width = lpRect.right - X;
Height = lpRect.bottom - Y;
RegisterClass(&wc);
hWnd = CreateWindowEx(WS_EX_TOOLWINDOW /* | WS_EX_TOPMOST*/, wc.lpszClassName, TEXT(""),
WS_VISIBLE, X, Y, Width, Height, NULL/*hwndParent*/, NULL, hInstance, NULL);
//AdjustParentCords(hWnd, hwndParent);
SetWindowLong(hWnd, GWL_STYLE, 0);
SetBackgroundColor(hWnd, cRed, cGreen, cBlue);
// Окно будет всегда ренедерится поверх другого
SetWindowLong(hWnd, GWL_HWNDPARENT, (long)hwndParent);
// А вот это засунет окно внутри родительского
//SetParent(hWnd, hwndParent);
MakeWindowTransparent(hWnd, cAlpha);
ShowWindow(hWnd, SW_SHOWNORMAL);
// Отключаем окно оверлея, чтобы на него нельзя было установить фокус
EnableWindow(hWnd, FALSE);
return hWnd;
}
static void AdjustParentCords(HWND hWnd, HWND hwndParent) {
int X, Y, Width, Height;
RECT lpRect;
lpRect = GetWorkingArea(hwndParent);
X = lpRect.left;
Y = lpRect.top;
Width = lpRect.right - X;
Height = lpRect.bottom - Y;
//HWND_NOTOPMOST
SetWindowPos(hWnd, hwndParent, X, Y, Width, Height, SWP_NOZORDER);
}
static RECT GetWorkingArea(HWND hwnd)
{
RECT rc;
GetClientRect(hwnd, &rc);
MapWindowPoints(hwnd, NULL, (POINT*)&rc, 2);
//MapWindowPoints(hwnd, nullptr, reinterpret_cast<POINT*>(&rc), 2);
return rc;
}
static void SetBackgroundColor(HWND hWnd, BYTE red, BYTE green, BYTE blue)
{
HBRUSH brush = CreateSolidBrush(RGB(red, green, blue));
overlaysBrushes[hWnd] = brush;
HDC hdc = GetDC(hWnd);
SetBkColor(hdc, RGB(255, 0, 0));
ReleaseDC(hWnd, hdc);
//SetClassLongPtr(hWnd, GCLP_HBRBACKGROUND, (LONG)brush);
}
static void MakeWindowTransparent(HWND hWnd, BYTE level)
{
SetWindowLong(hWnd, GWL_EXSTYLE,
GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(hWnd, 0, level, LWA_ALPHA);
}
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
RECT rect;
PAINTSTRUCT ps;
HDC hdc;
GetClientRect(hWnd, &rect);
hdc = BeginPaint(hWnd, &ps);
FillRect(hdc, &rect, overlaysBrushes[hWnd]);
EndPaint(hWnd, &ps);
}
break;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
default:
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment