Jump to content

Recommended Posts

Posted

Version 1.1.2 has been added to the first post.

I finally decided to rename the project so that it is more simple and to the point and with a lot less syllables. The new name is "Immersive UX". The main GUI script is ImmersiveUX while the engine is ImmersiveEngine.

Aside from the name change, there are some really nice improvements. I was able to significantly reduce the memory usage of the engine process which was nice to see. I also took care to ensure that the process is able to successfully run its cleanup routine of releasing resources and hook whether it is closed from the tray menu, the task ends or programmatically from the GUI functions.

For the system tray menu, a left-click opens the GUI now while a right-click opens the tray menu.

A ridiculous amount of work went into refining all of the functionality for installing, removing, restarting and upgrading (to admin) the scheduled task. I feel like I have finally smoothed it all out now.

Posted (edited)

Version 1.1.3 has been added to the first post.

As usual, detailed release notes are also updated on the first post with each release.

The main highlight of this release is adding a 1-click option to patch all VSCode/VSCodium install locations on the system to allow for backdrop materials to be applied. Modified files are backed up and restored if/when you choose to do so. Those files get restored with each VSCode/VSCodium update also. Therefore, patching is required with each VSCode/VSCodium update.

The entire GUI has been made draggable as well since there is space to do so and also because some of the backdrop materials can make it hard to tell where the titlebar is anyway. Also some nice bug fixes in this release.

Next release, I will try to make a 1-click patch to patch Windows Terminal settings.json file so that users do not have to do it manually.

Edited by WildByDesign
Posted

First post has been updated with version 1.1.4.

This adds a 1-click menu option to the Special Handling menu of the GUI for adding transparent background, tab row and tabs to Windows Terminal. That allows Immersive UX to apply all of the backdrop materials or blur behind to Terminal.

I also added some messaging to the user for the patch/unpatch operations for VSCode, VSCodium and Windows Terminal so that the user is aware of what is being done.

Posted

The next release is going to have the most significant performance improvement yet in comparison to any previous performance improvements that I have squeezed out of it.

The reason why? Well, I had an incorrect understanding of ContinueCase and therefore had something like 50+ occurrences of it.

Everything worked as expected. However, it was working harder than it needed to. I switched all of those occurrences from ContinueCase to Return and things are noticeably faster.

Posted (edited)

I just added version 1.2.0 to the first post. Also, I forgot to add version 1.1.5 a few days ago. So the release notes on the first post have been updated with both.

There were a lot of changes, improvements and fixes in this latest release. So if you are curious, the release notes would be worth while to check out.

The most important thing to me in this release was the performance improvements in SetWinEventHook. The reason for the performance improvements is mentioned in my post from yesterday.

Edited by WildByDesign
Posted

I haven't updated the source here for a bit and there has been a lot of changes. I just updated the first post with the source code for version 1.2.5. I also updated the Changelog section of the first post with all of the changes from 1.2.1 through 1.2.5.

Generally I like to summarize some of the important changes here bit by bit as I go, but there are just simply way too many significant changes and improvements to summarize. If anyone is curious about any of the changes, the Changelog on the first post has all of those details. Also, if you want to see actual changes between each version, the GitHub repo (https://github.com/WildByDesign/ImmersiveUX) would be the best place to see actual changes.

Somehow this project has matured and improved significantly in recent weeks.

  • 4 weeks later...
Posted

Just want to start by saying that I'm a big fan of how you're transforming these basic GUIs.

Now here's a question and I'm wondering if you've run into an issue like this. Unfortunately posting code is somewhat difficult as the scale is big but if needed I can trim.

I'm applying Mica effect to the GUIs within the same script. A lot of code is omitted but all GUIs follow same logic and are in the following order.

$GUI1 = GUICreate('GUI #1', 600, 400, -1, -1, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_COMPOSITED)
 ApplyBlur($GUI1)
 $GUI2 = GUICreate('GUI #2', 600, 400, -1, -1, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_COMPOSITED)
 ApplyBlur($GUI2)
 $GUI3 = GUICreate('GUI #3', 600, 400, -1, -1, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_COMPOSITED)
 ApplyBlur($GUI3)
 
 Func ApplyBlur($hWnd)
    DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $hWnd, 'dword', 20, 'dword*', 1, 'dword', 4)
    DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $hWnd, 'dword', 38, 'dword*', 4, 'dword', 4)
    _WinAPI_DwmExtendFrameIntoClientArea($hWnd, _WinAPI_CreateMargins(-1, -1, -1, -1))
 EndFunc

