windows – Win32 C++ Trouble Replacing DWM Extended Frame

I am working on a nonstandard caption and border for my application. But, either I cannot seem to stop Windows from doing what it’s used to doing, or Windows doesn’t understand what I want it to do (definitely the latter). So any help would be greatly appreciated.

My end goal is to completely (completely, literally) redraw the standard caption and border. I was following a tutorial on MSDN about DWM (https://docs.microsoft.com/en-us/windows/win32/dwm/customframe), but they never mention how to (properly) draw the border. From my research, people say to use WM_PAINT to draw the caption and border, yet there’s my problem. The only that happens is Windows will draw my caption and frame OVER its own caption and border. I can draw anything perfectly fine in the “nonclient” area, but windows keep’s the original frame underneath, and the color of my own caption and frame is altered by what’s underneath (dark grey makes my green system color turn a lighter green). I cannot get Window’s to stop drawing it’s own border underneath my own unless I override the WM_NCPAINT message. Is this behavior suppose to happen?

So far, I have tried setting DWMNCRENDERINGPOLICY to both DWMNCRP_ENABLED and DWMNCRP_USEWINDOWSTYLE, but that breaks the window.

I am using a Layered Window (I heard it’s good on performance), is that what’s causing the problem? The Layered Window doesn’t have the jittery buffer junk that non-layered windows have, so I’m not sure what’s going on.

I’ve also tried returning ((LONG_PTR)(WVR_VALIDRECTS)) and ((LONG_PTR)(WVR_HREDRAW | WVR_VREDRAW)) in the WM_NCCALCSIZE message, but that only left me with a glitched frame load of solid white junk around the frame.

Without DWMWA_ALLOW_NCPAINT

(1

And with DWMWA_ALLOW_NCPAINT

enter image description here

How would I prevent this awkward behavior? Everything I’ve tried so far as only made the caption and borders disappear or become… “unintelligible” to say the least. I’m worried about overriding WM_NCPAINT because I’ve heard that it’s not the “right way” to do a custom frame, and I’ve tried overriding that message before. But it really just obliterates the entire nonclient window, and I cannot get stuff to draw properly (transparent, looks like a phantom of Windows 7 Aero).

Thanks again for any help! And here is the code I have so far (the margins are correct: the window is supposed to resemble windows 7 and 8.1/8).

#include <dwmapi.h>
#include <Uxtheme.h>
#include <vssym32.h>
#include <windowsx.h>

#pragma comment(lib, "uxtheme.lib")
#pragma comment(lib, "dwmapi.lib")

#include <defs.h>

#define FRAMEWIDTH      8
#define CAPTIONHEIGHT   27

#define RECTRIGHT(v)  v.right
#define RECTBOTTOM(v) v.bottom
#define RECTLEFT(v)   v.left
#define RECTTOP(v)    v.top
#define RECTSIZE1(v)  (RECTRIGHT(v) - RECTLEFT(v))
#define RECTSIZE2(v)  (RECTBOTTOM(v) - RECTTOP(v))

#ifdef __cplusplus
extern "C"
{
#endif

HINSTANCE hDesktopApp;
TCHAR lpszTitle() = TEXT("wordproc");
TCHAR lpszWindowClass() = TEXT("DesktopApp");

VOID NewDesktopApp(HINSTANCE hInstance);
    
#define SDK_HGDI_SOLID_BRUSH_SIZE   8
#define SDK_HGDI_PEN_SIZE           8

HBRUSH  hFrameBrushPtr  (SDK_HGDI_SOLID_BRUSH_SIZE);
HPEN    hFramePenPtr    (SDK_HGDI_PEN_SIZE);

#define HWND_HT_FRAME_BA0   HTTOPLEFT
#define HWND_HT_FRAME_BA1   HTLEFT
#define HWND_HT_FRAME_BA2   HTBOTTOMLEFT        
#define HWND_HT_FRAME_BA3   HTBOTTOM        
#define HWND_HT_FRAME_BA4   HTBOTTOMRIGHT   
#define HWND_HT_FRAME_BA5   HTRIGHT     
#define HWND_HT_FRAME_BA6   HTTOPRIGHT  
#define HWND_HT_FRAME_BA7   HTTOP
#define HWND_HT_NULL        HTNOWHERE
#define HWND_HT_FRAME_BA8   HWND_HT_NULL
#define HWND_HT_CAPTION     HTCAPTION
#define HWND_HT_CLIENT      HTCLIENT
#define HWND_HT_MAXBUTTON   HTMINBUTTON
#define HWND_HT_MAXBUTTON   HTMAXBUTTON
#define HWND_HT_CLOSE       HTCLOSE
static
LRESULT WINAPI PaintNonClientArea(HWND hWnd, HRGN hNCregion)
{
    LONG_PTR    lRet    = (LONG_PTR)0;
    RECT        rNCRect;
    PAINTSTRUCT ps;
    HDC         hDC;
    HDC         hMemDC;             // <- might go unused, but here in case needed
    HANDLE      oldBrush;
    HANDLE      oldPen;
    
    hDC = BeginPaint(hWnd, &ps);
    FillRect(hDC, &ps.rcPaint, reinterpret_cast<HBRUSH>(hFrameBrushPtr(0)));

    BOOL bRet;
    bRet = EndPaint(hWnd, &ps);
    if (bRet == FALSE)
    {
        // error.
    }

    return (LONG_PTR)1;
}

static
LRESULT SetHWNDInfoForDWM(HWND hWnd)
{
    const MARGINS margins =
    {
        8,
        8,
        28,
        8
    };

    HRESULT hr = DwmExtendFrameIntoClientArea(hWnd, &margins);
    if (!SUCCEEDED(hr))
    {
        return (LONG_PTR)0;
    }

    DWMNCRENDERINGPOLICY ncrp = DWMNCRP_ENABLED;
    hr = DwmSetWindowAttribute(hWnd, DWMWA_NCRENDERING_POLICY, (void*)&ncrp, sizeof(DWMNCRENDERINGPOLICY));
    if (!SUCCEEDED(hr))
    {
        return (LONG_PTR)0;
    }

    BOOL bDrawNC = TRUE;
    hr = DwmSetWindowAttribute(hWnd, DWMWA_ALLOW_NCPAINT, (void*)&bDrawNC, sizeof(BOOL));
    if (!SUCCEEDED(hr))
    {
        return (LONG_PTR)0;
    }

    return (LONG_PTR)1;
}

static
LRESULT HitTest(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    bool fOnResizeBorder = false;
    BOOL bRet;
    LONG_PTR lRet = (LONG_PTR)0;
           
    RECT rcWindow = 
    {
        0,
        0,
        0,
        0
    };
    bRet = GetWindowRect(hWnd, &rcWindow);
    if (bRet == FALSE)
    {
    }

    DWORD dwExStyle = (DWORD)(WS_EX_LAYERED);
    DWORD dwStyle = ((DWORD)(WS_VISIBLE | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_DLGFRAME | WS_THICKFRAME | WS_CLIPCHILDREN | WS_CLIPSIBLINGS));

    RECT rcNCregion = 
    {
        0,
        0,
        0,
        0
    };
    bRet = AdjustWindowRectEx(&rcNCregion, dwStyle & ~WS_CAPTION, FALSE, dwExStyle);
    if (bRet == FALSE)
    {
    }

    INT dwRow = 1;
    INT dwCol = 1;

    POINT pt;
    pt.x = LOWORD(lParam);
    pt.y = HIWORD(lParam);

    if (pt.y >= rcWindow.top && pt.y < rcWindow.top + CAPTIONHEIGHT)
    {
        if (pt.y < (rcWindow.top - rcNCregion.top))
        {
            dwRow = 0;
        }
        else
        {
            return HTCAPTION;
        }
    }

    if (pt.y < rcWindow.bottom && pt.y >= rcWindow.bottom - FRAMEWIDTH)
    {
        dwRow = 2;
    }

    if (pt.x >= rcWindow.left && pt.x < rcWindow.left + FRAMEWIDTH)
    {
        dwCol = 0;
    }
    
    if (pt.x < rcWindow.right && pt.x >= rcWindow.right - FRAMEWIDTH)
    {
        dwCol = 2;
    }
    
    static LONG_PTR larrHitTest(3)(3) =
    {
        { HWND_HT_FRAME_BA0, HWND_HT_FRAME_BA7, HWND_HT_FRAME_BA6 },
        { HWND_HT_FRAME_BA1, HWND_HT_FRAME_BA8, HWND_HT_FRAME_BA5 },
        { HWND_HT_FRAME_BA2, HWND_HT_FRAME_BA3, HWND_HT_FRAME_BA4 }
    };

    return larrHitTest(dwRow)(dwCol);
}

static
LRESULT WINAPI RecalcNonClientArea(LPARAM lParam)
{
    LONG_PTR            lRet        = (LONG_PTR)0;
    NCCALCSIZE_PARAMS*  lpParams    = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);

    RECTLEFT  (lpParams->rgrc(0)) = RECTLEFT  (lpParams->rgrc(0)) + 0;
    RECTTOP   (lpParams->rgrc(0)) = RECTTOP   (lpParams->rgrc(0)) + 0;
    RECTBOTTOM(lpParams->rgrc(0)) = RECTBOTTOM(lpParams->rgrc(0)) - 0;
    RECTRIGHT (lpParams->rgrc(0)) = RECTRIGHT (lpParams->rgrc(0)) - 0;

    lRet = ((LONG_PTR)(WVR_VALIDRECTS));

    return lRet;
}

BOOL WINAPI InitializeResources(VOID)
{
    BOOL bRet = FALSE;

    // initialize solid-color paint brushes
    hFrameBrushPtr(0) = reinterpret_cast<HBRUSH>(CreateSolidBrush(RGB( 52,  52, 52)));  // color: Non-client Window Frame Border
    hFrameBrushPtr(1) = reinterpret_cast<HBRUSH>(CreateSolidBrush(RGB(203,  94, 72)));  // color: HTCLOSE color 
    hFrameBrushPtr(2) = reinterpret_cast<HBRUSH>(CreateSolidBrush(RGB( 68,  68, 68)));  // color: HTMINBUTTON and HTMAXBUTTON

    // initialize solid-color pens
    hFramePenPtr(0) = reinterpret_cast<HPEN>(CreatePen(PS_SOLID, 1, RGB( 47,  47,  47)));
    hFramePenPtr(1) = reinterpret_cast<HPEN>(CreatePen(PS_SOLID, 1, RGB(286, 186, 186)));
    hFramePenPtr(2) = reinterpret_cast<HPEN>(CreatePen(PS_SOLID, 1, RGB(145, 145, 145)));
    hFramePenPtr(3) = reinterpret_cast<HPEN>(CreatePen(PS_SOLID, 1, RGB( 42,  42,  42)));

    return bRet;
}

LRESULT CALLBACK DwmWndProc(bool* pfCallDWP, HWND message, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK AppWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    LONG_PTR lRet = (LONG_PTR)0;
    bool fCallDWP = true;
    BOOL fDwmEnabled = FALSE;

    HRESULT hr = DwmIsCompositionEnabled(&fDwmEnabled);
    if (!SUCCEEDED(hr))
    {
        MessageBox
            (
            nullptr, 
            __TEXT
                (

                "Call to function "HRESULT DwmIsCompositionEnabled" returned an unexpected error."
                "nn"
                "Resolve: The Desktop Window Manager (DWM) is required for this application. Please ensure that composition is enabled on your operating"
                "system, and try again."
                ),
            __TEXT
                (
                "Desktop Window Manager"
                ),
            MB_OK
            );
        abort();
    }
    else
    {
        lRet = DwmWndProc(&fCallDWP, hWnd, message, wParam, lParam);
    }

    if (fCallDWP)
    {
        lRet = AppWndProc(hWnd, message, wParam, lParam);
    }

    return lRet;
}

LRESULT CALLBACK DwmWndProc(bool* pfCallDWP, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    bool fCallDWP = true;
    LONG_PTR lRet = (LONG_PTR)0;
        
    /*++



    --*/
    if (message == WM_DESTROY)
    {
        PostQuitMessage(EXIT_SUCCESS);
        fCallDWP = true;
    }

    /*++



    --*/
    if (message == WM_CLOSE)
    {
        unsigned int i;
        for (i = 0; i < (unsigned int)SDK_HGDI_SOLID_BRUSH_SIZE; i++)
        {
            DeleteBrush(hFrameBrushPtr((unsigned int)i));
            DeletePen(hFramePenPtr((unsigned int)i));
        }

        DestroyWindow(hWnd);
        fCallDWP = true;
    }

    /*++

    
    
    --*/
    if ((message == WM_NCHITTEST) && (lRet == 0))
    {
        lRet = (LONG_PTR)HitTest(hWnd, wParam, lParam);
        if (lRet == HTNOWHERE)
        {
            fCallDWP = true;
        }
        else
        {
            fCallDWP = false;
        }
    }

    /*++



    --*/
    if ((message == WM_NCCALCSIZE) && (wParam == TRUE))
    {
        lRet = (LONG_PTR)RecalcNonClientArea(lParam);
        fCallDWP = false;
    }

    /*++



    --*/
    if (message == WM_CREATE)
    {
        lRet = SetHWNDInfoForDWM(hWnd);
    
        BOOL bRet;
        bRet = InitializeResources();
        if (bRet == FALSE)
        {
        }

        fCallDWP = true;
    }

    /*++



    --*/
    if (message == WM_ACTIVATE)
    {
        SetWindowPos(hWnd, nullptr, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER);
        fCallDWP = true;
    }

    /*++



    --*/
    if (message == WM_PAINT)
    {
        lRet = (LONG_PTR)PaintNonClientArea(hWnd, (HRGN)wParam);
        fCallDWP = true;
    }

    *pfCallDWP = fCallDWP;

    return lRet;
}

LRESULT CALLBACK AppWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    LONG_PTR lRet = (LONG_PTR)0;

    switch (message)
    {
    case WM_CREATE:
        {
            break;
        }
    case WM_COMMAND:
        {
            break;
        }
    case WM_PAINT:
        {
            break;
        }
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }

    return lRet;
}

extern
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
{
    try
    {
        NewDesktopApp(hInstance);
    }
    catch (std::exception& const e)
    {
        abort();
    }

    static MSG msg;

    BOOL bRet;
    while ((bRet = GetMessage(&msg, nullptr, 0, 0)) == TRUE)
    {
        if (bRet == FALSE)
        {
            // error.
        }
        else
        {
            TranslateMessage
            (
                &msg
            );
            DispatchMessage
            (
                &msg
            );
        }
    }

    return (INT)msg.wParam;
}

static
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;
    ZeroMemory(&wcex, sizeof(WNDCLASSEX));

    wcex.cbSize         = sizeof(WNDCLASSEX);
    wcex.hbrBackground  = NULL;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.style          = 0;
    wcex.hInstance      = hInstance;
    wcex.lpfnWndProc    = WndProc;
    wcex.hIcon          = LoadIcon  (wcex.hInstance, IDI_APPLICATION);
    wcex.hCursor        = LoadCursor(wcex.hInstance, IDC_ARROW);
    wcex.hIconSm        = LoadIcon  (wcex.hInstance, IDI_APPLICATION);
    wcex.lpszClassName  = lpszWindowClass;
    wcex.lpszMenuName   = NULL;

    return RegisterClassEx(&wcex);
}

