diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/auth/Loginbox/loginCurtain.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/auth/Loginbox/loginCurtain.cpp')
-rw-r--r-- | Src/auth/Loginbox/loginCurtain.cpp | 544 |
1 files changed, 544 insertions, 0 deletions
diff --git a/Src/auth/Loginbox/loginCurtain.cpp b/Src/auth/Loginbox/loginCurtain.cpp new file mode 100644 index 00000000..e6ca29f1 --- /dev/null +++ b/Src/auth/Loginbox/loginCurtain.cpp @@ -0,0 +1,544 @@ +#include "./loginCurtain.h" +#include "./loginPopup.h" +#include "./common.h" +#include "./graphics.h" +#include "./imageLoader.h" +#include "../resource.h" +#include "../api.h" + + +#define NWC_LOGINCURTAIN L"NullsoftLoginCurtain" + +typedef struct __LOGINCURTAINCREATEPARAM +{ + HWND owner; +} LOGINCURTAINCREATEPARAM; + +#define NLPF_IMAGEINVALID 0x00000001 + +typedef struct __LOGINCURTAIN +{ + HWND owner; + HBITMAP bkImage; + UINT flags; + UINT childCount; +} LOGINCURTAIN; + +typedef struct __DRAWBORDERPARAM +{ + HWND hParent; + RECT rect; + HDC hdc; + HDC hdcSrc; + HBITMAP bitmapFrame; + HBITMAP bitmapOrig; + BLENDFUNCTION blendFunc; +} DRAWBORDERPARAM; + + +typedef struct __UPDATEPOSPARAM +{ + HWND hParent; + RECT clientRect; + RECT childRect; + HDWP hdwp; + UINT childCount; +} UPDATEPOSPARAM; + +typedef struct __EXCLUDERGNPARAM +{ + HWND hParent; + HRGN exclude; + HRGN tmp; + RECT rect; +} EXCLUDERGNPARAM; + +#define BACKGROUND_ALPHA 200 + +#define GetCurtain(__hwnd) ((LOGINCURTAIN*)(LONG_PTR)(LONGX86)GetWindowLongPtr((__hwnd), 0)) + +static LRESULT WINAPI LoginCurtain_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + + +static BOOL LoginCurtain_RegisterClass(HINSTANCE hInstance) +{ + + WNDCLASSW wc; + if (FALSE != GetClassInfo(hInstance, NWC_LOGINCURTAIN, &wc)) + return TRUE; + + ZeroMemory(&wc, sizeof(wc)); + + wc.lpszClassName = NWC_LOGINCURTAIN; + wc.lpfnWndProc = LoginCurtain_WindowProc; + wc.style = CS_PARENTDC; + wc.cbWndExtra = sizeof(LOGINCURTAIN*); + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + + return ( 0 != RegisterClassW(&wc)); +} + +HWND LoginCurtain_CreateWindow(HWND hParent, HWND hOwner) +{ + if (FALSE == LoginCurtain_RegisterClass(WASABI_API_ORIG_HINST)) + return NULL; + + RECT rect; + if (FALSE == GetClientRect(hOwner, &rect)) + SetRectEmpty(&rect); + else + MapWindowPoints(hOwner, hParent, (POINT*)&rect, 2); + + LOGINCURTAINCREATEPARAM createParam; + createParam.owner = hOwner; + + return CreateWindowEx(WS_EX_CONTROLPARENT, NWC_LOGINCURTAIN, NULL, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | DS_CONTROL, + rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, + hParent, NULL, WASABI_API_ORIG_HINST, &createParam); + +} + +static BOOL CALLBACK LoginCurtain_ExcludeChildRgnCallback(HWND hwnd, LPARAM lParam) +{ + EXCLUDERGNPARAM *param = (EXCLUDERGNPARAM*)lParam; + if (NULL == param) return FALSE; + + RECT *r = ¶m->rect; + + if (0 == (WS_VISIBLE & GetWindowStyle(hwnd)) || + param->hParent != (HWND)(LONG_PTR)GetWindowLongPtr(hwnd, GWLP_HWNDPARENT) || + FALSE == GetWindowRect(hwnd, r)) + return TRUE; + + MapWindowPoints(HWND_DESKTOP, param->hParent, (POINT*)r, 2); + + if (NULL == param->tmp) + { + param->tmp = CreateRectRgn(0, 0, 0, 0); + if (NULL == param->tmp) return FALSE; + } + + if (NULL == param->exclude) + { + param->exclude = CreateRectRgn(0, 0, 0, 0); + if (NULL == param->exclude) return FALSE; + } + + INT regionType = GetWindowRgn(hwnd, param->tmp); + switch(regionType) + { + case NULLREGION: + SetRectRgn(param->tmp, r->left, r->top, r->right, r->bottom); + CombineRgn(param->exclude, param->exclude, param->tmp, RGN_OR); + break; + case SIMPLEREGION: + case COMPLEXREGION: + OffsetRgn(param->tmp, r->left, r->top); + CombineRgn(param->exclude, param->exclude, param->tmp, RGN_OR); + break; + } + + return TRUE; +} + +static void LoginCurtain_ExcludeChildren(HWND hwnd, HDC hdc) +{ + EXCLUDERGNPARAM param; + param.hParent = hwnd; + param.exclude = NULL; + param.tmp = NULL; + EnumChildWindows(hwnd, LoginCurtain_ExcludeChildRgnCallback, (LPARAM)¶m); + if (NULL != param.exclude) + { + ExtSelectClipRgn(hdc, param.exclude, RGN_DIFF); + DeleteObject(param.exclude); + } + + if (NULL != param.tmp) + DeleteObject(param.tmp); +} + +static BOOL CALLBACK LoginCurtain_DrawWindowBorderCallback(HWND hwnd, LPARAM lParam) +{ + DRAWBORDERPARAM *param = (DRAWBORDERPARAM*)lParam; + if (NULL == param) return FALSE; + + RECT *r = ¶m->rect; + + if (0 == (WS_VISIBLE & GetWindowStyle(hwnd)) || + param->hParent != (HWND)(LONG_PTR)GetWindowLongPtr(hwnd, GWLP_HWNDPARENT) || + FALSE == GetWindowRect(hwnd, r)) + return TRUE; + + MapWindowPoints(HWND_DESKTOP, param->hParent, (POINT*)r, 2); + + if (NULL == param->bitmapFrame) + { + INT frameHeight, frameWidth; + param->bitmapFrame = ImageLoader_LoadBitmap(WASABI_API_ORIG_HINST, MAKEINTRESOURCE(IDR_POPUPBORDER_IMAGE), + TRUE, &frameWidth, &frameHeight); + if (NULL == param->bitmapFrame) + return FALSE; + + param->hdcSrc = CreateCompatibleDC(param->hdc); + if (NULL == param->hdcSrc) return FALSE; + + param->bitmapOrig = (HBITMAP)SelectObject(param->hdcSrc, param->bitmapFrame); + + param->blendFunc.AlphaFormat = AC_SRC_ALPHA; + param->blendFunc.BlendFlags = 0; + param->blendFunc.BlendOp = AC_SRC_OVER; + param->blendFunc.SourceConstantAlpha = 255; + } + + r->left -= 14; + r->top -= 13; + r->right += 17; + r->bottom += 19; + + GdiAlphaBlend(param->hdc, r->left, r->top, 26, 26, param->hdcSrc, 0, 0, 26, 26, param->blendFunc); + GdiAlphaBlend(param->hdc, r->right - 28, r->top, 28, 26, param->hdcSrc, 27, 0, 28, 26, param->blendFunc); + GdiAlphaBlend(param->hdc, r->left, r->bottom - 31, 26, 31, param->hdcSrc, 0, 27, 26, 31, param->blendFunc); + GdiAlphaBlend(param->hdc, r->right - 28, r->bottom - 31, 28, 31, param->hdcSrc, 27, 27, 28, 31, param->blendFunc); + + LONG l = (r->right - r->left - (26 + 28)); + GdiAlphaBlend(param->hdc, r->left + 26, r->top, l, 26, param->hdcSrc, 25, 0, 1, 26, param->blendFunc); + GdiAlphaBlend(param->hdc, r->left + 26, r->bottom - 31, l, 31, param->hdcSrc, 25, 27, 1, 31, param->blendFunc); + + l = (r->bottom - r->top - (26 + 31)); + GdiAlphaBlend(param->hdc, r->left, r->top + 26, 26, l, param->hdcSrc, 0, 28, 26, 1, param->blendFunc); + GdiAlphaBlend(param->hdc, r->right - 28, r->top + 26, 28, l, param->hdcSrc, 27, 28, 28, 1, param->blendFunc); + + return TRUE; +} + +static void LoginCurtain_DrawChildBorders(HWND hwnd, HDC hdc) +{ + DRAWBORDERPARAM param; + ZeroMemory(¶m, sizeof(param)); + param.hdc = hdc; + param.hParent = hwnd; + + EnumChildWindows(hwnd, LoginCurtain_DrawWindowBorderCallback, (LPARAM)¶m); + + if (NULL != param.hdcSrc) + { + SelectObject(param.hdcSrc, param.bitmapOrig); + DeleteDC(param.hdcSrc); + } + + if (NULL != param.bitmapFrame) + DeleteObject(param.bitmapFrame); +} + +static HBITMAP LoginCurtain_CreateBkImage(HWND hwnd, HDC hdc, HBITMAP hBitmap, HWND hOwner) +{ + RECT rect; + if (FALSE == GetClientRect(hwnd, &rect)) + return NULL; + + LONG width = rect.right - rect.left; + LONG height = rect.bottom - rect.top; + + BITMAP bi; + + if (NULL == hBitmap || + sizeof(BITMAP) != GetObject(hBitmap, sizeof(BITMAP), &bi) || + bi.bmWidth < width || bi.bmHeight < height) + { + if (NULL != hBitmap) + DeleteObject(hBitmap); + + BITMAPINFOHEADER header; + ZeroMemory(&header, sizeof(BITMAPINFOHEADER)); + + header.biSize = sizeof(BITMAPINFOHEADER); + header.biCompression = BI_RGB; + header.biBitCount = 32; + header.biPlanes = 1; + header.biWidth = (width + 32); + header.biHeight = -(height + 32); + + bi.bmBitsPixel = header.biBitCount; + bi.bmWidth = header.biWidth; + bi.bmHeight = header.biHeight; + bi.bmPlanes = header.biPlanes; + + hBitmap = CreateDIBSection(NULL, (LPBITMAPINFO)&header, DIB_RGB_COLORS, (void**)&bi.bmBits, NULL, 0); + if (NULL == hBitmap) return NULL; + } + else + { + bi.bmHeight = -bi.bmHeight; + } + + HBRUSH bkBrush = (HBRUSH)SendMessage(hOwner, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hwnd); + + HBITMAP hbo = (HBITMAP)SelectObject(hdc, hBitmap); + + if (NULL == hOwner) + { + if (NULL != bkBrush) + FillRect(hdc, &rect, bkBrush); + else + ExtTextOut(hdc, 0, 0, OPAQUE, &rect, NULL, 0, NULL); + } + else + { + if (FALSE == LoginBox_PrintWindow(hOwner, hdc, 0)) + SendMessage(hOwner, WM_PRINT, (WPARAM)hdc, (LPARAM) (PRF_NONCLIENT | PRF_CLIENT | PRF_CHILDREN | PRF_ERASEBKGND)); + + COLORREF rgbBlend = GetDCBrushColor(hdc); + if (CLR_INVALID == rgbBlend) + rgbBlend = GetBkColor(hdc); + rgbBlend |= (BACKGROUND_ALPHA << 24); + Image_ColorOverEx((BYTE*)bi.bmBits, bi.bmWidth, bi.bmHeight, 0, 0, width, height, bi.bmBitsPixel, FALSE, rgbBlend); + } + + LoginCurtain_DrawChildBorders(hwnd, hdc); + + SelectObject(hdc, hbo); + return hBitmap; +} + +static void LoginCurtain_EraseBkGround(HWND hwnd, HDC hdc, const RECT *prcPaint) +{ + LOGINCURTAIN *curtain = GetCurtain(hwnd); + if (NULL == curtain) return; + + HDC hdcSrc = CreateCompatibleDC(hdc); + if (NULL == hdcSrc) return; + + + if (NULL == curtain->bkImage || 0 != (NLPF_IMAGEINVALID & curtain->flags)) + { + HRGN clipRegion = CreateRectRgn(0,0,0,0); + if (NULL != clipRegion) + { + INT regionType = GetClipRgn(hdc, clipRegion); + if (1 == regionType) + SelectClipRgn(hdcSrc, clipRegion); + DeleteObject(clipRegion); + } + curtain->bkImage = LoginCurtain_CreateBkImage(hwnd, hdcSrc, curtain->bkImage, curtain->owner); + curtain->flags &= ~NLPF_IMAGEINVALID; + } + + if (NULL != curtain->bkImage) + { + HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcSrc, curtain->bkImage); + BitBlt(hdc, prcPaint->left, prcPaint->top, + prcPaint->right - prcPaint->left, prcPaint->bottom - prcPaint->top, + hdcSrc, prcPaint->left, prcPaint->top, SRCCOPY); + + SelectObject(hdcSrc, hbmpOld); + } + + DeleteDC(hdcSrc); + +} + +static void LoginCurtain_Paint(HWND hwnd, HDC hdc, const RECT *prcPaint, BOOL fErase) +{ + if (FALSE != fErase) + { + LoginCurtain_ExcludeChildren(hwnd, hdc); + LoginCurtain_EraseBkGround(hwnd, hdc, prcPaint); + } +} + +static BOOL CALLBACK LoginCurtain_UpdateChildPosCallback(HWND hwnd, LPARAM lParam) +{ + UPDATEPOSPARAM *param = (UPDATEPOSPARAM*)lParam; + if (NULL == param) return FALSE; + + if (param->hParent != (HWND)(LONG_PTR)GetWindowLongPtr(hwnd, GWLP_HWNDPARENT)) + return TRUE; + + if (NULL == param->hdwp) + { + param->hdwp = BeginDeferWindowPos(param->childCount); + param->childCount = 0; + + if (NULL == param->hdwp) return FALSE; + } + + LONG prevWidth(0), prevHeight(0); + if (FALSE != GetWindowRect(hwnd, ¶m->childRect)) + { + prevWidth = param->childRect.right - param->childRect.left; + prevHeight = param->childRect.bottom - param->childRect.top; + } + + + if (FALSE != LoginPopup_UpdateWindowPos(hwnd, ¶m->clientRect, ¶m->childRect)) + { + param->hdwp = DeferWindowPos(param->hdwp, hwnd, NULL, param->childRect.left, param->childRect.top, + param->childRect.right - param->childRect.left, param->childRect.bottom - param->childRect.top, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW); + + if (NULL == param->hdwp) return FALSE; + + LONG width = param->childRect.right - param->childRect.left; + LONG height = param->childRect.bottom - param->childRect.top; + if (width != prevWidth || height != prevHeight) + { + HRGN clipRgn = CreateRoundRectRgn(0, 0, width, height, 9, 9); + SetWindowRgn(hwnd, clipRgn, FALSE); + } + } + param->childCount++; + return TRUE; +} + +static void LoginCurtain_UpdateLayout(HWND hwnd, BOOL fRedraw) +{ + LOGINCURTAIN *curtain = GetCurtain(hwnd); + if (NULL == curtain) return; + + curtain->flags |= NLPF_IMAGEINVALID; + + RECT clientRect; + GetClientRect(hwnd, &clientRect); + + UPDATEPOSPARAM param; + param.hParent = hwnd; + param.hdwp = 0; + param.childCount = curtain->childCount; + + CopyRect(¶m.clientRect, &clientRect); + param.clientRect.left += 15; + param.clientRect.top += 14; + param.clientRect.right -= 18; + param.clientRect.bottom -= 20; + + EnumChildWindows(hwnd, LoginCurtain_UpdateChildPosCallback, (LPARAM)¶m); + curtain->childCount = param.childCount; + if (NULL != param.hdwp) + EndDeferWindowPos(param.hdwp); + + if (FALSE != fRedraw) + { + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN); + } +} + +static LRESULT LoginCurtain_OnCreate(HWND hwnd, CREATESTRUCT* pcs) +{ + LOGINCURTAIN *curtain = (LOGINCURTAIN*)calloc(1, sizeof(LOGINCURTAIN)); + if (NULL != curtain) + { + SetLastError(ERROR_SUCCESS); + if (!SetWindowLongPtr(hwnd, 0, (LONGX86)(LONG_PTR)curtain) && ERROR_SUCCESS != GetLastError()) + { + free(curtain); + curtain = NULL; + } + } + + if (NULL == curtain) + return -1; + + LOGINCURTAINCREATEPARAM *createParam = (LOGINCURTAINCREATEPARAM*)pcs->lpCreateParams; + if (NULL != createParam) + { + curtain->owner = createParam->owner; + } + + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOREDRAW); + + return 0; +} + +static void LoginCurtain_OnDestroy(HWND hwnd) +{ + LOGINCURTAIN *curtain = GetCurtain(hwnd); + SetWindowLongPtr(hwnd, 0, 0L); + if (NULL == curtain) return; + + if (NULL != curtain->bkImage) + DeleteObject(curtain->bkImage); + + free(curtain); +} + +static void LoginCurtain_OnWindowPosChanged(HWND hwnd, WINDOWPOS *pwp) +{ + if (SWP_NOSIZE == ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags)) + return; + + LoginCurtain_UpdateLayout(hwnd, 0 == (SWP_NOREDRAW & pwp->flags)); +} + + +static void LoginCurtain_OnPaint(HWND hwnd) +{ + PAINTSTRUCT ps; + if (BeginPaint(hwnd, &ps)) + { + if (ps.rcPaint.left != ps.rcPaint.right) + LoginCurtain_Paint(hwnd, ps.hdc, &ps.rcPaint, ps.fErase); + EndPaint(hwnd, &ps); + } +} + +static void LoginCurtain_OnPrintClient(HWND hwnd, HDC hdc, UINT options) +{ + RECT clientRect; + if (GetClientRect(hwnd, &clientRect)) + LoginCurtain_Paint(hwnd, hdc, &clientRect, 0 != (PRF_ERASEBKGND & options)); +} + +static void LoginCurtain_OnParentNotify(HWND hwnd, INT eventId, INT childId, LPARAM eventParam) +{ + switch(eventId) + { + case WM_CREATE: + { + HWND hChild = (HWND)eventParam; + RECT rect; + GetWindowRect(hChild, &rect); + HRGN clipRgn = CreateRoundRectRgn(0, 0, rect.right - rect.left, rect.bottom - rect.top, 9, 9); + SetWindowRgn(hChild, clipRgn, FALSE); + } + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED ); + break; + + case WM_DESTROY: + { + HWND hChild = (HWND)eventParam; + SetWindowLongPtr(hChild, GWLP_ID, 0); + } + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED); + break; + } +} + +static LRESULT LoginCurtain_OnNotify(HWND hwnd, INT controlId, NMHDR *pnmh) +{ + HWND hAncestor = GetAncestor(hwnd, GA_PARENT); + if (NULL != hAncestor) + return SendMessage(hAncestor, WM_NOTIFY, (WPARAM)controlId, (LPARAM)pnmh); + return 0; +} + +static LRESULT WINAPI LoginCurtain_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_CREATE: return LoginCurtain_OnCreate(hwnd, (CREATESTRUCT*)lParam); + case WM_DESTROY: LoginCurtain_OnDestroy(hwnd); return 0; + case WM_ERASEBKGND: return 0; + case WM_PAINT: LoginCurtain_OnPaint(hwnd); return 0; + case WM_PRINTCLIENT: LoginCurtain_OnPrintClient(hwnd, (HDC)wParam, (UINT)lParam); return 0; + case WM_WINDOWPOSCHANGED: LoginCurtain_OnWindowPosChanged(hwnd, (WINDOWPOS*)lParam); return 0; + case WM_SIZE: return 0; + case WM_PARENTNOTIFY: LoginCurtain_OnParentNotify(hwnd, LOWORD(wParam), HIWORD(wParam), lParam); return 0; + case WM_NOTIFY: return LoginCurtain_OnNotify(hwnd, (INT)wParam, (NMHDR*)lParam); + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + |