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

Borderless window with native shadow (Vista+)

Post by chi »

Image

Code: Select all

Global oldProc, brush, DWMEnabled

#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, 0, 0, 0, #SWP_NOSIZE|#SWP_NOZORDER|#SWP_NOCOPYBITS)
      SetWindowPos_(GadgetID(2), 0, width-40, 0, 0, 0, #SWP_NOSIZE|#SWP_NOZORDER|#SWP_NOCOPYBITS)
      SetWindowPos_(GadgetID(1), 0, width-60, 0, 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+20)<<16 + p\x)
      EndSelect
     
    Case #WM_LBUTTONDOWN, #WM_LBUTTONDBLCLK
      GetCursorPos_(cursor.POINT)
      MapWindowPoints_(0, hWnd, cursor, 1)
      If cursor\y < 30
        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
     
    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, 4, 200, 20, txt$)
ButtonGadget(1, 0, 0, 20, 20, "_")
ButtonGadget(2, 0, 0, 20, 20, "")
ButtonGadget(3, 0, 0, 20, 20, "×")
ButtonGadget(4, 0, 0, 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)
Last edited by chi on Wed Jun 27, 2018 10:59 am, edited 4 times in total.
Et cetera is my worst enemy
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5350
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Borderless window with native shadow (Vista+)

Post by Kwai chang caine »

I don't know if it's the good behavior but the windows is black :wink: (W10 x64 / V5.61 x86)
Thanks CHI for sharing 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 »

Kwai chang caine wrote:I don't know if it's the good behavior but the windows is black :wink: (W10 x64 / V5.61 x86)
That's unexpected... I'm having no troubles here (W10 x64 1703)
Et cetera is my worst enemy
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Borderless window with native shadow (Vista+)

Post by Dude »

chi wrote:
Kwai chang caine wrote:I don't know if it's the good behavior but the windows is black :wink: (W10 x64 / V5.61 x86)
That's unexpected... I'm having no troubles here (W10 x64 1703)
The window is just a dark gray (51,51,51) block here on Win 7.

If I add a ButtonGadget to it, the gadget shows, but the title text (txt$) on the window disappears.

FYI.
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 »

Beats me! I tested the above code (again) with Vista, Win7, Win8.1 + Win10 and had no issues whatsoever...
Et cetera is my worst enemy
User avatar
VB6_to_PBx
Enthusiast
Enthusiast
Posts: 625
Joined: Mon May 09, 2011 9:36 am

Re: Borderless window with native shadow (Vista+)

Post by VB6_to_PBx »

chi wrote:Beats me! I tested the above code (again) with Vista, Win7, Win8.1 + Win10 and had no issues whatsoever...
with WIN7 i see just like your 1st Post's picture
but with no Shadow :(

and if i move my Mouse around near right top side of your Window
the Min Max Close normal Window Buttons appear
and i can click on those Window Buttons as well as the ones you created , with the same effects
this is , i can close your Window with either your created Button or close it with the typical Window Close Button that appears
likewise Min or Max Buttons

Edit : i just tested with PB 5.62 and PB 5.70 LTS Beta 1 , and same results on WIN7
 
PureBasic .... making tiny electrons do what you want !

"With every mistake we must surely be learning" - George Harrison
User avatar
Lord
Addict
Addict
Posts: 849
Joined: Tue May 26, 2009 2:11 pm

Re: Borderless window with native shadow (Vista+)

Post by Lord »

Here, the window shows up like in the first posting, no troubles,
no extra buttons showing up in right upper corner.
Win7x64ultimate, PB5.70LTSbeta1
Image
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 »

min/max/close should be fixed now... The shadow problem is still a mystery, though

Obviously the Move/Size option within the SysMenu wont work as is! If someone knows a workaround...
Et cetera is my worst enemy
kvitaliy
Enthusiast
Enthusiast
Posts: 162
Joined: Mon May 10, 2010 4:02 pm

Re: Borderless window with native shadow (Vista+)

Post by kvitaliy »

CreateMenu ?
Menu is not initially displayed on the windowis not initially displayed on the window
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 »

kvitaliy wrote:CreateMenu ?
nope, not without a workaround (e.g. 2nd window with menu, SetParent)
Et cetera is my worst enemy
User avatar
VB6_to_PBx
Enthusiast
Enthusiast
Posts: 625
Joined: Mon May 09, 2011 9:36 am

Re: Borderless window with native shadow (Vista+)

Post by VB6_to_PBx »

chi wrote:min/max/close should be fixed now... The shadow problem is still a mystery, though

Obviously the Move/Size option within the SysMenu wont work as is! If someone knows a workaround...
in WIN7 now i see your Pic but still without a Shadow , but i have Window's Theme set to WIN7 Basic , not Aero Theme

in latest WIN10 i see your Pic now with a Shadow , and everything works perfect !

Nice Window effect !
 
PureBasic .... making tiny electrons do what you want !

"With every mistake we must surely be learning" - George Harrison
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 »

VB6_to_PBx wrote:in WIN7 now i see your Pic but still without a Shadow , but i have Window's Theme set to WIN7 Basic , not Aero Theme
Of course Aero/Desktop composition needs to be turned on for the shadow to work ;)
Et cetera is my worst enemy
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5350
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Borderless window with native shadow (Vista+)

Post by Kwai chang caine »

That's works now with the "enable XP theme" in the debugger :D
I not use AERO too, but always i never thinking to enable this option when several codes have visuals problem :oops:
Thanks a lot for sharing 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 »

Nice, glad it works out now :P
Et cetera is my worst enemy
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 »

slightly modified, if you like to utilize a Menu and/or a Toolbar...

Code: Select all

Global oldProc, oldMnu, brush, DWMEnabled