static
VOID NewDesktopApp(HINSTANCE hInstance)
{
    hDesktopApp = hInstance;
    if (MyRegisterClass(hDesktopApp) == (ATOM)0)
    {
        MessageBox(nullptr, __TEXT("Failed to register window class "DesktopApp"!"), __TEXT("wordproc"), MB_OK);
        throw std::exception
        (
        );
    }

    DWORD dwExStyle = (DWORD)(WS_EX_LAYERED);
    DWORD dwStyle = ((DWORD)(WS_VISIBLE | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_DLGFRAME | WS_THICKFRAME | WS_CLIPCHILDREN | WS_CLIPSIBLINGS));
    RECT r =
    {
        0,
        0,
        1480,
        680
    };
    AdjustWindowRectEx(&r, dwStyle, FALSE, dwExStyle);
    HWND hWnd = CreateWindowEx
    (
        dwExStyle,
        lpszWindowClass,
        lpszTitle,
        dwStyle,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        //((INT)RECTSIZE1(r)),
        //((INT)RECTSIZE2(r)),
        nullptr,
        nullptr,
        hDesktopApp,
        nullptr
    );
    if (!hWnd)
    {
        MessageBox(nullptr, __TEXT("Failed to create window of class type "DesktopApp"!"), __TEXT("wordproc"), MB_OK);
        throw std::exception
        (
        );
    }

    SetLayeredWindowAttributes(hWnd, NULL, 255, LWA_ALPHA);
    //UpdateLayeredWindow()

    ShowWindow(hWnd, SW_NORMAL);
    UpdateWindow(hWnd);
}

