Control elements in caption while retaining standard Windows snap layout
Is this possible? Many Windows apps have this feature, but how do you do it?
Does anyone have any ideas?
Which elements? I don't know what you mean.
Not specifically, but as an example, a menu integrated into the title bar of a window — also known as a custom title bar menu
Notepad also has something similar, tabs in the title bar.
(https://www.planetsquires.com/images/notepad-tabs.png)
(https://www.planetsquires.com/images/vscode.png)
> Notepad also has something similar, tabs in the title bar.
Notepad has no tabs in the title bar. What it has is a menu.
Hi Paul,
Welcome back. Hope you have enjoyed your European travel.
Quote from: Paul Squires on August 25, 2025, 04:17:16 PM(https://www.planetsquires.com/images/vscode.png)
Such a menu is not very difficult, but how do you get the snap layout under the maximize button to work?
Quote from: José Roca on August 25, 2025, 04:43:06 PMHi Paul,
Welcome back. Hope you have enjoyed your European travel.
Thanks! Nice trip but always nice to come back home 😁
Okay, this looks promising.
So far, snaplayout works and there is a close button on the title bar in the non-client area as if it were the client area.
#define _WIN32_WINNT &h0602
#define FB_USE_WINDOWS ' gebruik API bindings in plaats van cross-platform varianten.
#define UNICODE ' gebruik Unicode strings
#Include once "windows.bi"
' #include once "win/dwmapi.bi" ' niet beschikbaar in freebasic
' Structs voor DWM (moet vóór de DWM declaraties staan)
Type MARGINS
cxLeftWidth As Long
cxRightWidth As Long
cyTopHeight As Long
cyBottomHeight As Long
End Type
' Define needed DWM constants (freebasic dont have header dwmapi.bi)
Const DWMWA_USE_IMMERSIVE_DARK_MODE As DWORD = 20
Const DWMWA_CAPTION_COLOR As DWORD = 35
Extern "windows-ms"
Declare Function DwmExtendFrameIntoClientArea Lib "dwmapi.dll" (ByVal hwnd As HWND, ByVal pMarInset As Any Ptr) As Long
Declare Function DwmDefWindowProc Lib "dwmapi.dll" (ByVal hwnd As HWND, ByVal msg As UINT, ByVal wParam As WPARAM, ByVal lParam As LPARAM, ByVal plResult As LRESULT Ptr) As BOOL
Declare Function DwmSetWindowAttribute Lib "dwmapi.dll" Alias "DwmSetWindowAttribute" (ByVal hwnd As HWND, ByVal dwAttribute As DWORD, ByVal pvAttribute As Any Ptr, ByVal cbAttribute As DWORD) As HRESULT
End Extern
DECLARE FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, BYVAL hPrevInstance AS HINSTANCE, BYVAL szCmdLine AS ZSTRING PTR, BYVAL nCmdShow AS LONG) AS LONG
'run the app
END WinMain(GetModuleHandleW(NULL), NULL, COMMAND(), SW_NORMAL)
FUNCTION WndProc (BYVAL hwnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT
Static margins As MARGINS = (0, 0, 60, 0)
Static border_thickness As RECT = (5, 5, 5, 5)
Dim lResult As LRESULT
Select Case uMsg
Case WM_NCCREATE
' lParam is een pointer naar CREATESTRUCT
' In FreeBASIC kun je direct casten
Dim pCreate As CREATESTRUCT Ptr = Cast(CREATESTRUCT Ptr, lParam)
Dim hInst As HINSTANCE = pCreate->hInstance
Return 1
Case WM_NCCALCSIZE
If wParam <> 0 Then
Dim sz As NCCALCSIZE_PARAMS Ptr = Cast(NCCALCSIZE_PARAMS Ptr, lParam)
sz->rgrc(0).left += border_thickness.left
sz->rgrc(0).right -= border_thickness.right
sz->rgrc(0).bottom -= border_thickness.bottom
Else
Dim sz As RECT Ptr = Cast(RECT Ptr, lParam)
sz->left += border_thickness.left
sz->right -= border_thickness.right
sz->bottom -= border_thickness.bottom
End If
Return 0
Case WM_CREATE
' DWM frame uitbreiden
Dim hr As Long
hr = DwmExtendFrameIntoClientArea(hwnd, @margins)
' Knop aanmaken
CreateWindowExW(0, "Button", "Close", WS_CHILD Or WS_VISIBLE Or WS_TABSTOP, 25, 5, 300, 100, hwnd, Cast(HMENU, IDCANCEL), GetModuleHandle(0), 0)
Return DefWindowProcW(hwnd, uMsg, wParam, lParam)
Case WM_COMMAND
Select Case LoWord(wParam)
Case IDCANCEL
PostQuitMessage(0)
End Select
return 0
Case WM_NCHITTEST
' DWM standaardverwerking
If DwmDefWindowProc(hwnd, uMsg, wParam, lParam, @lResult) Then
Return lResult
End If
lResult = DefWindowProc(hwnd, uMsg, wParam, lParam)
If lResult = HTCLIENT Then
Dim pt As POINT
pt.x = LoWord(lParam)
pt.y = HiWord(lParam)
ScreenToClient(hwnd, @pt)
If pt.y < border_thickness.top Then Return HTTOP
If pt.y < margins.cyTopHeight Then Return HTCAPTION
End If
Return lResult
End Select
' // Default processing of Windows messages
FUNCTION = DefWindowProcW(hWnd, uMsg, wParam, lParam)
END FUNCTION
' Functie om RGB naar BGR DWORD (COLORREF) te converteren
Function ColorToBgrDWORD(ByVal r As UByte, ByVal g As UByte, ByVal b As UByte) As DWORD
Return (CUInt(b) Shl 16) Or (CUInt(g) Shl 8) Or CUInt(r)
End Function
FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, BYVAL hPrevInstance AS HINSTANCE, BYVAL szCmdLine AS ZSTRING PTR, BYVAL nCmdShow AS LONG) AS LONG
Dim CLASS_NAME As WString * 64 = "CustomTitlebarWindow"
Dim wc As WNDCLASSW
wc.lpfnWndProc = @wndproc
wc.hInstance = GetModuleHandleW(0)
wc.lpszClassName = StrPtr(CLASS_NAME)
wc.hCursor = LoadCursor(0, IDC_ARROW)
wc.hbrBackground = Cast(HBRUSH, COLOR_WINDOW + 1)
RegisterClassW(@wc)
Dim hWndMain As HWND
hWndMain = CreateWindowExW(0, StrPtr(CLASS_NAME), "Button on Titlebar + Snap Layouts", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, 0, 0, wc.hInstance, 0)
' Enable dark mode title bar (if supported)
Dim dark As BOOL: dark = TRUE
DwmSetWindowAttribute(hWndMain, DWMWA_USE_IMMERSIVE_DARK_MODE, @dark, SizeOf(dark))
' Set caption color
Dim activeCaption As DWORD = ColorToBgrDWORD(31, 31, 31)
DwmSetWindowAttribute(hWndMain, DWMWA_CAPTION_COLOR, @activeCaption, SizeOf(activeCaption))
ShowWindow(hWndMain, SW_SHOWNORMAL)
UpdateWindow(hWndMain)
' // Dispatch Windows messages
DIM uMsg AS MSG
WHILE (GetMessageW(@uMsg, NULL, 0, 0) <> FALSE)
IF IsDialogMessageW(hWndMain, @uMsg) = 0 THEN
TranslateMessage(@uMsg)
DispatchMessageW(@uMsg)
END IF
WEND
FUNCTION = uMsg.wParam
END FUNCTION
A canvas (STATIC) will be needed in the client area because the real title bar is not intended for custom drawing and you don't have reliable, modern drawing functionality there.