Borderless window with native shadow (Vista+)

Share your advanced PureBasic knowledge/code with the community.
User avatar
chi
Addict
Addict
Posts: 1034
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

Re: Borderless window with native shadow (Vista+)

Post by chi »

Louise wrote:But how to choose color for the border and title bar or the thickness of the border and title bar.?
For the Titlebar you could do something like:

Code: Select all

;CreateImage(0, 8, 8, 32, RGB(127,127,127)) ;;; replace this line with...

CreateImage(0, 8, GetSystemMetrics_(1)+50, 32, RGB(127,127,127))
StartDrawing(ImageOutput(0))
  Box(0, 0, 8, 30, RGB(100,100,100))
StopDrawing()
But if you want a border, I guess you have to draw an image with the titlebar, border, client area, etc. first and then set it as the current window background (#WM_ERASEBKGND)
Et cetera is my worst enemy
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5353
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Borderless window with native shadow (Vista+)

Post by Kwai chang caine »

Hello CHI, it's again me :oops:
I have try your last code and when i clic on the menu, the normal windows (with blue titlebar) appears over your gray windows and i can't acces to the command in the right/top corner :|
So this time even with the XP theme actived with W7 X86 / v5.61 X86
ImageThe happiness is a road...
Not a destination
User avatar
chi
Addict
Addict
Posts: 1034
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

Re: Borderless window with native shadow (Vista+)

Post by chi »

Hello Kwai chang caine :)
Kwai chang caine wrote:I have try your last code and when i clic on the menu, the normal windows (with blue titlebar) appears over your gray windows and i can't acces to the command in the right/top corner :|
Should be fixed now... Could you please try again?
Et cetera is my worst enemy
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5353
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Borderless window with native shadow (Vista+)

Post by Kwai chang caine »

Yeees That works fine now :D
Thanks a lot CHI 8)
ImageThe happiness is a road...
Not a destination
User avatar
chi
Addict
Addict
Posts: 1034
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

Re: Borderless window with native shadow (Vista+)

Post by chi »

You're welcome :D
Et cetera is my worst enemy
Poshu
Enthusiast
Enthusiast
Posts: 459
Joined: Tue Jan 25, 2005 7:01 pm
Location: Canada

Re: Borderless window with native shadow (Vista+)

Post by Poshu »

Wow! It retains the default functionality and shortcuts on windows 10 (windows + directional arrow, stuff like that).
Any way to keep the resizing capability on the windows itself? I'm not a big fan of the status bar.

From what I can understand, it has to do with the WM_NCCALCSIZE message; I'm toying with it but I have little to no knowledge of the win32 api.
User avatar
chi
Addict
Addict
Posts: 1034
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

Re: Borderless window with native shadow (Vista+)

Post by chi »

Poshu wrote:Any way to keep the resizing capability on the windows itself? I'm not a big fan of the status bar.
Something like this?

Code: Select all

Global oldProc, brush, DWMEnabled, sizeCursor, border=8

#WM_SYSMENU = $313

