Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to customize the window's title bar and frame #221

Closed
xland opened this issue Oct 9, 2023 · 2 comments
Closed

How to customize the window's title bar and frame #221

xland opened this issue Oct 9, 2023 · 2 comments

Comments

@xland
Copy link

xland commented Oct 9, 2023

OS : WIN10
TGUI : Latest version

To customize a window's title bar the following code is required:

    // #include <dwmapi.h>
   //create window
    HWND hwnd = CreateWindowEx(NULL, wcx.lpszClassName, title.c_str(),
        WS_OVERLAPPEDWINDOW, x, y, w, h, NULL, NULL, hinstance, static_cast<LPVOID>(this));
   //set window shadow
    SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, 
        SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
    const MARGINS shadowState{ 1,1,1,1 };
    DwmExtendFrameIntoClientArea(hwnd, &shadowState);
// disable title bar
case WM_NCCALCSIZE:
{
    if (wParam == TRUE)
    {
        return false;
    }
    break;
}

I can set sfml window's style to disable the title bar

sf::RenderWindow window(sf::VideoMode(sf::Vector2u(800, 600)), "MyWin", sf::Style::None);

But I don't know how to draw the window shadow.
Could you give me some advice?
Thanks very much.

image

@xland xland changed the title How to customize the title bar(How to implement a polygon window) How to customize the title bar Oct 9, 2023
@xland xland changed the title How to customize the title bar How to customize the window's title bar and frame Oct 9, 2023
@texus
Copy link
Owner

texus commented Oct 9, 2023

This is unrelated to TGUI and specific about the Windows API. I have no experience with functions like DwmExtendFrameIntoClientArea, so I can't help with this.

@texus texus closed this as completed Oct 9, 2023
@xland
Copy link
Author

xland commented Oct 10, 2023

Thanks for reply.

I found out a way.
But only for windows.

#include <TGUI/TGUI.hpp>
#include <TGUI/Backend/SFML-Graphics.hpp>
#include <Windows.h>
#include <windowsx.h>
#include <dwmapi.h>

WNDPROC SFMLWndProc;
const POINT border{
    GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER),
    GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)
};

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
    switch (msg) {
        case WM_NCCALCSIZE:
        {
            if (wparam == TRUE)
            {
                WINDOWPLACEMENT placement;
                GetWindowPlacement(hwnd, &placement);
                if (placement.showCmd == SW_MAXIMIZE) {                        
                    auto monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
                    MONITORINFO monitor_info{};
                    monitor_info.cbSize = sizeof(monitor_info);
                    GetMonitorInfo(monitor, &monitor_info);
                    auto& params = *reinterpret_cast<NCCALCSIZE_PARAMS*>(lparam);
                    params.rgrc[0] = monitor_info.rcWork;
                }
                return false;
            }
            break;
        }
        case WM_NCHITTEST: {
            POINT cursor{ GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) };
            RECT winRect;
            if (!GetWindowRect(hwnd, &winRect)) {
                return HTNOWHERE;
            }
            static const unsigned client{ 0b0000 }, left{ 0b0001 }, 
                right{ 0b0010 }, top{ 0b0100 }, bottom{ 0b1000 };
            const auto result =
                left * (cursor.x < (winRect.left + border.x)) |
                right * (cursor.x >= (winRect.right - border.x)) |
                top * (cursor.y < (winRect.top + border.y)) |
                bottom * (cursor.y >= (winRect.bottom - border.y));
            switch (result) {
                case left: return HTLEFT;
                case right: return HTRIGHT;
                case top: return HTTOP;
                case bottom: return HTBOTTOM;
                case top | left: return HTTOPLEFT;
                case top | right: return HTTOPRIGHT;
                case bottom | left: return HTBOTTOMLEFT;
                case bottom | right: return HTBOTTOMRIGHT;
                case client: return HTCAPTION;
                default: return HTNOWHERE;
            }
            break;
        }
    }
    return CallWindowProc(SFMLWndProc, hwnd, msg, wparam, lparam);
}

int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
     _In_ LPTSTR lpCmdLine, _In_ int nCmdShow)
{
    sf::RenderWindow window(sf::VideoMode(sf::Vector2u(800, 600)), "MyWin");
    tgui::Gui gui{ window };
    auto hwnd = window.getNativeHandle();
    SFMLWndProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)WndProc);
    SetWindowPos(hwnd, nullptr, 0, 0, 0, 0,
        SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
    const MARGINS shadowState{ 0,0,0,1 };
    DwmExtendFrameIntoClientArea(hwnd, &shadowState);
    gui.mainLoop();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants