1

Тема: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Доброго всем здоровячка.

Вот от СЮДА пользую скрипт. Возможно ли сделать так чтобы при наведение на кнопку Пуск выскакивал не тултип с текстом "Начните работу с....", а с текстом имени процесса занимающего в текущий момент наибольшее процессорное время?

Спасибо.

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

2

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Нехилая задача. В принципе, думаю, возможно. Но затрудняюсь сказать, как именно это можно реализовать.

3

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Если нет возможность/желания заниматься, то я думаю и не стоит. У меня это просто "хотелка"

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

4

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Может, создать прозрачное GUI окно, которое будет с теми же координатами и размерами, что и Shell_TrayWnd. И при наведении курсора появляется tooltip, который перекрывает "Начните работу с...."?

5

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Ну, я лично имел в виду, как узнать этот самый процесс, который наибольшее время занимает.

6

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Сначала так, потом вот так.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Вот и отлично. Ты делаешь расчётную часть, а ypppu отобразительную. На этом позвольте считать мою (руководительную) часть работы успешно выполненной.
Цели ясны, задачи определены, за работу, товарищи! (с)

8

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Абижяишь, насяльника! Мала-мала деньга давай!

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

9 (изменено: ypppu, 2010-10-14 21:53:16)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Как ни крути, коряво получается. У одних кнопка "Пуск" в одном месте, у других в другом. И она может менять позицию при скрытии панели задач. Поэтому нужно очень часто проверять позицию кнопки (окна). И "Начните работу с...." останется маячить. Пока универсального решения не вижу.

10 (изменено: teadrinker, 2010-10-15 04:07:24)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Вот так получилось:

   #Persistent
   EnvGet, NumCPU, NUMBER_OF_PROCESSORS
   SetTimer, GetMaxLoadProcess, 1000

GetMaxLoadProcess:
   MouseGetPos,,, WinID, Control
   WinGetClass, Class, ahk_id %WinID%
   if !(Class = "Shell_TrayWnd" && Control = "Button1")
   {
      once =
      ToolTip
      Return
   }
   MaxLoad = 0
   Process, Exist, System
   List := GetProcessList() . "System," . ErrorLevel
   Loop, parse, List, |
   {
      PID := RegExReplace(A_LoopField, ".*,(.*)", "$1")
      Time%PID% := GetProcessTimes(PID)

      Load := Round((Time%PID% - OldTime%PID%)/NumCPU/10000000 * 100)
      OldTime%PID% := Time%PID%

      if (Load >= MaxLoad)
         MaxLoad := Load, MaxProcess := RegExReplace(A_LoopField, "(.*),.*", "$1")
   }
   if !once
   {
      once = 1
      Return
   }
   ToolTip % MaxProcess "   " MaxLoad "%"
   Return

GetProcessList()
{
   s := 4096  ; size of buffers and arrays (4 KB)

   Process, Exist  ; sets ErrorLevel to the PID of this running script
   ; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
   ; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
   DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
   VarSetCapacity(ti, 16, 0)  ; structure of privileges
   NumPut(1, ti, 0)  ; one entry in the privileges array...
   ; Retrieves the locally unique identifier of the debug privilege:
   DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
   NumPut(luid, ti, 4, "int64")
   NumPut(2, ti, 12)  ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
   ; Update the privileges of this process with the new access token:
   DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false
                                               , "UInt", &ti, "UInt", 0
                                               , "UInt", 0, "UInt", 0)
   DllCall("CloseHandle", "UInt", h)  ; close this process handle to save memory

   hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")  ; increase performance by preloading the libaray
   s := VarSetCapacity(a, s)  ; an array that receives the list of process identifiers:
   c := 0  ; counter for process idendifiers
   DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
   Loop, % r // 4  ; parse array for identifiers as DWORDs (32 bits):
   {
      id := NumGet(a, A_Index * 4)
      ; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
      h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)
      VarSetCapacity(n, s, 0)  ; a buffer that receives the base name of the module:
      e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", 0, "Str", n, "UInt", s)
      DllCall("CloseHandle", "UInt", h)  ; close process handle to save memory
      if (n && e)  ; if image is not null add to list:
         l .= n . "," . id . "|"
   }
   DllCall("FreeLibrary", "UInt", hModule)  ; unload the library to free memory
   Return l
}

GetProcessTimes(PID)
{
   hProc := DllCall("OpenProcess", "Uint", 0x400, "int", 0, "Uint", pid)
   DllCall("GetProcessTimes", "Uint", hProc, "int64P", CreationTime, "int64P"
           , ExitTime, "int64P", KrnlTime, "int64P", UserTime)

   DllCall("CloseHandle", "Uint", hProc)
   Return KrnlTime + UserTime
}

При наведении курсора на кнопку "Пуск" возникает ToolTip с названием наиболее загружающего процесса и процент процессорного времени, занимаемого данным процессом. Как бороться с системным ToolTip'ом, пока не думал.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

11

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Работает. В принципе удобная возможность, если нужно посмотреть, кто именно сильно грузит процессор. Хотя это может быть и не один процесс, а два-три в сумме. Системный тултип — ерунда, по-моему. Не сильно он и мешает.

12

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Немного рациональнее, объединив две функции в одну:

   #Persistent
   EnvGet, NumCPU, NUMBER_OF_PROCESSORS
   SetTimer, GetMaxLoadProcess, 1000

GetMaxLoadProcess:
   MouseGetPos,,, WinID, Control
   WinGetClass, Class, ahk_id %WinID%
   if !(Class = "Shell_TrayWnd" && Control = "Button1")
   {
      once =
      ToolTip
      Return
   }
   MaxLoad = 0
   List := GetProcessList()
   Loop, parse, List, |
   {
      PID := RegExReplace(A_LoopField, ".*?,(.*),.*", "$1")
      Time%PID% := RegExReplace(A_LoopField, ".*,(.*)", "$1")

      Load := Round((Time%PID% - OldTime%PID%)/NumCPU/10000000 * 100)
      OldTime%PID% := Time%PID%

      if (Load > MaxLoad)
         MaxLoad := Load, MaxProcess := RegExReplace(A_LoopField, "(.*?),.*", "$1")
   }
   if !once
   {
      once = 1
      Return
   }
   ToolTip % MaxProcess "   " MaxLoad "%"
   Return

GetProcessList()
{
   s := 4096  ; size of buffers and arrays (4 KB)

   Process, Exist  ; sets ErrorLevel to the PID of this running script
   ; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
   ; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
   DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
   VarSetCapacity(ti, 16, 0)  ; structure of privileges
   NumPut(1, ti, 0)  ; one entry in the privileges array...
   ; Retrieves the locally unique identifier of the debug privilege:
   DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
   NumPut(luid, ti, 4, "int64")
   NumPut(2, ti, 12)  ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
   ; Update the privileges of this process with the new access token:
   DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false
                                               , "UInt", &ti, "UInt", 0
                                               , "UInt", 0, "UInt", 0)
   DllCall("CloseHandle", "UInt", h)  ; close this process handle to save memory

   hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")  ; increase performance by preloading the libaray
   s := VarSetCapacity(a, s)  ; an array that receives the list of process identifiers:
   c := 0  ; counter for process idendifiers
   DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
   Loop, % r // 4  ; parse array for identifiers as DWORDs (32 bits):
   {
      id := NumGet(a, A_Index * 4)
      ; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
      h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)
      VarSetCapacity(n, s, 0)  ; a buffer that receives the base name of the module:
      e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", 0, "Str", n, "UInt", s)
      
      DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
              , ExitTime, "int64P", KrnlTime, "int64P", UserTime)
      
      DllCall("CloseHandle", "UInt", h)  ; close process handle to save memory
      if (n && e)  ; if image is not null add to list:
         l .= n . "," . id . "," . KrnlTime + UserTime . "|"
   }
   
   Process, Exist, System
   id := ErrorLevel
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", id)
      DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
              , ExitTime, "int64P", KrnlTime, "int64P", UserTime)
   DllCall("CloseHandle", "UInt", h)
   l .= "System," . id . "," . KrnlTime + UserTime
   
   DllCall("FreeLibrary", "UInt", hModule)  ; unload the library to free memory
   Return l
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

13

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Что интересно, подпрограмма, составляющая список процессов, у меня сработала и без части, отвечающей за выделение привилегий:

d = `n  ; string separator
s := 4096  ; size of buffers and arrays (4 KB)

hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")  ; increase performance by preloading the libaray
s := VarSetCapacity(a, s)  ; an array that receives the list of process identifiers:
c := 0  ; counter for process idendifiers
DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
Loop, % r // 4  ; parse array for identifiers as DWORDs (32 bits):
{
   id := NumGet(a, A_Index * 4)
   ; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
   h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)
   VarSetCapacity(n, s, 0)  ; a buffer that receives the base name of the module:
   e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", 0, "Str", n, "UInt", s)
   DllCall("CloseHandle", "UInt", h)  ; close process handle to save memory
   if (n && e)  ; if image is not null add to list:
      l .= n . d, c++
}
DllCall("FreeLibrary", "UInt", hModule)  ; unload the library to free memory
Sort, l, C  ; uncomment this line to sort the list alphabetically
MsgBox, 0, %c% Processes, %l%

Это как-то связано с наличием/отсутствием прав администратора?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

14

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

У меня тоже сработала, но показала на 5 процессов меньше. В частности, 2 svchost.exe вместо 5. Также не показала csrss.exe и alg.exe.

15

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

А, да, точно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

16 (изменено: teadrinker, 2010-10-16 00:33:20)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Объединение двух скриптов:

   #Persistent
   HowManyProcShow = 3   ; сколько процессов с загрузкой > 0 показывать
   
   SetBatchLines, -1
   EnvGet, NumCPU, NUMBER_OF_PROCESSORS    ; Добавлено.
   VarSetCapacity(IdleTicks, 8)
   SetTimer, CheckCPULoad, 1000
   return

CheckCPULoad:
   CoordMode, Mouse
   ControlMove, Button1, -7,, 110,, ahk_class Shell_TrayWnd
   SetFormat, float, 02
   ControlSetText, Button1, % " " GetCPULoad() " %", ahk_class Shell_TrayWnd
   
   MouseGetPos,Xm,Ym, WinID, Control
   WinGetClass, Class, ahk_id %WinID%
   if !(Class = "Shell_TrayWnd" && Control = "Button1")
   {
      WinClose, ahk_id %hBT%
      once := hBT := ""
      Return
   }
   List := GetProcessList()
   Loop, parse, List, |
   {
      PID := RegExReplace(A_LoopField, ".*?,(.*),.*", "$1")
      Time%PID% := RegExReplace(A_LoopField, ".*,(.*)", "$1")

      Load := Round((Time%PID% - OldTime%PID%)/NumCPU/10000000 * 100)
      OldTime%PID% := Time%PID%
      RankedProcessList .= RegExReplace(A_LoopField, "(.*?),.*", "$1") . "|" . Load "%`n"
   }
   if !once
   {
      once = 1
      Return
   }
   StringTrimRight, RankedProcessList, RankedProcessList, 1
   Sort, RankedProcessList, F FSort D`n
   Loop, parse, RankedProcessList, `n
   {
      if (RegExReplace(A_LoopField, ".*\|(.*)%", "$1") = 0 || A_Index = HowManyProcShow + 1)
         Break
      ShortProcessList .= A_LoopField . "`n"
   }
   SPL := RegExReplace(SubStr(ShortProcessList, 1, -1), "\|", "   ")
   
   hBT := BalloonTip(Xm, Ym, SPL ? SPL : "Нет загрузки", "Max Load:", 1)
   RankedProcessList := ShortProcessList := ""
   Return

FSort(a1, a2)
{
   Return RegExReplace(a2, ".*\|(.*)%", "$1") - RegExReplace(a1, ".*\|(.*)%", "$1")
}

GetCPULoad()
{
   Global
   SetBatchLines, -1
   IdleTime0 = %IdleTime%  ; Save previous values
   Tick0 = %Tick%
   DllCall("kernel32.dll\GetSystemTimes", UInt, &IdleTicks, UInt, 0, UInt, 0)
   IdleTime := *(&IdleTicks)
   Loop 7                  ; Ticks when Windows was idle
     IdleTime += *( &IdleTicks + A_Index ) << ( 8 * A_Index )
   Tick := A_TickCount     ; Ticks all together
   load := 100 - 0.01*(IdleTime - IdleTime0)/NumCPU/(Tick - Tick0)
   Return, load
}

GetProcessList()
{
   s := 4096  ; size of buffers and arrays (4 KB)

   Process, Exist  ; sets ErrorLevel to the PID of this running script
   ; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
   ; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
   DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
   VarSetCapacity(ti, 16, 0)  ; structure of privileges
   NumPut(1, ti, 0)  ; one entry in the privileges array...
   ; Retrieves the locally unique identifier of the debug privilege:
   DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
   NumPut(luid, ti, 4, "int64")
   NumPut(2, ti, 12)  ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
   ; Update the privileges of this process with the new access token:
   DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false
                                               , "UInt", &ti, "UInt", 0
                                               , "UInt", 0, "UInt", 0)
   DllCall("CloseHandle", "UInt", h)  ; close this process handle to save memory

   hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")  ; increase performance by preloading the libaray
   s := VarSetCapacity(a, s)  ; an array that receives the list of process identifiers:
   c := 0  ; counter for process idendifiers
   DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
   Loop, % r // 4  ; parse array for identifiers as DWORDs (32 bits):
   {
      id := NumGet(a, A_Index * 4)
      ; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
      h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)
      VarSetCapacity(n, s, 0)  ; a buffer that receives the base name of the module:
      e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", 0, "Str", n, "UInt", s)

      DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
              , ExitTime, "int64P", KrnlTime, "int64P", UserTime)

      DllCall("CloseHandle", "UInt", h)  ; close process handle to save memory
      if (n && e)  ; if image is not null add to list:
         l .= n . "," . id . "," . KrnlTime + UserTime . "|"
   }

   Process, Exist, System
   id := ErrorLevel
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", id)
   DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
           , ExitTime, "int64P", KrnlTime, "int64P", UserTime)
   DllCall("CloseHandle", "UInt", h)
   l .= "System," . id . "," . KrnlTime + UserTime

   DllCall("FreeLibrary", "UInt", hModule)  ; unload the library to free memory
   Return l
}

