1 (изменено: funtaps, 2010-09-24 13:43:43)

Тема: AHK: Exposed (как в Маке)

Собственно мне очень нравится многое на маке. недавно нашёл AHK и передумал покупать мак, ибо с её помощью, можно всё настроить так же, а можно и лучше.
Захотелось, чтобы когда относительно много окон, можно было бы в них нормально разобраться, как например, в маке=)
Суть этой функции, что при нажатии на хоткей, компьютер отображает сразу все окна, но в уменьшенном размере (так, чтобы они были нормально видны на экране). и после нажатия на любое из окон, все окна возвращаются в исходный размер и позицию, а то, на которое вы нажали, становится активным.
Собственно, написал этот скрипт. Многое в нём мне не до конца нравится, но к сожалению, только начал писать такие скрипты, и многого не умею.
Из недостатков, которые мне не нравятся:
-До 9 окон
-Нет крутого затемнения фона
-Проблема с минимизированными окнами. Конечно их можно все раскрыть, но потом сложить те, которые были сложены, будет труднее. Есть ли функция, которая позволяет узнать, минимизированно ли окно?
-Хотелось бы уменьшить не размер окна, а как в маке, полностью его уменьшить. Чёрт говорю не по-русски. Хорошо бы, чтобы содержание в окне не менялось, просто размер бы окна менялся, соответственно уменьшая содержание. Чтобы вместе с окном, уменьшались шрифт, картинки, строка меню, кнопки управления окном и т.д. *Есть мысли по поводу создавания неких превьюшек, и размещения их вместо реальных окон, но боюсь это будет сильно грузить систему.

