Jump to content

Recommended Posts

Posted

Hi,

I would like to invert the colors of a window. Basically I want 'light theme' some dark programs because dark theme hurts my eyes.

I know windows magnifier can do this, I started with this but I can't figure it out.

Posted (edited)

I found an autohotkey script which does exactly what I want with all the dll calls. It would be nice to 'convert' it to autoit.

Edited by kisstom
Posted
Posted (edited)

You can play around with this...

#include <WinAPI.au3>

Run("Calc")
Sleep(1000)

$Pos = WinGetPos("Calculator")
$DDC = _WinAPI_GetDC(0)
       _WinAPI_BitBlt($DDC, $Pos[0], $Pos[1], $Pos[2], $Pos[3], $DDC, $Pos[0], $Pos[1], 0x00550009); (0x00550009 = $DSTINVERT)
Exit

...you would likely want a backbuffer.

Edited by Werty

Some guy's script + some other guy's script = my script!

Posted
7 hours ago, kisstom said:

I need to invert a region

Then you will need to use the following (see UDF examples) :

_MagnifierGUICreate ; to create a region at a specified location
_MagnifierSetSource ; to set the magnify where you want it to look
_MagnifierSetColorEffect ; to change the colors

Try putting some code up, and we will help if you struggle somewhere...

Posted

OK, thanks. Seems I now getting somewhere :)

I do GUI update in the while loop. The problem is it's sometimes (but not always) always on top (I can't move another window on top).

#include "WinMagnifier.au3"
#include <WinAPIGdi.au3>

HotKeySet("{ESC}", "Quit")

Run("Calc")
Sleep(1000)
$Pos = WinGetPos("Calculator")

_MagnifierInit()

$aTmp = _MagnifierGUICreate($Pos[2], $Pos[3], $Pos[0], $Pos[1], False, False)
$hMagnifyGUI = $aTmp[0]
$hMagnifyCtrl = $aTmp[1]

; -- SET SOURCE (on screen) --
_MagnifierSetSource($hMagnifyCtrl, $Pos[0], $Pos[1], $Pos[2], $Pos[3])

;show gui and set always on top
GUISetState(@SW_SHOW, $hMagnifyGUI)
WinSetOnTop($hMagnifyGUI,"" , 1)

; Inverted Colors
Dim $aColorFX[5][5] = [ _
    [-1.0,   0,    0,   0,   0], _
    [  0, -1.0,    0,   0,   0], _
    [  0,    0, -1.0,   0,   0], _
    [  0,    0,    0, 1.0,   0], _
    [1.0,  1.0,  1.0,   0, 1.0] ]
_MagnifierSetColorEffect($hMagnifyCtrl, $aColorFX)

While 1
    ;ToolTip (WinGetTitle("[active]"))
    ;update the gui
    If WinActive ("Calculator" ) Then
        _MagnifierSetSource($hMagnifyCtrl, $Pos[0], $Pos[1], $Pos[2], $Pos[3])
        GUISetState(@SW_SHOW, $hMagnifyGUI)
        WinSetOnTop($hMagnifyGUI,"" , $WINDOWS_ONTOP)
    ;   ToolTip ("active")
    Else
        WinSetOnTop($hMagnifyGUI,"" ,  $WINDOWS_NOONTOP)
    ;   ToolTip ("NOT active")
    EndIf
    Sleep (10)
WEnd

Func Quit()
    ; -- CLEAR COLOR EFFECTS --
    _MagnifierClearColorEffects($hMagnifyCtrl)
    GUIDelete($hMagnifyGUI)
    Exit
EndFunc

 

Posted (edited)

Well done.  Here my take on it, seems to be working fine on my end :

#include "WinMagnifier.au3"

_MagnifierInit()
Run("Calc")
Sleep(500)
Local $hWnd = WinGetHandle("Calculatrice"), $aPos[4]
WinGetPosEx($hWnd, $aPos)

Local $aHndl = _MagnifierGUICreate($aPos[2], $aPos[3], $aPos[0], $aPos[1]), $hMagnifyGUI = $aHndl[0], $hMagnifyCtrl = $aHndl[1]