BalloonTip(x, y, sText, sTitle = "", h_icon = 0)
{
   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error. n > 3: assumed to be an hIcon.
   static
   global hBT
   WS_EX_TOPMOST := 8, TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40
   
   if !hBT
   {
      hWnd := DllCall("CreateWindowEx" , UInt, WS_EX_TOPMOST
                                       , Str, "tooltips_class32"
                                       , Str, ""
                                       , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_BALLOON
                                       , Int, 0, Int, 0, Int, 0, Int, 0
                                       , UInt, 0, UInt, 0, UInt, 0, UInt, 0)

      VarSetCapacity(TOOLINFO, 40, 0)
      NumPut(40, TOOLINFO)
      NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
      NumPut(&sText, TOOLINFO, 36)

   ; используется DllCall, т. к. работает и со скрытыми окнами, в отличие от SendMessage.
      DllCall("SendMessage", UInt, hWnd, UInt, 1048, UInt, 0, UInt, 500)      ; TTM_SETMAXTIPWIDTH
      DllCall("SendMessage", UInt, hWnd, UInt, 1028, UInt, 0, UInt, &TOOLINFO)   ; TTM_ADDTOOL
      DllCall("SendMessage", UInt, hWnd, UInt, 1042, UInt, 0, UInt         ; TTM_TRACKPOSITION
         , (x & 0xFFFF)|(y & 0xFFFF)<<16)
      DllCall("SendMessage", UInt, hWnd, UInt, 1041, UInt, 1, UInt, &TOOLINFO)   ; TTM_TRACKACTIVATE

      DllCall("SendMessage", UInt, hWnd, UInt, 1056, UInt, h_icon            ; TTM_SETTITLE
         , UInt, &sTitle)
      DllCall("SendMessage", UInt, hWnd, UInt, 1036, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXT
   }
   else
   {
      NumPut(&sText, TOOLINFO, 36)
      DllCall("SendMessage", UInt, hBT, UInt, 1036, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXT
   }
   Return hWnd
}

Попробуйте, кому не лень! Если не будет замечаний, дополню Коллекцию, а то раздел AutoHotKey у нас совсем что-то запылился!

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

17

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Будут .

Окно, закрывающее стандартный Пуск имеет иной размер и местоположение, нежели «родной» элемент управления: (высота, вроде, и расположение по вертикали совпадает только).

Class:    Shell_TrayWnd
Position:    -2, -2
Size:    1404, 55

Class:    Button
Instance:    1
ClassnameNN:    Button1
Name:    
Advanced (Class):    [CLASS:Button; INSTANCE:1]
ID:    304
Text:    Пуск
Position:    0, 0
Size:    52, 22

У меня панель задач сверху, в две строки, не скрывается (я пробовал стандарт — снизу, одна строка — на результат не влияет). Пользую классический стиль.

Balloon может показывать один и тот же процесс в двух экземплярах (не постоянно, видно, где-то на переходах случается): я запустил для пробы простейший скрипт VBS:

Do
    a= 1
Loop

и спорадически наблюдаю, например:

cscript.exe 103%
cscript.exe 51%
…

Пару раз увидел даже за 2000% (в первой строке).

Если потребуется, информация о процессоре (по данным CPU-Z):

Processors Information
------------------------------------------------------------------------------------

Processor 1 (ID = 0)
Number of cores        2 (max 2)
Number of threads    2 (max 2)
Name            Intel Pentium D 930
Codename        Presler
Specification        Intel(R) Pentium(R) D CPU 3.00GHz
Package            Socket 775 LGA (platform ID = 2h)
CPUID            F.6.2
Extended CPUID        F.6
Core Stepping        B1
Technology        65 nm
Core Speed        3010.6 MHz (15.0 x 200.7 MHz)
Rated Bus speed        802.8 MHz
Stock frequency        3000 MHz

18

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Ага, спасибо, а так?

   #Persistent
   HowManyProcShow = 3   ; сколько процессов с загрузкой > 0 показывать
   
   SetBatchLines, -1
   EnvGet, NumCPU, NUMBER_OF_PROCESSORS    ; Добавлено.
   WinGetPos, XTray, YTray,,, ahk_class Shell_TrayWnd
   ControlGetPos, XButt, YButt, WButt, HButt, Button1, ahk_class Shell_TrayWnd
   VarSetCapacity(IdleTicks, 8)
   SetTimer, CheckCPULoad, 1000
   return

CheckCPULoad:
   CoordMode, Mouse
   ControlMove, Button1,,, WButt + 5,, ahk_class Shell_TrayWnd
   SetFormat, float, 02
   ControlSetText, Button1
      , % (GC:=GetCPULoad())<100 ? " " GC " %" : GC "%", ahk_class Shell_TrayWnd
   
   MouseGetPos,,, WinID, Control
   WinGetClass, Class, ahk_id %WinID%
   if !(Class = "Shell_TrayWnd" && Control = "Button1")
   {
      WinClose, ahk_id %hBT%
      once := hBT := ""
      Return
   }
   List := GetProcessList()
   RankedProcessList := ShortProcessList := ""
   Loop, parse, List, |
   {
      PID := RegExReplace(A_LoopField, ".*?,(.*),.*", "$1")
      Time%PID% := RegExReplace(A_LoopField, ".*,(.*)", "$1")

      Load := Round((Time%PID% - OldTime%PID%)/NumCPU/10000000 * 100)
      OldTime%PID% := Time%PID%
      RankedProcessList .= RegExReplace(A_LoopField, "(.*?),.*", "$1") . "|" . Load "%`n"
   }
   if !once
   {
      once = 1
      Return
   }
   StringTrimRight, RankedProcessList, RankedProcessList, 1
   Sort, RankedProcessList, F FSort D`n
   Loop, parse, RankedProcessList, `n
   {
      if (RegExReplace(A_LoopField, ".*\|(.*)%", "$1") = 0 || A_Index = HowManyProcShow + 1)
         Break
      ShortProcessList .= A_LoopField . "`n"
   }
   SPL := RegExReplace(SubStr(ShortProcessList, 1, -1), "\|", "   ")
   xBT := XTray > 10 ? XTray+XButt : XTray+XButt+WButt
   yBT := YTray > 10 ? YTray+YButt : YTray+YButt+HButt
   hBT := BalloonTip(xBT, yBT, SPL ? SPL : "Нет загрузки", "Max Load:", 1)
   Return

FSort(a1, a2)
{
   Return RegExReplace(a2, ".*\|(.*)%", "$1") - RegExReplace(a1, ".*\|(.*)%", "$1")
}

GetCPULoad()
{
   Global
   SetBatchLines, -1
   IdleTime0 = %IdleTime%  ; Save previous values
   Tick0 = %Tick%
   DllCall("kernel32.dll\GetSystemTimes", UInt, &IdleTicks, UInt, 0, UInt, 0)
   IdleTime := *(&IdleTicks)
   Loop 7                  ; Ticks when Windows was idle
     IdleTime += *( &IdleTicks + A_Index ) << ( 8 * A_Index )
   Tick := A_TickCount     ; Ticks all together
   load := 100 - 0.01*(IdleTime - IdleTime0)/NumCPU/(Tick - Tick0)
   Return, load
}

GetProcessList()
{
   s := 4096  ; size of buffers and arrays (4 KB)

   Process, Exist  ; sets ErrorLevel to the PID of this running script
   ; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
   ; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
   DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
   VarSetCapacity(ti, 16, 0)  ; structure of privileges
   NumPut(1, ti, 0)  ; one entry in the privileges array...
   ; Retrieves the locally unique identifier of the debug privilege:
   DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
   NumPut(luid, ti, 4, "int64")
   NumPut(2, ti, 12)  ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
   ; Update the privileges of this process with the new access token:
   DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false
                                               , "UInt", &ti, "UInt", 0
                                               , "UInt", 0, "UInt", 0)
   DllCall("CloseHandle", "UInt", h)  ; close this process handle to save memory

   hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")  ; increase performance by preloading the libaray
   s := VarSetCapacity(a, s)  ; an array that receives the list of process identifiers:
   c := 0  ; counter for process idendifiers
   DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
   Loop, % r // 4  ; parse array for identifiers as DWORDs (32 bits):
   {
      id := NumGet(a, A_Index * 4)
      ; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
      h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)
      VarSetCapacity(n, s, 0)  ; a buffer that receives the base name of the module:
      e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", 0, "Str", n, "UInt", s)

      DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
              , ExitTime, "int64P", KrnlTime, "int64P", UserTime)

      DllCall("CloseHandle", "UInt", h)  ; close process handle to save memory
      if (n && e)  ; if image is not null add to list:
         l .= n . "," . id . "," . KrnlTime + UserTime . "|"
   }

   Process, Exist, System
   id := ErrorLevel
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", id)
   DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
           , ExitTime, "int64P", KrnlTime, "int64P", UserTime)
   DllCall("CloseHandle", "UInt", h)
   l .= "System," . id . "," . KrnlTime + UserTime

   DllCall("FreeLibrary", "UInt", hModule)  ; unload the library to free memory
   Return l
}

BalloonTip(x, y, sText, sTitle = "", h_icon = 0)
{
   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error. n > 3: assumed to be an hIcon.
   static
   global hBT
   WS_EX_TOPMOST := 8, TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40
   
   if !hBT
   {
      hWnd := DllCall("CreateWindowEx" , UInt, WS_EX_TOPMOST
                                       , Str, "tooltips_class32"
                                       , Str, ""
                                       , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_BALLOON
                                       , Int, 0, Int, 0, Int, 0, Int, 0
                                       , UInt, 0, UInt, 0, UInt, 0, UInt, 0)

      VarSetCapacity(TOOLINFO, 40, 0)
      NumPut(40, TOOLINFO)
      NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
      NumPut(&sText, TOOLINFO, 36)

   ; используется DllCall, т. к. работает и со скрытыми окнами, в отличие от SendMessage.
      DllCall("SendMessage", UInt, hWnd, UInt, 1048, UInt, 0, UInt, 500)      ; TTM_SETMAXTIPWIDTH
      DllCall("SendMessage", UInt, hWnd, UInt, 1028, UInt, 0, UInt, &TOOLINFO)   ; TTM_ADDTOOL
      DllCall("SendMessage", UInt, hWnd, UInt, 1042, UInt, 0, UInt         ; TTM_TRACKPOSITION
         , (x & 0xFFFF)|(y & 0xFFFF)<<16)
      DllCall("SendMessage", UInt, hWnd, UInt, 1041, UInt, 1, UInt, &TOOLINFO)   ; TTM_TRACKACTIVATE

      DllCall("SendMessage", UInt, hWnd, UInt, 1056, UInt, h_icon            ; TTM_SETTITLE
         , UInt, &sTitle)
      DllCall("SendMessage", UInt, hWnd, UInt, 1036, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXT
   }
   else
   {
      NumPut(&sText, TOOLINFO, 36)
      DllCall("SendMessage", UInt, hBT, UInt, 1036, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXT
   }
   Return hWnd
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

19

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Теперь нормально: положение и размер окна в порядке, дубликаты процессов и загрузка тоже.

20

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

У меня нормально работает. Но есть чисто эстетическое пожелание — чтобы баллон не менял свою высоту туда-сюда, не дёргался. По-моему, так бы лучше было.

И что это за "окно, закрывающее стандартный Пуск", что-то я не пойму, о чём речь.

21 (изменено: teadrinker, 2010-10-16 09:43:52)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Вот такой вариант, с окном настроек, которое появляется при щелчке по BalloonTip'у:

   #Persistent
   SetBatchLines, -1

   IniRead, HowManyProcShow
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, HowManyProcShow, 3   ; сколько процессов с загрузкой > 0 показывать
   IniRead, AddEmptyString
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, AddEmptyString, 1      ; дописывать ли пустые строки, чтобы окно BalloonTip
                                                ; не меняло размера, 1 — да, 0 — нет
   EnvGet, NumCPU, NUMBER_OF_PROCESSORS
   WinGetPos, XTray, YTray,,, ahk_class Shell_TrayWnd
   ControlGetPos, XButt, YButt, WButt, HButt, Button1, ahk_class Shell_TrayWnd
   VarSetCapacity(IdleTicks, 8)
   SetTimer, CheckCPULoad, 1000
   OnMessage(WM_LBUTTONDOWN := 0x201, "Settings")

CheckCPULoad:
   CoordMode, Mouse
   ControlMove, Button1,,, WButt + 5,, ahk_class Shell_TrayWnd
   SetFormat, float, 02
   ControlSetText, Button1
      , % (GC:=GetCPULoad())<100 ? " " GC " %" : GC "%", ahk_class Shell_TrayWnd

   MouseGetPos,,, WinID, Control
   WinGetClass, Class, ahk_id %WinID%
   if !(Class = "Shell_TrayWnd" && Control = "Button1")
   {
      once =
      Sleep, 300
      WinClose, ahk_id %hBT%
      hBT =
      Return
   }
   List := GetProcessList()
   RankedProcessList := ShortProcessList := ""
   Loop, parse, List, |
   {
      PID := RegExReplace(A_LoopField, ".*?,(.*),.*", "$1")
      Time%PID% := RegExReplace(A_LoopField, ".*,(.*)", "$1")

      Load := Round((Time%PID% - OldTime%PID%)/NumCPU/10000000 * 100)
      OldTime%PID% := Time%PID%
      RankedProcessList .= RegExReplace(A_LoopField, "(.*?),.*", "$1") . "|" . Load "%`n"
   }
   if !once
   {
      once = 1
      Return
   }
   StringTrimRight, RankedProcessList, RankedProcessList, 1
   Sort, RankedProcessList, F FSort D`n

   EmptyString =
   Loop % HowManyProcShow
      EmptyString .= "`n"

   Loop, parse, RankedProcessList, `n
   {
      if (RegExReplace(A_LoopField, ".*\|(.*)%", "$1") = 0 || A_Index = HowManyProcShow + 1)
         Break
      ShortProcessList .= A_LoopField . "`n"
      StringTrimRight, EmptyString, EmptyString, 1
   }
   SPL := RegExReplace(SubStr(ShortProcessList, 1, -1), "\|", "   ")
   xBT := XTray > 10 ? XTray+XButt : XTray+XButt+WButt
   yBT := YTray > 10 ? YTray+YButt : YTray+YButt+HButt
   if AddEmptyString
      hBT := BalloonTip(xBT, yBT, SPL ? SPL . EmptyString : "Нет загрузки" . SubStr(EmptyString,1,-1)
                                , "Max Load:", 1)
   else
      hBT := BalloonTip(xBT, yBT, SPL ? SPL : "Нет загрузки", "Max Load:", 1)
   Return

FSort(a1, a2)
{
   Return RegExReplace(a2, ".*\|(.*)%", "$1") - RegExReplace(a1, ".*\|(.*)%", "$1")
}

GetCPULoad()
{
   Global
   SetBatchLines, -1
   IdleTime0 = %IdleTime%  ; Save previous values
   Tick0 = %Tick%
   DllCall("kernel32.dll\GetSystemTimes", UInt, &IdleTicks, UInt, 0, UInt, 0)
   IdleTime := *(&IdleTicks)
   Loop 7                  ; Ticks when Windows was idle
     IdleTime += *( &IdleTicks + A_Index ) << ( 8 * A_Index )
   Tick := A_TickCount     ; Ticks all together
   load := 100 - 0.01*(IdleTime - IdleTime0)/NumCPU/(Tick - Tick0)
   Return, load
}

GetProcessList()
{
   s := 4096  ; size of buffers and arrays (4 KB)

   Process, Exist  ; sets ErrorLevel to the PID of this running script
   ; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
   ; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
   DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
   VarSetCapacity(ti, 16, 0)  ; structure of privileges
   NumPut(1, ti, 0)  ; one entry in the privileges array...
   ; Retrieves the locally unique identifier of the debug privilege:
   DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
   NumPut(luid, ti, 4, "int64")
   NumPut(2, ti, 12)  ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
   ; Update the privileges of this process with the new access token:
   DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false
                                               , "UInt", &ti, "UInt", 0
                                               , "UInt", 0, "UInt", 0)
   DllCall("CloseHandle", "UInt", h)  ; close this process handle to save memory

   hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")  ; increase performance by preloading the libaray
   s := VarSetCapacity(a, s)  ; an array that receives the list of process identifiers:
   c := 0  ; counter for process idendifiers
   DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
   Loop, % r // 4  ; parse array for identifiers as DWORDs (32 bits):
   {
      id := NumGet(a, A_Index * 4)
      ; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
      h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)
      VarSetCapacity(n, s, 0)  ; a buffer that receives the base name of the module:
      e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", 0, "Str", n, "UInt", s)

      DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
              , ExitTime, "int64P", KrnlTime, "int64P", UserTime)

      DllCall("CloseHandle", "UInt", h)  ; close process handle to save memory
      if (n && e)  ; if image is not null add to list:
         l .= n . "," . id . "," . KrnlTime + UserTime . "|"
   }

   Process, Exist, System
   id := ErrorLevel
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", id)
   DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
           , ExitTime, "int64P", KrnlTime, "int64P", UserTime)
   DllCall("CloseHandle", "UInt", h)
   l .= "System," . id . "," . KrnlTime + UserTime

   DllCall("FreeLibrary", "UInt", hModule)  ; unload the library to free memory
   Return l
}