F3::                           ; Я назначил на F3, но это понятно, кому как удобно
if(ExposedOpened==""){                    ;Флаг открытых Exposed
WinGet, id, list,,, Program Manager              ;Создаю массив id с открытыми окнами
numwin=0                               ;Счётчик окон, которые я буду использовать
Loop, %id%
{
    this_id := id%A_Index%
   WinGetTitle, this_title, ahk_id %this_id%      
                             ;Получаю title текущего в цикле окна, а затем отсеиваю ненужные.
                             ;Я не знаю, как лучше сделать, чем просто назвать,те, которые мне не надо. Если кто придумает способ лучше моего, это было бы здорово
 if(this_title!="Пуск"&&this_title!="Raspisanie"&&this_title!="Custom Calendar"&&this_title!="System Controls"&&this_title!=""&&this_title!="        QIP        ")
{
numwin++     
                             ;Сохраняю массив позиций, размеров и названий окон: wind - названия, windx и windy - позиции, windw и windh - размеры
   WinGetPos, this_x, this_y, this_w, this_h, ahk_id %this_id%
wind%numwin%=%this_title%
windx%numwin%=%this_x%
windy%numwin%=%this_y%
windw%numwin%=%this_w%
windh%numwin%=%this_h%

}
}
if(numwin>1&&numwin<10){       
                             ;Я работаю с количеством окон от 2 до 9 включительно.
                             ;Это связанно с тем, как я считаю координаты и размер новых окон, а делаю я это очень очень криво. опять же, любая помощь - это здорово
Loop %numwin%
{
                                ;Собственно кривым образом, зависящим от количества окон (кстати, я не нашёл свитча он есть тут вообще?), считаю новую позицию окон
if(numwin==2){
    new_x:=((A_ScreenWidth/2)*(A_Index-1))+10
    new_y:=10
    new_w:=(A_ScreenWidth-30)/2
    new_h:=(A_Screenheight)-20
    if(windw%A_Index%<new_w)
    new_w:=windw%A_Index%
    if(windh%A_Index%<new_h)
    new_h:=windh%A_Index%
}
if(numwin==3){
    new_x:=((A_ScreenWidth/3)*(A_Index-1))+10
    new_y:=10
    new_w:=(A_ScreenWidth-40)/3
    new_h:=(A_Screenheight)-20
    if(windw%A_Index%<new_w)
    new_w:=windw%A_Index%
    if(windh%A_Index%<new_h)
    new_h:=windh%A_Index%
}
if(numwin==4){
    if(A_Index<3){
        new_x:=((A_ScreenWidth/2)*(A_Index-1))+10
        new_y:=10
    }
    else{
        new_x:=((A_ScreenWidth/2)*(A_Index-3))+10
        new_y:=(A_Screenheight/2)+10
    }
    new_w:=(A_ScreenWidth-30)/2
    new_h:=(A_Screenheight-30)/2
    if(windw%A_Index%<new_w)
    new_w:=windw%A_Index%
    if(windh%A_Index%<new_h)
    new_h:=windh%A_Index%
}
if(numwin==5||numwin==6){
    if(A_Index<4){
        new_x:=((A_ScreenWidth/3)*(A_Index-1))+10
        new_y:=10
    }
    else{
        new_x:=((A_ScreenWidth/3)*(A_Index-4))+10
        new_y:=(A_Screenheight/2)+10
    }
    new_w:=(A_ScreenWidth-40)/3
    new_h:=(A_Screenheight-30)/2
    if(windw%A_Index%<new_w)
    new_w:=windw%A_Index%
    if(windh%A_Index%<new_h)
    new_h:=windh%A_Index%
}
if(numwin==7||numwin==8||numwin==9){
    if(A_Index<4){
        new_x:=((A_ScreenWidth/3)*(A_Index-1))+10
        new_y:=10
    }
    else if(A_Index<7){
        new_x:=((A_ScreenWidth/3)*(A_Index-4))+10
        new_y:=(A_Screenheight/3)+10
    }
    else{
    new_x:=((A_ScreenWidth/3)*(A_Index-7))+10
    new_y:=((A_Screenheight/3)*2)+10
    }
    new_w:=(A_ScreenWidth-40)/3
    new_h:=(A_Screenheight-40)/3
    if(windw%A_Index%<new_w)
    new_w:=windw%A_Index%
    if(windh%A_Index%<new_h)
    new_h:=windh%A_Index%
}
the_t:=wind%A_Index%
WinMove, %the_t%, , new_x, new_y , new_w, new_h               ;Двигаю окно (Видимо, одну из этих строк можно убрать)
}
ExposedOpened:="yes"       ;Ставлю флаг и хоткеи на все кнопки мыши
Hotkey, MButton, ChooseTheWindow, On
Hotkey, LButton, ChooseTheWindow, On
Hotkey, RButton, ChooseTheWindow, On
}
}
else{                                   ;Функция, когда флаг ExposedOpened чему-нибудь равен (в данном случае "yes") 
Loop %numwin%{
the_t:=wind%A_Index%
the_x:=windx%A_Index%
the_y:=windy%A_Index%
the_w:=windw%A_Index%
the_h:=windh%A_Index%
;Ставлю окна на место. (Опять же, видимо можно было обойтись без the_t)
WinMove, %the_t%, , the_x, the_y , the_w, the_h
}
ExposedOpened:=""                             ;Флаг на место, хоткеи убрать
Hotkey, MButton, ChooseTheWindow, Off
Hotkey, LButton, ChooseTheWindow, Off
Hotkey, RButton, ChooseTheWindow, Off
}
return

ChooseTheWindow:
MouseGetPos, , , the_win_id                          ;Определение над каким окном (получаю идентификатор его) находится мышь
Send, {F3}                                          ;Мне показалось, что это самый простой способ поставить всё на место
WinActivate, ahk_id %the_win_id%                     ;Активировать выбранное окно
return

2

Re: AHK: Exposed (как в Маке)

После if нужно пробелы оставлять, иначе выдаёт ошибки. И "==" использовано не по делу, читай мануал.

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

3

Re: AHK: Exposed (как в Маке)

Ошибки без пробелов? Никогда не наблюдал такого.

4

Re: AHK: Exposed (как в Маке)