Issue #1: The first created GUI never receives the full Mica treatment so to speak. It will not go grey when not active, which in my case is actually a good thing since it has layered child windows which steal focus and WOULD turn it grey which in turn would make it looks strange. So I'm glad it's bugged? But my question still remains; why?

Issue #2: WinMove() or _WinAPI_SetWindowPos() remove the Mica effect. I assume this is due to client area changing and it needing an update in a form of another call to the dwmapi. However the strange thing is that the title bar seems to come back during the move functions and after that I am neither able to remove it nor is it even detectable with _WinAPI_GetWindowLong($hWnd, $GWL_STYLE). Which now leaves my $WS_POPUP window with a title bar as if it had a $WS_CAPTION style. Have you had something similar or is this an issue that I am simply still to find within my own script.

It's the second one I'd like to solve as in one particular case I wrote a custom function to create own dark-themed context menu that works like a drop-down. It's a single GUI that receives its information from a 2D array based on a button that was pressed (if that makes sense). I have dozens of these buttons around my various GUIs and I like to keep it clean so a single context GUI that's resizable solves my problem. But once it's resized the Mica effect disappears (specifically the GUI loses all color) and no matter what I can't seem to reapply it. The only difference between this GUI and the others from the example is that it has only $WS_EX_TOPMOST as extended style.

I tried also adding $WS_CAPTION style before dwm calls and then removing but no luck. Which weirdly enough worked for some windows without me needing to even remove the style as visually it wasn't even present but that straight up further complicated everything because this inconsistency now makes no sense to me.

Any feedback is appreciated!

Posted
1 hour ago, NMS said:

Just want to start by saying that I'm a big fan of how you're transforming these basic GUIs.

Thank you, I appreciate it. There are a lot of limitations in AutoIt for making certain types of controls transparent, so I had to find ways to get creative. I've only made about 5 or 6 GUI's in AutoIt so far and I had to do a bunch of weird stuff in all of them to make happen what I needed to do.

1 hour ago, NMS said:

Issue #1: The first created GUI never receives the full Mica treatment so to speak. It will not go grey when not active, which in my case is actually a good thing since it has layered child windows which steal focus and WOULD turn it grey which in turn would make it looks strange. So I'm glad it's bugged? But my question still remains; why?

I'm not 100% sure why. I would really need to see code that I can run that is reproducible to get a better understanding. $WS_CAPTION would definitely be needed since the whole extending to client thing is all about extending that titlebar into the frame. However, in this case, it likely has more to do with the layered child windows. But I would really need to run some reproducible code to see because I haven't had this issue before.

1 hour ago, NMS said:

Issue #2: WinMove() or _WinAPI_SetWindowPos() remove the Mica effect. I assume this is due to client area changing and it needing an update in a form of another call to the dwmapi. However the strange thing is that the title bar seems to come back during the move functions and after that I am neither able to remove it nor is it even detectable with _WinAPI_GetWindowLong($hWnd, $GWL_STYLE). Which now leaves my $WS_POPUP window with a title bar as if it had a $WS_CAPTION style. Have you had something similar or is this an issue that I am simply still to find within my own script.

It's the second one I'd like to solve as in one particular case I wrote a custom function to create own dark-themed context menu that works like a drop-down. It's a single GUI that receives its information from a 2D array based on a button that was pressed (if that makes sense). I have dozens of these buttons around my various GUIs and I like to keep it clean so a single context GUI that's resizable solves my problem. But once it's resized the Mica effect disappears (specifically the GUI loses all color) and no matter what I can't seem to reapply it. The only difference between this GUI and the others from the example is that it has only $WS_EX_TOPMOST as extended style.

First of all, I respect the creativity that you're attempting here. You're making a custom context menu and I assume that one of your main goals here is being able to show the mica material on the context menu which explains why you are using a GUI for it. I've tried to find ways to show mica material on system menus and things like that but was never able to since they technically don't have a titlebar. So what you are trying to do here is pretty awesome.