BalloonTip(x, y, sText, sTitle = "", h_icon = 0)
{
   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error. n > 3: assumed to be an hIcon.
   static
   global hBT
   WS_EX_TOPMOST := 8, TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40

   if !hBT
   {
      hWnd := DllCall("CreateWindowEx" , UInt, WS_EX_TOPMOST
                                       , Str, "tooltips_class32"
                                       , Str, ""
                                       , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_BALLOON
                                       , Int, 0, Int, 0, Int, 0, Int, 0
                                       , UInt, 0, UInt, 0, UInt, 0, UInt, 0)

      VarSetCapacity(TOOLINFO, 40, 0)
      NumPut(40, TOOLINFO)
      NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
      NumPut(&sText, TOOLINFO, 36)

   ; используется DllCall, т. к. работает и со скрытыми окнами, в отличие от SendMessage.
      DllCall("SendMessage", UInt, hWnd, UInt, 1048, UInt, 0, UInt, 500)      ; TTM_SETMAXTIPWIDTH
      DllCall("SendMessage", UInt, hWnd, UInt, 1028, UInt, 0, UInt, &TOOLINFO)   ; TTM_ADDTOOL
      DllCall("SendMessage", UInt, hWnd, UInt, 1042, UInt, 0, UInt         ; TTM_TRACKPOSITION
         , (x & 0xFFFF)|(y & 0xFFFF)<<16)
      DllCall("SendMessage", UInt, hWnd, UInt, 1041, UInt, 1, UInt, &TOOLINFO)   ; TTM_TRACKACTIVATE

      DllCall("SendMessage", UInt, hWnd, UInt, 1056, UInt, h_icon            ; TTM_SETTITLE
         , UInt, &sTitle)
      DllCall("SendMessage", UInt, hWnd, UInt, 1036, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXT
   }
   else
   {
      NumPut(&sText, TOOLINFO, 36)
      DllCall("SendMessage", UInt, hBT, UInt, 1036, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXT
   }
   Return hWnd
}

Settings(wParam, lParam, msg, hwnd)
{
   local Str
   if (hwnd != hBT || WinExist("Настройки CPULoad ahk_class AutoHotkeyGUI"))
      Return
   WinGetPos, xBT, yBT,,, ahk_id %hwnd%
   WinClose, ahk_id %hwnd%
   Gui, -Caption +Border +AlwaysOnTop +Owner
   Gui, Color, FFFEE1
   Gui, Add, Text, x7 y10, Сколько процессов показать?
   Loop 10
      Str .= A_Index "|"
   StringReplace, Str, Str, % HowManyProcShow "|", % HowManyProcShow "||"
   Gui, Add, DDL, vHowManyProcShow xp+160 yp-3 w35 r5, % Str
   Gui, Add, Checkbox, vAddEmptyString x8 y46, Сохранять высоту окна
   GuiControl,, AddEmptyString, % AddEmptyString ? 1 : 0
   Gui, Add, Button, x150 yp-5 w53 h23, OK
   xSett := XTray > 10 ? A_ScreenWidth - 230 : 20
   ySett := YTray > 10 ? YTray - 95 : yBT
   Gui, Show, x%xSett% y%ySett% w209 h70, Настройки CPULoad
   Return

ButtonOK:
   Gui, Submit
   Gui, Destroy
   IniWrite, % HowManyProcShow
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, HowManyProcShow
   IniWrite, % AddEmptyString
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, AddEmptyString
   Return
}

При установке чекбокса "Сохранять высоту окна" высота BalloonTip'а остаётся постоянной.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

22

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Круто! Не успел я пожелать, а оно уже есть. Только иногда слегка дурит — показывает "-0%".

23

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Где, на кнопке, или в BalloonTip'е?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

24

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

На кнопке. Кроме того, в AHKLw баллон коряво текст показывает.

25 (изменено: teadrinker, 2010-10-16 11:36:35)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

На кнопку поставил костыль! В AHKLw вот так попробуй (не забудь сохранить в UTF-8):

   #Persistent
   SetBatchLines, -1

   IniRead, HowManyProcShow
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, HowManyProcShow, 3   ; сколько процессов с загрузкой > 0 показывать
   IniRead, AddEmptyString
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, AddEmptyString, 1      ; дописывать ли пустые строки, чтобы окно BalloonTip
                                                ; не меняло размера, 1 — да, 0 — нет
   EnvGet, NumCPU, NUMBER_OF_PROCESSORS
   WinGetPos, XTray, YTray,,, ahk_class Shell_TrayWnd
   ControlGetPos, XButt, YButt, WButt, HButt, Button1, ahk_class Shell_TrayWnd
   VarSetCapacity(IdleTicks, 8)
   SetTimer, CheckCPULoad, 1000
   OnMessage(WM_LBUTTONDOWN := 0x201, "Settings")

CheckCPULoad:
   CoordMode, Mouse
   ControlMove, Button1,,, WButt + 5,, ahk_class Shell_TrayWnd
   SetFormat, float, 02
   ControlSetText, Button1
      , % (GC:=GetCPULoad())<100 ? " " GC " %" : GC "%", ahk_class Shell_TrayWnd

   MouseGetPos,,, WinID, Control
   WinGetClass, Class, ahk_id %WinID%
   if !(Class = "Shell_TrayWnd" && Control = "Button1")
   {
      once =
      Sleep, 300
      WinClose, ahk_id %hBT%
      hBT =
      Return
   }
   List := GetProcessList()
   RankedProcessList := ShortProcessList := ""
   Loop, parse, List, |
   {
      PID := RegExReplace(A_LoopField, ".*?,(.*),.*", "$1")
      Time%PID% := RegExReplace(A_LoopField, ".*,(.*)", "$1")

      Load := Round((Time%PID% - OldTime%PID%)/NumCPU/10000000 * 100)
      OldTime%PID% := Time%PID%
      RankedProcessList .= RegExReplace(A_LoopField, "(.*?),.*", "$1") . "|" . Load "%`n"
   }
   if !once
   {
      once = 1
      Return
   }
   StringTrimRight, RankedProcessList, RankedProcessList, 1
   Sort, RankedProcessList, F FSort D`n

   EmptyString =
   Loop % HowManyProcShow
      EmptyString .= "`n"

   Loop, parse, RankedProcessList, `n
   {
      if (RegExReplace(A_LoopField, ".*\|(.*)%", "$1") = 0 || A_Index = HowManyProcShow + 1)
         Break
      ShortProcessList .= A_LoopField . "`n"
      StringTrimRight, EmptyString, EmptyString, 1
   }
   SPL := RegExReplace(SubStr(ShortProcessList, 1, -1), "\|", "   ")
   xBT := XTray > 10 ? XTray+XButt : XTray+XButt+WButt
   yBT := YTray > 10 ? YTray+YButt : YTray+YButt+HButt
   if AddEmptyString
      hBT := BalloonTip(xBT, yBT, SPL ? SPL . EmptyString : "Нет загрузки" . SubStr(EmptyString,1,-1)
                                , "Max Load:", 1)
   else
      hBT := BalloonTip(xBT, yBT, SPL ? SPL : "Нет загрузки", "Max Load:", 1)
   Return

FSort(a1, a2)
{
   Return RegExReplace(a2, ".*\|(.*)%", "$1") - RegExReplace(a1, ".*\|(.*)%", "$1")
}

GetCPULoad()
{
   Global
   SetBatchLines, -1
   IdleTime0 = %IdleTime%  ; Save previous values
   Tick0 = %Tick%
   DllCall("kernel32.dll\GetSystemTimes", UInt, &IdleTicks, UInt, 0, UInt, 0)
   IdleTime := *(&IdleTicks)
   Loop 7                  ; Ticks when Windows was idle
     IdleTime += *( &IdleTicks + A_Index ) << ( 8 * A_Index )
   Tick := A_TickCount     ; Ticks all together
   load := 100 - 0.01*(IdleTime - IdleTime0)/NumCPU/(Tick - Tick0)
   Return, load < 0 ? 00 : load
}

GetProcessList()
{
   s := 4096  ; size of buffers and arrays (4 KB)

   Process, Exist  ; sets ErrorLevel to the PID of this running script
   ; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
   ; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
   DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
   VarSetCapacity(ti, 16, 0)  ; structure of privileges
   NumPut(1, ti, 0)  ; one entry in the privileges array...
   ; Retrieves the locally unique identifier of the debug privilege:
   DllCall("Advapi32.dll\LookupPrivilegeValueW", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
   NumPut(luid, ti, 4, "int64")
   NumPut(2, ti, 12)  ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
   ; Update the privileges of this process with the new access token:
   DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false
                                               , "UInt", &ti, "UInt", 0
                                               , "UInt", 0, "UInt", 0)
   DllCall("CloseHandle", "UInt", h)  ; close this process handle to save memory

   hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")  ; increase performance by preloading the libaray
   s := VarSetCapacity(a, s)  ; an array that receives the list of process identifiers:
   c := 0  ; counter for process idendifiers
   DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
   Loop, % r // 4  ; parse array for identifiers as DWORDs (32 bits):
   {
      id := NumGet(a, A_Index * 4)
      ; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
      h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)
      VarSetCapacity(n, s, 0)  ; a buffer that receives the base name of the module:
      e := DllCall("Psapi.dll\GetModuleBaseNameW", "UInt", h, "UInt", 0, "Str", n, "UInt", s)

      DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
              , ExitTime, "int64P", KrnlTime, "int64P", UserTime)

      DllCall("CloseHandle", "UInt", h)  ; close process handle to save memory
      if (n && e)  ; if image is not null add to list:
         l .= n . "," . id . "," . KrnlTime + UserTime . "|"
   }

   Process, Exist, System
   id := ErrorLevel
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", id)
   DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
           , ExitTime, "int64P", KrnlTime, "int64P", UserTime)
   DllCall("CloseHandle", "UInt", h)
   l .= "System," . id . "," . KrnlTime + UserTime

   DllCall("FreeLibrary", "UInt", hModule)  ; unload the library to free memory
   Return l
}

BalloonTip(x, y, sText, sTitle = "", h_icon = 0)
{
   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error. n > 3: assumed to be an hIcon.
   static
   global hBT
   WS_EX_TOPMOST := 8, TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40

   if !hBT
   {
      hWnd := DllCall("CreateWindowEx" , UInt, WS_EX_TOPMOST
                                       , Str, "tooltips_class32"
                                       , Str, ""
                                       , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_BALLOON
                                       , Int, 0, Int, 0, Int, 0, Int, 0
                                       , UInt, 0, UInt, 0, UInt, 0, UInt, 0)

      VarSetCapacity(TOOLINFO, 40, 0)
      NumPut(40, TOOLINFO)
      NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
      NumPut(&sText, TOOLINFO, 36)

   ; используется DllCall, т. к. работает и со скрытыми окнами, в отличие от SendMessage.
      DllCall("SendMessage", UInt, hWnd, UInt, 1048, UInt, 0, UInt, 500)      ; TTM_SETMAXTIPWIDTH
      DllCall("SendMessage", UInt, hWnd, UInt, 1028, UInt, 0, UInt, &TOOLINFO)   ; TTM_ADDTOOL
      DllCall("SendMessage", UInt, hWnd, UInt, 1042, UInt, 0, UInt         ; TTM_TRACKPOSITION
         , (x & 0xFFFF)|(y & 0xFFFF)<<16)
      DllCall("SendMessage", UInt, hWnd, UInt, 1041, UInt, 1, UInt, &TOOLINFO)   ; TTM_TRACKACTIVATE

      DllCall("SendMessage", UInt, hWnd, UInt, 1057, UInt, h_icon            ; TTM_SETTITLEW
         , UInt, &sTitle)
      DllCall("SendMessage", UInt, hWnd, UInt, 1081, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXTW
   }
   else
   {
      NumPut(&sText, TOOLINFO, 36)
      DllCall("SendMessage", UInt, hBT, UInt, 1081, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXTW
   }
   Return hWnd
}

Settings(wParam, lParam, msg, hwnd)
{
   local Str
   if (hwnd != hBT || WinExist("Настройки CPULoad ahk_class AutoHotkeyGUI"))
      Return
   WinGetPos, xBT, yBT,,, ahk_id %hwnd%
   WinClose, ahk_id %hwnd%
   Gui, -Caption +Border +AlwaysOnTop +Owner
   Gui, Color, FFFEE1
   Gui, Add, Text, x7 y10, Сколько процессов показать?
   Loop 10
      Str .= A_Index "|"
   StringReplace, Str, Str, % HowManyProcShow "|", % HowManyProcShow "||"
   Gui, Add, DDL, vHowManyProcShow xp+160 yp-3 w35 r5, % Str
   Gui, Add, Checkbox, vAddEmptyString x8 y46, Сохранять высоту окна
   GuiControl,, AddEmptyString, % AddEmptyString ? 1 : 0
   Gui, Add, Button, x150 yp-5 w53 h23, OK
   xSett := XTray > 10 ? A_ScreenWidth - 230 : 20
   ySett := YTray > 10 ? YTray - 95 : yBT
   Gui, Show, x%xSett% y%ySett% w209 h70, Настройки CPULoad
   Return

ButtonOK:
   Gui, Submit
   Gui, Destroy
   IniWrite, % HowManyProcShow
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, HowManyProcShow
   IniWrite, % AddEmptyString
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, AddEmptyString
   Return
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

26

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

YMP пишет:

И что это за "окно, закрывающее стандартный Пуск", что-то я не пойму, о чём речь.

Наверно, в классическом стиле кнопка "Пуск" уезжает вбок.

27

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

teadrinker пишет:

В AHKLw вот так попробуй

Работает. Но лучше сделать универсальный, проверяющий переменную A_IsUnicode. Учитывая переходный период.

ypppu пишет:

Наверно, в классическом стиле кнопка "Пуск" уезжает вбок.

Ну и что? Всё равно не понял, о каком закрывающем окне речь.

28

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

YMP пишет:

Но лучше сделать универсальный, проверяющий переменную A_IsUnicode. Учитывая переходный период

Тогда типа того:

   #Persistent
   SetBatchLines, -1

   IniRead, HowManyProcShow
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, HowManyProcShow, 3   ; сколько процессов с загрузкой > 0 показывать
   IniRead, AddEmptyString
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, AddEmptyString, 1      ; дописывать ли пустые строки, чтобы окно BalloonTip
                                                ; не меняло размера, 1 — да, 0 — нет
   EnvGet, NumCPU, NUMBER_OF_PROCESSORS
   WinGetPos, XTray, YTray,,, ahk_class Shell_TrayWnd
   ControlGetPos, XButt, YButt, WButt, HButt, Button1, ahk_class Shell_TrayWnd
   VarSetCapacity(IdleTicks, 8)
   SetTimer, CheckCPULoad, 1000
   OnMessage(WM_LBUTTONDOWN := 0x201, "Settings")

CheckCPULoad:
   CoordMode, Mouse
   ControlMove, Button1,,, WButt + 5,, ahk_class Shell_TrayWnd
   SetFormat, float, 02
   ControlSetText, Button1
      , % (GC:=GetCPULoad())<100 ? " " GC " %" : GC "%", ahk_class Shell_TrayWnd

   MouseGetPos,,, WinID, Control
   WinGetClass, Class, ahk_id %WinID%
   if !(Class = "Shell_TrayWnd" && Control = "Button1")
   {
      once =
      Sleep, 300
      WinClose, ahk_id %hBT%
      hBT =
      Return
   }
   List := GetProcessList()
   RankedProcessList := ShortProcessList := ""
   Loop, parse, List, |
   {
      PID := RegExReplace(A_LoopField, ".*?,(.*),.*", "$1")
      Time%PID% := RegExReplace(A_LoopField, ".*,(.*)", "$1")

      Load := Round((Time%PID% - OldTime%PID%)/NumCPU/10000000 * 100)
      OldTime%PID% := Time%PID%
      RankedProcessList .= RegExReplace(A_LoopField, "(.*?),.*", "$1") . "|" . Load "%`n"
   }
   if !once
   {
      once = 1
      Return
   }
   StringTrimRight, RankedProcessList, RankedProcessList, 1
   Sort, RankedProcessList, F FSort D`n

   EmptyString =
   Loop % HowManyProcShow
      EmptyString .= "`n"

   Loop, parse, RankedProcessList, `n
   {
      if (RegExReplace(A_LoopField, ".*\|(.*)%", "$1") = 0 || A_Index = HowManyProcShow + 1)
         Break
      ShortProcessList .= A_LoopField . "`n"
      StringTrimRight, EmptyString, EmptyString, 1
   }
   SPL := RegExReplace(SubStr(ShortProcessList, 1, -1), "\|", "   ")
   xBT := XTray > 10 ? XTray+XButt : XTray+XButt+WButt
   yBT := YTray > 10 ? YTray+YButt : YTray+YButt+HButt
   if AddEmptyString
      hBT := BalloonTip(xBT, yBT, SPL ? SPL . EmptyString : "Нет загрузки" . SubStr(EmptyString,1,-1)
                                , "Max Load:", 1)
   else
      hBT := BalloonTip(xBT, yBT, SPL ? SPL : "Нет загрузки", "Max Load:", 1)
   Return

FSort(a1, a2)
{
   Return RegExReplace(a2, ".*\|(.*)%", "$1") - RegExReplace(a1, ".*\|(.*)%", "$1")
}

GetCPULoad()
{
   Global
   SetBatchLines, -1
   IdleTime0 = %IdleTime%  ; Save previous values
   Tick0 = %Tick%
   DllCall("kernel32.dll\GetSystemTimes", UInt, &IdleTicks, UInt, 0, UInt, 0)
   IdleTime := *(&IdleTicks)
   Loop 7                  ; Ticks when Windows was idle
     IdleTime += *( &IdleTicks + A_Index ) << ( 8 * A_Index )
   Tick := A_TickCount     ; Ticks all together
   load := 100 - 0.01*(IdleTime - IdleTime0)/NumCPU/(Tick - Tick0)
   Return, load < 0 ? 00 : load
}

GetProcessList()
{
   s := 4096  ; size of buffers and arrays (4 KB)

   Process, Exist  ; sets ErrorLevel to the PID of this running script
   ; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
   ; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
   DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
   VarSetCapacity(ti, 16, 0)  ; structure of privileges
   NumPut(1, ti, 0)  ; one entry in the privileges array...
   ; Retrieves the locally unique identifier of the debug privilege:
    if A_IsUnicode
        DllCall("Advapi32.dll\LookupPrivilegeValueW", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
    else
        DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
   NumPut(luid, ti, 4, "int64")
   NumPut(2, ti, 12)  ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
   ; Update the privileges of this process with the new access token:
   DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false
                                               , "UInt", &ti, "UInt", 0
                                               , "UInt", 0, "UInt", 0)
   DllCall("CloseHandle", "UInt", h)  ; close this process handle to save memory

   hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")  ; increase performance by preloading the libaray
   s := VarSetCapacity(a, s)  ; an array that receives the list of process identifiers:
   c := 0  ; counter for process idendifiers
   DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
   Loop, % r // 4  ; parse array for identifiers as DWORDs (32 bits):
   {
      id := NumGet(a, A_Index * 4)
      ; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
      h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)
      VarSetCapacity(n, s, 0)  ; a buffer that receives the base name of the module:
        if A_IsUnicode
            e := DllCall("Psapi.dll\GetModuleBaseNameW", "UInt", h, "UInt", 0, "Str", n, "UInt", s)
        Else
            e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", 0, "Str", n, "UInt", s)

      DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
              , ExitTime, "int64P", KrnlTime, "int64P", UserTime)

      DllCall("CloseHandle", "UInt", h)  ; close process handle to save memory
      if (n && e)  ; if image is not null add to list:
         l .= n . "," . id . "," . KrnlTime + UserTime . "|"
   }

   Process, Exist, System
   id := ErrorLevel
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", id)
   DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
           , ExitTime, "int64P", KrnlTime, "int64P", UserTime)
   DllCall("CloseHandle", "UInt", h)
   l .= "System," . id . "," . KrnlTime + UserTime

   DllCall("FreeLibrary", "UInt", hModule)  ; unload the library to free memory
   Return l
}

