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

OverlappedPresenter SetBorderAndTitleBar not hide titlebar #10137

Closed
ourfor opened this issue Nov 3, 2024 · 7 comments
Closed

OverlappedPresenter SetBorderAndTitleBar not hide titlebar #10137

ourfor opened this issue Nov 3, 2024 · 7 comments

Comments

@ourfor
Copy link

ourfor commented Nov 3, 2024

Describe the bug

I want the window to be resizable and hide system control button

    MainWindow::MainWindow()
    {
        InitializeComponent();

        auto presenter = AppWindow().Presenter().as<Microsoft::UI::Windowing::OverlappedPresenter>();
        presenter.IsMaximizable(false);
        presenter.IsMinimizable(false);
        presenter.SetBorderAndTitleBar(true, false);
    }

Image

There is a small region at the top of the window which looks like Windows is drawing part of the title bar.

if I set resizable equals to false

    MainWindow::MainWindow()
    {
        InitializeComponent();

        auto wn = try_as<IWindowNative>();

        HWND window_handle{};
        wn->get_WindowHandle(&window_handle);

        auto presenter = AppWindow().Presenter().as<Microsoft::UI::Windowing::OverlappedPresenter>();
        presenter.IsMaximizable(false);
        presenter.IsMinimizable(false);
        presenter.IsResizable(false);
        presenter.SetBorderAndTitleBar(true, false);
    }

Image

Steps to reproduce the bug

  1. AppWindow().Presenter().as<Microsoft::UI::Windowing::OverlappedPresenter>()
  2. SetBorderAndTitleBar(true, false)
  3. IsResizable(true)

There is a small region at the top of the window which looks like Windows is drawing part of the title bar.

Expected behavior

There shouldn't be a small area at the top of the window

Screenshots

No response

NuGet package version

None

Packaging type

No response

Windows version

No response

IDE

No response

Additional context

No response

@microsoft-github-policy-service microsoft-github-policy-service bot added the needs-triage Issue needs to be triaged by the area owners label Nov 3, 2024
@ghost1372
Copy link
Contributor

Duplicate

Temporary fix is awailable

#9978 (comment)

@ourfor
Copy link
Author

ourfor commented Nov 3, 2024

Duplicate

Temporary fix is awailable

microsoft/microsoft-ui-xaml#9978 (comment)