GUISetState(@SW_SHOWNOACTIVATE, $hMagnifyGUI)
WinSetOnTop($hMagnifyGUI, "", $WINDOWS_ONTOP)
;_MagnifierSetScale($hMagnifyCtrl, 1.0)

_MagnifierSetSource($hMagnifyCtrl, $aPos[0], $aPos[1], $aPos[2], $aPos[3])

; create the matrix of your choice
Local $aColorFX[5][5] = [ _
        [-1.0,   0,    0,   0,   0], _
        [  0, -1.0,    0,   0,   0], _
        [  0,    0, -1.0,   0,   0], _
        [  0,    0,    0, 1.0,   0], _
        [1.0,  1.0,  1.0,   0, 1.0] ]
_MagnifierSetColorEffect($hMagnifyCtrl, $aColorFX)

While WinExists($hWnd)
  Sleep(10)
  If WinActive($hWnd) Then
    WinSetOnTop($hMagnifyGUI, "", $WINDOWS_ONTOP)
    _WinAPI_RedrawWindow($hMagnifyCtrl)
  Else
    WinSetOnTop($hMagnifyGUI,"" ,  $WINDOWS_NOONTOP)
  EndIf
WEnd

_WinAPI_DestroyWindow($hMagnifyCtrl)
GUIDelete($hMagnifyGUI)

Func WinGetPosEx($hWnd, ByRef $aPos)
  Local $aTmp = WinGetPos($hWnd)
  If @error Then Return
  $aPos = $aTmp

  ; adjust magnifier to the edge of the window
  $aPos[0] += 8
  $aPos[1] += 1
  $aPos[2] -= 16
  $aPos[3] -= 9
EndFunc

 

Edited by Nine
Posted

Thanks. It does the same 'sometimes always on top' behavior, but I managed to narrow the issue down:

If I press a button on the calculator then click on another window and drag over it's behind the calculator. If I first click on the title bar (or try icon) of another window then click again and drag over it's OK.

Can you please test it?

Posted

The issue mentioned above is still exists but I extended the program, now it can invert any active window with F1.

Next step is to check if the window moved/resized. As far as I see the inverted window can't be moved/resized (and not shows up in Autoit Window Info), do I have to erase/recreate if the original window moved/resized?

 

#include "WinMagnifier.au3"
#include <WinAPIGdi.au3>

HotKeySet("{ESC}", "Quit")
HotKeySet("{F1}", "Invert_Window")

While 1
    Sleep (10)
WEnd

Func Invert_Window()
$hWindow = WinGetTitle("[active]")
$aPos = WinGetPos($hWindow)
; adjust magnifier to the edge of the window
$aPos[0] += 8
$aPos[1] += 1
$aPos[2] -= 16
$aPos[3] -= 9

_MagnifierInit()

$aTmp = _MagnifierGUICreate($aPos[2], $aPos[3], $aPos[0], $aPos[1], False, False)
$hMagnifyGUI = $aTmp[0]
$hMagnifyCtrl = $aTmp[1]

; -- SET SOURCE (on screen) --
_MagnifierSetSource($hMagnifyCtrl, $aPos[0], $aPos[1], $aPos[2], $aPos[3])

;show gui and set always on top
GUISetState(@SW_SHOW, $hMagnifyGUI)
WinActivate($hWindow)
WinSetOnTop($hMagnifyGUI,"" , 1)

; Inverted Colors
Dim $aColorFX[5][5] = [ _
    [-1.0,   0,    0,   0,   0], _
    [  0, -1.0,    0,   0,   0], _
    [  0,    0, -1.0,   0,   0], _
    [  0,    0,    0, 1.0,   0], _
    [1.0,  1.0,  1.0,   0, 1.0] ]
_MagnifierSetColorEffect($hMagnifyCtrl, $aColorFX)

While WinExists($hWindow)
    ;update the gui
    If WinActive ($hWindow) Then
        ;
        ;check if the window moved/resized here
        ;
        _MagnifierSetSource($hMagnifyCtrl, $aPos[0], $aPos[1], $aPos[2], $aPos[3])
        ;GUISetState(@SW_SHOW, $hMagnifyGUI)
        WinSetOnTop($hMagnifyGUI,"" , $WINDOWS_ONTOP)
        _WinAPI_RedrawWindow($hMagnifyCtrl)
        ;ToolTip ("active")
    Else
        WinSetOnTop($hMagnifyGUI,"" ,  $WINDOWS_NOONTOP)
        _WinAPI_RedrawWindow($hMagnifyCtrl)
        ;ToolTip ("NOT active")
    EndIf
    Sleep (10)
