Refactoring custom titlebar

This commit is contained in:
Mirek Fidler 2025-11-28 14:35:41 +01:00
parent 6185f5cd43
commit 34efc9037c
8 changed files with 103 additions and 42 deletions

View file

@ -3,8 +3,6 @@
using namespace Upp;
struct MyApp : TopWindow {
FrameTop<StaticRect> bararea; // we represent whole TitleBar area as frame
ParentCtrl barrect; // to do custom caption clipping
MenuBar menubar;
LineEdit editor;
Label title;
@ -34,22 +32,15 @@ struct MyApp : TopWindow {
Icon(CtrlImg::new_doc());
int h = menubar.GetStdHeight();
CustomTitleBar(h); // h is suggested minimum height
Ctrl *custom_bar = CustomTitleBar(h);
if(IsCustomTitleBar()) {
if(custom_bar) {
menubar.Transparent();
auto cm = GetCustomTitleBarMetrics();
bararea.Height(cm.height);
AddFrame(bararea);
bararea << barrect.VSizePos().HSizePos(cm.lm, cm.rm);
ImageBuffer m(1, 2);
m[0][0] = Blend(SWhite(), SLtCyan());
m[0][1] = Blend(SWhite(), SLtMagenta());
bararea.Background(Image(m)); // simple gradient
barrect << menubar;
*custom_bar << menubar;
SetMenuBar(); // run it here to get GetWidth
menubar.LeftPos(0, menubar.GetWidth()).TopPos((cm.height - h) / 2, h);
barrect << title.HSizePos(menubar.GetWidth(), cm.rm).VSizePos();
*custom_bar << title.HSizePos(menubar.GetWidth(), cm.rm).VSizePos();
title.SetLabel("This is CustomTitleBar example");
title.AlignCenter();
title.AlignVCenter();

28
s Normal file
View file

@ -0,0 +1,28 @@
DarkModeContent
* DisplayPopup3
NewDisplayPopup
_t
animations
bad_alloc
blocksel
custom_caption
custom_titlebar
diagram_dev
display_popup
ext2
gui_sizeof
ide_ext
ide_external
ime
layzoom
+ llbm_ide
logs
master
mt_painter
newmouse
next2025_1
pixelmode
skin
stable
wchar

View file

@ -184,9 +184,39 @@ void TopWindow::SyncCaption()
SetIco();
Ptr<TopWindow> ptr = this;
PostCallback([=] { // windows 11 ignores icon if Window does not start processing messages within ~200ms
PostCallback([=] { // windows 11 seems to ignore icon if Window does not start processing messages within ~200ms
if(ptr) ptr->SetIco(); // set it again when we are processing events
});
SyncCustomBar();
}
void TopWindow::SyncCustomBar()
{
if(custom_bar_frame)
custom_bar_frame->Height(GetCustomTitleBarMetrics().height);
if(custom_bar) {
auto cm = GetCustomTitleBarMetrics();
custom_bar->VSizePos().HSizePos(cm.lm, cm.rm);
}
}
bool TopWindow::IsCustomTitleBar__() const
{
return custom_bar;
}
Ctrl *TopWindow::MakeCustomTitleBar__(int mincy)
{
if(!custom_bar && IsWin11()) {
custom_titlebar_cy = mincy;
AddFrame(custom_bar_frame.Create());
custom_bar_frame->Transparent();
custom_bar.Create();
custom_bar_frame->Add(*custom_bar);
SyncCustomBar();
}
return ~custom_bar;
}
void TopWindow::SetIco()

View file

@ -421,26 +421,26 @@ TopWindow& TopWindow::Icon(const Image& smallicon, const Image& _largeicon)
return *this;
}
bool is_custom_titlebar_available__;
bool TopWindow::IsCustomTitleBar() const
{
return custom_titlebar && is_custom_titlebar_available__;
}
TopWindow& TopWindow::CustomTitleBar(int cy)
{
custom_titlebar = is_custom_titlebar_available__;
custom_titlebar_cy = cy;
return *this;
}
// avoid the need to implement custom titlebar in all platforms:
Function<bool (const TopWindow *)> is_custom_titlebar__;
Function<Ctrl *(TopWindow *, int)> custom_titlebar_make__;
Event<const TopWindow *, TopWindow::CustomTitleBarMetrics&> custom_titlebar_metrics__ =
[](const TopWindow *, TopWindow::CustomTitleBarMetrics& m) {
m.lm = m.rm = m.height = 0;
m.background = SColorPaper();
};
bool TopWindow::IsCustomTitleBar() const
{
return is_custom_titlebar__(this);
}
Ctrl *TopWindow::CustomTitleBar(int cy)
{
return custom_titlebar_make__(this, cy);
}
TopWindow::CustomTitleBarMetrics TopWindow::GetCustomTitleBarMetrics() const
{
CustomTitleBarMetrics m;
@ -545,8 +545,6 @@ TopWindow::TopWindow()
dokeys = true;
fullscreen = frameless = urgent = false;
close_rejects = false;
custom_titlebar = false;
custom_titlebar_cy = 0;
}
TopWindow::~TopWindow()

View file

@ -80,14 +80,9 @@ private:
bool frameless:1;
bool urgent:1;
bool close_rejects:1;
bool custom_titlebar:1;
byte state;
Image icon, largeicon;
int custom_titlebar_cy = 0;
int active_titlebar_button = -1;
bool active_titlebar_active = false;
const TopStyle *st;
void GuiPlatformConstruct();
@ -181,7 +176,9 @@ public:
TopWindow& LargeIcon(const Image& m);
TopWindow& Icon(const Image& smallicon, const Image& largeicon);
TopWindow& CustomTitleBar(int min_cy = 0);
Ctrl *CustomTitleBar(int min_cy = 0);
// TopWindow& CustomTitleBar(int min_cy = 0);
bool IsCustomTitleBar() const;
struct CustomTitleBarMetrics {

View file

@ -10,6 +10,16 @@ private:
void SetIco();
void CenterRect(HWND owner, int center);
One<FrameTop<Ctrl>> custom_bar_frame;
One<Ctrl> custom_bar;
int custom_titlebar_cy = 0;
int active_titlebar_button = -1;
bool active_titlebar_active = false;
bool IsCustomTitleBar__() const;
Ctrl *MakeCustomTitleBar__(int mincy);
void SyncCustomBar();
public:
void Open(HWND ownerhwnd);
TopWindow& Style(dword _style);

View file

@ -220,8 +220,9 @@ void Ctrl::InstallPanicBox()
InstallPanicMessageBox(&Win32PanicMessageBox);
}
extern bool is_custom_titlebar_available__;
extern Event<const TopWindow *, TopWindow::CustomTitleBarMetrics&> custom_titlebar_metrics__;
extern Function<bool (const TopWindow *)> is_custom_titlebar__;
extern Function<Ctrl *(TopWindow *, int)> custom_titlebar_make__;
void Ctrl::InitWin32(HINSTANCE hInstance)
{
@ -284,10 +285,8 @@ void Ctrl::InitWin32(HINSTANCE hInstance)
GlobalBackPaint();
is_custom_titlebar_available__ = IsWin11();
custom_titlebar_metrics__ = [=](const TopWindow *tw, TopWindow::CustomTitleBarMetrics& m) {
if(!tw->custom_titlebar)
custom_titlebar_metrics__ = [](const TopWindow *tw, TopWindow::CustomTitleBarMetrics& m) {
if(!tw->custom_bar)
return;
m.height = GetWin32TitleBarHeight(tw);
m.lm = 0;
@ -296,7 +295,15 @@ void Ctrl::InitWin32(HINSTANCE hInstance)
m.lm = DPI(4) + min(icon.GetWidth(), 32);
m.rm = (tw->IsZoomable() ? 3 : 1) * GetWin32TitleBarButtonWidth();
};
is_custom_titlebar__ = [](const TopWindow *win) {
return win->IsCustomTitleBar__();
};
custom_titlebar_make__ = [=](TopWindow *win, int mincy) -> Ctrl * {
return win->MakeCustomTitleBar__(mincy);
};
EnterGuiMutex();
}

View file

@ -108,8 +108,8 @@ bool DisplayPopup::MouseHook(Ctrl *, bool, int, Point, int, dword)
}
void DisplayPopup::Set(Ctrl *_ctrl, const Rect& _item,
const Value& _value, const Display *_display,
Color _ink, Color _paper, dword _style, int _margin)
const Value& _value, const Display *_display,
Color _ink, Color _paper, dword _style, int _margin)
{
if(!GUI_ToolTips())
return;