#ifdef __cplusplus
}
#endif

libgdx – Aligning animation frame assets with different sizes

I have code that changes texture in each frame depending on the player’s state – walking, idle.

My problem is that the idle texture (from separate png) has a slightly different size, and due to that it appears not in line with rest of the animations, seemingly being in a slightly different position when returning to idle.

How can I position the frames based on the center of texture instead of the bottom left?

batch.draw(determineTexture(), position.x, position.y,
            currentFrame.getRegionWidth()/2f, currentFrame.getRegionHeight()/2f,
            currentFrame.getRegionWidth(), currentFrame.getRegionHeight(),1f,1f, rotation,false);

TextureRegion determineTexture(){
        if(playerState == State.idle)
            currentFrame = idleAnimation.getKeyFrame(stateTime, true);
        else if (playerState == State.walkingUP || playerState == State.walkingDOWN || playerState == State.walkingRIGHT || playerState == State.walkingLEFT )
            currentFrame = walkAnimation.getKeyFrame(stateTime, true);
        return currentFrame;
}

One png has a height of 57 – idle, while 6 columns and one row of walking frames have a height of 87 pixels.

long exposure – Issues with dark frame subtraction: Dark frames adding “noise” and changing image color/tint

While editing some landscape shots with stars, I tried to use darkframes to reduce the noise.
More precisely, my approach was to take a series of shots, then firstly to subtract dark frames from each shot, secondly to use the mean of the series for the foreground to further reduce noise, and thirdly to use an astro stacking tool (Sequator) to stack the sky.

Instead of reducing noise, the darkframe subtraction:

  1. increased the noise- or rather, added some dark/monochrome noise.
  2. changed the white-balance/tinted the image.
    (see below)
    I do not understand why this is happening/What I am doing wrong.

Procedure/Employed Troubleshooting:

  • All photos were shot in succession, with the same settings (15sec, @ISO6400, in-camera dark frame disabled).

  • All photos were shot with the same white balance.

  • While shooting the darkframes, both the lens cap and the viewfinder cover were applied.

  • Photos were imported from my Pentax K1ii, converted to DNG in LR, and exported to PS without any editing/import presets applied.

  • I used PS, placed the darkframe layer(s) above my picture, and used the subtract blending mode.

  • I followed basic instructions found here/in various videos on dark frame subtraction in photoshop. Note that basically, all of those cover dark frame subtraction with one frame (or use tools other than photoshop). I have tried both using one, and 3 frames. The results are similar, albeit more pronounced with 3.

  • I used the free tool “sequator” to subtract darkframes instead (and to align stars). Adding the dark frames here made absolutely no difference.

  • (This is an edit/composite done with the frames I tried to subtract darkframes of)

  • A crop of the first picture, with (3) dark frames subtracted:
    with (3) dark frames

  • A crop of the second picture, without dark frames subtracted:
    without dark frames