I've used _WinAPI_SetWindowPos and _WinAPI_GetWindowLong a bit before including to remove $WS_CAPTION. But I've never kind of repeatedly added/removed it and therefore never experienced this specific issue either.

I am intrigued by what you are trying to do though and I would like to help if possible. If you want, you can send a private message or whatever with some reproducible code and I can do my best to help.

Posted

So here's a quick example for the second issue. There's a lot of error checking and other stuff not included but for the sake of reproducing a problem it works.

You can toggle between the lines 137 and 138. I've tried various methods but none worked so far.

#include <WindowsStylesConstants.au3>
#include <GUIConstantsEx.au3>
#include <WinAPIGdi.au3>
#include <ButtonConstants.au3>
#include <Array.au3>
#include <Misc.au3>

Global $PROGRAM_WindowContextArray[0][5]
Global $PROGRAM_ContextWindowCheck

Global $GUI_WindowContext = GUICreate('GUI Context', 200, 100, -1, -1, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_TOPMOST)
GUISetBkColor(0x191919, $GUI_WindowContext)
Global $GUI_WindowContext_Button_1 = GUICtrlCreateLabel('1', 0, 0, 200, 20, $BS_LEFT)
GUICtrlSetColor(-1, 0xCCCCCC)
Global $GUI_WindowContext_Button_2 = GUICtrlCreateLabel('2', 0, 20, 200, 20, $BS_LEFT)
GUICtrlSetColor(-1, 0xCCCCCC)
Global $GUI_WindowContext_Button_3 = GUICtrlCreateLabel('3', 0, 40, 200, 20, $BS_LEFT)
GUICtrlSetColor(-1, 0xCCCCCC)
Global $GUI_WindowContext_Button_4 = GUICtrlCreateLabel('4', 0, 60, 200, 20, $BS_LEFT)
GUICtrlSetColor(-1, 0xCCCCCC)
Global $GUI_WindowContext_Button_5 = GUICtrlCreateLabel('5', 0, 80, 200, 20, $BS_LEFT)
GUICtrlSetColor(-1, 0xCCCCCC)
GUISetState(@SW_HIDE, $GUI_WindowContext)
ApplyMica($GUI_WindowContext)

Global $GUI_Window1 = GUICreate('GUI 1', 200, 200, 100, 100, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_COMPOSITED)
GUISetBkColor(0x191919, $GUI_Window1)
Global $GUI_Window1_Button_1 = GUICtrlCreateButton('▼', 80, 90, 40, 20)
GUICtrlCreateContextWindow($GUI_Window1_Button_1, $GUI_Window1, 100, 'GUI1_1|GUI1_2|GUI1_3', 'Func1()|Func2()|Func3()')
GUICtrlCreateLabel('GUI 1', 10, 10, 200, 50)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
GUICtrlSetColor(-1, 0xCCCCCC)
GUICtrlSetStyle(-1, $GUI_DISABLE)
GUISetState(@SW_HIDE, $GUI_Window1)
ApplyMica($GUI_Window1)

Global $GUI_Window2 = GUICreate('GUI 2', 200, 200, 320, 100, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_COMPOSITED)
GUISetBkColor(0x191919, $GUI_Window2)
Global $GUI_Window2_Button_1 = GUICtrlCreateButton('▼', 80, 90, 40, 20)
GUICtrlCreateContextWindow($GUI_Window2_Button_1, $GUI_Window2, 200, 'GUI2_1|GUI2_2|GUI2_3|GUI2_4|GUI2_5', 'Func4()|Func5()|Func6()|Func7()|Func8()')
GUICtrlCreateLabel('GUI 2', 10, 10, 200, 50)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
GUICtrlSetColor(-1, 0xCCCCCC)
GUICtrlSetStyle(-1, $GUI_DISABLE)
GUISetState(@SW_HIDE, $GUI_Window2)
ApplyMica($GUI_Window2)

Sleep(1000)
GUISetState(@SW_SHOW, $GUI_Window1)
GUISetState(@SW_SHOW, $GUI_Window2)