#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, 0, 0, 0, #SWP_NOSIZE|#SWP_NOZORDER|#SWP_NOCOPYBITS|#SWP_NOACTIVATE)
      SetWindowPos_(GadgetID(2), 0, width-40, 0, 0, 0, #SWP_NOSIZE|#SWP_NOZORDER|#SWP_NOCOPYBITS|#SWP_NOACTIVATE)
      SetWindowPos_(GadgetID(1), 0, width-60, 0, 0, 0, #SWP_NOSIZE|#SWP_NOZORDER|#SWP_NOCOPYBITS|#SWP_NOACTIVATE)
      SetWindowPos_(WindowID(1), 0, 0, 0, width, 19, #SWP_NOMOVE|#SWP_NOZORDER|#SWP_NOACTIVATE)
      RedrawWindow_(hWnd, 0, 0, #RDW_UPDATENOW)

    Case #WM_LBUTTONDOWN, #WM_LBUTTONDBLCLK
      GetCursorPos_(cursor.POINT)
      MapWindowPoints_(0, hWnd, cursor, 1)
      If cursor\y < 22
        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
     
    Case #WM_ACTIVATE
      If (wParam & $FFFF = #WA_INACTIVE And lParam = WindowID(1)) = 0
        SendMessage_(WindowID(1), #WM_NCACTIVATE, Bool(wParam & $FFFF), Bool(lParam))
      EndIf
     
    Case #WM_NCACTIVATE
      If DWMEnabled=0
        ProcedureReturn 1
      EndIf
     
    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_(hWnd, #GWL_WNDPROC, oldProc)
      ProcedureReturn 0
     
  EndSelect
  ProcedureReturn CallWindowProc_(oldProc, hWnd, Msg, wParam, lParam)
EndProcedure

Procedure MnuCallback(hWnd, Msg, wParam, lParam)
  Select Msg
     
    Case #WM_ACTIVATE
      If (wParam & $FFFF = #WA_INACTIVE And lParam = WindowID(0)) = 0
        SendMessage_(WindowID(0), #WM_NCACTIVATE, Bool(wParam & $FFFF), Bool(lParam))
      EndIf
     
    Case #WM_NCDESTROY
      SetWindowLongPtr_(hWnd, #GWL_WNDPROC, oldMnu)
      ProcedureReturn 0
     
  EndSelect
  ProcedureReturn CallWindowProc_(oldMnu, 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, 5, 200, 15, txt$)
ButtonGadget(1, 0, 0, 20, 20, "_")
ButtonGadget(2, 0, 0, 20, 20, "")
ButtonGadget(3, 0, 0, 20, 20, "×")
ButtonGadget(4, 0, 0, 20, 20, "!")

CreateStatusBar(0, WindowID(0))

CreateToolBar(0, WindowID(0), #PB_ToolBar_Text|#PB_ToolBar_Small|#PB_ToolBar_InlineText);
SetWindowLongPtr_(ToolBarID(0),#GWL_STYLE, GetWindowLongPtr_(ToolBarID(0), #GWL_STYLE)|#CCS_NODIVIDER|#CCS_NOPARENTALIGN)
SetWindowPos_(ToolBarID(0), #HWND_TOP, 1, 40, 0, 0, #SWP_NOSIZE|#SWP_NOZORDER|#SWP_NOACTIVATE)
ToolBarStandardButton(0, #PB_ToolBarIcon_New, #PB_ToolBar_Normal, "New")
ToolBarStandardButton(1, #PB_ToolBarIcon_Open, #PB_ToolBar_Normal, "Open")
ToolBarStandardButton(2, #PB_ToolBarIcon_Save, #PB_ToolBar_Normal, "Save")

OpenWindow(1, 0, 22, 100, 0, "", #PB_Window_TitleBar)
SetWindowLongPtr_(WindowID(1), #GWL_STYLE, GetWindowLongPtr_(WindowID(1), #GWL_STYLE) &~#WS_CAPTION)
SetParent_(WindowID(1), WindowID(0))
CreateMenu(0, WindowID(1))
MenuTitle("  File  ")
MenuItem(0, "New")
MenuItem(1, "Open")
MenuItem(2, "Save")
MenuBar()
MenuItem(3, "Quit")
MenuTitle("  Help  ")
MenuItem(4, "About")

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())
oldMnu  = SetWindowLongPtr_(WindowID(1), #GWL_WNDPROC, @MnuCallback())

SetWindowPos_(WindowID(0), 0, 0, 0, 0, 0, #SWP_NOSIZE|#SWP_NOMOVE|#SWP_FRAMECHANGED|#SWP_SHOWWINDOW)

Repeat
  event = WaitWindowEvent()
  Select event
     
    Case #PB_Event_Menu
      Select EventMenu()
         
        Case 3
          event = #PB_Event_CloseWindow
         
        Default
          SetActiveWindow_(WindowID(0))
          MessageRequester("Menu", "MenuID: " + EventMenu())
         
      EndSelect
     
    Case #PB_Event_Gadget
      Select EventGadget()
         
        Case 1
          ShowWindow_(WindowID(0), #SW_MINIMIZE)
         
        Case 2
          If IsZoomed_(WindowID(0))
            ShowWindow_(WindowID(0), #SW_RESTORE)
          Else
            ShowWindow_(WindowID(0), #SW_MAXIMIZE)
          EndIf
         
        Case 3
          SendMessage_(WindowID(0), #WM_CLOSE, 0, 0)
         
        Case 4
          MapWindowPoints_(WindowID(0), 0, p.POINT, 1)
          SendMessage_(WindowID(0), #WM_SYSMENU, 0, (p\y+20)<<16 + p\x)
         
      EndSelect
  EndSelect
Until event = #PB_Event_CloseWindow
DeleteObject_(brush)
[/size]
Last edited by chi on Wed Jun 27, 2018 5:27 pm, edited 4 times in total.
Et cetera is my worst enemy
Post Reply