BalloonTip(x, y, sText, sTitle = "", h_icon = 0)
{
   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error. n > 3: assumed to be an hIcon.
   static
   global hBT
   WS_EX_TOPMOST := 8, TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40

   if !hBT
   {
      hWnd := DllCall("CreateWindowEx" , UInt, WS_EX_TOPMOST
                                       , Str, "tooltips_class32"
                                       , Str, ""
                                       , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_BALLOON
                                       , Int, 0, Int, 0, Int, 0, Int, 0
                                       , UInt, 0, UInt, 0, UInt, 0, UInt, 0)

      VarSetCapacity(TOOLINFO, 40, 0)
      NumPut(40, TOOLINFO)
      NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
      NumPut(&sText, TOOLINFO, 36)

   ; используется DllCall, т. к. работает и со скрытыми окнами, в отличие от SendMessage.
      DllCall("SendMessage", UInt, hWnd, UInt, 1048, UInt, 0, UInt, 500)      ; TTM_SETMAXTIPWIDTH
      DllCall("SendMessage", UInt, hWnd, UInt, 1028, UInt, 0, UInt, &TOOLINFO)   ; TTM_ADDTOOL
      DllCall("SendMessage", UInt, hWnd, UInt, 1042, UInt, 0, UInt         ; TTM_TRACKPOSITION
         , (x & 0xFFFF)|(y & 0xFFFF)<<16)
      DllCall("SendMessage", UInt, hWnd, UInt, 1041, UInt, 1, UInt, &TOOLINFO)   ; TTM_TRACKACTIVATE
        if A_IsUnicode
        {
            DllCall("SendMessage", UInt, hWnd, UInt, 1057, UInt, h_icon            ; TTM_SETTITLEW
                , UInt, &sTitle)
            DllCall("SendMessage", UInt, hWnd, UInt, 1081, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXTW
        }
        Else
        {
            DllCall("SendMessage", UInt, hWnd, UInt, 1056, UInt, h_icon            ; TTM_SETTITLE
                , UInt, &sTitle)
            DllCall("SendMessage", UInt, hWnd, UInt, 1036, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXT
        }
   }
   else
   {
      NumPut(&sText, TOOLINFO, 36)
        if A_IsUnicode
            DllCall("SendMessage", UInt, hWnd, UInt, 1081, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXTW
        Else
            DllCall("SendMessage", UInt, hBT, UInt, 1036, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXT
   }
   Return hWnd
}

Settings(wParam, lParam, msg, hwnd)
{
   local Str
   if (hwnd != hBT || WinExist("Настройки CPULoad ahk_class AutoHotkeyGUI"))
      Return
   WinGetPos, xBT, yBT,,, ahk_id %hwnd%
   WinClose, ahk_id %hwnd%
   Gui, -Caption +Border +AlwaysOnTop +Owner
   Gui, Color, FFFEE1
   Gui, Add, Text, x7 y10, Сколько процессов показать?
   Loop 10
      Str .= A_Index "|"
   StringReplace, Str, Str, % HowManyProcShow "|", % HowManyProcShow "||"
   Gui, Add, DDL, vHowManyProcShow xp+160 yp-3 w35 r5, % Str
   Gui, Add, Checkbox, vAddEmptyString x8 y46, Сохранять высоту окна
   GuiControl,, AddEmptyString, % AddEmptyString ? 1 : 0
   Gui, Add, Button, x150 yp-5 w53 h23, OK
   xSett := XTray > 10 ? A_ScreenWidth - 230 : 20
   ySett := YTray > 10 ? YTray - 95 : yBT
   Gui, Show, x%xSett% y%ySett% w209 h70, Настройки CPULoad
   Return

ButtonOK:
   Gui, Submit
   Gui, Destroy
   IniWrite, % HowManyProcShow
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, HowManyProcShow
   IniWrite, % AddEmptyString
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, AddEmptyString
   Return
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

29

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

YMP пишет:

Ну и что? Всё равно не понял, о каком закрывающем окне речь.

Думается мне, alexii назвал кнопку Пуск окном.

30

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Кстати, tooltip - это окно? Я его видел в Winspector Spy.

31

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

tooltip — окно!

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

32

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

teadrinker
Да, так работает на обоих.

ypppu
По-моему, что-то не то. В общем, alexii напустил туману и исчез.

33

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Тогда можно попробовать убрать его. Сам пробовал - не получается, на WinMove не реагирует. Возможно, я просто чего-то не понимаю.
Выглядит так: 0001001E: tooltips_class32 "??????? ?????? ? ??????? ???? ??????"

34

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

YMP пишет:

И что это за "окно, закрывающее стандартный Пуск", что-то я не пойму, о чём речь.

Это я, не посмотрев внимательно код, решил, по внешнему виду (Button1 становился куда шире и перемещался левее так, что значок уползал почти за пределы экрана), что это «окно поверх».

P.S. Я не исчез. Я пока живой.

35

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Кажется придумал, как УБИТЬ его (ToolTip "Начните работу с нажатия этой кнопки"):

   #Persistent
   DetectHiddenWindows, On
   SetTimer, ToolTipKill, 1000

ToolTipKill:
   WinGet, TTList, List, ahk_class tooltips_class32
   Loop % TTList
   {
      ControlGetText, Text,, % "ahk_id " TTList%A_Index%
      if InStr(Text, "Начните работу")
      {
         WinClose, % "ahk_id " TTList%A_Index%
         ExitApp
      }
   }
   Return

Иногда срабатывает сразу, иногда после наведения курсора на кнопку "Пуск".
Вроде, не появляется до следующей перезагрузки.
Это не может на что-нибудь плохо повлиять (закрытие окна иногда равно завершению процесса), как думаете?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

36

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Работает!
Explorer не погибает, наверное всё в порядке.

37

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Возможно, какой-то код и обламывается, который с ним работает (показывает и прячет). Я как-то и не думал, что его один раз закрыть можно — и всё.

38

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Интересный баг отловил: моя функция

     ...
Sort, ProcessList, F FSort D`n
     ...
FSort(a1, a2)
{
   Return RegExReplace(a2, ".*\|(.*)%", "$1") - RegExReplace(a1, ".*\|(.*)%", "$1")
}

самым бессовестным образом пожирает память, с каждой итерацией таймера всё больше (при наведении курсора на "Пуск").
Если заменить на

     ...
Sort, ProcessList, F FSort D`n
     ...
FSort(a1, a2)
{
   Return a2 - a1
}

естественно, выдаёт результат не тот, что нужен, но пожирать перестаёт. Что-то не так в этих RegExReplace'ах!
Нашёл выход:

     ...
Sort, ProcessList, F FSort D`n
     ...
FSort(a1, a2)
{
   Result := RegExReplace(a2, ".*\|(.*)%", "$1") - RegExReplace(a1, ".*\|(.*)%", "$1")
    a1 := a2 := ""
    Return Result
}

Последний вариант скрипта, оптимизированный, работает пошустрее. Функция ToolTipKill() включена!

   #Persistent
   SetBatchLines, -1

   IniRead, HowManyProcShow
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, HowManyProcShow, 3   ; сколько процессов с загрузкой > 0 показывать
   IniRead, AddEmptyString
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, AddEmptyString, 1      ; дописывать ли пустые строки, чтобы окно BalloonTip
                                                ; не меняло размера, 1 — да, 0 — нет
   WinGetPos, XTray, YTray,,, ahk_class Shell_TrayWnd
   ControlGetPos, XButt, YButt, WButt, HButt, Button1, ahk_class Shell_TrayWnd

   AdjustPrivileges()
   EnvGet, NumCPU, NUMBER_OF_PROCESSORS
   SetTimer, CheckCPULoad, 1000
   OnMessage(WM_LBUTTONDOWN := 0x201, "Settings")

CheckCPULoad:
   CoordMode, Mouse
   ControlMove, Button1,,, WButt + 5,, ahk_class Shell_TrayWnd

   SetFormat, float, 02
   CPULoad := GetCPULoad()
   List := GetProcessList()
   
   ProcessList := ShortProcessList := ""
   Loop, parse, List, |
   {
      PID := RegExReplace(A_LoopField, ".*?,(.*),.*", "$1")
      Time%PID% := RegExReplace(A_LoopField, ".*,(.*)", "$1")

      Load := Round((Time%PID% - OldTime%PID%)/NumCPU/10000000 * 100)
      OldTime%PID% := Time%PID%
      ProcessList .= RegExReplace(A_LoopField, "(.*?),.*", "$1") . "|" . Load "%`n"
   }
   if !once
   {
      once = 1
      Return
   }
   
   ControlSetText, Button1, % CPULoad < 100 ? " " CPULoad " %" : CPULoad "%"
      , ahk_class Shell_TrayWnd

   MouseGetPos,,, WinID, Control
   WinGetClass, Class, ahk_id %WinID%
   if !(Class = "Shell_TrayWnd" && Control = "Button1")
   {
      if hBT
         SetTimer, CloseBalloon, -300
      Return
   }

   if (!(ToolTipDead := ToolTipKill()) && AttemptKill < 3)
      AttemptKill++

   StringTrimRight, ProcessList, ProcessList, 1
   Sort, ProcessList, F FSort D`n

   EmptyString =
   if AddEmptyString
      Loop % HowManyProcShow
         EmptyString .= "`n"

   Loop, parse, ProcessList, `n
   {
      if (RegExReplace(A_LoopField, ".*\|(.*)%", "$1") = 0 || A_Index = HowManyProcShow + 1)
         Break
      ShortProcessList .= A_LoopField . "`n"
      StringTrimRight, EmptyString, EmptyString, 1
   }
   SPL := RegExReplace(SubStr(ShortProcessList, 1, -1), "\|", "   ")
   xBT := XTray > 10 ? XTray+XButt : XTray+XButt+WButt
   yBT := YTray > 10 ? YTray+YButt : YTray+YButt+HButt

   hBT := BalloonTip(xBT, yBT, SPL ? SPL . EmptyString : "Нет загрузки" . SubStr(EmptyString,1,-1)
                                , "Max Load:", 1)
   Return
   
CloseBalloon:
   WinClose, ahk_id %hBT%
   hBT =
   Return

FSort(a1, a2)
{
   Result := RegExReplace(a2, ".*\|(.*)%", "$1") - RegExReplace(a1, ".*\|(.*)%", "$1")
   a1 := a2 := ""
   Return Result
}

ToolTipKill()
{
   DetectHiddenWindows, On
   WinGet, TTList, List, ahk_class tooltips_class32
   Loop % TTList
   {
      ControlGetText, Text,, % "ahk_id " TTList%A_Index%
      if InStr(Text, "Начните работу")
      {
         WinClose, % "ahk_id " TTList%A_Index%
         if !WinExist("ahk_id " TTList%A_Index%)
            ToolTipDead = 1
         Break
      }
   }
   Return ToolTipDead
}

AdjustPrivileges()
{
   Process, Exist  ; sets ErrorLevel to the PID of this running script
   ; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
   ; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
   DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
   VarSetCapacity(ti, 16, 0)  ; structure of privileges
   NumPut(1, ti, 0)  ; one entry in the privileges array...
   ; Retrieves the locally unique identifier of the debug privilege:
    if A_IsUnicode
        DllCall("Advapi32.dll\LookupPrivilegeValueW", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
    else
        DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
   NumPut(luid, ti, 4, "int64")
   NumPut(2, ti, 12)  ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
   ; Update the privileges of this process with the new access token:
   DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false
                                               , "UInt", &ti, "UInt", 0
                                               , "UInt", 0, "UInt", 0)
   DllCall("CloseHandle", "UInt", h)  ; close this process handle to save memory
}

GetCPULoad()
{
   static
   global NumCPU
   IdleTime0 = %IdleTime%  ; Save previous values
   Tick0 = %Tick%
   if !IdleTicksCapacity
      IdleTicksCapacity := VarSetCapacity(IdleTicks, 8)
   DllCall("kernel32.dll\GetSystemTimes", UInt, &IdleTicks, UInt, 0, UInt, 0)
   IdleTime := *(&IdleTicks)
   Loop 7                  ; Ticks when Windows was idle
     IdleTime += *( &IdleTicks + A_Index ) << ( 8 * A_Index )
   Tick := A_TickCount     ; Ticks all together
   load := 100 - 0.01*(IdleTime - IdleTime0)/NumCPU/(Tick - Tick0)
   Return, load < 0 ? 00 : load
}

GetProcessList()
{
   s := 4096  ; size of buffers and arrays (4 KB)

   hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")  ; increase performance by preloading the libaray
   s := VarSetCapacity(a, s)  ; an array that receives the list of process identifiers:
   DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
   Loop, % r // 4  ; parse array for identifiers as DWORDs (32 bits):
   {
      id := NumGet(a, A_Index * 4)
      ; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
      h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)

      VarSetCapacity(n, s, 0)  ; a buffer that receives the base name of the module:
      if A_IsUnicode
         e := DllCall("Psapi.dll\GetModuleBaseNameW", "UInt", h, "UInt", 0, "Str", n, "UInt", s)
      Else
         e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", 0, "Str", n, "UInt", s)

      DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
              , ExitTime, "int64P", KrnlTime, "int64P", UserTime)

      DllCall("CloseHandle", "UInt", h)  ; close process handle to save memory
      if (n && e)  ; if image is not null add to list:
         l .= n . "," . id . "," . KrnlTime + UserTime . "|"
   }

   Process, Exist, System
   id := ErrorLevel
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", id)
   DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
           , ExitTime, "int64P", KrnlTime, "int64P", UserTime)
   DllCall("CloseHandle", "UInt", h)
   l .= "System," . id . "," . KrnlTime + UserTime

   DllCall("FreeLibrary", "UInt", hModule)  ; unload the library to free memory
   Return l
}