Local $Msg
While 1
    $Msg = GUIGetMsg()
    Select
        Case $Msg = $GUI_WindowContext_Button_1 Or _
             $Msg = $GUI_WindowContext_Button_2 Or _
             $Msg = $GUI_WindowContext_Button_3 Or _
             $Msg = $GUI_WindowContext_Button_4 Or _
             $Msg = $GUI_WindowContext_Button_5
            ContextWindowHandler($Msg)
        Case $Msg = $GUI_Window1_Button_1
            ContextWindowCaller($Msg)
        Case $Msg = $GUI_Window2_Button_1
            ContextWindowCaller($Msg)
        Case $Msg = $GUI_EVENT_CLOSE
            Exit
    EndSelect

    If $PROGRAM_ContextWindowCheck Then ContextWindowCheck()
WEnd

Func ApplyMica($TempWindow)
    GUISetStyle($WS_CAPTION, -1, $TempWindow)
    DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $TempWindow, 'dword', 20, 'dword*', 1, 'dword', 4)
    DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $TempWindow, 'dword', 33, 'dword*', 1, 'dword', 4)
    DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $TempWindow, 'dword', 38, 'dword*', 4, 'dword', 4)
    _WinAPI_DwmExtendFrameIntoClientArea($TempWindow, _WinAPI_CreateMargins(-1, -1, -1, -1))
EndFunc

Func IsMouseInWnd($TempValue)
    Local $TempWinPos = WinGetPos($TempValue)
    Local $TempPos = MouseGetPos()
    If $TempPos[0] < $TempWinPos[0] Or $TempPos[0] > $TempWinPos[0] + $TempWinPos[2] Or $TempPos[1] < $TempWinPos[1] Or $TempPos[1] > $TempWinPos[1] + $TempWinPos[3] Then
        Return False
    Else
        Return True
    EndIf
EndFunc

Func GUICtrlCreateContextWindow($TempControlHandle, $TempParentHandle, $TempWidth = 200, $TempButtonName = '', $TempFunction = '') ;Initialize array
    If Not $TempWidth Or $TempWidth = Default Then $TempWidth = 200
    Local $TempArrayButtonName = StringSplit($TempButtonName, '|', $STR_NOCOUNT)
    Local $TempArrayFunction = StringSplit($TempFunction, '|', $STR_NOCOUNT)
    For $i = 0 To UBound($TempArrayButtonName) - 1
        _ArrayAdd($PROGRAM_WindowContextArray, $TempControlHandle & '|' & $TempParentHandle & '|' & $TempArrayButtonName[$i] & '|' & $TempArrayFunction[$i] & '|' & $TempWidth, 0, '|')
    Next
;~  _ArrayDisplay($PROGRAM_WindowContextArray)
EndFunc

Func ContextWindowCaller($TempHandle) ;Parent window making the call
    If $PROGRAM_ContextWindowCheck Then GUISetState(@SW_HIDE, $GUI_WindowContext)
    ;Now we look for which control called the window
    Local $TempIndex
    For $i = 0 To UBound($PROGRAM_WindowContextArray) - 1
        If $TempHandle = $PROGRAM_WindowContextArray[$i][0] Then ;Match found
            $TempIndex = $i
            ExitLoop
        EndIf
    Next

    ;Swap arrow if exists
    Local $TempRead = GUICtrlRead($PROGRAM_WindowContextArray[$TempIndex][0])
    If StringInStr($TempRead, '▼') Then
        Local $TempNewName = StringReplace($TempRead, '▼', '▲')
        GUICtrlSetData($PROGRAM_WindowContextArray[$TempIndex][0], $TempNewName)
    EndIf

    ;Populate buttons
    Local $j = 0
    For $i = $TempIndex To UBound($PROGRAM_WindowContextArray) - 1
        If $PROGRAM_WindowContextArray[$i][0] = $TempHandle Then
            $j += 1
            ;I don't know why but the label positioning doesn't work properly in this script, in my own I use GUIFlatButton UDF which works as expected. And once window is resized the unneeded buttons are simply cut off.
            ;In this example I've changed these buttons to labels so to not include another UDF.
            ;Anyway, that's not the point.
            GUICtrlSetData(Eval('GUI_WindowContext_Button_' & $j), $PROGRAM_WindowContextArray[$i][2])
            GUICtrlSetPos(Eval('GUI_WindowContext_Button_' & $j), 0, ($j * 20) - 20, $PROGRAM_WindowContextArray[$i][4])
        ElseIf $j >= 1 And $PROGRAM_WindowContextArray[$i][0] <> $TempHandle Then
            ExitLoop
        EndIf
    Next

    ;Get position and show + activate
    Local $TempPosWin = WinGetPos(HWnd($PROGRAM_WindowContextArray[$TempIndex][1]))
    Local $TempPos = ControlGetPos(HWnd($PROGRAM_WindowContextArray[$TempIndex][1]), '', $TempHandle)
    WinMove($GUI_WindowContext, '', $TempPosWin[0] + $TempPos[0], $TempPosWin[1] + $TempPos[1] + $TempPos[3], $PROGRAM_WindowContextArray[$TempIndex][4], $j * 20) ;With resizing