I made adjustments according to the mentioned issue. There is no border when in full screen, but the blank area at the top still exists
Image

        const int GWL_STYLE = (-16);
        const int GWL_EXSTYLE = (-20);
        public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong) {
            if (IntPtr.Size == 4) {
                return SetWindowLongPtr32(hWnd, nIndex, dwNewLong);
            }
            return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
        }

        [DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SetWindowLong")]
        public static extern IntPtr SetWindowLongPtr32(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        [DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SetWindowLongPtr")]
        public static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        public static long GetWindowLong(IntPtr hWnd, int nIndex) {
            if (IntPtr.Size == 4) {
                return GetWindowLong32(hWnd, nIndex);
            }
            return GetWindowLongPtr64(hWnd, nIndex);
        }

        [DllImport("User32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Auto)]
        public static extern long GetWindowLong32(IntPtr hWnd, int nIndex);

        [DllImport("User32.dll", EntryPoint = "GetWindowLongPtr", CharSet = CharSet.Auto)]
        public static extern long GetWindowLongPtr64(IntPtr hWnd, int nIndex);

        public const int WS_DLGFRAME = 0x00400000;

and then in MainWindow

            ExtendsContentIntoTitleBar = true;
            var overlapPresenter = m_AppWindow.Presenter as OverlappedPresenter;
            overlapPresenter.IsResizable = true;
            overlapPresenter.SetBorderAndTitleBar(false, false);
            var hwnd = WindowNative.GetWindowHandle(this);
            var hWndMain = WinRT.Interop.WindowNative.GetWindowHandle(this);
            SetWindowLong(hWndMain, GWL_STYLE, (IntPtr)(GetWindowLong(hWndMain, GWL_STYLE) & ~(WS_DLGFRAME)));

@ourfor
Copy link
Author

ourfor commented Nov 3, 2024

I set the window to be resizable, and then a small area appears at the top of the window, which is not expected. If the window is not resizable, there is no such small area

@ghost1372
Copy link
Contributor

Duplicate

Temporary fix is awailable

microsoft/microsoft-ui-xaml#9978 (comment)

I made adjustments according to the mentioned issue. There is no border when in full screen, but the blank area at the top still exists
Image

        const int GWL_STYLE = (-16);
        const int GWL_EXSTYLE = (-20);
        public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong) {
            if (IntPtr.Size == 4) {
                return SetWindowLongPtr32(hWnd, nIndex, dwNewLong);
            }
            return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
        }

        [DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SetWindowLong")]
        public static extern IntPtr SetWindowLongPtr32(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        [DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SetWindowLongPtr")]
        public static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        public static long GetWindowLong(IntPtr hWnd, int nIndex) {
            if (IntPtr.Size == 4) {
                return GetWindowLong32(hWnd, nIndex);
            }
            return GetWindowLongPtr64(hWnd, nIndex);
        }

        [DllImport("User32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Auto)]
        public static extern long GetWindowLong32(IntPtr hWnd, int nIndex);

        [DllImport("User32.dll", EntryPoint = "GetWindowLongPtr", CharSet = CharSet.Auto)]
        public static extern long GetWindowLongPtr64(IntPtr hWnd, int nIndex);

        public const int WS_DLGFRAME = 0x00400000;

and then in MainWindow

            ExtendsContentIntoTitleBar = true;
            var overlapPresenter = m_AppWindow.Presenter as OverlappedPresenter;
            overlapPresenter.IsResizable = true;
            overlapPresenter.SetBorderAndTitleBar(false, false);
            var hwnd = WindowNative.GetWindowHandle(this);
            var hWndMain = WinRT.Interop.WindowNative.GetWindowHandle(this);
            SetWindowLong(hWndMain, GWL_STYLE, (IntPtr)(GetWindowLong(hWndMain, GWL_STYLE) & ~(WS_DLGFRAME)));

Mybe you should set true for border

SetBorderAndTitleBar(true, false)

@ourfor
Copy link
Author

ourfor commented Nov 3, 2024

Duplicate
Temporary fix is awailable
microsoft/microsoft-ui-xaml#9978 (comment)

I made adjustments according to the mentioned issue. There is no border when in full screen, but the blank area at the top still exists
Image
const int GWL_STYLE = (-16);
const int GWL_EXSTYLE = (-20);
public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong) {
if (IntPtr.Size == 4) {
return SetWindowLongPtr32(hWnd, nIndex, dwNewLong);
}
return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
}

    [DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SetWindowLong")]
    public static extern IntPtr SetWindowLongPtr32(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

    [DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SetWindowLongPtr")]
    public static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

    public static long GetWindowLong(IntPtr hWnd, int nIndex) {
        if (IntPtr.Size == 4) {
            return GetWindowLong32(hWnd, nIndex);
        }
        return GetWindowLongPtr64(hWnd, nIndex);
    }

    [DllImport("User32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Auto)]
    public static extern long GetWindowLong32(IntPtr hWnd, int nIndex);

    [DllImport("User32.dll", EntryPoint = "GetWindowLongPtr", CharSet = CharSet.Auto)]
    public static extern long GetWindowLongPtr64(IntPtr hWnd, int nIndex);

    public const int WS_DLGFRAME = 0x00400000;

and then in MainWindow
ExtendsContentIntoTitleBar = true;
var overlapPresenter = m_AppWindow.Presenter as OverlappedPresenter;
overlapPresenter.IsResizable = true;
overlapPresenter.SetBorderAndTitleBar(false, false);
var hwnd = WindowNative.GetWindowHandle(this);
var hWndMain = WinRT.Interop.WindowNative.GetWindowHandle(this);
SetWindowLong(hWndMain, GWL_STYLE, (IntPtr)(GetWindowLong(hWndMain, GWL_STYLE) & ~(WS_DLGFRAME)));

Mybe you should set true for border

SetBorderAndTitleBar(true, false)

I adjusted it, it didn't work

@DarranRowe
Copy link

DarranRowe commented Nov 3, 2024

This is a Windows bug.

--Edit--

To give an example of what I mean. Consider the following basic Windows API application written in C++.

#include <Windows.h>

LRESULT CALLBACK WndProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	switch (msg)
	{
	case WM_CLOSE:
	{
		DestroyWindow(wnd);
		return 0;
	}
	case WM_DESTROY:
	{
		PostQuitMessage(0);
		return 0;
	}
	default:
	{
		return DefWindowProcW(wnd, msg, wparam, lparam);
	}
	}
}

int APIENTRY wWinMain(_In_ HINSTANCE inst, _In_opt_ HINSTANCE, _In_ LPWSTR, _In_ int cmdshow)
{
	WNDCLASSEXW wcx{ sizeof(WNDCLASSEXW) };

	wcx.hInstance = inst;
	wcx.lpszClassName = L"TestClass";
	wcx.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
	wcx.hCursor = reinterpret_cast<HCURSOR>(LoadImageW(nullptr, MAKEINTRESOURCEW(32512), IMAGE_CURSOR, 0, 0, LR_SHARED | LR_DEFAULTSIZE));
	wcx.hIcon = reinterpret_cast<HICON>(LoadImageW(nullptr, MAKEINTRESOURCEW(32512), IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE));
	wcx.hIconSm = reinterpret_cast<HICON>(LoadImageW(nullptr, MAKEINTRESOURCEW(32512), IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE));
	wcx.lpfnWndProc = WndProc;
	wcx.style = CS_HREDRAW | CS_VREDRAW;

	RegisterClassExW(&wcx);

	//CreateWindowEx ignores the style and forces in a caption. This is why we don't try too hard here and just use WS_OVERLAPPED.
	HWND wnd = CreateWindowExW(0, L"TestClass", L"Test Window", WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, inst, nullptr);

	SetWindowLongPtrW(wnd, GWL_STYLE, WS_THICKFRAME); //This is the important part. The only style on the window is the resizable border.
	SetWindowPos(wnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); //This only forces the window to reset its cached data. Needed because we remove the caption that CreateWindowEx forces in.

	ShowWindow(wnd, cmdshow);
	UpdateWindow(wnd);

	MSG msg{};
	while (GetMessageW(&msg, nullptr, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessageW(&msg);
	}

	return static_cast<int>(msg.wParam);
}

Image

This is how the window looks. Doesn't it look familiar?
Basically, that extra bar drawn at the top comes from Windows itself when you do not have a caption but the border is a resizable border. It has also been in Windows for a while.

@RDMacLachlan RDMacLachlan transferred this issue from microsoft/WindowsAppSDK Nov 4, 2024
@karkarl
Copy link
Contributor

karkarl commented Nov 7, 2024

Resolving as dupe of #9978

@karkarl karkarl closed this as not planned Won't fix, can't repro, duplicate, stale Nov 7, 2024
@microsoft-github-policy-service microsoft-github-policy-service bot removed the needs-triage Issue needs to be triaged by the area owners label Nov 7, 2024
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

4 participants