BalloonTip(x, y, sText, sTitle = "", h_icon = 0)
{
   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error. n > 3: assumed to be an hIcon.
   static
   global hBT
   WS_EX_TOPMOST := 8, TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40

   if !hBT
   {
      hWnd := DllCall("CreateWindowEx" , UInt, WS_EX_TOPMOST
                                       , Str, "tooltips_class32"
                                       , Str, ""
                                       , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_BALLOON
                                       , Int, 0, Int, 0, Int, 0, Int, 0
                                       , UInt, 0, UInt, 0, UInt, 0, UInt, 0)

      VarSetCapacity(TOOLINFO, 40, 0)
      NumPut(40, TOOLINFO)
      NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
      NumPut(&sText, TOOLINFO, 36)

   ; используется DllCall, т. к. работает и со скрытыми окнами, в отличие от SendMessage.
      DllCall("SendMessage", UInt, hWnd, UInt, 1048, UInt, 0, UInt, 500)      ; TTM_SETMAXTIPWIDTH
      DllCall("SendMessage", UInt, hWnd, UInt, 1028, UInt, 0, UInt, &TOOLINFO)   ; TTM_ADDTOOL
      DllCall("SendMessage", UInt, hWnd, UInt, 1042, UInt, 0, UInt         ; TTM_TRACKPOSITION
         , (x & 0xFFFF)|(y & 0xFFFF)<<16)
      DllCall("SendMessage", UInt, hWnd, UInt, 1041, UInt, 1, UInt, &TOOLINFO)   ; TTM_TRACKACTIVATE
      if A_IsUnicode
      {
         DllCall("SendMessage", UInt, hWnd, UInt, 1057, UInt, h_icon            ; TTM_SETTITLEW
             , UInt, &sTitle)
         DllCall("SendMessage", UInt, hWnd, UInt, 1081, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXTW
      }
      Else
      {
         DllCall("SendMessage", UInt, hWnd, UInt, 1056, UInt, h_icon            ; TTM_SETTITLE
             , UInt, &sTitle)
         DllCall("SendMessage", UInt, hWnd, UInt, 1036, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXT
      }
   }
   else
   {
      NumPut(&sText, TOOLINFO, 36)
      if A_IsUnicode
         DllCall("SendMessage", UInt, hWnd, UInt, 1081, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXTW
      Else
         DllCall("SendMessage", UInt, hBT, UInt, 1036, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXT
   }
   Return hWnd
}

Settings(wParam, lParam, msg, hwnd)
{
   local Str
   if (hwnd != hBT || WinExist("Настройки CPULoad ahk_class AutoHotkeyGUI"))
      Return
   WinGetPos, xBT, yBT,,, ahk_id %hwnd%
   WinClose, ahk_id %hwnd%
   Gui, -Caption +Border +AlwaysOnTop +Owner
   Gui, Color, FFFEE1
   Gui, Add, Text, x7 y10, Сколько процессов показать?
   Loop 10
      Str .= A_Index "|"
   StringReplace, Str, Str, % HowManyProcShow "|", % HowManyProcShow "||"
   Gui, Add, DDL, vHowManyProcShow xp+160 yp-3 w35 r5, % Str
   Gui, Add, Checkbox, vAddEmptyString x8 y46, Сохранять высоту окна
   GuiControl,, AddEmptyString, % AddEmptyString ? 1 : 0
   Gui, Add, Button, x150 yp-5 w53 h23, OK
   xSett := XTray > 10 ? A_ScreenWidth - 240 : 20
   ySett := YTray > 10 ? YTray - 95 : yBT
   Gui, Show, x%xSett% y%ySett% w209 h70, Настройки CPULoad
   Return

ButtonOK:
   Gui, Submit
   Gui, Destroy
   IniWrite, % HowManyProcShow
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, HowManyProcShow
   IniWrite, % AddEmptyString
      , % A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
      , Settings, AddEmptyString
   Return
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

39

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Объясните, пожалуйста, как убрать заголовок Max load и иконку слева от него?

40

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Заменить строку

hBT := BalloonTip(xBT, yBT, SPL ? SPL . EmptyString : "Нет загрузки" . SubStr(EmptyString,1,-1), "Max Load:", 1)

на

hBT := BalloonTip(xBT, yBT, SPL ? SPL . EmptyString : "Нет загрузки" . SubStr(EmptyString,1,-1))
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

41 (изменено: teadrinker, 2010-10-18 20:03:48)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Эта версия ещё не окончательная, будут изменения. А что, без заголовка лучше? Может, так и оставить? Или сделать лишний пункт в настройках? Кстати, можно наоборот сделать его подлиннее, например "Max Load Info:", тогда размер окна будет сохраняться и по горизонтали.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

42 (изменено: ypppu, 2010-10-18 20:49:01)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

По-моему, без заголовка лучше, компактнее. Если б я знал как, то использовал tooltip вместо balloontip.

Вот два бага нашёл.
Один непонятный какой-то: у меня панель выдвинута на две строки (так что отображается время, день недели и дата). При этом BalloonTip отображается вверх ногами и под кнопкой, а не над кнопкой. А если этот же скрипт запустить под другим пользователем, то там всё нормально. Буду пока тестировать...

А второй - если перетащить панель задач к другой стороне рабочего стола, то BalloonTip будет появляться на прежнем месте. Так же и при изменении высоты и автоскрытии панели задач. Видимо, координаты кнопки нужно проверять каждый раз.

Добавлено
Да, и ещё я планирую убрать знак процента и восстановить размер кнопки Пуск.

43

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

ypppu пишет:

По-моему, без заголовка лучше, компактнее. Если б я знал как, то использовал tooltip вместо balloontip. ... Да, и ещё я планирую убрать знак процента и восстановить размер кнопки Пуск.

Я понимаю, ты минималист!

ypppu пишет:

Вот два бага нашёл.
Один непонятный какой-то: у меня панель выдвинута на две строки (так что отображается время, день недели и дата). При этом BalloonTip отображается вверх ногами и под кнопкой, а не над кнопкой.

Я не совсем понял, как это у тебя выглядит. Покажи скриншот.

ypppu пишет:

А второй - если перетащить панель задач к другой стороне рабочего стола, то BalloonTip будет появляться на прежнем месте. Так же и при изменении высоты и автоскрытии панели задач. Видимо, координаты кнопки нужно проверять каждый раз.

Координаты кнопки проверяются в начале скрипта. При смене положения панели задач нужно просто перезапустить скрипт. А при автоматическом скрытии координаты не меняются, всё должно быть в порядке.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

44 (изменено: ypppu, 2010-10-18 22:05:30)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

http://www.loadpicture.ru/images/cpuload.jpg

Координаты кнопки проверяются в начале скрипта. При смене положения панели задач нужно просто перезапустить скрипт. А при автоматическом скрытии координаты не меняются, всё должно быть в порядке.

Вот хотелось бы проверять координаты при наведении курсора.

Минимализм, кстати, на ноутбуке актуален.

45

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

ypppu пишет:

Вот хотелось бы проверять координаты при наведении курсора.

Это, думаю, можно. Насчёт расположения BalloonTip'а ещё подумаю.

ypppu пишет:

Минимализм, кстати, на ноутбуке актуален.

Да, но это-то окно временное. Есть ли разница, какого оно размера?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

46 (изменено: Mikki, 2010-10-19 14:36:06)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Ух! Ну, мужики, вы и наваяли. Монументально.

Одно меня смущает - скрипт из поста №38 (тот что после слов "Последний вариант скрипта, оптимизированный, работает ...") у меня вылетает на команде static. стр.140

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

47

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Mikki, боюсь, у тебя какая-то очень старая версия AHK. Попробуй обновить.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

48 (изменено: teadrinker, 2010-10-20 02:18:01)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Выяснилось, что положение BallonTip'а нельзя задать однозначно вниз хвостиком, он всегда будет хвостиком вверх, если есть место на экране. Поэтому из соображений универсальности пришлось от него отказаться в пользу обычного ToolTip'а. Зато теперь можно задавать положение окон скрипта, просто двигая их мышью. Потом, оказалось, что после закрытия "Начните работу с нажатия этой кнопки" перестала появляться и подсказка при наведении курсора на часы в правом нижнем углу. Это исправлено. Щелчком левой кнопки по ToolTip'у вызывается Диспетчер задач, правой — окно настроек.

   #Persistent
   SetBatchLines, -1
   CoordMode, Mouse
   CoordMode, ToolTip
   SetWinDelay, 0

   Title = Max Load Info:   ; заголовок ToolTip'а

   IniName := A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"
   IniRead, HowManyProcShow, % IniName, Settings, HowManyProcShow, 3
   IniRead, ShowTitle, % IniName, Settings, ShowTitle, 1
   IniRead, ShowDate, % IniName, Settings, ShowDate, 1
   IniRead, xTT, % IniName, Positions, xTT, % " "
   IniRead, yTT, % IniName, Positions, yTT, % " "
   IniRead, xSett, % IniName, Positions, xSett, % " "
   IniRead, ySett, % IniName, Positions, ySett, % " "
   ControlGetPos, XButt,, WButt,, Button1, ahk_class Shell_TrayWnd

   WinGetPos, XTray, YTray, WTray, HTray, ahk_class Shell_TrayWnd
   if (xTT = "" || yTT = "")
   {
      xTT := XTray > 10 ? XTray-120 : XTray+30
      yTT := YTray > 10 ? YTray-100 : 50
   }
   if (xSett = "" || ySett = "")
   {
      xSett := XTray > 10 ? XTray-220 : XTray+25
      ySett := YTray > 10 ? YTray-120 : 50
   }

   hTT := TrackToolTip("", "", "", "", 1)

   AdjustPrivileges()
   EnvGet, NumCPU, NUMBER_OF_PROCESSORS
   OnMessage(WM_LBUTTONDOWN := 0x201, "ToolMove")
   OnMessage(WM_RBUTTONUP := 0x205, "Settings")
   SetTimer, CheckCPULoad, 1000

CheckCPULoad:
   SetFormat, float, 02
   CPULoad := GetCPULoad()
   List := GetProcessList()

   ProcessList := ShortProcessList := ""
   Loop, parse, List, |
   {
      PID := RegExReplace(A_LoopField, ".*?,(.*),.*", "$1")
      Time%PID% := RegExReplace(A_LoopField, ".*,(.*)", "$1")

      Load := Round((Time%PID% - OldTime%PID%)/NumCPU/10000000 * 100)
      OldTime%PID% := Time%PID%
      ProcessList .= Load . "%" . RegExReplace(A_LoopField, "(.*?),.*", "$1") "`n"
   }
   if !once
   {
      once = 1
      Return
   }

   if WTray > 100
      ControlMove, Button1, XButt - 5,, WButt + 10,, ahk_class Shell_TrayWnd
   Else
      ControlMove, Button1, XButt - 5,, WButt + 15,, ahk_class Shell_TrayWnd

   ControlSetText, Button1, % CPULoad < 100 ? " " CPULoad " %" : CPULoad "%"
      , ahk_class Shell_TrayWnd

   MouseGetPos,, yMouse, WinID, Control
   WinGetClass, Class, ahk_id %WinID%

   if (ShowDate && Class = "Shell_TrayWnd" && Control = "TrayClockWClass1")
   {
      FormatTime, Date
      WinGetPos, XTray, YTray, WTray, HTray, ahk_class Shell_TrayWnd
      if (WTray > 200 && HTray > 40)
         ToolTip
      else if (HTray > 200 && WTray > 40)
         ToolTip
      else
         ToolTip, % SubStr(Date, 6),, YTray > 40 ? YTray - 25 : YTray + HTray + 10
   }
   Else
      ToolTip

   if !((Class = "Shell_TrayWnd" && Control = "Button1") || WinID = hTT)
   {
      if hTT
         SetTimer, CloseToolTip, -300
      Return
   }

   if (!(ToolTipDead := ToolTipKill()) && AttemptKill < 3)
      AttemptKill++

   StringTrimRight, ProcessList, ProcessList, 1
   Sort, ProcessList, N R D`n

   EmptyString =
   Loop % HowManyProcShow
      EmptyString .= "`n"

   Loop, parse, ProcessList, `n
   {
      if (RegExReplace(A_LoopField, "(.*)%.*", "$1") = 0 || A_Index = HowManyProcShow + 1)
         Break
      ShortProcessList .= A_LoopField . "`n"
      StringTrimRight, EmptyString, EmptyString, 1
   }

   SPL := RegExReplace(SubStr(ShortProcessList, 1, -1), "m`a)(.*%)(.*)", "$2   $1")
   ToolTipText := SPL ? SPL . EmptyString : "Нет загрузки" . SubStr(EmptyString, 1, -1)

   TrackToolTip(xTT, yTT, ToolTipText, ShowTitle ? Title : "", 1)
   PosCorrection()
   Return

CloseToolTip:
   DllCall("SendMessage", UInt, hTT, UInt, 1041, UInt, 0, UInt, &TOOLINFO)   ; TTM_TRACKACTIVATE
   Return

ToolTipKill()
{
   DetectHiddenWindows, On
   WinGet, TTList, List, ahk_class tooltips_class32
   Loop % TTList
   {
      ControlGetText, Text,, % "ahk_id " TTList%A_Index%
      if InStr(Text, "Начните работу")
      {
         WinClose, % "ahk_id " TTList%A_Index%
         if !WinExist("ahk_id " TTList%A_Index%)
            ToolTipDead = 1
         Break
      }
   }
   Return ToolTipDead
}

AdjustPrivileges()
{
   Process, Exist  ; sets ErrorLevel to the PID of this running script
   ; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
   ; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
   DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
   VarSetCapacity(ti, 16, 0)  ; structure of privileges
   NumPut(1, ti, 0)  ; one entry in the privileges array...
   ; Retrieves the locally unique identifier of the debug privilege:
    if A_IsUnicode
        DllCall("Advapi32.dll\LookupPrivilegeValueW", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
    else
        DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
   NumPut(luid, ti, 4, "int64")
   NumPut(2, ti, 12)  ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
   ; Update the privileges of this process with the new access token:
   DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false
                                               , "UInt", &ti, "UInt", 0
                                               , "UInt", 0, "UInt", 0)
   DllCall("CloseHandle", "UInt", h)  ; close this process handle to save memory
}

GetCPULoad()
{
   static
   global NumCPU
   IdleTime0 = %IdleTime%  ; Save previous values
   Tick0 = %Tick%
   if !IdleTicksCapacity
      IdleTicksCapacity := VarSetCapacity(IdleTicks, 8)
   DllCall("kernel32.dll\GetSystemTimes", UInt, &IdleTicks, UInt, 0, UInt, 0)
   IdleTime := *(&IdleTicks)
   Loop 7                  ; Ticks when Windows was idle
     IdleTime += *( &IdleTicks + A_Index ) << ( 8 * A_Index )
   Tick := A_TickCount     ; Ticks all together
   load := 100 - 0.01*(IdleTime - IdleTime0)/NumCPU/(Tick - Tick0)
   Return, InStr(load, "-") ? 00 : load
}

GetProcessList()
{
   s := 4096  ; size of buffers and arrays (4 KB)

   hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")  ; increase performance by preloading the libaray
   s := VarSetCapacity(a, s)  ; an array that receives the list of process identifiers:
   DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
   Loop, % r // 4  ; parse array for identifiers as DWORDs (32 bits):
   {
      id := NumGet(a, A_Index * 4)
      ; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
      h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)

      VarSetCapacity(n, s, 0)  ; a buffer that receives the base name of the module:
      if A_IsUnicode
         e := DllCall("Psapi.dll\GetModuleBaseNameW", "UInt", h, "UInt", 0, "Str", n, "UInt", s)
      Else
         e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", 0, "Str", n, "UInt", s)

      DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
              , ExitTime, "int64P", KrnlTime, "int64P", UserTime)

      DllCall("CloseHandle", "UInt", h)  ; close process handle to save memory
      if (n && e)  ; if image is not null add to list:
         l .= n . "," . id . "," . KrnlTime + UserTime . "|"
   }

   Process, Exist, System
   id := ErrorLevel
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", id)
   DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
           , ExitTime, "int64P", KrnlTime, "int64P", UserTime)
   DllCall("CloseHandle", "UInt", h)
   l .= "System," . id . "," . KrnlTime + UserTime

   DllCall("FreeLibrary", "UInt", hModule)  ; unload the library to free memory
   Return l
}

TrackToolTip(x, y, sText, sTitle = "", h_icon = 0)
{
   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error. n > 3: assumed to be an hIcon.
   static
   global hTT, TOOLINFO
   WS_EX_TOPMOST := 8, TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1

   if !hTT
   {
      hWnd := DllCall("CreateWindowEx" , UInt, WS_EX_TOPMOST
                                       , Str, "tooltips_class32"
                                       , Str, ""
                                       , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP
                                       , Int, 0, Int, 0, Int, 0, Int, 0
                                       , UInt, 0, UInt, 0, UInt, 0, UInt, 0)

      VarSetCapacity(TOOLINFO, 40, 0)
      NumPut(40, TOOLINFO)
      NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
      NumPut(&sText, TOOLINFO, 36)

      VarSetCapacity(Rect, 16)
      NumPut(4, Rect)
      NumPut(5, Rect, 4)
      NumPut(5, Rect, 8)
      NumPut(5, Rect, 12)

      VarSetCapacity(Rect0, 16)
      NumPut(0, Rect0)
      NumPut(0, Rect0, 4)
      NumPut(0, Rect0, 8)
      NumPut(0, Rect0, 12)

   ; используется DllCall, т. к. работает и со скрытыми окнами, в отличие от SendMessage.
      DllCall("SendMessage", UInt, hWnd, UInt, 1048, UInt, 0, UInt, 500)      ; TTM_SETMAXTIPWIDTH
      DllCall("SendMessage", UInt, hWnd, UInt, 1028, UInt, 0, UInt, &TOOLINFO)   ; TTM_ADDTOOL
      Return hWnd
   }
   else
   {
      if !sTitle
         DllCall("SendMessage", UInt, hWnd, UInt, 1050, UInt, 0, UInt, &Rect)   ; TTM_SETMARGIN
      Else
         DllCall("SendMessage", UInt, hWnd, UInt, 1050, UInt, 0, UInt, &Rect0)   ; TTM_SETMARGIN

      NumPut(&sText, TOOLINFO, 36)
      if A_IsUnicode
      {
         DllCall("SendMessage", UInt, hWnd, UInt, 1057, UInt, h_icon            ; TTM_SETTITLEW
             , UInt, &sTitle)
         DllCall("SendMessage", UInt, hWnd, UInt, 1081, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXTW
      }
      Else
      {
         DllCall("SendMessage", UInt, hWnd, UInt, 1056, UInt, h_icon            ; TTM_SETTITLE
             , UInt, &sTitle)
         DllCall("SendMessage", UInt, hWnd, UInt, 1036, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXT
      }
      DllCall("SendMessage", UInt, hWnd, UInt, 1042, UInt, 0, UInt         ; TTM_TRACKPOSITION
         , (x & 0xFFFF)|(y & 0xFFFF)<<16)
      DllCall("SendMessage", UInt, hWnd, UInt, 1041, UInt, 1, UInt, &TOOLINFO)   ; TTM_TRACKACTIVATE
   }
}

ToolMove(wParam, lParam, msg, hwnd)
{
   global
   if (hwnd = hSett)
      PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2

   if (hwnd != hTT)
      Return

   StartTime := A_TickCount
   MouseGetPos, _MouseX, _MouseY
   SetTimer, CheckCPULoad, Off

   While GetKeyState("Lbutton", "P")
   {
      MouseGetPos, MouseX_, MouseY_
      WinMove, ahk_id %hTT%,, MouseX_ - _MouseX + xTT, MouseY_ - _MouseY + yTT
      Sleep, 10
   }

   if (A_TickCount - StartTime) < 200
      Run Taskmgr
   else
   {
      xTT += (MouseX_ - _MouseX), yTT += (MouseY_ - _MouseY)
      DllCall("SendMessage", UInt, hwnd, UInt, 1042, UInt, 0, UInt         ; TTM_TRACKPOSITION
         , (xTT & 0xFFFF)|(yTT <<16))
      IniWrite, % xTT, % IniName, Positions, xTT
      IniWrite, % yTT, % IniName, Positions, yTT
      PosCorrection()
   }
   SetTimer, CheckCPULoad, On
}

Settings(wParam, lParam, msg, hwnd)
{
   local Str
   if (hwnd != hTT || WinExist("Настройки CPULoad ahk_class AutoHotkeyGUI"))
      Return
   DllCall("SendMessage", UInt, hTT, UInt, 1041, UInt, 0, UInt, &TOOLINFO)   ; TTM_TRACKACTIVATE
   Gui, -Caption +Border +AlwaysOnTop +Owner +LastFound
   WinGet, hSett
   Gui, Color, FFFEE1
   Gui, Add, Text, x0 y0 w209 h12 +0x5
   Gui, Add, Text, x7 yp+24, Сколько процессов показать?
   Loop 10
      Str .= A_Index "|"
   StringReplace, Str, Str, % HowManyProcShow "|", % HowManyProcShow "||"
   Gui, Add, DDL, vHowManyProcShow xp+160 yp-3 w35 r5, % Str
   Gui, Add, Checkbox, vShowTitle x8 yp+29, Показывать заголовок
   Gui, Add, Checkbox, VShowDate xp yp+28, Показывать дату
   GuiControl,, ShowTitle, % ShowTitle ? 1 : 0
   GuiControl,, ShowDate, % ShowDate ? 1 : 0
   Gui, Add, Button, x150 yp-6 w53 h23, OK
   Gui, Show, x%xSett% y%ySett% w209 h103, Настройки CPULoad
   Return

ButtonOK:
   WinGetPos, xSett, ySett,,, ahk_id %hSett%
   Gui, Submit
   Gui, Destroy
   IniWrite, % HowManyProcShow, % IniName, Settings, HowManyProcShow
   IniWrite, % ShowTitle, % IniName, Settings, ShowTitle
   IniWrite, % ShowDate, % IniName, Settings, ShowDate
   IniWrite, % xSett, % IniName, Positions, xSett
   IniWrite, % ySett, % IniName, Positions, ySett
   Return
}

PosCorrection()
{
   global
   WinGetPos, _xTT, _yTT, _wTT, _hTT, ahk_id %hTT%
   if (yTT != _yTT || xTT != _xTT)
   {
      yTT := (yTT - _yTT > 300) ? A_ScreenHeight - _hTT - 5 : _yTT
      xTT := _xTT
      WinMove, ahk_id %hTT%,, xTT, yTT
      DllCall("SendMessage", UInt, hwnd, UInt, 1042, UInt, 0, UInt         ; TTM_TRACKPOSITION
         , (xTT & 0xFFFF)|(yTT <<16))
      IniWrite, % xTT, % IniName, Positions, xTT
      IniWrite, % yTT, % IniName, Positions, yTT
   }
}

Посмотрите. Будут ли ещё какие-нибудь пожелания?

P. S.
ypppu, специально для тебя, заголовок можно убрать в настройках, не надо из кода выковыривать!

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

49

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Ну, посоветовали - теперь спасайте

Установил AHK_L (ANSI) и скрипты (все где есть буква "я") перестали запускаться: не понимает букву "я" в каментах, ругается компилятор. Переделал ее на букву "ё" - запустились.
Установил AHK_L (UNICODE) - ваш скрипт из этой темы запускается, мои - нет. На что ругается - не понятно? ибо вместо русских букв - квадратики.

:WinXP SP3, FrameWork 3.5,

PS. в общем- временно переделал "я" в "ё" и все работает и показывает русские буквы.

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

50 (изменено: teadrinker, 2010-10-20 02:42:23)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Да, сорри, забыл предупредить, что ANSI-версию не нужно устанавливать. Эту тему мы здесь уже обсуждали. На AHK_Lw прежние скрипты должны запускаться (с некоторыми оговорками), если их сохранить предварительно в формате UTF-8 (или UTF-16).

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

51

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

По-моему, отлично получилось. Только нужно добавить в скрипт заголовок с описанием.

52

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Все работает. Большое спасибо!

Однозначно в Коллекцию!

PS: немного "почертыхался" когда отлаживал  параметры определяющие положение новой кнопки Пуск у меня на компе , но разобрался. все Куль!

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

53

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Mikki пишет:

PS: немного "почертыхался" когда отлаживал  параметры определяющие положение новой кнопки Пуск у меня на компе

Так может ещё добавить в настройки возможность корректировки положения кнопки? Скажем, два слайдера — для левой и для правой стороны.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

54

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Я еще чертыхался, когда мне тултип главное меню закрывал, но сейчас, вроде, исправил.

55

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Это тогда будет однозначно великолепно.

Просто в моем случае имели место постоянные сдвиги (самой кнопки влево) и (правой границы вправо) при перезапусках скрипта. Пока не понял что он берет текушие параметры.. и +5, +10 ))) или на стока на скока я ввел. Но ваш вариант - спасение

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