WEnd

; -- CLEAR COLOR EFFECTS --
_MagnifierClearColorEffects($hMagnifyCtrl)
GUIDelete($hMagnifyGUI)
Exit
EndFunc

Func Quit()
    Exit
EndFunc

 

Posted
; Inverted Colors
Dim $aColorFX[5][5] = [ _
    [-1.0,   0,    0,   0,   0], _
    [  0, -1.0,    0,   0,   0], _
    [  0,    0, -1.0,   0,   0], _
    [  0,    0,    0, 1.0,   0], _
    [1.0,  1.0,  1.0,   0, 1.0] ]
_MagnifierSetColorEffect($hMagnifyCtrl, $aColorFX)

You dont need the $aColors matrix, it's already defined as a constant in the WinMagnifier.au3 udf.

; Inverted Colors
_MagnifierSetColorEffect($hMagnifyCtrl, $COLOR_EFFECTS_INVERSION_MATRIX)

 

Some guy's script + some other guy's script = my script!

Posted (edited)

Here my take on it, working great on my side, I can move/minimize/resize/maximize :

#include <WindowsConstants.au3>
#include "WinMagnifier.au3"

_MagnifierInit()
Run("Notepad")
Sleep(100)
Local $hWnd = WinGetHandle("[CLASS:Notepad]"), $aPos[4], $aPosTmp[4]
WinGetPosEx($hWnd, $aPos)

Local $aHndl = _MagnifierGUICreate($aPos[2], $aPos[3], $aPos[0], $aPos[1]), $hMagnifyGUI = $aHndl[0], $hMagnifyCtrl = $aHndl[1]

GUISetState(@SW_SHOWNOACTIVATE, $hMagnifyGUI)

_MagnifierSetSource($hMagnifyCtrl, $aPos[0], $aPos[1], $aPos[2], $aPos[3])
_MagnifierSetColorEffect($hMagnifyCtrl, $COLOR_EFFECTS_INVERSION_MATRIX)

While WinExists($hWnd)
  Sleep(10)
  If WinActive($hWnd) Or _WinAPI_GetParent(WinGetHandle("[ACTIVE]")) = $hWnd Then
    If Not BitAND(WinGetState($hMagnifyGUI), $WIN_STATE_VISIBLE) Then GUISetState(@SW_SHOWNOACTIVATE, $hMagnifyGUI)
    WinGetPosEx($hWnd, $aPosTmp)
    If $aPos[0] <> $aPosTmp[0] Or $aPos[1] <> $aPosTmp[1] Or $aPos[2] <> $aPosTmp[2] Or $aPos[3] <> $aPosTmp[3] Then
      $aPos = $aPosTmp
      WinMove($hMagnifyGUI, "", $aPos[0], $aPos[1], $aPos[2], $aPos[3])
      _WinAPI_MoveWindow($hMagnifyCtrl, 0, 0, $aPos[2], $aPos[3], False)
      _MagnifierSetSource($hMagnifyCtrl, $aPos[0], $aPos[1], $aPos[2], $aPos[3])
    EndIf
    WinSetOnTop($hMagnifyGUI, "", $WINDOWS_ONTOP)
    _WinAPI_RedrawWindow($hMagnifyCtrl)
  ElseIf Not BitAND(WinGetState($hWnd), $WIN_STATE_MINIMIZED) Then
    WinSetOnTop($hMagnifyGUI,"" ,  $WINDOWS_NOONTOP)
  ElseIf BitAND(WinGetState($hMagnifyGUI), $WIN_STATE_VISIBLE) Then
    GUISetState(@SW_HIDE, $hMagnifyGUI)
  EndIf
WEnd

_WinAPI_DestroyWindow($hMagnifyCtrl)
GUIDelete($hMagnifyGUI)