differential geometry – frame bundle of an n-sphere is $O(n+1)$?

I’m trying to understand frame bundles (mostly from a physics point of view). It is standard for some n-dimensional Riemannian manifold that the frame bundle has an $O(n)$ structure. However; It seems there is some exception for an n-sphere where I come across references to it’s oriented-orthonormal frame bundle being diffeomorphic to $SO(n+1)$. In such cases they say that the matrix with columns $left(phi,hat{e}_{i}…hat{e}_{n}right)in SO(n+1)$. Where $phi$ are the coordinates of the n-sphere as embedded within $mathbb{R}^{n+1}$ and the hat’s are the unit frame vectors.

Can someone please elaborate upon this for me, I don’t quite get it, does this only apply to a sphere of constant curvature? I was trying to construct an explicit example for the 3-sphere but couldn’t quite get it. Does this apply to the general topological n-sphere or just a constant curvature one?

unity – Why does my in-game frame calculation not correlate with animation length?

I need to play an animation in such a way that each frame is for sure being played and not skipped.
To do that, I use a very slow animator speed like this:

_animator.speed = 0.01f;

The Unity editor says this about the animation:

enter image description here

To make sure that each frame is really shown / played, I have implemented my own counter.
My counter however returns 43 frames and not 51 frames as the Inspector.
No matter how often I repeat this process, it always return 43 frames.

