1

Тема: AHK: Оконтуривание рамки активного окна

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

Можно средствами AHK как-то оконтурить активное окно или как-то иначе сделать "рамку"?

2

Re: AHK: Оконтуривание рамки активного окна

Можно так:

Толщина_Рамки = 5
F11::Highlight(Толщина_Рамки)

Highlight(TH)
{
   WinGetPos, X, Y, W, H, A
   Gui, +LastFound +ToolWindow -Caption +AlwaysOnTop
   Gui, Color, Red
   Gui, Show, x%X% y%Y% w%W% h%H% Hide
   Options := "0-0 " W "-0 " W "-" H " 0-" H " 0-0 " TH "-" TH
      . " " W-TH "-" TH " " W-TH "-" H-TH " " TH "-" H-TH " " TH "-" TH
   WinSet, Region, % Options
   Gui, Show, NA
   KeyWait, F11
   Gui, Destroy
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3

Re: AHK: Оконтуривание рамки активного окна

teadrinker, спасибо, отлично работает по кнопке!

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

  Заранее спасибо!

4

Re: AHK: Оконтуривание рамки активного окна

Если у окна будет постоянная рамка, перекрывающая его периметр, возникнут проблемы с изменением размера этого окна растаскиванием за стороны. Или их размер менять не предполагается?

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

5

Re: AHK: Оконтуривание рамки активного окна

Жаль, что так, но так тоже подходит!
  Если скрипт ставить на паузу, то управление окнами ведь опять станет стандартным?

6

Re: AHK: Оконтуривание рамки активного окна

Pokerist пишет:

Если скрипт ставить на паузу, то управление окнами ведь опять станет стандартным?

Да. Можно, в принципе, рамку сделать не сосем по периметру, а внутри, или наоборот, вне границ окна, тогда, по идее, всё должно быть нормально. Тебе какой вариант больше подходит?

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

7

Re: AHK: Оконтуривание рамки активного окна

1-2 пиксела наружу было бы самое то!

8

Re: AHK: Оконтуривание рамки активного окна

   TH = 2

   SetWinDelay, 0
   Gui, +LastFound +ToolWindow -Caption +AlwaysOnTop +Disabled
   Gui, Color, Red

   Loop
   {
      WinGetPos, X, Y, W, H, A
      Sleep, 50
      if (X = XPrev && Y = YPrev && W = WPrev && H = HPrev)
         Continue
         
      XPrev := X, YPrev := Y, WPrev := W, HPrev := H
      X -= TH, Y -= TH, W += 2*TH, H += 2*TH
      
      Gui, Show, x%X% y%Y% w%W% h%H% Hide
      Options := "0-0 " W "-0 " W "-" H " 0-" H " 0-0 " TH "-" TH
         . " " W-TH "-" TH " " W-TH "-" H-TH " " TH "-" H-TH " " TH "-" TH
      WinSet, Region, % Options
      Gui, Show, NA
   }
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

9

Re: AHK: Оконтуривание рамки активного окна

Спасибо, teadrinker, ты гений! Это то что нужно!
Единственное: не исчезает рамка после постановки скрипта в паузу. 
Уже не переключатся на новые окна и за последним не следует, а просто остаётся на экране том месте,  где была в момент приостановки скрипта.
Можно её стирать на время приостановки? Вписать какую-то команду в скрипт, где прописна горячая клавиша для приостановки:

;--------------Управление скриптом
String = Скрипт работает!
    X := A_ScreenWidth/2, Y := A_ScreenHeight/2
    CoordMode, ToolTip
    StringSplit, String, String
    SetTimer, Declaration, 300
    Return
    
Declaration:
    counter++
    Declaration .= String%counter%
    ToolTip, % Declaration, X, Y
    if (counter > String0)
        Declaration := counter := ""
    Return

!1:: MsgBox, Горячая клавиша работает!
!2::
    Suspend        ; команда служит для отключения и включения горячих клавиш
    If (A_IsSuspended)
    {
    SetTimer, Declaration, OFF
    ToolTip, Скрипт остановлен!, X, Y
    Sleep, 500
    Tooltip
    }
    Else
    SetTimer, Declaration, 300
    Pause,, 1
    Return

или как-то по другому осуществить?

10

Re: AHK: Оконтуривание рамки активного окна

Вот с паузой, а уж как в свой скрипт вставить, подумай сам!

   TH = 2   ; толщина рамки

   SetWinDelay, 0
   Gui, +LastFound +ToolWindow -Caption +AlwaysOnTop +Disabled
   WinGet, ID
   Gui, Color, Red

   SetTimer, Frame, 50
   Return

Frame:
   WinGetPos, X, Y, W, H, A
   if (X = XPrev && Y = YPrev && W = WPrev && H = HPrev)
      Return

   XPrev := X, YPrev := Y, WPrev := W, HPrev := H
   X -= TH, Y -= TH, W += 2*TH, H += 2*TH

   Gui, Show, x%X% y%Y% w%W% h%H% Hide
   Options := "0-0 " W "-0 " W "-" H " 0-" H " 0-0 " TH "-" TH
      . " " W-TH "-" TH " " W-TH "-" H-TH " " TH "-" H-TH " " TH "-" TH
   DetectHiddenWindows, On
   WinSet, Region, % Options, ahk_id %ID%
   Gui, Show, NA
   Return

Pause::
   Pause,, 1
   Gui, Show, % i := !i ? "Hide" : ""
   Return
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

11

Re: AHK: Оконтуривание рамки активного окна

Всё отлично получилось!  Спасибо ОГРАМАДНОЕ!

12 (изменено: Pokerist, 2011-09-18 11:43:17)

Re: AHK: Оконтуривание рамки активного окна

Вынужден вернуться к этой теме. Всё отлично работало до последнего времени, за что большое спасибо!

  Сейчас стал работать с другим приложением и появилась проблема. Время от времени происходит зависание многоокнонного приложения в момент закрытия одного из окон.  Окно исчезает, а рамка, не переходит на новое окно, а остаётся на месте. С этого момента приложение не отзывается.

  Очень прошу помочь в решении этой проблемы. Может при изменении какич-то параметров удасться избежать этих глюков?  Готов рассмотреть какие-то другие способы выделения окна из общей массы. Не знаю, но вдруг возможны смена цвета самого окна, или заголовка, какие-то другие способы маркирования? Хотя рамка была бы явно удобнее.


На данный момент этот фрагмент кода выглядит вот так:


DetectHiddenWindows, On
SetWinDelay, 0
TH := 2
Capacity := 10
WinArray := []
Gui, +LastFound +ToolWindow -Caption +AlwaysOnTop +Disabled
WinGet, FrameID
Gui, Color, Yellow
SetTimer, Frame, 50
Loop
   {
      WinGet, ID,, A
      If (!ChangeActiveHotkey && ID != WinArray.1)
         {
            WinArray.Insert(1, ID)
            WinArray.Remove(Capacity + 1)
            CurrentWin = 1
         }
      ChangeActiveHotkey =
      WinWaitNotActive % "ahk_id" ID
   }
Return
 
Frame:
   WinGetPos, X, Y, W, H, A
   If (X = XPrev && Y = YPrev && W = WPrev && H = HPrev)
      Return
   XPrev := X, YPrev := Y, WPrev := W, HPrev := H
   X -= TH, Y -= TH, W += 2*TH, H += 2*TH
   Gui, Show, x%X% y%Y% w%W% h%H% Hide
   Options := "0-0 "W "-0 "W "-"H " 0-"H " 0-0 "TH "-"TH
   . " "W-TH "-"TH " "W-TH "-"H-TH " "TH "-"H-TH " "TH "-"TH
   WinSet, Region, % Options, % "ahk_id" FrameID
   Gui, Show, NA
   Return
 
^Left::
^Right::
^WheelDown::
   limit := A_ThisHotkey = "^Left" ? WinArray.MaxIndex() : 1
   If (CurrentWin = limit)
      Return
   ChangeActiveHotkey = 1
   CurrentWin := A_ThisHotkey = "^Left" ? ++CurrentWin : --CurrentWin
   WinActivate % "ahk_id " WinArray[CurrentWin]
   Return

Он тут, правда, совмещён с кодом по запоминанию последних активных окон, но думаю, Вам не сложно будет разобраться где - что.

  Заранее спасибо аз помощь!

13

Re: AHK: Оконтуривание рамки активного окна

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

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

14

Re: AHK: Оконтуривание рамки активного окна

Пока, вроде бы, получается.

15

Re: AHK: Оконтуривание рамки активного окна

Так ещё можно:

DetectHiddenWindows, On
SetWinDelay, 0
TH := 2
Capacity := 10
WinArray := []
Gui, +LastFound +ToolWindow -Caption +AlwaysOnTop +Disabled
WinGet, FrameID
Gui, Color, Yellow
Loop
{
   WinGet, ID,, A
   WinGetPos, X, Y, W, H, A
   If !(X = XPrev && Y = YPrev && W = WPrev && H = HPrev)
   {
      XPrev := X, YPrev := Y, WPrev := W, HPrev := H
      X -= TH, Y -= TH, W += 2*TH, H += 2*TH
      Gui, Show, x%X% y%Y% w%W% h%H% Hide
      Options := "0-0 "W "-0 "W "-"H " 0-"H " 0-0 "TH "-"TH
      . " "W-TH "-"TH " "W-TH "-"H-TH " "TH "-"H-TH " "TH "-"TH
      WinSet, Region, % Options, % "ahk_id" FrameID
      Gui, Show, NA
   }
   If (!ChangeActiveHotkey && ID != WinArray.1)
   {
      WinArray.Insert(1, ID)
      WinArray.Remove(Capacity + 1)
      CurrentWin = 1
   }
   ChangeActiveHotkey =
   WinWaitNotActive % "ahk_id" ID
}
Return

^Left::
^Right::
^WheelDown::
   limit := A_ThisHotkey = "^Left" ? WinArray.MaxIndex() : 1
   If (CurrentWin = limit)
      Return
   ChangeActiveHotkey = 1
   CurrentWin := A_ThisHotkey = "^Left" ? ++CurrentWin : --CurrentWin
   WinActivate % "ahk_id " WinArray[CurrentWin]
   Return
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

16

Re: AHK: Оконтуривание рамки активного окна

Снова зависло при закрытии окна.
teadrinker, спасибо, попробую новый код!

17 (изменено: Pokerist, 2011-09-22 04:18:51)

Re: AHK: Оконтуривание рамки активного окна

Без рамки тоже зависает, значит не в ней дело.
Спасибо за помощь!

18

Re: AHK: Оконтуривание рамки активного окна

Подскажите как сделать что бы рамка шла по границе окна, а не за ней ?

19

Re: AHK: Оконтуривание рамки активного окна

...
X-=TH-2, Y-=TH-2, W+=2*TH-4, H+=2*TH-4
...

20

Re: AHK: Оконтуривание рамки активного окна

Pokerist пишет:

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

Можно средствами AHK как-то оконтурить активное окно или как-то иначе сделать "рамку"?

у тебя наверно 7-ка стоит?
у мена 7-я винда и очень трудно различались активные окна с неактивными.
но я обошёлся без АНК скриптов.
зашёл в настройки : Перрсонализация/цвет и внешний вид окна
там я убрал прозрачность и подвигал ползунки.
теперь вроде норм всё
http://h1813090.stratoserver.net/files/previews/18_2_2012/OibDBOM1QESzcFpzTfQpIw.jpg

21

Re: AHK: Оконтуривание рамки активного окна

> Win32: Оконтуривание рамки окна (эл-та управления)

Кто может подсказать, как реализуется грамотное оконтуривание на "низком уровне", т.е. непосредственно на WinAPI?

22

Re: AHK: Оконтуривание рамки активного окна

Аскет, я вижу два способа:
1) Получать дескриптор контекста рабочего стола и рисовать на нем контуры в соответствии с координатами искомого окна — GetDC(0), BitBlt
2) Создавать свое окно и применять SetLayeredWindowEx. Грубо говоря, создаем окно с переменной прозрачностью (32 бита). Располагаем его под искомым окном.

23

Re: AHK: Оконтуривание рамки активного окна

Спасибо, ясно.

Я подумал о "трюкачестве" с SendMessage: придумать что-то с бордюром и его толщиной. Буду ковырять.

24 (изменено: Grey, 2012-03-16 02:43:37)

Re: AHK: Оконтуривание рамки активного окна

2 Аскет Ходить далеко на стал, идею взял из соседней темы.

CoordMode, Mouse
ArrayNames:={1:"R2_BLACK"      ,  2:"R2_NOTMERGEPEN"
          ,  3:"R2_MASKNOTPEN" ,  4:"R2_NOTCOPYPEN"
          ,  5:"R2_MASKPENNOT" ,  6:"R2_NOT"
          ,  7:"R2_XORPEN"     ,  8:"R2_NOTMASKPEN"
          ,  9:"R2_MASKPEN"    , 10:"R2_NOTXORPEN"
          , 12:"R2_MERGENOTPEN", 13:"R2_COPYPEN"
          , 14:"R2_MERGEPENNOT", 15:"R2_MERGEPEN"
          , 16:"R2_WHITE"}
r2:=13 ; R2_COPYPEN
BitMapDimension= ; BGRA
(Join
00000000
00000000
00000000
        00000000
        0000ffff
        00000000
                00000000
                00000000
                00000000
)
VarSetCapacity(RECT, 16, 0), VarSetCapacity(POINT,8)
VarSetCapacity(Buffer, nSize:=StrLen(BitMapDimension)//2, 0)
Loop, % nSize
   NumPut("0x"SubStr(BitMapDimension, 2*A_Index-1, 2)
                                    , Buffer, A_Index-1, "UChar")
hbrbm:=DllCall("CreateBitmap", "Int", 3
                             , "Int", 3
                             , "UInt", 1
                             , "UInt", 32
                             , "UInt", &Buffer)
hpatbr:=DllCall("CreatePatternBrush", "UInt", hbrbm)
DllCall("DeleteObject", "UInt", hbrbm)

Ctrl & LButton::
   DllCall("GetCursorPos", "UInt", &POINT)
   hWnd:=DllCall("WindowFromPoint", "UInt", NumGet(POINT)
                                  , "UInt", NumGet(POINT, 4))
   hWnd:=DllCall("GetAncestor", "UInt", hWnd
                              , "UInt", 2) ; GA_ROOT
   DllCall("GetWindowRect", "Ptr", hWnd, "Ptr", &RECT)
   hdc:=DllCall("GetDC", "UInt", 0) ; screen
   DllCall("SetROP2", "UInt", hdc, "Int", r2)
   hrgn:=DllCall("CreateRectRgn", "Int", NumGet(RECT)
                                , "Int", NumGet(RECT, 4)
                                , "Int", NumGet(RECT, 8)
                                , "Int", NumGet(RECT, 12))
   DllCall("FrameRgn", "UInt", hdc
                     , "UInt", hrgn
                     , "UInt", hpatbr
                     , "UInt", 9
                     , "UInt", 9)
   DllCall("ReleaseDC", "UInt", 0
                      , "UInt", hdc)
   DllCall("Sleep", "UInt", 1000)
   DllCall("RedrawWindow", "UInt", 0
                         , "UInt", 0
                         , "UInt", hrgn
                         , "UInt", 0x787)
   DllCall("DeleteObject", "UInt", hrgn)
   Return
Ctrl & WheelUp::TrayTip,, % ArrayNames[r2=16
                        ? r2:++r2=11 ? ++r2:r2]" ("r2 ")"
Ctrl & WheelDown::TrayTip,, % ArrayNames[r2=1
                        ? r2:--r2=11 ? --r2:r2]" ("r2 ")"
Esc::
   DllCall("DeleteObject", "UInt", hpatbr)
   DllCall("DeleteObject", "UInt", hrgn)
   ExitApp

25 (изменено: kirtech, 2012-03-10 00:48:15)

Re: AHK: Оконтуривание рамки активного окна

Аскет, расскажите подробнее что необходимо получить в итоге - рамку вокруг окна или рамку вместо бордюра и заголовка, активного окна или любого другого (дочернего под курсором мыши к примеру) и т.д. Есть несколько наполовину готовых примеров, приведу пару из них:
1.

Gui, +LastFound
hwnd:=WinExist()
hDesktop:=DllCall("GetDesktopWindow")

VarSetCapacity(RECT,16,0)
VarSetCapacity(XFORM,24,0)
NumPut(1,XFORM,0,"float")
NumPut(1,XFORM,12,"float")
NumPut(1,XFORM,16,"float")
NumPut(1,XFORM,20,"float")
hbr:=DllCall("CreateSolidBrush","uint",0x507fff) ; 0x50a4f4
hrgn:=DllCall("CreateRectRgn","int",0,"int",0,"int",0,"int",0)

DllCall( "RegisterShellHookWindow","uint",hwnd)
MsgNum:=DllCall("RegisterWindowMessage","str","SHELLHOOK")
OnMessage(MsgNum,"ShellMessage")
Return

ShellMessage(wParam,lParam)
  {
    global hwnd
    If (wParam = (HSHELL_WINDOWACTIVATED:=4))
    {
      hwnd:=lParam
      SetTimer, DrawActiveWindowFrame, -1
    }
  }

DrawActiveWindowFrame:
  If (hwnd!=hDesktop)
  {
    If (prevhwnd!=hwnd)
    {
      hdc:=DllCall("GetWindowDC","uint",prevhwnd)
      DllCall("GetWindowRgn","uint",prevhwnd,"uint",hrgn)
      DllCall("CombineRgn","uint",hrgn,"uint",hrgn,"uint",hrgn_2,"int",(RGN_XOR:=3))
      DllCall("RedrawWindow","uint",prevhwnd,"uint",0,"uint",hrgn,"uint",1|2|4|128|256|512|1024)
      DllCall("ReleaseDC","uint",hwnd,"uint",hdc)
      DllCall("DeleteObject","uint",hrgn_2)
    }
    If hwnd
    {
      hdc:=DllCall("GetWindowDC","uint",hwnd)
      DllCall("GetRandomRgn","uint",hdc,"uint",hrgn,"int",4)
      dwCount:=DllCall("GetRegionData","uint",hrgn,"uint",0,"uint",0)
      VarSetCapacity(RgnData,dwCount,0)
      DllCall("GetRegionData","uint",hrgn,"uint",dwCount,"uint",&RgnData)
      hrgn_2:=DllCall("ExtCreateRegion","uint",&XFORM,"uint",dwCount,"uint",&RgnData)
      DllCall("GetWindowRect","uint",hwnd,"uint",&RECT)
      DllCall("OffsetRgn","uint",hrgn_2,"int",-(x_offset:=NumGet(RECT)),"int",-(y_offset:=NumGet(&RECT+4)))
      DllCall("FrameRgn","uint",hdc,"uint",hrgn_2,"uint",hbr,"int",4,"int",4)
      DllCall("ReleaseDC","uint",hwnd,"uint",hdc)
      prevhwnd:=hwnd
    }
  }
Return

Return
Esc::
DllCall("DeleteObject","uint",hrgn)
DllCall("DeleteObject","uint",hbr)
DllCall("DeregisterShellHookWindow","uint",hwnd)
ExitApp

/*
RDW_INVALIDATE = 1
RDW_INTERNALPAINT = 2
RDW_ERASE = 4
RDW_VALIDATE = 8
RDW_NOINTERNALPAINT = 16
RDW_NOERASE = 32
RDW_NOCHILDREN = 64
RDW_ALLCHILDREN = 128
RDW_UPDATENOW = 256
RDW_ERASENOW = 512
RDW_FRAME = 1024
RDW_NOFRAME = 2048
*/

2.ранее, который модифицировал Grey

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

26

Re: AHK: Оконтуривание рамки активного окна

kirtech пишет:

...вопрос только в заинтересованности форумчан и в наличии свободного времени.

Первое не наблюдается, со вторым тоже весьма не однозначно.

27 (изменено: Raam, 2012-03-14 17:13:58)

Re: AHK: Оконтуривание рамки активного окна

Интерес есть.
Хотелось бы скрипт для биндинга кнопок. При этом хотелось бы обрамлять не активное окно, а элемент GUI. Это нужно для быстрого перехода между треками в Аудио Редакторе. Если точнее то хочется обрамлять и назначать клик в иконку гитары, барабана и т.д. (см Скриншот). Редактор этого сам не умеет, а для использования функция необходимая для перехода между разными инструментами в реальном времени.
http://cachepe.zzounds.com/media/quality,85/SHS7_ConsoleView-760df984399caca22c8adc86a38bff41.jpg

Структурная схема Кода:

^RButton:: ; ctrl + правый клик в иконку гитары
Создает красную рамку вокруг иконки и ждет нажатие клавиши которая будет назначена( Hotkey1). После назначения клавиши перекрашивается в желтую.

Каждый клик создает новую рамку с новым биндом(Hotkey2 , 3...).

Hotkey1::Клик в центр привязанной рамки рамки

28

Re: AHK: Оконтуривание рамки активного окна

Вам надо проверить, каким образом устроены контролы в окне Вашей программы. Если они устроены стандартно, т.е. у каждого отображается его название, то можно для начала попробовать выделить контрол под курсором. Для этого нужно воспользоваться тем скриптом, предварительно закомментировав строки вида:

...
   hWnd:=DllCall("GetAncestor", "UInt", hWnd
                              , "UInt", 2) ; GA_ROOT
...

А там видно будет...

29

Re: AHK: Оконтуривание рамки активного окна

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

Выделяется весь столбик целиком. В частном случае и этого достаточно, так как назначение скрипта биндить столбец. Конечно если возможно выделить только элемент, то это расширит область применения скрипта. 
  Попробовал на win-калькуляторе - каждая кнопочка выделяется И хоть нет необходимости биндить Нампад на калькулятор, на его теле можно и скрипт потестить... а вдруг у кого то нампад умер Спасибо за отзыв.

30

Re: AHK: Оконтуривание рамки активного окна

Чтоб не оффтопить, перенес  мой случай в отдельную тему. Однако тема создания рамки вокруг окна или элемента, которая не будет затираться по прежнему актуальна.