Func WinGetPosEx($hWnd, ByRef $aPos)
  Local $aTmp = WinGetPos($hWnd)
  If @error Then Return
  $aPos = $aTmp

  ; adjust magnifier to the edge of the window
  $aPos[0] += 8
  $aPos[1] += 1
  $aPos[2] -= 16
  $aPos[3] -= 9
EndFunc

As per your issue, I would need a more detailed explanation in order for me to replicate it.

ps.  thanks @Werty, I must have slept when reading that part...

Edited by Nine
Posted (edited)

@kisstom  Just saw that.  Let me check if can reproduce it.

10 hours ago, kisstom said:

If I press a button on the calculator then click on another window and drag over it's behind the calculator. If I first click on the title bar (or try icon) of another window then click again and drag over it's OK.

edit : I was able to replicate your issue.  When I give focus to the magnified window, and then go directly to another window and drag it without giving it the focus first, it won't go over the magnifier.  It seems the topmost is interfering...I need to look at it

Edited by Nine
  • Solution
Posted

Could you try this one, I think I have found a better way to remove topmost to the magnifier in a more efficient way :

#include <WindowsConstants.au3>
#include "WinMagnifier.au3"

_MagnifierInit()
Run("Notepad")
Sleep(100)
Local $hWnd = WinGetHandle("[CLASS:Notepad]"), $aPos[4], $aPosTmp[4]
WinGetPosEx($hWnd, $aPos)

Local $aHndl = _MagnifierGUICreate($aPos[2], $aPos[3], $aPos[0], $aPos[1]), $hMagnifyGUI = $aHndl[0], $hMagnifyCtrl = $aHndl[1]

GUISetState(@SW_SHOWNOACTIVATE, $hMagnifyGUI)

_MagnifierSetSource($hMagnifyCtrl, $aPos[0], $aPos[1], $aPos[2], $aPos[3])
_MagnifierSetColorEffect($hMagnifyCtrl, $COLOR_EFFECTS_INVERSION_MATRIX)

While WinExists($hWnd)
  Sleep(10)
  If WinActive($hWnd) Or _WinAPI_GetParent(WinGetHandle("[ACTIVE]")) = $hWnd Then
    If Not BitAND(WinGetState($hMagnifyGUI), $WIN_STATE_VISIBLE) Then GUISetState(@SW_SHOWNOACTIVATE, $hMagnifyGUI)
    WinGetPosEx($hWnd, $aPosTmp)
    If $aPos[0] <> $aPosTmp[0] Or $aPos[1] <> $aPosTmp[1] Or $aPos[2] <> $aPosTmp[2] Or $aPos[3] <> $aPosTmp[3] Then
      $aPos = $aPosTmp
      WinMove($hMagnifyGUI, "", $aPos[0], $aPos[1], $aPos[2], $aPos[3])
      _WinAPI_MoveWindow($hMagnifyCtrl, 0, 0, $aPos[2], $aPos[3], False)
      _MagnifierSetSource($hMagnifyCtrl, $aPos[0], $aPos[1], $aPos[2], $aPos[3])
    EndIf
    WinSetOnTop($hMagnifyGUI, "", $WINDOWS_ONTOP)
    _WinAPI_RedrawWindow($hMagnifyCtrl)
  ElseIf Not BitAND(WinGetState($hWnd), $WIN_STATE_MINIMIZED) Then
    If BitAND(_WinAPI_GetWindowLong($hMagnifyGUI, $GWL_EXSTYLE), $WS_EX_TOPMOST) Then
      _WinAPI_SetWindowPos($hMagnifyGUI, WinGetHandle("[ACTIVE]"), 0, 0, 0, 0, $SWP_NOMOVE + $SWP_NOSIZE + $SWP_SHOWWINDOW)
    EndIf
  ElseIf BitAND(WinGetState($hMagnifyGUI), $WIN_STATE_VISIBLE) Then
    GUISetState(@SW_HIDE, $hMagnifyGUI)
  EndIf
WEnd

_WinAPI_DestroyWindow($hMagnifyCtrl)
GUIDelete($hMagnifyGUI)

Func WinGetPosEx($hWnd, ByRef $aPos)
  Local $aTmp = WinGetPos($hWnd)
  If @error Then Return
  $aPos = $aTmp

  ; adjust magnifier to the edge of the window
  $aPos[0] += 8
  $aPos[1] += 1
  $aPos[2] -= 16
  $aPos[3] -= 9
