Tray app to change power plans

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
kiwichick
Posts: 166
Joined: 21 Jan 2014, 22:03

Tray app to change power plans

Post by kiwichick » 16 May 2024, 17:11

I know I'm probably missing something rather obvious (or maybe it actually isn't possible) but how do I create a script that will sit in the system tray and do nothing until I click it and then it just gives me a menu with some options to choose from? I want to create a script that will allow me to change power plans by clicking the tray icon and selecting a new plan.

User avatar
mikeyww
Posts: 27351
Joined: 09 Sep 2014, 18:38

Re: Tray app to change power plans

Post by mikeyww » 16 May 2024, 19:11

Code: Select all

#Requires AutoHotkey v2.0
Persistent
tray := A_TrayMenu
tray.Add 'Power', (itemName, itemPos, m) => power.Show()
tray.Default    := 'Power'
tray.ClickCount := 1
power := Menu()
power.Add 'High'    , powerSelect
power.Add 'Balanced', powerSelect
power.Add 'Low'     , powerSelect

powerSelect(itemName, itemPos, m) {
 MsgBox itemName, 'Item name', 'Iconi'
}

XMCQCX
Posts: 256
Joined: 14 Oct 2020, 23:44

Re: Tray app to change power plans

Post by XMCQCX » 16 May 2024, 19:27

Proof of concept from an intermediate user. Not extensively tested. Requires RunCMD by SKAN. viewtopic.php?p=448912#p448912

Code: Select all

#Requires AutoHotkey v2.0
#SingleInstance
Persistent

#Include <v2\RunCMD\RunCMD>

listPowerPlan := RunWaitOne('powercfg /list')

m := Map()

while RegExMatch(listPowerPlan, 'i)Power Scheme GUID: (\S+)  \(([^)]+)\)', &match, IsSet(match) ? match.Pos + match.Len : 1)
    m[match[2]] := match[1]

;==============================================

A_TrayMenu.Delete

for plan, GUID in m
    A_TrayMenu.Add(plan, Change_PowerPlan.Bind(GUID))

A_TrayMenu.Add()
A_TrayMenu.Add('Open Script Folder', (*) => Run(A_WorkingDir))
A_TrayMenu.Add('Edit Script', (*) => Edit())
A_TrayMenu.Add('Reload', (*) => Reload())
A_TrayMenu.Add('Exit', (*) => ExitApp())

Change_PowerPlan(GUID, *) => Run('powercfg -setactive ' GUID,, 'Hide')

;==============================================

OnMessage(0x404, AHK_NOTIFYICON)

AHK_NOTIFYICON(wParam, lParam, msg, hwnd)
{
    if (lParam = 517) 
    {
        activePowerPlan := RunCMD('powercfg /GetActiveScheme')

        for plan, GUID in m {
            if InStr(activePowerPlan, GUID)
                A_TrayMenu.Check(plan)
            else
                A_TrayMenu.UnCheck(plan)
        }
    }
}

;==============================================

RunWaitOne(command) {
    shell := ComObject("WScript.Shell")
    exec := shell.Exec(A_ComSpec " /C " command)
    return exec.StdOut.ReadAll()
}

XMCQCX
Posts: 256
Joined: 14 Oct 2020, 23:44

Re: Tray app to change power plans

Post by XMCQCX » 16 May 2024, 19:33

I've created a script that I'm using to automatically change power plans when windows/processes are detected. WinExeCommander viewtopic.php?f=83&t=128956"

kiwichick
Posts: 166
Joined: 21 Jan 2014, 22:03

Re: Tray app to change power plans

Post by kiwichick » 16 May 2024, 19:50

XMCQCX wrote:
16 May 2024, 19:33
I've created a script that I'm using to automatically change power plans when windows/processes are detected. WinExeCommander viewtopic.php?f=83&t=128956"
Thanks but that's quite a bit more than what I need.

kiwichick
Posts: 166
Joined: 21 Jan 2014, 22:03

Re: Tray app to change power plans

Post by kiwichick » 16 May 2024, 19:55

mikeyww wrote:
16 May 2024, 19:11
Thanks Mike, that's just what I need. But I'm having a bit of a brain fart. How do I add the code for the individual power plan GUIDs?

For example, for the Balanced plan:

Code: Select all

Run("powercfg /s 381b4222-f694-41f0-9685-ff5bb260df2e")

User avatar
mikeyww
Posts: 27351
Joined: 09 Sep 2014, 18:38

Re: Tray app to change power plans

Post by mikeyww » 16 May 2024, 20:23

Code: Select all

#Requires AutoHotkey v2.0
Persistent
guid := Map(
           'Balanced', '381b4222-f694-41f0-9685-ff5bb260df2e'
         , 'Custom'  , '429ad934-c04d-49b7-893a-e80c306b7eed' ; Change as needed
        )
tray := A_TrayMenu
tray.Add 'Power', (itemName, itemPos, m) => power.Show()
tray.Default    := 'Power'
tray.ClickCount := 1
power := Menu()
For scheme in guid
 power.Add scheme, powerSelect

powerSelect(itemName, itemPos, m) {
 RunWait 'powercfg.exe /s ' guid[itemName],, 'Hide'
 MsgBox 'Done!', itemName, 'Iconi T.8'
}

kiwichick
Posts: 166
Joined: 21 Jan 2014, 22:03