;~  WinMove($GUI_WindowContext, '', $TempPosWin[0] + $TempPos[0], $TempPosWin[1] + $TempPos[1] + $TempPos[3]) ;No resizing

    GUISetState(@SW_SHOWNORMAL, $GUI_WindowContext)
;~  ApplyMica($GUI_WindowContext)
    $PROGRAM_ContextWindowCheck = $PROGRAM_WindowContextArray[$TempIndex][0]
EndFunc

Func ContextWindowCheck() ;Check if click is outside of window when active
    If _IsPressed($VK_LBUTTON, 'user32.dll') And IsMouseInWnd($GUI_WindowContext) = False Then
        GUISetState(@SW_HIDE, $GUI_WindowContext)

        ;Reset original arrow for button if present
        Local $TempRead = GUICtrlRead($PROGRAM_ContextWindowCheck)
        If StringInStr($TempRead, '▲') Then
            Local $TempNewName = StringReplace($TempRead, '▲', '▼')
            GUICtrlSetData($PROGRAM_ContextWindowCheck, $TempNewName)
        EndIf
        $PROGRAM_ContextWindowCheck = False
    EndIf
EndFunc

Func ContextWindowHandler($TempIndex) ;Context button click
    Local $TempMenuRead = GUICtrlRead($TempIndex)
    For $i = 0 To UBound($PROGRAM_WindowContextArray) - 1
        If $PROGRAM_WindowContextArray[$i][2] = $TempMenuRead Then
            Local $TempRead = GUICtrlRead($PROGRAM_WindowContextArray[$i][0])
            If StringInStr($TempRead, '▲') Then
                Local $TempNewName = StringReplace($TempRead, '▲', '▼')
                GUICtrlSetData($PROGRAM_WindowContextArray[$i][0], $TempNewName)
            EndIf
            $PROGRAM_ContextWindowCheck = False
            GUISetState(@SW_HIDE, $GUI_WindowContext)
            ConsoleWrite($PROGRAM_WindowContextArray[$i][2] & ' - ' & $PROGRAM_WindowContextArray[$i][3] & @CRLF)
;~          Execute($PROGRAM_WindowContextArray[$i][3])
            ExitLoop
        EndIf
    Next
EndFunc

 

Posted

@NMS Try this:

Spoiler
#include <WindowsStylesConstants.au3>
#include <GUIConstantsEx.au3>
#include <WinAPIGdi.au3>
#include <ButtonConstants.au3>
#include <Array.au3>
#include <Misc.au3>
#include <WinAPIMisc.au3>
#include <WinAPISysWin.au3>

Global $PROGRAM_WindowContextArray[0][5]
Global $PROGRAM_ContextWindowCheck