56

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

pant-79 пишет:

Я еще чертыхался, когда мне тултип главное меню закрывал, но сейчас, вроде, исправил.

Тултип можно просто передвинуть мышью, новое положение будет сохранено. В коде исправлять ничего не нужно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

57

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Я же и говорю, описание нужно. Скрипт достаточно сложный.

58

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Потом, оказалось, что после закрытия "Начните работу с нажатия этой кнопки" перестала появляться и подсказка при наведении курсора на часы в правом нижнем углу. Это исправлено.

Лично мне это не критично, но ради справедливости скажу, что подсказка не появляется.

59

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

ypppu пишет:

... ради справедливости скажу, что подсказка не появляется.

Галочка "Показывать дату" стоит - подсказка появляется. (у меня)

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

60 (изменено: ypppu, 2010-10-20 17:24:56)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

А у меня не появляется.
Вот ещё на всякий случай поделюсь мыслью.
Если заменить вот это шаманство

;   if WTray > 100
;      ControlMove, Button1, XButt - 5,, WButt + 10,, ahk_class Shell_TrayWnd
;   Else
;      ControlMove, Button1, XButt - 5,, WButt + 15,, ahk_class Shell_TrayWnd

;   ControlSetText, Button1, % CPULoad < 100 ? " " CPULoad " %" : CPULoad "%"
;      , ahk_class Shell_TrayWnd

на 

ControlSetText, Button1, %CPULoad%, ahk_class Shell_TrayWnd

, то пропадёт значок процента, и не надо будет кнопку двигать. В стиле ХР и классическом всё смотрится нормально. Ну это дело вкуса, вообще-то... А если панель вертикальная, цифры уже не влезают. В общем кому нужно - подгонит под себя.

61

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Mikki пишет:

Галочка "Показывать дату" стоит - подсказка появляется. (у меня)

Аналогично.

62

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

ypppu пишет:

Лично мне это не критично, но ради справедливости скажу, что подсказка не появляется.

Просто когда панель задач развёрнута в две полосы, то там и так пишется число, день недели и год (не так ли?), в этом случае подсказка не нужна, т. к. будет дублировать информацию, и блокируется. В следующей версии попытаюсь описать это более явно. Кроме того, попытаюсь в настройках сделать возможным изменение размеров и положения кнопки, чтобы каждый мог отрегулировать, как ему нужно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

63 (изменено: teadrinker, 2010-10-22 08:17:49)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Оцените последний релиз:

/*
   Скрипт предназначен для отображения сведений о загрузке CPU на кнопке Пуск (вместо
надписи "Пуск"). При наведении курсора на кнопку Пуск появляется ToolTip, в котором
отображается информация о нескольких (по умолчанию 3-х) процессах, занимающих в данный
период (1 секунду) наибольшую часть процессорного времени.

   ToolTip можно передвинуть левой кнопкой мыши в любое удобное место на экране, новое
положение будет сохранено в ini-файле.

   Щёлкнув левой кнопкой мыши по ToolTip'у, можно вызвать Диспетчер задач Windows,
правой — окно настроек. Пункты настроек:

1. Сколько процессов показать?
   Выбрать, сколько процессов, загрузка которых не менее 1% будут отображаться
   в ToolTip'е.

2. Показывать заголовок.
   При снятии галочки в ToolTip'е не будет появляться заголовок "Max Load Info"
   с иконкой.

3. Показывать дату.
   При запуске скрипта уничтожается системная всплывающая подсказка при наведении
   курсора на часы на панели задач с отображением даты. При установленной галочке
   скрипт покажет её. Работает, только если панель задач не растянута в несколько
   строк (при этом дата отображается на панели задач).

4. Настройка размеров кнопки Пуск.
   Можно скорректировать размеры кнопки Пуск, изменяя положение её левой и правой
   границы. Для этого поместите курсор в соответствующее поле, нажмите левую кнопку
   мыши и двигайте влево или вправо. Соответственно будет сдвигаться граница кнопки.
   Новые размеры будут сохранены в ini-файле, по окончании работы скрипта система
   восстановит первоначальные.

5. Знак % на кнопке.
   Показывать ли знак % при отображении загрузки CPU на кнопке Пуск.

Прошу свои отзывы о работе скрипта, предложения и сообщения о замеченных багах
оставлять здесь: http://forum.script-coding.com/viewtopic.php?id=5038
*/

   #Persistent
   SetBatchLines, -1
   CoordMode, Mouse
   CoordMode, ToolTip
   SetWinDelay, 0

   Title = Max Load Info   ; заголовок ToolTip'а

   AttemptKill = 0
   IniName := A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1") ".ini"

   IniRead, HowManyProcShow, % IniName, Settings, HowManyProcShow, 3
   IniRead, ShowTitle, % IniName, Settings, ShowTitle, 1
   IniRead, ShowDate, % IniName, Settings, ShowDate, 1
   IniRead, ShowPercent, % IniName, Settings, ShowPercent, 1
   IniRead, xTT, % IniName, Positions, xTT, % " "
   IniRead, yTT, % IniName, Positions, yTT, % " "
   IniRead, xSett, % IniName, Positions, xSett, % " "
   IniRead, ySett, % IniName, Positions, ySett, % " "
   IniRead, xButt, % IniName, Positions, xButt, % " "
   IniRead, wButt, % IniName, Positions, wButt, % " "

   ControlGetPos, _XButt,, _WButt,, Button1, ahk_class Shell_TrayWnd
   WinGetPos, XTray, YTray, WTray, HTray, ahk_class Shell_TrayWnd
   if (xTT = "" || yTT = "")
   {
      xTT := XTray > 10 ? XTray-120 : XTray+30
      yTT := YTray > 10 ? YTray-100 : 50
   }
   if (xSett = "" || ySett = "")
   {
      xSett := XTray > 10 ? XTray-220 : XTray+25
      ySett := YTray > 10 ? YTray-230 : 50
   }

   hTT := TrackToolTip("", "", "", "", "")

   AdjustPrivileges()
   EnvGet, NumCPU, NUMBER_OF_PROCESSORS
   OnMessage(WM_LBUTTONDOWN := 0x201, "ToolMove")
   OnMessage(WM_RBUTTONUP := 0x205, "Settings")
   SetTimer, CheckCPULoad, 1000

CheckCPULoad:
   WinWait, ahk_class Shell_TrayWnd
   SetFormat, float, 02
   CPULoad := GetCPULoad()
   List := GetProcessList()

   ProcessList := ShortProcessList := ""
   Loop, parse, List, |
   {
      PID := RegExReplace(A_LoopField, ".*?,(.*),.*", "$1")
      Time%PID% := RegExReplace(A_LoopField, ".*,(.*)", "$1")

      Load := Round((Time%PID% - OldTime%PID%)/NumCPU/10000000 * 100)
      OldTime%PID% := Time%PID%
      ProcessList .= Load . "%" . RegExReplace(A_LoopField, "(.*?),.*", "$1") "`n"
   }
   if !once
   {
      once = 1
      Return
   }

   ControlMove, Button1, xButt ? XButt : _XButt - 5,
      , wButt ? wButt : (WTray > 100 ? _WButt + 10 : _WButt + 15)

   if ShowPercent
      ControlSetText, Button1, % CPULoad < 100 ? " " CPULoad " %" : CPULoad "%"
   Else
      ControlSetText, Button1, % CPULoad < 100 ? "  " CPULoad : " " CPULoad

   MouseGetPos,, yMouse, WinID, Control
   WinGetClass, Class, ahk_id %WinID%

   if (ShowDate && Class = "Shell_TrayWnd" && Control = "TrayClockWClass1")
   {
      FormatTime, Date
      WinGetPos, XTray, YTray, WTray, HTray, ahk_class Shell_TrayWnd
      if !((WTray > 200 && HTray > 40) || (HTray > 200 && WTray > 40))
      {
         if !(AttemptKill > 2 || ToolTipDead)
            ToolTipDead := ToolTipKill(A_YYYY), ++AttemptKill
         Date := RegExReplace(Date, ".*:.. +(.*)", " $1")
         ToolTip, % Date,, YTray > 40 ? YTray - 25 : YTray + HTray + 10
      }
   }
   Else
      ToolTip

   if !((Class = "Shell_TrayWnd" && Control = "Button1") || WinID = hTT)
   {
      SetTimer, CloseToolTip, -300
      Return
   }

   if !(AttemptKill > 2 || ToolTipDead)
      ToolTipDead := ToolTipKill("Начните работу"), ++AttemptKill

   StringTrimRight, ProcessList, ProcessList, 1
   Sort, ProcessList, N R D`n

   EmptyString =
   Loop % HowManyProcShow
      EmptyString .= "`n"

   Loop, parse, ProcessList, `n
   {
      if (RegExReplace(A_LoopField, "(.*)%.*", "$1") = 0 || A_Index = HowManyProcShow + 1)
         Break
      ShortProcessList .= A_LoopField . "`n"
      StringTrimRight, EmptyString, EmptyString, 1
   }

   SPL := RegExReplace(SubStr(ShortProcessList, 1, -1), "m`a)(.*%)(.*)", "$2   $1")
   ToolTipText := SPL ? SPL . EmptyString : "Нет загрузки" . SubStr(EmptyString, 1, -1)

   TrackToolTip(xTT, yTT, ToolTipText, ShowTitle ? Title : "", 1)
   PosCorrection()
   Return

CloseToolTip:
   DllCall("SendMessage", UInt, hTT, UInt, 1041, UInt, 0, UInt, &TOOLINFO)   ; TTM_TRACKACTIVATE
   Return

ToolTipKill(Text)
{
   local PID
   DetectHiddenWindows, On
   WinGet, TTList, List, ahk_class tooltips_class32
   Loop % TTList
   {
      ControlGetText, Content,, % "ahk_id " TTList%A_Index%
      if InStr(Content, Text)
      {
         WinGet, PID, PID, % "ahk_id " TTList%A_Index%
         if (PID != DllCall("GetCurrentProcessId"))
            WinClose, % "ahk_id " TTList%A_Index%
         if !WinExist("ahk_id " TTList%A_Index%)
            ToolTipDead = 1
         Break
      }
   }
   Return ToolTipDead
}

AdjustPrivileges()
{
   Process, Exist  ; sets ErrorLevel to the PID of this running script
   ; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
   ; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
   DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
   VarSetCapacity(ti, 16, 0)  ; structure of privileges
   NumPut(1, ti, 0)  ; one entry in the privileges array...
   ; Retrieves the locally unique identifier of the debug privilege:
    if A_IsUnicode
        DllCall("Advapi32.dll\LookupPrivilegeValueW", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
    else
        DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege"
                                               , "Int64P", luid)
   NumPut(luid, ti, 4, "int64")
   NumPut(2, ti, 12)  ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
   ; Update the privileges of this process with the new access token:
   DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false
                                               , "UInt", &ti, "UInt", 0
                                               , "UInt", 0, "UInt", 0)
   DllCall("CloseHandle", "UInt", h)  ; close this process handle to save memory
}

GetCPULoad()
{
   static
   global NumCPU
   IdleTime0 = %IdleTime%  ; Save previous values
   Tick0 = %Tick%
   if !IdleTicksCapacity
      IdleTicksCapacity := VarSetCapacity(IdleTicks, 8)
   DllCall("kernel32.dll\GetSystemTimes", UInt, &IdleTicks, UInt, 0, UInt, 0)
   IdleTime := *(&IdleTicks)
   Loop 7                  ; Ticks when Windows was idle
     IdleTime += *( &IdleTicks + A_Index ) << ( 8 * A_Index )
   Tick := A_TickCount     ; Ticks all together
   load := 100 - 0.01*(IdleTime - IdleTime0)/NumCPU/(Tick - Tick0)
   Return, InStr(load, "-") ? 00 : load
}