Procedure WndCallback(hWnd, Msg, wParam, lParam)
  Select Msg
      
    Case #WM_GETMINMAXINFO
      Protected *mmi.MINMAXINFO = lParam
      Protected hMon = MonitorFromWindow_(hWnd, #MONITOR_DEFAULTTONEAREST)
      Protected mie.MONITORINFOEX\cbSize = SizeOf(mie)
      GetMonitorInfo_(hMon, mie)
      *mmi\ptMaxPosition\x = Abs(mie\rcWork\left - mie\rcMonitor\left)
      *mmi\ptMaxPosition\y = Abs(mie\rcWork\top - mie\rcMonitor\top)
      *mmi\ptMaxSize\x = Abs(mie\rcWork\right - mie\rcWork\left)
      *mmi\ptMaxSize\y = Abs(mie\rcWork\bottom - mie\rcWork\top) - 1
      ProcedureReturn 0
      
    Case #WM_NCCALCSIZE
      ProcedureReturn 0
      
    Case #WM_CTLCOLORSTATIC, #WM_CTLCOLORBTN
      SetBkMode_(wParam, #TRANSPARENT)
      ProcedureReturn brush
      
    Case #WM_SIZE
      width = WindowWidth(0)
      SetWindowPos_(GadgetID(3), 0, width-20-border, border, 0, 0, #SWP_NOSIZE|#SWP_NOZORDER|#SWP_NOCOPYBITS)
      SetWindowPos_(GadgetID(2), 0, width-40-border, border, 0, 0, #SWP_NOSIZE|#SWP_NOZORDER|#SWP_NOCOPYBITS)
      SetWindowPos_(GadgetID(1), 0, width-60-border, border, 0, 0, #SWP_NOSIZE|#SWP_NOZORDER|#SWP_NOCOPYBITS)
      
    Case #WM_NCACTIVATE
      If DWMEnabled=0
        ProcedureReturn 1
      EndIf
      
    Case #WM_COMMAND
      Select wParam
        Case 1
          ShowWindow_(hWnd, #SW_MINIMIZE)
        Case 2
          If IsZoomed_(hWnd)
            ShowWindow_(hWnd, #SW_RESTORE)
          Else
            ShowWindow_(hWnd, #SW_MAXIMIZE)
          EndIf
        Case 3
          SendMessage_(hWnd, #WM_CLOSE, 0, 0)
        Case 4
          MapWindowPoints_(hWnd, 0, p.POINT, 1)
          SendMessage_(hWnd, #WM_SYSMENU, 0, (p\y+22+border)<<16 + p\x)
      EndSelect
      
    Case #WM_MOUSEMOVE
      posX = lParam & $FFFF
      posY = (lParam >> 16) & $FFFF
      width = WindowWidth(0)
      height = WindowHeight(0)
      sizeCursor = 0
      If IsZoomed_(hWnd) = 0
        If posX <= border And posY <= border
          SetCursor_(LoadCursor_(0, #IDC_SIZENWSE))
          sizeCursor = #HTTOPLEFT
        ElseIf posX > border And posX <= width - border And posY <= border
          SetCursor_(LoadCursor_(0, #IDC_SIZENS))
          sizeCursor = #HTTOP
        ElseIf posX > width - border And posY <= border
          SetCursor_(LoadCursor_(0, #IDC_SIZENESW))
          sizeCursor = #HTTOPRIGHT
        ElseIf posX > width - border And posY > border And posY <= height - border
          SetCursor_(LoadCursor_(0, #IDC_SIZEWE))
          sizeCursor = #HTRIGHT
        ElseIf posX > width - border And posY > height - border
          SetCursor_(LoadCursor_(0, #IDC_SIZENWSE))
          sizeCursor = #HTBOTTOMRIGHT
        ElseIf posX > border And posX <= width - border And posY > height - border
          SetCursor_(LoadCursor_(0, #IDC_SIZENS))
          sizeCursor = #HTBOTTOM
        ElseIf posX <= border And posY > height - border
          SetCursor_(LoadCursor_(0, #IDC_SIZENESW))
          sizeCursor = #HTBOTTOMLEFT
        ElseIf posX <= border And posY > border And posY <= height - border
          SetCursor_(LoadCursor_(0, #IDC_SIZEWE))
          sizeCursor = #HTLEFT
        EndIf
      EndIf
      If wParam = 0 And sizeCursor = 0
        SetCursor_(LoadCursor_(0, #IDC_ARROW))
      ElseIf wParam = #MK_LBUTTON
        SendMessage_(hWnd, #WM_NCLBUTTONDOWN, sizeCursor, 0)
      EndIf
      
    Case #WM_LBUTTONDOWN, #WM_LBUTTONDBLCLK
      GetCursorPos_(cursor.POINT)
      MapWindowPoints_(0, hWnd, cursor, 1)
      If cursor\y <= 22+border And sizeCursor = 0
        If Msg = #WM_LBUTTONDBLCLK
          If IsZoomed_(hWnd)
            ShowWindow_(hWnd, #SW_RESTORE)
          Else
            ShowWindow_(hWnd, #SW_MAXIMIZE)
          EndIf
        Else
          SendMessage_(hWnd, #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
        EndIf
      EndIf
      Select sizeCursor
        Case #HTTOPLEFT, #HTBOTTOMRIGHT
          SetCursor_(LoadCursor_(0, #IDC_SIZENWSE))
        Case #HTTOP, #HTBOTTOM
          SetCursor_(LoadCursor_(0, #IDC_SIZENS))
        Case #HTTOPRIGHT, #HTBOTTOMLEFT
          SetCursor_(LoadCursor_(0, #IDC_SIZENESW))
        Case #HTLEFT, #HTRIGHT
          SetCursor_(LoadCursor_(0, #IDC_SIZEWE))
      EndSelect
      If Msg = #WM_LBUTTONDBLCLK
        If sizeCursor = #HTTOP
          SendMessage_(hWnd, #WM_NCLBUTTONDBLCLK, #HTTOP, 0)
        ElseIf sizeCursor = #HTBOTTOM
          SendMessage_(hWnd, #WM_NCLBUTTONDBLCLK, #HTBOTTOM, 0)
        EndIf
      EndIf
      
    Case #WM_LBUTTONUP
      Select sizeCursor
        Case #HTTOPLEFT, #HTBOTTOMRIGHT
          SetCursor_(LoadCursor_(0, #IDC_SIZENWSE))
        Case #HTTOP, #HTBOTTOM
          SetCursor_(LoadCursor_(0, #IDC_SIZENS))
        Case #HTTOPRIGHT, #HTBOTTOMLEFT
          SetCursor_(LoadCursor_(0, #IDC_SIZENESW))
        Case #HTLEFT, #HTRIGHT
          SetCursor_(LoadCursor_(0, #IDC_SIZEWE))
      EndSelect
      
    Case #WM_SYSMENU
      SetWindowLongPtr_(hwnd, #GWL_STYLE, GetWindowLongPtr_(hwnd, #GWL_STYLE)|#WS_SYSMENU)
      DefWindowProc_(hWnd, Msg, wParam, lParam)
      SetWindowLongPtr_(hwnd, #GWL_STYLE, GetWindowLongPtr_(hwnd, #GWL_STYLE)&~#WS_SYSMENU)
      ProcedureReturn 0
      
    Case #WM_NCDESTROY
      SetWindowLongPtr_(WindowID(0), #GWL_WNDPROC, oldProc)
      ProcedureReturn 0
      
  EndSelect
  ProcedureReturn CallWindowProc_(oldProc, hWnd, Msg, wParam, lParam)
EndProcedure

txt$ = "Borderless window with native shadow..."
OpenWindow(0, 0, 0, 320, 200, txt$, #WS_OVERLAPPEDWINDOW&~#WS_SYSMENU|#PB_Window_ScreenCentered|#PB_Window_Invisible)
TextGadget(0, 22+border, 4+border, 200, 20, txt$)
ButtonGadget(1, 0, 0, 20, 20, "_")
ButtonGadget(2, 0, 0, 20, 20, "")
ButtonGadget(3, 0, 0, 20, 20, "×")
ButtonGadget(4, border, border, 20, 20, "!")
;CreateStatusBar(0, WindowID(0))

SetRect_(@Margin.RECT, 0, 0, 1, 0)
If OpenLibrary(0, "dwmapi.dll")
  CallFunction(0, "DwmExtendFrameIntoClientArea", WindowID(0), @Margin)
  CallFunction(0, "DwmIsCompositionEnabled", @DWMEnabled)
  If DWMEnabled=0
    MessageRequester("Info", "Desktop composition is disabled! Sorry, no shadow...")
    SetWindowTheme_(WindowID(0), "", "")
  EndIf
  CloseLibrary(0)
EndIf

CreateImage(0, 8, 8, 32, RGB(127,127,127))
brush = CreatePatternBrush_(ImageID(0))
FreeImage(0)
SetClassLongPtr_(WindowID(0), #GCL_HBRBACKGROUND, brush)

oldProc = SetWindowLongPtr_(WindowID(0), #GWL_WNDPROC, @WndCallback())

SetWindowPos_(WindowID(0), 0, 0, 0, 0, 0, #SWP_NOSIZE|#SWP_NOMOVE|#SWP_FRAMECHANGED|#SWP_SHOWWINDOW)
While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
DeleteObject_(brush)
[/size]
Et cetera is my worst enemy
Poshu
Enthusiast
Enthusiast
Posts: 459
Joined: Tue Jan 25, 2005 7:01 pm
Location: Canada

Re: Borderless window with native shadow (Vista+)

Post by Poshu »

Yup. Damn you're fast!
Thanks a lot!
User avatar
chi
Addict
Addict
Posts: 1034
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

Re: Borderless window with native shadow (Vista+)

Post by chi »

np, I was going to do it sometime anyway ;)
Et cetera is my worst enemy
BarryG
Addict
Addict
Posts: 3324
Joined: Thu Apr 18, 2019 8:17 am

Re: Borderless window with native shadow (Vista+)

Post by BarryG »

chi wrote:Something like this?
Hi Chi, I tried your code and it's good except for one tiny problem: sometimes when I hover the mouse over a corner, I get the resize icon (good), but then clicking and dragging does nothing - the mouse just moves away off the window and the window stays the same. If I go back and do it again, it works. Rinse and repeat.
User avatar
chi
Addict
Addict
Posts: 1034
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

Re: Borderless window with native shadow (Vista+)

Post by chi »

BarryG wrote:
chi wrote:Something like this?
Hi Chi, I tried your code and it's good except for one tiny problem: sometimes when I hover the mouse over a corner, I get the resize icon (good), but then clicking and dragging does nothing - the mouse just moves away off the window and the window stays the same. If I go back and do it again, it works. Rinse and repeat.
Yeah, I just noticed too... It's because I used #MK_LBUTTON with #WM_MOUSEMOVE. If you put the mouse on the last most outer pixel, press the LMB and move out of the window, there is obviously no #WM_MOUSEMOVE anymore to catch the #MK_LBUTTON message!
I'll fix it next time I have a few minutes ;)
Et cetera is my worst enemy
Post Reply