EndFunc

 

Posted (edited)

@Nine as an idea

putting an additional parameter in WinMagnifier.au3 in the function
Func _MagnifierGUICreate($nWidth, $nHeight, $iX1, $iY1, $bInvertColors = False, $bShowCursor = False, $hParent = 0 )
and filling in the following
$hMagnifyGUI = GUICreate("", $nWidth, $nHeight, $iX1, $iY1, 0x80000000, BitOR(0x08000000, 0x080000, 0x80, 0x20), $hParent)

that simplifies things ?
 

#include <WindowsConstants.au3>
#include "WinMagnifier.au3"

_MagnifierInit()
Run("Notepad")
Sleep(100)
Local $hWnd = WinGetHandle("[CLASS:Notepad]"), $aPos[4], $aPosTmp[4]
Local $hDesktop = WinGetHandle("[CLASS:Progman]")
WinGetPosEx($hDesktop, $aPos)

Local $aHndl = _MagnifierGUICreate($aPos[2], $aPos[3], $aPos[0], $aPos[1], True, False, $hWnd)
Local $hMagnifyGUI = $aHndl[0], $hMagnifyCtrl = $aHndl[1]

_MagnifierSetSource($hMagnifyCtrl, $aPos[0], $aPos[1], $aPos[2], $aPos[3])
GUISetState(@SW_SHOWNOACTIVATE, $hMagnifyGUI)

While WinExists($hWnd)

    If WinActive($hWnd) Then
        WinGetPosEx($hWnd, $aPosTmp)
        If $aPos[0] <> $aPosTmp[0] Or $aPos[1] <> $aPosTmp[1] Or $aPos[2] <> $aPosTmp[2] Or $aPos[3] <> $aPosTmp[3] Then
            $aPos = $aPosTmp
            WinMove($hMagnifyGUI, "", $aPos[0], $aPos[1], $aPos[2], $aPos[3])
            _MagnifierSetSource($hMagnifyCtrl, $aPos[0], $aPos[1], $aPos[2], $aPos[3])
        EndIf
        _WinAPI_RedrawWindow($hMagnifyCtrl)
        Sleep(10)
    Else
        Sleep(300)
    EndIf

WEnd

_WinAPI_DestroyWindow($hMagnifyCtrl)
GUIDelete($hMagnifyGUI)

Func WinGetPosEx($hWnd, ByRef $aPos)
    Local $aTmp = WinGetPos($hWnd)
    If @error Then Return
    $aPos = $aTmp

    ; adjust magnifier to the edge of the window
    $aPos[0] += 8
    $aPos[1] += 1
    $aPos[2] -= 16
    $aPos[3] -= 9
EndFunc   ;==>WinGetPosEx

Edit:
after the observation made below by the @Nine 
Maximize does not produce proper result, same goes with resizing larger than initial display.
I added the initialization in start
Local $hDesktop = WinGetHandle("[CLASS:Progman]")
WinGetPosEx($hDesktop, $aPos)
as a temporary solution

Edited by ioa747

I know that I know nothing

Posted (edited)

@ioa747  I thought about it but, to be honest, never tried it seriously.  Using your code (with modification to the UDF) solves the issue mentioned before, but created (in my perspective) larger problems.  Invert the colors, you will see that submenus and popup windows do not display correctly.  Maximize does not produce proper result, same goes with resizing larger than initial display.  I stopped testing at this point.

I have invested enough of my time on my proposal, sorry to say, I will not try to solve the problems of yours. ;)

Thanks for sharing.

PS.  I need a good night sleep, maybe tomorrow I will be more likely to further analyse your solution...

Edited by Nine
Posted (edited)

Thanks Nine, it seem OK now. The only thing is the title bar remains in active color when it's in the background so I just removed from the inverted area for now.

Edited by kisstom
Posted
2 hours ago, kisstom said:

The only thing is the title bar remains in active color when it's in the background

Any non-covered region of the window will stay inverted when the window is in the background.  That's totally normal with the code I wrote.

Posted

I mean in my setup the active title bar is blue, the inactive is grey (not the default OS setting) and it remains in active color in background. Maybe I tinker with it in the future. Thanks again.

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