What am I missing?

Thank you!

private void LateUpdate()
{

    float f = _animator.GetCurrentAnimatorClipInfo(0)(0).clip.length * (_animator.GetCurrentAnimatorStateInfo(0).normalizedTime % 1) * _animator.GetCurrentAnimatorClipInfo(0)(0).clip.frameRate;
    int iCurrentFrameIDInAnimationFile = (int)f;

    bool bIsNewFrame = (iCurrentFrameIDInAnimationFile != _iLastFrameIDInAnimationFile);

    if (!bIsNewFrame)
    {
        return;
    }
    else if (bIsNewFrame)
    {
        _iFrameCount += 1;
    }

    _iLastFrameIDInAnimationFile = iCurrentFrameIDInAnimationFile;

    if (_animator.GetCurrentAnimatorStateInfo(0).normalizedTime > 1 && !_animator.IsInTransition(0))
    {
        //animation has finished playing
        Debug.Log("Frames: " + _iFrameCount); //this returns 43 frames. Why???
    }

unity – Nearest Vector3 to Vector3 from last frame

Suppose you have a Vector3 provider of pointcloud positions that update every frame – call it Nullable<NativeSlice<Vector3>> pointClouds

Say you want to use particles whose emitters create continuous animation effects, how do you find the nearest Vector3 in the current frame for a previous frame’s point cloud particle to “migrate” there (instead of being destroyed and re-created each frame)?

Youtube video frame size has accidentally got larger. How to reduce it?

I recently hit something in my keyboard while i was distracted and my youtube video frame size suddenly increased. It is not the zoom or ctrl+/- thing. That is still at 100%. It is something else that has changed, and it shows a larger video size only when i open youtube in incognito window. In the normal window, Youtube video frame is still the normal size. And it is not the theater mode either. I have it on default view. Below is how it normally looks vs how it is looking now

enter image description here

how it normally looks
.

.

..

enter image description here
How it is looking now

Can anyone suggest how to reduce it back to its normal size?