Re: Tray app to change power plans

Post by kiwichick » 16 May 2024, 21:39

mikeyww wrote:
16 May 2024, 20:23

Code: Select all

#Requires AutoHotkey v2.0
Persistent
guid := Map(
           'Balanced', '381b4222-f694-41f0-9685-ff5bb260df2e'
         , 'Custom'  , '429ad934-c04d-49b7-893a-e80c306b7eed' ; Change as needed
        )
tray := A_TrayMenu
tray.Add 'Power', (itemName, itemPos, m) => power.Show()
tray.Default    := 'Power'
tray.ClickCount := 1
power := Menu()
For scheme in guid
 power.Add scheme, powerSelect

powerSelect(itemName, itemPos, m) {
 RunWait 'powercfg.exe /s ' guid[itemName],, 'Hide'
 MsgBox 'Done!', itemName, 'Iconi T.8'
}
Thank you so much, Mike. That works great. I've just got to figure out how to use plan names with spaces.

User avatar
mikeyww
Posts: 27351
Joined: 09 Sep 2014, 18:38

Re: Tray app to change power plans

Post by mikeyww » 16 May 2024, 21:45

The script that I posted lets you assign the GUID to a scheme (name) specific to the AHK script. These names are independent of the Windows plan name and can include spaces if you like. XMCQCX has shown an alternative that retrieves the Windows plan information.

kiwichick
Posts: 166
Joined: 21 Jan 2014, 22:03

Re: Tray app to change power plans

Post by kiwichick » 16 May 2024, 22:12

mikeyww wrote:
16 May 2024, 21:45
The script that I posted lets you assign the GUID to a scheme (name) specific to the AHK script. These names are independent of the Windows plan name and can include spaces if you like. XMCQCX has shown an alternative that retrieves the Windows plan information.
Thanks again, Mike. I didn't realise you'd posted two different lots of code. I was working with the first one and couldn't figure out how to use plan names with spaces. I've just tried the second one and it works fine with spaces. Your help is greatly appreciated.

teadrinker
Posts: 4409
Joined: 29 Mar 2015, 09:41
Contact:

Re: Tray app to change power plans

Post by teadrinker » 17 May 2024, 03:45

Solving this task, it is quite possible to do without external applications and libraries. :)

Code: Select all

#Requires AutoHotkey v2

class PowerSchemeSwitch
{
    /*
    This class modifies the script's tray icon menu
    so that you can switch the computer's power scheme through it.
    */
   
    static __New() {
        Persistent
        this.knownPowerSchemes := Map(
            '{A1841308-3541-4FAB-BC81-F71556F20B4A}', 'Max Power Savings',
            '{8C5E7FDA-E8BF-4A96-9A85-A6E23A8C635C}', 'Min Power Savings',
            '{381B4222-F694-41F0-9685-FF5BB260DF2E}', 'Typical Power Savings',
            '{7EAEB2FF-542B-4CF6-8302-EBA010D31244}', 'High Performance'
        )
        this.existingPowerSchemes := this.EnumeratePowerSchemes()
        this.CreateTrayMenu()
        OnMessage(0x404, ObjBindMethod(this, 'AHK_NOTIFYICON'))
    }

    static EnumeratePowerSchemes() {
        strGUID := Buffer(78), existingPowerSchemes := Map()
        while !DllCall('PowrProf\PowerEnumerate', 'Ptr', 0, 'Ptr', 0, 'Ptr', 0, 'UInt', ACCESS_SCHEME := 16,
                                                  'UInt', A_Index - 1, 'Ptr', GUID := Buffer(16), 'UIntP', &size := 16)
        {
            DllCall('Ole32\StringFromGUID2', 'Ptr', GUID, 'Ptr', strGUID, 'Int', 39)
            existingPowerSchemes[StrGet(strGUID)] := GUID
        }
        return existingPowerSchemes
    }

    static CreateTrayMenu() {
        static unknownSchemeCounter := 0
        A_TrayMenu.Delete()
        for strGuid, GUID in this.existingPowerSchemes {
            if !this.knownPowerSchemes.Has(strGuid) {
                this.knownPowerSchemes[strGuid] := 'Unknown Power Scheme' . ' ' . ++unknownSchemeCounter
            }
            A_TrayMenu.Add(this.knownPowerSchemes[strGuid],
                ((GUID, *) => DllCall('PowrProf\PowerSetActiveScheme', 'Ptr', 0, 'Ptr', GUID)).Bind(GUID))
        }
        A_TrayMenu.Add()
        A_TrayMenu.Add('Exit', (*) => ExitApp())
    }

    static AHK_NOTIFYICON(wp, lp, *) {
        static WM_RBUTTONDOWN := 0x204, prevChecked := ''
        if lp == WM_RBUTTONDOWN {
            DllCall('PowrProf\PowerGetActiveScheme', 'Ptr', 0, 'PtrP', &pGUID := 0)
            DllCall('Ole32\StringFromGUID2', 'Ptr', pGUID, 'Ptr', buf := Buffer(78), 'Int', 39)
            DllCall('LocalFree', 'Ptr', pGUID)
            (prevChecked && A_TrayMenu.UnCheck(prevChecked))
            A_TrayMenu.Check(prevChecked := this.knownPowerSchemes[StrGet(buf)])
        }
    }
}

Post Reply

Return to “Ask for Help (v2)”