GetProcessList()
{
   s := 4096  ; size of buffers and arrays (4 KB)

   hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")  ; increase performance by preloading the libaray
   s := VarSetCapacity(a, s)  ; an array that receives the list of process identifiers:
   DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
   Loop, % r // 4  ; parse array for identifiers as DWORDs (32 bits):
   {
      id := NumGet(a, A_Index * 4)
      ; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
      h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)

      VarSetCapacity(n, s, 0)  ; a buffer that receives the base name of the module:
      e := DllCall("Psapi.dll\GetModuleBaseName" . (A_IsUnicode ? "W" : "A")
         , "UInt", h, "UInt", 0, "Str", n, "UInt", s)

      DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
              , ExitTime, "int64P", KrnlTime, "int64P", UserTime)

      DllCall("CloseHandle", "UInt", h)  ; close process handle to save memory
      if (n && e)  ; if image is not null add to list:
         l .= n . "," . id . "," . KrnlTime + UserTime . "|"
   }

   Process, Exist, System
   id := ErrorLevel
   h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", id)
   DllCall("GetProcessTimes", "Uint", h, "int64P", CreationTime, "int64P"
           , ExitTime, "int64P", KrnlTime, "int64P", UserTime)
   DllCall("CloseHandle", "UInt", h)
   l .= "System," . id . "," . KrnlTime + UserTime

   DllCall("FreeLibrary", "UInt", hModule)  ; unload the library to free memory
   Return l
}

TrackToolTip(x, y, sText, sTitle = "", h_icon = 0)
{
   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error. n > 3: assumed to be an hIcon.
   static
   global hTT, TOOLINFO
   WS_EX_TOPMOST := 8, TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1

   if !hTT
   {
      hWnd := DllCall("CreateWindowEx" , UInt, WS_EX_TOPMOST
                                       , Str, "tooltips_class32"
                                       , Str, ""
                                       , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP
                                       , Int, 0, Int, 0, Int, 0, Int, 0
                                       , UInt, 0, UInt, 0, UInt, 0, UInt, 0)

      VarSetCapacity(TOOLINFO, 40, 0)
      NumPut(40, TOOLINFO)
      NumPut(0x20, TOOLINFO, 4)      ; TTF_TRACK = 0x20
      NumPut(&sText, TOOLINFO, 36)

      VarSetCapacity(Rect, 16)
      NumPut(4, Rect)
      NumPut(5, Rect, 4)
      NumPut(5, Rect, 8)
      NumPut(5, Rect, 12)

      VarSetCapacity(Rect0, 16)
      NumPut(0, Rect0)
      NumPut(0, Rect0, 4)
      NumPut(0, Rect0, 8)
      NumPut(0, Rect0, 12)

   ; используется DllCall, т. к. работает и со скрытыми окнами, в отличие от SendMessage.
      DllCall("SendMessage", UInt, hWnd, UInt, 1048, UInt, 0, UInt, 500)      ; TTM_SETMAXTIPWIDTH
      DllCall("SendMessage", UInt, hWnd, UInt, 1028, UInt, 0, UInt, &TOOLINFO)   ; TTM_ADDTOOL
      Return hWnd
   }
   else
   {
      if sTitle
         DllCall("SendMessage", UInt, hWnd, UInt, 1050, UInt, 0, UInt, &Rect0)   ; TTM_SETMARGIN
      Else
         DllCall("SendMessage", UInt, hWnd, UInt, 1050, UInt, 0, UInt, &Rect)   ; TTM_SETMARGIN

      NumPut(&sText, TOOLINFO, 36)
      if A_IsUnicode
      {
         DllCall("SendMessage", UInt, hWnd, UInt, 1057, UInt, h_icon            ; TTM_SETTITLEW
             , UInt, &sTitle)
         DllCall("SendMessage", UInt, hWnd, UInt, 1081, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXTW
      }
      Else
      {
         DllCall("SendMessage", UInt, hWnd, UInt, 1056, UInt, h_icon            ; TTM_SETTITLE
             , UInt, &sTitle)
         DllCall("SendMessage", UInt, hWnd, UInt, 1036, UInt, 0, UInt, &TOOLINFO)   ; TTM_UPDATETIPTEXT
      }
      DllCall("SendMessage", UInt, hWnd, UInt, 1042, UInt, 0, UInt         ; TTM_TRACKPOSITION
         , (x & 0xFFFF)|(y & 0xFFFF)<<16)
      DllCall("SendMessage", UInt, hWnd, UInt, 1041, UInt, 1, UInt, &TOOLINFO)   ; TTM_TRACKACTIVATE
   }
}

ToolMove(wParam, lParam, msg, hwnd)
{
   global
   if (hwnd = hSett)
      PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2

   if (hwnd != hTT)
      Return

   StartTime := A_TickCount
   MouseGetPos, _MouseX, _MouseY
   SetTimer, CheckCPULoad, Off

   While GetKeyState("Lbutton", "P")
   {
      MouseGetPos, MouseX_, MouseY_
      WinMove, ahk_id %hTT%,, MouseX_ - _MouseX + xTT, MouseY_ - _MouseY + yTT
      Sleep, 10
   }

   if (A_TickCount - StartTime) < 200
      Run Taskmgr
   else
   {
      xTT += (MouseX_ - _MouseX), yTT += (MouseY_ - _MouseY)
      DllCall("SendMessage", UInt, hwnd, UInt, 1042, UInt, 0, UInt         ; TTM_TRACKPOSITION
         , (xTT & 0xFFFF)|(yTT <<16))
      IniWrite, % xTT, % IniName, Positions, xTT
      IniWrite, % yTT, % IniName, Positions, yTT
      PosCorrection()
   }
   SetTimer, CheckCPULoad, On
}

Settings(wParam, lParam, msg, hwnd)
{
   local Str
   if (hwnd != hTT || WinExist("Настройки CPULoad ahk_class AutoHotkeyGUI"))
      Return
   DllCall("SendMessage", UInt, hTT, UInt, 1041, UInt, 0, UInt, &TOOLINFO)   ; TTM_TRACKACTIVATE
   Gui, -Caption +Border +AlwaysOnTop +Owner +LastFound
   WinGet, hSett
   Gui, Color, FFFEE1
   Gui, Add, Text, gWinMove x0 y0 w209 h12 +0x5
   Gui, Add, Text, x7 yp+24, Сколько процессов показать?
   Loop 10
      Str .= A_Index "|"
   StringReplace, Str, Str, % HowManyProcShow "|", % HowManyProcShow "||"
   Gui, Add, DDL, vHowManyProcShow gSettChange xp+160 yp-3 w35, % Str
   Gui, Add, Checkbox, vShowTitle gSettChange x8 yp+29, Показывать заголовок
   Gui, Add, Checkbox, VShowDate gSettChange xp yp+28, Показывать дату
   Gui, Add, GroupBox, x8 yp+28 w193 h60, Настройка размеров кнопки Пуск
   Gui, Add, Text, x105 yp+17 w1 hp-24 +0x8
   Gui, Add, Text, vLeft gButtonMove x9 yp-4 w96 h46 cAAAAAA BackgroundTrans Center, `nЛевая сторона
   Gui, Add, Text, vRight gButtonMove x106 yp wp-1 hp cAAAAAA BackgroundTrans Center, `nПравая сторона
   Gui, Add, Checkbox, vShowPercent gSettChange x8 y185, Знак `% на кнопке
   Gui, Add, Button, x150 y187 w53 h23 Default, OK

   GuiControl,, ShowTitle, % ShowTitle ? 1 : 0
   GuiControl,, ShowPercent, % ShowPercent ? 1 : 0
   GuiControl,, ShowDate, % ShowDate ? 1 : 0

   Gui, Show, x%xSett% y%ySett% w209 h218, Настройки CPULoad
   GuiControl, Focus, Static1
   Return

SettChange:
   Gui, Submit, NoHide
   IniWrite, % %A_GuiControl%, % IniName, Settings, % A_GuiControl
   Return

WinMove:
   PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
   Return

ButtonMove:
   WinWait, ahk_class Shell_TrayWnd
   SetTimer, CheckCPULoad, Off
   Gui, Font, c00AA00
   GuiControl, Font, % A_GuiControl
   MouseGetPos, xM
   ControlGetPos, xB,, wB,, Button1, ahk_class Shell_TrayWnd
   hCursor := DllCall("LoadCursor" . (A_IsUnicode ? "W" : "A"), UInt, 0, Int, OCR_SIZEWE := 32644)
   DllCall("SetSystemCursor", Uint, hCursor, Int, OCR_NORMAL := 32512)

   While GetKeyState("LButton", "P")
   {
      MouseGetPos, xM_
      Shift := (xM_ - xM)/4
      if A_GuiControl = Left
         ControlMove, Button1, xButt := xB + Shift,, wButt := wB - Shift
      Else
         ControlMove, Button1,,, wButt := wB + Shift
      Sleep, 10
   }
;   DllCall("SystemParametersInfo" . (A_IsUnicode ? "W" : "A")      ; на офф. форуме восстанавливают
;      , UInt, SPI_SETCURSORS := 0x57, UInt, 0, UInt, 0, UInt, 0)   ; курсор так
   DllCall("SetSystemCursor", UInt, hCursor, Int, OCR_NORMAL := 32512)   ; но вроде, можно и так

   Gui, Font, cAAAAAA
   GuiControl, Font, % A_GuiControl
   IniWrite, % xButt, % IniName, Positions, xButt
   IniWrite, % wButt, % IniName, Positions, wButt
   SetTimer, CheckCPULoad, On
   Return

GuiClose:
GuiEscape:
   Gui, Destroy
   Return

ButtonOK:
   WinGetPos, xSett, ySett,,, ahk_id %hSett%
   Gui, Destroy
   IniWrite, % xSett, % IniName, Positions, xSett
   IniWrite, % ySett, % IniName, Positions, ySett
   Return
}

PosCorrection()
{
   global
   WinGetPos, _xTT, _yTT, _wTT, _hTT, ahk_id %hTT%
   if (yTT != _yTT || xTT != _xTT)
   {
      yTT := (yTT - _yTT > 300) ? A_ScreenHeight - _hTT - 5 : _yTT
      xTT := _xTT
      WinMove, ahk_id %hTT%,, xTT, yTT
      DllCall("SendMessage", UInt, hwnd, UInt, 1042, UInt, 0, UInt         ; TTM_TRACKPOSITION
         , (xTT & 0xFFFF)|(yTT <<16))
      IniWrite, % xTT, % IniName, Positions, xTT
      IniWrite, % yTT, % IniName, Positions, yTT
   }
}

У меня скрипт не видит процессы фаервола (Outpost), при попытке дописать их вручную показывает всякую ерунду — 1450%.
Пользуйтесь только последней версией, в предыдущих обнаружены баги!

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

64

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Гениально!

65

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

....Огромное..человеческое..спасибо.

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

66

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Исправил маленькую ошибочку.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

67

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Видимо, ту, о которой я уже собирался написать. При выходе из настроек без сохранения потом они уже не открывались, а вылазила ошибка.

Наверно, всё-таки надо бы кнопку Отмена или крестик в заголовке окна. Я как-то с трудом вспомнил про Alt-F4 и Esc.

68

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Да, эту!

YMP пишет:

Наверно, всё-таки надо бы кнопку Отмена или крестик в заголовке окна. Я как-то с трудом вспомнил про Alt-F4 и Esc.

Дело в том, установки в этой версии применяются сразу же, а кнопка OK просто закрывает окно. Есть ли смысл в кнопке Отмена?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

69

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Если сразу же, то смысла нет.

70

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Запустил программу для нагрева процессора, tooltip показал 103% одного процесса и 2% другого процесса.

71

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Да, есть процессы, с которыми работает не совсем корректно. Но другого алгоритма вроде бы нет.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

72

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Изменил  SetWinDelay на -1, теперь сумма не превышает 100%. Сам не понимаю, в чём связь.

73

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Не могу проэкспериментировать, у меня за 100% не зашкаливает!

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

74

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Экспериментирую....

Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди

75

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Последняя здесь опубликованная версия уже в коллекции или еще нет и требуются доработки?
Спасибо за скрипт, просто супер!

Позже попробую поэкспериментировать с такой идеей: на серваке под виндовс 2008 при наведении кнопки пуск показать 7 ip адресов активных (что-то качают и т.д.), а если активных нет, то в сером фоне последние из подключавшихся... Правда для меня это еще трудновато, но если Вы изобретете на основе существуюшей версии то что я описал - я и многие другие будут рады и выразят вам благодарность за реализацию идеи.

Любители построили Ковчег, а профессионалы - Титаник.

76

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

stir пишет:

…при наведении кнопки пуск показать 7 ip адресов активных (что-то качают и т.д.), а если активных нет, то в сером фоне последние из подключавшихся … если Вы изобретете на основе существуюшей версии то что я описал - я и многие другие будут рады и выразят вам благодарность за реализацию идеи.

stir, Ваш случай слишком частный.

77

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

stir пишет:

Последняя здесь опубликованная версия уже в коллекции или еще нет и требуются доработки?

В Коллекции.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

78 (изменено: Indomito, 2012-04-22 13:13:05)

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Не знаю у кого как, но у меня скрипт привёл к интересным последствиям:
- кнопка Пуск стала мигать;
- исчез трей, т.е. не весь, а не отображаемая(то что скрыто) часть;
- "выгрузились" другие скрипты, но это не точно, т.е. некоторые хоткей отрубились, которые были описаны статически, например


;=====Блокируем отдельное нажатие клавиши WIN
~LWin Up::
~RWin Up::
return

;=====Замена CapsLock на Shift
CapsLock::Shift
return

Я использовал скрипт из поста #2 от 2007-04-03 10:51:57, кодировка UTF-8, запуск из среды Notepad++ v 6.1.1, запущен TrueLaunchBar, AHK_L v 1.1.07.03... не знаю ещё что могло привести к такой реакции.
OS Win 7 Ult SP1 x64

P.S. Думаю, что ТТХ "железа" не важны, но проц новый, памяти много, ну и всего много

"На каждое действие есть равная ему противодействующая критика." Постулат Харриссона
OS Windows 7 x64
AutoHotkey v1.1.32.00 - November 24, 2019
Click to Download

79

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Хе, так оно, вообще-то, для 7 не предназначено. Делалось под ХР.

80

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Ясно... жаль, хотя это баловство, ну т.е. я скачал и запустил скрипт для других целей, ну да ладно, спасибо за ответ.

"На каждое действие есть равная ему противодействующая критика." Постулат Харриссона
OS Windows 7 x64
AutoHotkey v1.1.32.00 - November 24, 2019
Click to Download

81

Re: AHK: "Дораскраска" скрипта "Загрузка процессора на клавише Пуск"

Попробовал на Windows 7 x64. Вроде работает, остаётся только показать загрузку ЦП визуально. При включённой "классической" теме оформления кнопка превращается в прямоугольник, и в ней можно менять надпись.