Global $GUI_WindowContext = GUICreate('GUI Context', 200, 100, -1, -1, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_TOPMOST)
GUISetBkColor(0x191919, $GUI_WindowContext)
Global $GUI_WindowContext_Button_1 = GUICtrlCreateLabel('1', 0, 0, 200, 20, $BS_LEFT)
GUICtrlSetColor(-1, 0xCCCCCC)
Global $GUI_WindowContext_Button_2 = GUICtrlCreateLabel('2', 0, 20, 200, 20, $BS_LEFT)
GUICtrlSetColor(-1, 0xCCCCCC)
Global $GUI_WindowContext_Button_3 = GUICtrlCreateLabel('3', 0, 40, 200, 20, $BS_LEFT)
GUICtrlSetColor(-1, 0xCCCCCC)
Global $GUI_WindowContext_Button_4 = GUICtrlCreateLabel('4', 0, 60, 200, 20, $BS_LEFT)
GUICtrlSetColor(-1, 0xCCCCCC)
Global $GUI_WindowContext_Button_5 = GUICtrlCreateLabel('5', 0, 80, 200, 20, $BS_LEFT)
GUICtrlSetColor(-1, 0xCCCCCC)
GUISetState(@SW_HIDE, $GUI_WindowContext)
ApplyMica($GUI_WindowContext)

Global $GUI_Window1 = GUICreate('GUI 1', 200, 200, 100, 100, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_COMPOSITED)
GUISetBkColor(0x191919, $GUI_Window1)
Global $GUI_Window1_Button_1 = GUICtrlCreateButton('▼', 80, 90, 40, 20)
GUICtrlCreateContextWindow($GUI_Window1_Button_1, $GUI_Window1, 100, 'GUI1_1|GUI1_2|GUI1_3', 'Func1()|Func2()|Func3()')
GUICtrlCreateLabel('GUI 1', 10, 10, 200, 50)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
GUICtrlSetColor(-1, 0xCCCCCC)
GUICtrlSetStyle(-1, $GUI_DISABLE)
GUISetState(@SW_HIDE, $GUI_Window1)
ApplyMica($GUI_Window1)

Global $GUI_Window2 = GUICreate('GUI 2', 200, 200, 320, 100, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_COMPOSITED)
GUISetBkColor(0x191919, $GUI_Window2)
Global $GUI_Window2_Button_1 = GUICtrlCreateButton('▼', 80, 90, 40, 20)
GUICtrlCreateContextWindow($GUI_Window2_Button_1, $GUI_Window2, 200, 'GUI2_1|GUI2_2|GUI2_3|GUI2_4|GUI2_5', 'Func4()|Func5()|Func6()|Func7()|Func8()')
GUICtrlCreateLabel('GUI 2', 10, 10, 200, 50)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
GUICtrlSetColor(-1, 0xCCCCCC)
GUICtrlSetStyle(-1, $GUI_DISABLE)
GUISetState(@SW_HIDE, $GUI_Window2)
ApplyMica($GUI_Window2)

Sleep(1000)
GUISetState(@SW_SHOW, $GUI_Window1)
GUISetState(@SW_SHOW, $GUI_Window2)

Local $Msg
While 1
    $Msg = GUIGetMsg()
    Select
        Case $Msg = $GUI_WindowContext_Button_1 Or _
             $Msg = $GUI_WindowContext_Button_2 Or _
             $Msg = $GUI_WindowContext_Button_3 Or _
             $Msg = $GUI_WindowContext_Button_4 Or _
             $Msg = $GUI_WindowContext_Button_5
            ContextWindowHandler($Msg)
        Case $Msg = $GUI_Window1_Button_1
            ContextWindowCaller($Msg)
        Case $Msg = $GUI_Window2_Button_1
            ContextWindowCaller($Msg)
        Case $Msg = $GUI_EVENT_CLOSE
            Exit
    EndSelect

    If $PROGRAM_ContextWindowCheck Then ContextWindowCheck()
WEnd

Func ApplyMica($TempWindow)
    GUISetStyle($WS_CAPTION, -1, $TempWindow)
    DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $TempWindow, 'dword', 20, 'dword*', 1, 'dword', 4)
    DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $TempWindow, 'dword', 33, 'dword*', 1, 'dword', 4)
    DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $TempWindow, 'dword', 38, 'dword*', 4, 'dword', 4)
    _WinAPI_DwmExtendFrameIntoClientArea($TempWindow, _WinAPI_CreateMargins(-1, -1, -1, -1))
EndFunc

Func IsMouseInWnd($TempValue)
    Local $TempWinPos = WinGetPos($TempValue)
    Local $TempPos = MouseGetPos()
    If $TempPos[0] < $TempWinPos[0] Or $TempPos[0] > $TempWinPos[0] + $TempWinPos[2] Or $TempPos[1] < $TempWinPos[1] Or $TempPos[1] > $TempWinPos[1] + $TempWinPos[3] Then
        Return False
    Else
        Return True
    EndIf