Да, у меня AHK_L стоит, в обычном не выдаёт, видимо. Ну всё равно, с пробелами лучше читается!

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

5

Re: AHK: Exposed (как в Маке)

Не знаю. Сейчас проверил на новейшем AHK_L, тоже нет ошибки. Кстати, == у меня тоже везде работает нормально.

6

Re: AHK: Exposed (как в Маке)

У меня не самый новый. А "==" у меня тоже работает, но одно "=" лишнее!

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

7

Re: AHK: Exposed (как в Маке)

Да, действительно. Привык писать на си. даже не задумывался в этом месте.
А всё-таки, можно ли как-то опознать минимизированность окна, чтобы потом его вернуть в то же состояние?

8 (изменено: teadrinker, 2010-09-24 22:50:57)

Re: AHK: Exposed (как в Маке)

Можно:

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

9

Re: AHK: Exposed (как в Маке)

teadrinker пишет:

У меня не самый новый.

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

10

Re: AHK: Exposed (как в Маке)

А у тебя какая версия — ANSI или Unicode?
Дело в том, что у ANSI-версии есть такой странный баг (по-крайней мере у меня): она букву "я" воспринимает как перевод строки, т. е. результатом скрипта

MsgBox, яMsgBox

будет два последовательно появляющихся окна MsgBox, а скрипт

; я хакер
MsgBox

вообще вообще отказывается выполнять:

Error at line 2.

Line Text: хакер
Error: This line does not contain a recognized action.

The program will exit.

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

11

Re: AHK: Exposed (как в Маке)

У меня стоят оба и плюс ещё обычный. Просто зарегистрировал для них разные расширения файлов. Проблему с "я" я докладывал Lexikos'у, уже довольно давно (здесь), но он отреагировал вяло и исправлять не стал. Она ещё проявляется при чтении/записи файлов, что делает использование ANSI-билда для русских вообще бессмысленным.

12

Re: AHK: Exposed (как в Маке)

видимо, у меня Unicode.
Кстати, обновлённая версия скрипта, с учётом минимизированных окон:

F8::
if(ExposedOpened="") {

    WinGet, id, list,,, Program Manager
    numwin=0

    Loop, %id%
    {
        this_id := id%A_Index%
        WinGetTitle, this_title, ahk_id %this_id%
        if(this_title!="Пуск"&&this_title!="Raspisanie"&&this_title!="Custom Calendar"&&this_title!="System Controls"&&this_title!=""&&this_title!="        QIP        ")
        {
            numwin++
            WinGet, windmin%numwin%, MinMax, ahk_id %this_id%
            WinRestore, ahk_id %this_id%
            WinGetPos, windx%numwin%, windy%numwin%, windw%numwin%, windh%numwin%, ahk_id %this_id%
            wind%numwin%=%this_title%
        }
    }

    if(numwin>1&&numwin<10)
    {
        Loop %numwin%
        {
            if(numwin=2) {
                new_x:=((A_ScreenWidth/2)*(A_Index-1))+10
                new_y:=10
                new_w:=(A_ScreenWidth-30)/2
                new_h:=(A_Screenheight)-20
            }
            if(numwin=3) {
                new_x:=((A_ScreenWidth/3)*(A_Index-1))+10
                new_y:=10
                new_w:=(A_ScreenWidth-40)/3
                new_h:=(A_Screenheight)-20
            }
            if(numwin=4) {
                if(A_Index<3) {
                    new_x:=((A_ScreenWidth/2)*(A_Index-1))+10
                    new_y:=10
                }
                else{
                    new_x:=((A_ScreenWidth/2)*(A_Index-3))+10
                    new_y:=(A_Screenheight/2)+10
                }
                new_w:=(A_ScreenWidth-30)/2
                new_h:=(A_Screenheight-30)/2
            }
            if(numwin=5||numwin=6) {
                if(A_Index<4) {
                    new_x:=((A_ScreenWidth/3)*(A_Index-1))+10
                    new_y:=10
                }
                else{
                    new_x:=((A_ScreenWidth/3)*(A_Index-4))+10
                    new_y:=(A_Screenheight/2)+10
                }
                new_w:=(A_ScreenWidth-40)/3
                new_h:=(A_Screenheight-30)/2
            }
            if(numwin=7||numwin=8||numwin=9) {
                if(A_Index<4) {
                    new_x:=((A_ScreenWidth/3)*(A_Index-1))+10
                    new_y:=10
                }
                else if(A_Index<7) {
                    new_x:=((A_ScreenWidth/3)*(A_Index-4))+10
                    new_y:=(A_Screenheight/3)+10
                }
                else{
                    new_x:=((A_ScreenWidth/3)*(A_Index-7))+10
                    new_y:=((A_Screenheight/3)*2)+10
                }
                new_w:=(A_ScreenWidth-40)/3
                new_h:=(A_Screenheight-40)/3
            }

            if(windw%A_Index%<new_w)
                new_w:=windw%A_Index%
            if(windh%A_Index%<new_h)
                new_h:=windh%A_Index%

            the_t:=wind%A_Index%
            WinMove, %the_t%, , new_x, new_y , new_w, new_h
        }
        ExposedOpened:="yes"
        Hotkey, MButton, ChooseTheWindow, On
        Hotkey, LButton, ChooseTheWindow, On
        Hotkey, RButton, ChooseTheWindow, On
    }
}
else{
    Loop %numwin%
    {

        the_t:=wind%A_Index%
        WinMove, %the_t%, , windx%A_Index%, windy%A_Index%, windw%A_Index%, windh%A_Index%

        if(windmin%A_Index%=1)
            WinMaximize, %the_t%
        else if(windmin%A_Index%=-1)
            WinMinimize, %the_t%

    }
    ExposedOpened:=""
    Hotkey, MButton, ChooseTheWindow, Off
    Hotkey, LButton, ChooseTheWindow, Off
    Hotkey, RButton, ChooseTheWindow, Off
}
return

ChooseTheWindow:
MouseGetPos, , , the_win_id 
Send, {F8}
WinActivate, ahk_id %the_win_id%
return

13

Re: AHK: Exposed (как в Маке)

Идея, наверное, имеет право на существование, только всё происходит слишком медленно (у меня Windows XP), особенно с восстановлением—минимизацией.
Для ускорения советую в начало скрипта добавить

SetWinDelay, 0

а строчку

WinRestore, ahk_id %this_id%

заменить на

WinHide, ahk_id %this_id%
DllCall("ShowWindow", UInt, this_id, Int, 9)   ; SW_RESTORE = 9 — восстановление, используется DllCall, т. к. работает и со скрытыми окнами.
WinShow, ahk_id %this_id%

Аналогично с WinMinimize.
ShowWindow Function

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

14

Re: AHK: Exposed (как в Маке)

Народ, вы зря так надрываетесь
http://www.goldsoftware.ru/switcher

15

Re: AHK: Exposed (как в Маке)

Недостаток Switcher в ее «задумчивости». На мощном ПК медлительность почти незаметна, но на ноутбуке задержка запуска и рывки анимации уже раздражают. Еще один нюанс — утилита работает только при включенном интерфейсе Aero, так что вам понадобится что-то новее Windows XP.

И то, и то - очень плохо=)

16

Re: AHK: Exposed (как в Маке)

Ну, это да. Кстати, насчет затемненного фона - поможет только черное полупрозрачное окно на фоне по типу:

....
gui, +toolwindow -caption
gui, color, 0x000000
gui, show, x0 y0 w%a_screenwidth% h%a_screenheight%, background
winset, transparent, 100, background
....

А вообще интересно сделать все это дело чувствительным к координатам клика и чтоб могло само кликнуть в адекватную точку реального окна даже без его активации.

17

Re: AHK: Exposed (как в Маке)

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