EndFunc

Func GUICtrlCreateContextWindow($TempControlHandle, $TempParentHandle, $TempWidth = 200, $TempButtonName = '', $TempFunction = '') ;Initialize array
    If Not $TempWidth Or $TempWidth = Default Then $TempWidth = 200
    Local $TempArrayButtonName = StringSplit($TempButtonName, '|', $STR_NOCOUNT)
    Local $TempArrayFunction = StringSplit($TempFunction, '|', $STR_NOCOUNT)
    For $i = 0 To UBound($TempArrayButtonName) - 1
        _ArrayAdd($PROGRAM_WindowContextArray, $TempControlHandle & '|' & $TempParentHandle & '|' & $TempArrayButtonName[$i] & '|' & $TempArrayFunction[$i] & '|' & $TempWidth, 0, '|')
    Next
;~  _ArrayDisplay($PROGRAM_WindowContextArray)
EndFunc

Func ContextWindowCaller($TempHandle) ;Parent window making the call
    If $PROGRAM_ContextWindowCheck Then GUISetState(@SW_HIDE, $GUI_WindowContext)
    ;Now we look for which control called the window
    Local $TempIndex
    For $i = 0 To UBound($PROGRAM_WindowContextArray) - 1
        If $TempHandle = $PROGRAM_WindowContextArray[$i][0] Then ;Match found
            $TempIndex = $i
            ExitLoop
        EndIf
    Next

    ;Swap arrow if exists
    Local $TempRead = GUICtrlRead($PROGRAM_WindowContextArray[$TempIndex][0])
    If StringInStr($TempRead, '▼') Then
        Local $TempNewName = StringReplace($TempRead, '▼', '▲')
        GUICtrlSetData($PROGRAM_WindowContextArray[$TempIndex][0], $TempNewName)
    EndIf

    ;Populate buttons
    Local $j = 0
    For $i = $TempIndex To UBound($PROGRAM_WindowContextArray) - 1
        If $PROGRAM_WindowContextArray[$i][0] = $TempHandle Then
            $j += 1
            ;I don't know why but the label positioning doesn't work properly in this script, in my own I use GUIFlatButton UDF which works as expected. And once window is resized the unneeded buttons are simply cut off.
            ;In this example I've changed these buttons to labels so to not include another UDF.
            ;Anyway, that's not the point.
            GUICtrlSetData(Eval('GUI_WindowContext_Button_' & $j), $PROGRAM_WindowContextArray[$i][2])
            GUICtrlSetPos(Eval('GUI_WindowContext_Button_' & $j), 0, ($j * 20) - 20, $PROGRAM_WindowContextArray[$i][4])
        ElseIf $j >= 1 And $PROGRAM_WindowContextArray[$i][0] <> $TempHandle Then
            ExitLoop
        EndIf
    Next

    ;Get position and show + activate
    Local $TempPosWin = WinGetPos(HWnd($PROGRAM_WindowContextArray[$TempIndex][1]))
    Local $TempPos = ControlGetPos(HWnd($PROGRAM_WindowContextArray[$TempIndex][1]), '', $TempHandle)
    WinMove($GUI_WindowContext, '', $TempPosWin[0] + $TempPos[0], $TempPosWin[1] + $TempPos[1] + $TempPos[3], $PROGRAM_WindowContextArray[$TempIndex][4], $j * 20) ;With resizing
;   WinMove($GUI_WindowContext, '', $TempPosWin[0] + $TempPos[0], $TempPosWin[1] + $TempPos[1] + $TempPos[3]) ;No resizing

    GUISetState(@SW_SHOWNORMAL, $GUI_WindowContext)

    ; re-apply Mica since it is lost
    ApplyMica($GUI_WindowContext)

    ; removing $WS_CAPTION
    __WinAPI_Set_Window_Style($GUI_WindowContext, $WS_CAPTION, False, False)

    $PROGRAM_ContextWindowCheck = $PROGRAM_WindowContextArray[$TempIndex][0]
EndFunc

Func ContextWindowCheck() ;Check if click is outside of window when active
    If _IsPressed($VK_LBUTTON, 'user32.dll') And IsMouseInWnd($GUI_WindowContext) = False Then
        GUISetState(@SW_HIDE, $GUI_WindowContext)

        ;Reset original arrow for button if present
        Local $TempRead = GUICtrlRead($PROGRAM_ContextWindowCheck)
        If StringInStr($TempRead, '▲') Then
            Local $TempNewName = StringReplace($TempRead, '▲', '▼')
            GUICtrlSetData($PROGRAM_ContextWindowCheck, $TempNewName)
        EndIf
        $PROGRAM_ContextWindowCheck = False
    EndIf
EndFunc

Func ContextWindowHandler($TempIndex) ;Context button click
    Local $TempMenuRead = GUICtrlRead($TempIndex)
    For $i = 0 To UBound($PROGRAM_WindowContextArray) - 1
        If $PROGRAM_WindowContextArray[$i][2] = $TempMenuRead Then
            Local $TempRead = GUICtrlRead($PROGRAM_WindowContextArray[$i][0])
            If StringInStr($TempRead, '▲') Then
                Local $TempNewName = StringReplace($TempRead, '▲', '▼')
                GUICtrlSetData($PROGRAM_WindowContextArray[$i][0], $TempNewName)
            EndIf
            $PROGRAM_ContextWindowCheck = False
            GUISetState(@SW_HIDE, $GUI_WindowContext)
            ConsoleWrite($PROGRAM_WindowContextArray[$i][2] & ' - ' & $PROGRAM_WindowContextArray[$i][3] & @CRLF)
;~          Execute($PROGRAM_WindowContextArray[$i][3])
            ExitLoop
        EndIf
    Next
EndFunc

;===========================================
Func __WinAPI_Set_Window_Style($hWnd, $i_Style, $b_Add, $b_exStyle = False) ; compacted code (from Kafu's original)

    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
    Local $iIndex = $b_exStyle ? $GWL_EXSTYLE : $GWL_STYLE ; $iIndex as named by msdn & help file
    Local $i_Style_Old = _WinAPI_GetWindowLong($hWnd, $iIndex)

    If $b_Add Then
        If BitAND($i_Style_Old, $i_Style) Then Return ; style already applied
        _WinAPI_SetWindowLong($hWnd, $iIndex, BitOR($i_Style_Old, $i_Style))
    Else ; remove
        If Not BitAND($i_Style_Old, $i_Style) Then Return ; style not set
        _WinAPI_SetWindowLong($hWnd, $iIndex, BitXOR($i_Style_Old, $i_Style))
    EndIf

    Local $iRet = _WinAPI_SetWindowPos($hWnd, $HWND_TOP, 0, 0, 0, 0, BitOR($SWP_FRAMECHANGED, $SWP_NOACTIVATE, $SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOZORDER)) ; +++
    If Not $iRet Then MsgBox($MB_TOPMOST, "_WinAPI_SetWindowPos", "Error = " & _WinAPI_GetLastError() & "   Message = " & _WinAPI_GetLastErrorMessage())

EndFunc   ;==>__WinAPI_Set_Window_Style

 

 

Posted (edited)

@WildByDesign yes that worked for the most part. I'll figure out the border style myself.

What I don't understand is why it didn't work when I used GUISetStyle() instead of _WinAPI_SetWindowLong(). Or I must've missed something.

Well thank you so much!

Edit: The difference is showing the window first and then applying the style...

Edited by NMS
Posted (edited)
6 hours ago, NMS said:

Well thank you so much!

Edit: The difference is showing the window first and then applying the style...

You're welcome. I'm glad it's working.

You can apply the mica first before showing the window. But the removal of the caption seems to have to be after showing the window.

; re-apply Mica since it is lost
    ApplyMica($GUI_WindowContext)

    GUISetState(@SW_SHOWNORMAL, $GUI_WindowContext)

    ; removing $WS_CAPTION
    __WinAPI_Set_Window_Style($GUI_WindowContext, $WS_CAPTION, False, False)

This above also works. It might actually be better to prevent any possibility of flicker with the GUI context menu.

Edited by WildByDesign

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...