Задача управления окнами

Обсуждение программ nnCron и nnCron LITE

Задача управления окнами

Postby dothen » Thu, 26 May 2016, 05:44

Короче Оконный комбайн.

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

Code: Select all
# Файл:       nncron_window.tab
# Автор:      dothen
# Дата:       28.03.2017
# Версия:     1.070
# Описание:
# Оконный комбайн.
# Использование клавиш мыши для управления окнами.
# Выполнение некоторых действий в один клик по разным участкам окна.

# Подключить плагины:
# keystate.spf, windows.spf, win2tray.spf, extwords.spf, sendinput.spf, read-by-line.spf

# Подключить кронтаб nncron_extwords2.tab
# ---------------------------------------------

# Идея и наработки взяты с форума, вот некоторые ссылки:
# http://www.nncron.ru/forums/viewtopic.php?f=5&t=693
# http://www.nncron.ru/forums/viewtopic.php?f=5&t=1435
# http://www.nncron.ru/forums/viewtopic.php?f=5&t=1542

# ---------------------------------------------

#  Задача умеет:
#  Перемещение окна с помощью клавиатуры     (Ctrl+CapsLock+стрелка)
#  Изменение позиции и габаритов окна        (LShift+CapsLock и двигать мышь)
#  Открепить/закрепить панель задач          (LWin+CapsLock)
#  Перетаскивание окна мышью за любое место  (MBM внутри окна, или LCtrl+LBM внутри окна, или LCtrl+RBM внутри окна)
#  Перетаскивание с изменением высоты окна   (MBM на заголовке неразвернутого окна)
#  Изменение развернутого окна               (MBM на заголовке развернутого окна)
#  Изменение прозрачности окна               (LAlt+MBM на заголовке)
#  Регулировка общей громкости               (RBM на заголовке)
#  Регулировка громкости  "Wave"             (LShift+RBM на заголовке)
#  Регулировка баланса "Wave"                (LCtrl+RBM и LAlt+RBM на заголовке)
#  Звук ВКЛ\ВЫКЛ                             (LShift+RBM на заголовке)
#  Копирование заголовка окна в буфер обмена (LCtrl+LBM на заголовке)
#  Копир-ние дескриптора окна в буфер обмена (LAlt+LBM на заголовке)
#  TOPMOST NOTOPMOST                         (LShift+LBM на заголовке)
#  Индикация в заголовке окна (координаты, громкость, прозрачность ...)
#  Свернуть окно в трей                (RBM на кнопке [свернуть])
#  Скрыть окно                         (RBM на кнопке [развернуть])
#  Свернуть все окна                   (RBM на кнопке [закрыть], или в всплывающем меню со списком окон)
#  Восстановить все окна               (LAlt+LBM на рабочем столе, или в всплывающем меню со списком окон)
#  Показать скрытое окно               (В всплывающем меню со списком окон нижние пункты)
#  Развернуть все окна                 (В всплывающем меню со списком окон)
#  Нормальный размер все окна          (В всплывающем меню со списком окон)
#  Окна каскадом                       (В всплывающем меню со списком окон)
#  Закрыть все окна                    (В всплывающем меню со списком окон)
#  Диалог выбора окна (Alt+Ctrl+Tab)   (MBM на значке, или в левом верхнем углу экрана) нет в XP
#  Всплывающее меню со списком окон    (MBM на заголовке, или в правом верхнем углу экрана)
#  Всплывающее меню Стандартные        (RBM на заголовке. MBM на рабочем столе, или в левом нижнем углу экрана)
#  Всплывающее меню nnCron             (RBM на значке. MBM в правом нижнем углу экрана)


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


# При закрытии всех окон закрываются только те окна,
# которые есть на панели задач или в диспетчере задач.
# Окна свернутые в трей не закрываются.
# Окна которые закрываются через подтверждение - ждут подтверждения.


# ---Всплывающее меню nnCron---
# В nncron.ini надо назначить хоткей для вызова меню nnCron
# например:      MenuHotKey: "+{BREAK}"

# ---Перемещение окна стрелками.---
# Ctrl+CapsLock  Включение сдвига
# Затем удерживая CapsLock:
# CapsLock+Стрелка          нормальный сдвиг
# CapsLock+Ctrl+Стрелка     медленный сдвиг
# CapsLock+Shift+Стрелка    ускоренный сдвиг.
# Можно нажать сразу две стрелки и окно пойдёт по диагонали.
# Игнорируются развёрнутые окна, свёрнутые окна,
# а так же Program Manager и Панель задач.

# ---Изменение размеров окна.---
# Shift+CapsLock
# Курсор мыши перемещается в ближайший от него угол активного окна,
# и удерживая CapsLock двигать мышью не нажимая.
# Игнорируются развёрнутые окна, свёрнутые окна,
# и окна без рамки изменения размеров (стиль WS_THICKFRAME).


# LWin+ScrollLock
# Хоткей, переключает режим работы задачи (активный/пассивный).
# В активном режиме задача в цикле проверяет нажатия сочетаний клавиш мыши и клавиатуры.
# В пассивном режиме задача в цикле ожидает только нажатие хоткея LWin+ScrollLock

# LWin+RShift+ScrollLock
# Выход из задачи.
# Или через консоль: ExitWinCraft ON
# Задача автоматически запустится при перечитывании кронтабов (если в настройках будет ExitWinCraft OFF).
# Можно запустить вручную из консоли словом WinCraft
# ----------------------------------------------

# WINDOW-MOVE-KBD
# Перемещение окна с помощью клавиатуры (стрелками)
# Игнорируем развёрнутые окна, свёрнутые окна,
# а так же Program Manager и Панель задач.
# Если в настройках клавиатуры в ОС установлено отключение
# режима Caps Lock клавишей Shift то слово работает неправильно.

# WINDOW-DRAG
# Перетаскивание окна мышкой за любое место.
# Игнорируем развёрнутые окна, свёрнутые окна,
# а так же Program Manager и Панель задач.

# WINDOW-RESIZE
# Изменение позиции и габаритов окна.
# Игнорируем развёрнутые окна, свёрнутые окна,
# и окна без рамки изменения размеров (стиль WS_THICKFRAME).

# WINDOW-DRAG-RESIZE
# Перетаскивание с изменением высоты окна.
# Игнорируем развёрнутые окна, свёрнутые окна,
# и окна без рамки изменения размеров (стиль WS_THICKFRAME)

# WINDOW-MAX-RESIZE
# Изменение размера и позиции развернутого окна.
# Уменьшает в 2 раза развернутое окно (по вертикали и(или) горизонтали),
# и помещает окно в выбранный край(угол) экрана, выбор производится
# быстрым движением мыши в нужную сторону на заголовке окна при зажатой средней кнопке.
# Заголовок условно разделен на три одинаковых участка (левый средний и правый).
# При вертикальных жестах мыши на левом или правом участках заголовка,
# окно уменьшается сразу по вертикали и горизонтали и помещается в соответствующий верхний или нижний угол экрана.
# Чтобы уменьшить окно к верхнему краю(углу) экрана надо зажатую мышь сначала
# медленно сдвинуть с заголовка немного вниз и затем быстро сдвинуть вверх.

# WINDOW-DRAG-MAX-RESIZE
# Выполняется или WINDOW-DRAG-RESIZE или WINDOW-MAX-RESIZE

# MIXER-MOUSE
# Изменить общую громкость (нажать и сдвигать мышь).
# В Vista и выше просто эмулирует нажатие виртуальных клавиш
# VK_VOLUME_DOWN VK_VOLUME_UP без индикации уровня громкости.

# WAVEOUT-MOUSE
# Изменить громкость "Wave" (нажать и сдвигать мышь).
# В Vista и выше не работает.

# WAVEOUT-BALANCE-MOUSE
# Регулировка отдельно левого и правого каналов "Wave" (нажать и сдвигать мышь).
# В Vista и выше не работает.

# MIXER-ON-OFF
# Звук ВКЛ\ВЫКЛ
# В Vista и выше просто эмулирует нажатие виртуальной клавиши VK_VOLUME_MUTE

# WIN-TRANSPARENCY-MOUSE
# Прозрачность окна (нажать и сдвигать мышь).

# TASKBAR-LOCK-UNLOCK
# Открепить/закрепить панель задач.

# WINDOW-HIDE
# Прячет (скрывает) активное окно.

# WINDOW-SHOW
# Восстанавливает на экране окна, скрытые с помощью слова WINDOW-HIDE
# Список скрытых окон доступен в всплывающем меню Список окон.

# WIN-CLOSE-ALL
# Закрыть все окна.
# Закрываются только те окна, которые есть на панели задач или в диспетчере задач.
# Окна свернутые в трей не закрываются.
# Окна которые закрываются через подтверждение - ждут подтверждения.

# WIN-MAXIMIZE-ALL  Развернуть все окна
# WIN-MINIMIZE-ALL  Свернуть все окна
# WIN-RESTORE-ALL   Восстановить все окна
# WIN-NORMAL-ALL    Нормальный размер всем окнам
# WIN-CASCADE       Окна каскадом

# WIN-TOP-NOTOP
# Поверх всех окон ON\OFF

# CTRL-ALT-TAB
# Диалог выбора окна, только в G7(Windows 7 Or Greater).

# WIN-TITLE2CLIPBOARD
# Заголовок окна копировать в буфер обмена.

# WIN-HWND2CLIPBOARD
# Дескриптор окна (HWND) копировать в буфер обмена.

# Menu-Accessories
# Всплывающее меню - Стандартные.

# Menu-WinList
# Всплывающее меню - Список окон.
# Также показывает координаты и hwnd окон (настройки в конце).

# Menu-nnCron
# Всплывающее меню nnCron
# В nncron.ini надо задать хоткей для вызова меню nnCron
# например:       MenuHotKey: "+{BREAK}"

# ---------------------------------------------


<%


WINAPI: GetShellWindow USER32.DLL

: Desktop ( -- hwnd ) GetDesktopWindow ;
: Progman ( -- hwnd ) GetShellWindow ;
: Taskbar ( -- hwnd ) 0 Z" Shell_TrayWnd" FindWindowA ;

CREATE WIN-TITLE-BUF 260 ALLOT \ Буфер для оригинального заголовка окна.
CREATE WIN-CLASS-BUF 260 ALLOT \ Буфер для названия класса окна.

0 VALUE VK_#BUTTON
0 VALUE WIN~HWND

: WIN~CLASS ( -- a u ) WIN-CLASS-BUF ASCIIZ> ;
: WIN~TITLE ( -- a u ) WIN-TITLE-BUF ASCIIZ> ;

: Progman? ( hwnd -- ? ) Progman = WIN~CLASS S" WorkerW" COMPARE 0= OR ;
: Taskbar? ( hwnd -- ? ) Taskbar = ;

: GET-HWND ( -- ) GetForegroundWindow TO WIN~HWND ;
: GET-WINCLASS ( -- ) WIN~HWND GET-WCLASS WIN-CLASS-BUF ZPLACE ;
: GET-WINTEXT  ( -- ) WIN~HWND GET-WTEXT WIN-TITLE-BUF ZPLACE ;

: GET-WIN ( -- )
    GET-HWND
    GET-WINCLASS
    GET-WINTEXT
;

\ Отправить сообщение WM_NCHITTEST активному окну.
: WinSendMsg ( -- n )
    GET-WIN
    WIN~HWND SEND-WM_NCHITTEST \ DUP . CR
;

\ Закрыть системное или контекстное меню окна.
: SysMenuClose ( -- ) Alt( [CHAR] Ъ AKEY )Alt ;
\ Можно просто Alt или Esc но при ОТжатии RBM курсор может находится
\ за пределами заголовка окна, тогда системное меню не откроется,
\ и по Alt фокус перейдёт в строку меню если оно есть,
\ а по Esc окно закроется если оно диалоговое.

\ Изменить заголовок окна.
: WinSetTitle ( -- ) ZPAD WIN~HWND SetWindowTextA DROP ;

\ Восстановить заголовка окна.
: WinRestoreTitle ( -- ) WIN-TITLE-BUF WIN~HWND SetWindowTextA DROP ;

\ Показывает в заголовке координаты и размер окна.
: Coordinates2Title ( h w b r y x -- )
    S"  (" >ZPAD
    N>S    +ZPAD
    S" , " +ZPAD
    N>S    +ZPAD
    S" )"  +ZPAD
    S" -(" +ZPAD
    1- N>S +ZPAD
    S" , " +ZPAD
    1- N>S +ZPAD
    S" ) " +ZPAD
    N>S    +ZPAD
    S" x"  +ZPAD
    N>S    +ZPAD
    WinSetTitle
;

WINAPI: MoveWindow USER32.DLL
WINAPI: ClipCursor USER32.DLL
WINAPI: GetClipCursor USER32.DLL
WINAPI: GetSystemMetrics USER32.DLL


0
CELL -- ClipX
CELL -- ClipY
CELL -- ClipR
CELL -- ClipB
CREATE ClipRect ALLOT

CREATE rect  16 ALLOT
CREATE rect1 16 ALLOT
CREATE rect2 16 ALLOT

\ ---------------------------------------------
\ Window move, drag, resize
\ ---------------------------------------------

\ Перемещение окна с помощью клавиатуры (стрелками)
\ Если в настройках клавиатуры в ОС установлено отключение режима Caps Lock клавишей Shift то слово работает неправильно.
: WINDOW-MOVE-KBD ( -- ) { \ x y r b w h maxR maxL maxU maxD br inc -- }
\ Игнорируем развёрнутые окна, свёрнутые окна,
\ а так же Program Manager и Панель задач
    WIN~HWND MAXIMIZED?
    WIN~HWND MINIMIZED? OR
    WIN~HWND Progman?
    WIN~HWND Taskbar? OR OR
    IFNOT
      15 TO br   \ Край окна шириной br остаётся на рабочем столе.
      WIN~HWND WIN-RECT TO x TO y TO r TO b
      r x - TO w
      b y - TO h

      WIN~HWND TOPMOST? IF Desktop WIN-RECT ELSE GetWorkArea THEN
      w NEGATE br + + TO maxL
      h NEGATE br + + TO maxU
      br - TO maxR
      br - TO maxD

      BEGIN VK_CAPITAL KEY-PRESSED? WHILE \ Пока нажата CapsLock
        10 TO inc \ Величина сдвига за один цикл.
        VK_SHIFT   KEY-PRESSED? IF 30 TO inc THEN \ Shift Быстрее.
        VK_CONTROL KEY-PRESSED? IF  1 TO inc THEN \ Ctrl Медленнее.
        VK_DOWN    KEY-PRESSED? IF y inc + maxD MIN TO y THEN
        VK_UP      KEY-PRESSED? IF y inc - maxU MAX TO y THEN
        VK_LEFT    KEY-PRESSED? IF x inc - maxL MAX TO x THEN
        VK_RIGHT   KEY-PRESSED? IF x inc + maxR MIN TO x THEN
        x y WIN-MOVE
        x w + TO r
        y h + TO b
        h w b r y x Coordinates2Title
        20 PAUSE
      REPEAT
    THEN
    VK_CAPITAL WAIT-KUP CapsLock Shift \ Восстановить предыдущее состояние (Shift на случай если он переключает режим Caps Lock)
    WinRestoreTitle
;

\ Перетаскивание окна мышкой за любое место.
\ Возвращает ноль если мышь в исходном месте, иначе не ноль.
: WINDOW-DRAG ( -- ? )
\ Игнорируем развёрнутые окна, свёрнутые окна,
\ а так же Program Manager и Панель задач
    FALSE
    WIN~HWND MAXIMIZED?
    WIN~HWND MINIMIZED? OR
    WIN~HWND Progman?
    WIN~HWND Taskbar? OR OR
    IFNOT
      rect GetClipCursor DROP \ Сохранили ограничение курсора.
      WIN~HWND TOPMOST? IF Desktop WIN-RECT ELSE GetWorkArea THEN
      SP@ ClipCursor DROP 2DROP 2DROP \ Установили новое ограничение курсора.

      WIN~HWND WIN-RECT
      CURSOR-INRECT? \ Для корректной работы с модальными окнами проверяем где мышь - в окне или нет?
      IF             \ т.к. они перетаскиваются даже если мышь нажата за пределами модального окна.
        WIN~HWND WIN-POS
        MOUSE-POS 2DUP 2>R
        ROT - SWAP ROT -             \ Разница координат мыши и окна
        BEGIN VK_#BUTTON KEY-PRESSED? WHILE
          2DUP MOUSE-POS
          SWAP ROT - SWAP ROT -      \ Новые координаты для окна

          2DUP SWAP
          S"  x=" >ZPAD
          N>S     +ZPAD
          S"  y=" +ZPAD
          N>S     +ZPAD
          WinSetTitle

          WIN-MOVE
          10 PAUSE
        REPEAT
        2DROP               \ Удаляем разницу координат мыши и окна.
        MOUSE-POS 2R>
        D- OR 0 <> NIP
      THEN
      rect ClipCursor DROP \ Восстановили ограничение курсора.
    THEN
 WinRestoreTitle
;

\ Можно задать определенные окна которые можно перемещать.
\ Пример:
\ SCONSTANT WinPattern1 /(ConsoleWindowClass)|(spfwinclass)|(#32770)/
\ SCONSTANT WinPattern2 /.*([Cc]alc)|([Кк]алькулятор).*/
\ WinPattern1 WIN-ACTIVE? IF WINDOW-DRAG DROP THEN
\ WinPattern1 WIN-ACTIVE? IF GET-WIN WINDOW-MOVE-KBD THEN

\ Изменение позиции и габаритов окна.
: WINDOW-RESIZE ( -- )
  { \ x y r b w h mx my area Xmin Xmax Ymin Ymax Rmax Bmax Wmin Hmin -- }
\ Игнорируем развёрнутые окна, свёрнутые окна,
\ и окна без рамки изменения размеров (стиль WS_THICKFRAME)
    WIN~HWND MAXIMIZED? WIN~HWND MINIMIZED? OR 0=
    -16 WIN~HWND GetWindowLongA 0x40000 AND 0<>  \ #define GWL_STYLE (-16) #define WS_THICKFRAME 0x40000
    AND
    IF
      34 GetSystemMetrics TO Wmin \ Минимальная изменяемая ширина окна  #define SM_CXMINTRACK 34
      35 GetSystemMetrics TO Hmin \ Минимальная изменяемая высота окна  #define SM_CYMINTRACK 35

      rect GetClipCursor DROP \ Сохранили ограничение курсора.
      WIN~HWND TOPMOST? IF Desktop WIN-RECT ELSE GetWorkArea THEN

      2DUP  TO Xmin TO Ymin
      2OVER TO Rmax TO Bmax
      Rmax Wmin - TO Xmax
      Bmax Hmin - TO Ymax

      3 + >R 3 + >R 2- >R 2- R> R> R>
      SP@ ClipCursor DROP 2DROP 2DROP \ Установили новое ограничение курсора.

      WIN~HWND WIN-RECT TO x TO y TO r TO b

\ Устанавливаем координаты окна в пределах рабочего стола.
          x Xmin MAX Xmax MIN TO x
          y Ymin MAX Ymax MIN TO y
          r Wmin MAX Rmax MIN TO r
          b Hmin MAX Bmax MIN TO b
          r x - TO w
          b y - TO h

      MOUSE-POS TO my TO mx
      r mx - mx x - > IF x 3 + 1 TO area ELSE r 3 - 2 TO area THEN \ В area запоминаем выбранный угол окна
      b my - my y - > IF y 3 + ELSE b 3 - area 2+ TO area THEN     \ 1=(x,y) 2=(r,y) 3=(x,b) 4=(r,b)

      MOUSE-MOVE \ Курсор мыши перемещается в ближайший от него угол окна.

      BEGIN VK_CAPITAL KEY-PRESSED?  \ Пока нажата CapsLock и не нажата LBM
            VK_LBUTTON KEY-PRESSED? 0= AND WHILE
        mx my MOUSE-POS TO my TO mx my - SWAP mx - OR
        IF
          area
          CASE
            1 OF
                mx 3 - TO x
                my 3 - TO y
                r Wmin - x < IF x Wmin + TO r THEN
                b Hmin - y < IF y Hmin + TO b THEN
              ENDOF
            2 OF
                mx 3 + TO r
                my 3 - TO y
                r Wmin - x < IF r Wmin - TO x THEN
                b Hmin - y < IF y Hmin + TO b THEN
              ENDOF
            3 OF
                mx 3 - TO x
                my 3 + TO b
                r Wmin - x < IF x Wmin + TO r THEN
                b Hmin - y < IF b Hmin - TO y THEN
              ENDOF
            4 OF
                mx 3 + TO r
                my 3 + TO b
                r Wmin - x < IF r Wmin - TO x THEN
                b Hmin - y < IF b Hmin - TO y THEN
              ENDOF
          ENDCASE

          x Xmin MAX Xmax MIN TO x
          y Ymin MAX Ymax MIN TO y
          r Wmin MAX Rmax MIN TO r
          b Hmin MAX Bmax MIN TO b
          r x - TO w
          b y - TO h

          -1 h w y x WIN~HWND MoveWindow DROP
          h w b r y x  Coordinates2Title
        THEN
        20 PAUSE
      REPEAT
      rect ClipCursor DROP \ Восстановили ограничение курсора.
    THEN
    VK_CAPITAL WAIT-KUP CapsLock \ Восстановить предыдущее состояние
    WinRestoreTitle
;

\ Перетаскивание с изменением высоты окна.
\ Возвращает ноль если мышь не перемещалась, иначе не ноль.
\ На правой кнопке работает не так как надо.
: WINDOW-DRAG-RESIZE ( -- ? )
  { \ x y r b w h mx my Xmin Ymin Ymax Rmax Bmax Wmax Hmax Hmin f0 f1 f2 m -- ? }
\ Игнорируем развёрнутые окна, свёрнутые окна,
\ и окна без рамки изменения размеров (стиль WS_THICKFRAME)
    FALSE TO m \ Если m=TRUE то мышь перемещалась (для случая когда мышь становится в исходное положение).
    WIN~HWND MAXIMIZED? WIN~HWND MINIMIZED? OR 0=
    -16 WIN~HWND GetWindowLongA 0x40000 AND 0<>  \ #define GWL_STYLE (-16) #define WS_THICKFRAME 0x40000
    AND
    IF
      35 GetSystemMetrics TO Hmin \ Минимальная изменяемая высота окна  #define SM_CYMINTRACK 35
      GetWorkArea TO Xmin TO Ymin TO Rmax TO Bmax
      Rmax Xmin - TO Wmax
      Bmax Ymin - TO Hmax
      Bmax Hmin - TO Ymax

      rect GetClipCursor DROP \ Сохранили ограничение курсора.
      Bmax Rmax Ymin Xmin
      SP@ ClipCursor DROP 2DROP 2DROP \ Ограничили курсор клиентской областью рабочего стола.

\ Если ширина окна больше рабочего стола то уменьшаем окно
\ с той стороны которая вышла за пределы рабочего стола.
      WIN~HWND WIN-RECT TO x TO y TO r TO b
      r x - TO w
      b y - TO h
      w Wmax > x Xmin < AND IF x w Wmax - + TO x Wmax TO w THEN
      w Wmax > r Rmax > AND IF r w Wmax - - TO r Wmax TO w THEN

      h w b r y x Coordinates2Title

      MOUSE-POS

\ Вычисляем и запоминаем прямоугольник ограничения курсора.
\ Это ограничение не позволит перемещать окно за пределы рабочего стола.
      OVER x - Xmin +              ClipRect ClipX !
      OVER r SWAP - Rmax SWAP - 1+ ClipRect ClipR !
      DUP y - Ymin +               ClipRect ClipY !
      DUP y - Ymax + 1+            ClipRect ClipB !
\ Если до цикла установить ClipRect ограничение то курсор и окно будут
\ сразу прыгать в это ограничение если курсор находится за пределами ограничения.

      Bmax
      ClipRect ClipR @
      Ymin
      ClipRect ClipX @
      SP@ rect1 16 CMOVE 2DROP 2DROP

      ClipRect ClipB @
      Rmax
      ClipRect ClipY @
      Xmin
      SP@ rect2 16 CMOVE 2DROP 2DROP

      TRUE TO f0
      TRUE TO f1
      TRUE TO f2

      BEGIN VK_#BUTTON KEY-PRESSED?
            VK_LBUTTON KEY-PRESSED? 0= AND WHILE
        MOUSE-POS 2DUP 2ROT ROT SWAP - TO my - TO mx \ Смещение мыши.
        mx my OR
        IF
\ Вычисляем новую позицию и высоту окна.
          x mx + TO x
          y my + TO y
          h my - Hmin MAX TO h
          x w  + TO r
          y h  + TO b

          f0 IF \ f0=TRUE до тех пор пока окно выходит за рабочий стол.
            TRUE TO m
            b Bmax > IF Bmax TO b b y - TO h THEN \ Если нижний край окна ниже рабочего стола.
            y Ymax > IF y Hmin + TO b Hmin TO h THEN \ Если заголовок ниже рабочего стола.

            x Xmin  10 -  < NOT \ 10 это люфт чтобы легче фиксировать(останавливать) широкие окна.
            r Rmax  10 +  > NOT AND
            y Ymin < NOT
            b Bmax > NOT AND AND \ Если всё окно на рабочем столе.
            IF ClipRect ClipCursor DROP FALSE TO f0 FALSE TO f1 FALSE TO f2 THEN \ Устанавливаем основное ограничение курсора.

            f1 IF
              x Xmin  10 -  < NOT
              r Rmax  10 +  > NOT AND \ Если левый и правый край окна на рабочем столе.
              IF rect1 ClipCursor DROP FALSE TO f1 THEN \ Горизонтальное ограничение.
            THEN

            f2 IF
              y Ymin < NOT
              b Bmax > NOT AND \ Если верхний и нижний край окна на рабочем столе.
              IF rect2 ClipCursor DROP FALSE TO f2 THEN \ Вертикальное ограничение.
            THEN
          THEN

          -1 h w y x WIN~HWND MoveWindow DROP
          h w b r y x Coordinates2Title
        THEN
        20 PAUSE
      REPEAT
      2DROP
      rect ClipCursor DROP
    THEN
    m
    WinRestoreTitle
;

\ Уменьшает в 2 раза развернутое окно (по вертикали и(или) горизонтали),
\ и помещает окно в выбранный край(угол) экрана, выбор производится
\ быстрым движением мыши в нужную сторону на заголовке окна при зажатой средней кнопке.
\ Заголовок условно разделен на три одинаковых участка (левый средний и правый).
\ При вертикальных жестах мыши на левом или правом участках заголовка,
\ окно уменьшается сразу по вертикали и горизонтали и помещается в соответствующий верхний или нижний угол экрана.
\ Чтобы уменьшить окно к верхнему краю(углу) экрана надо зажатую мышь сначала
\ медленно сдвинуть с заголовка немного вниз и затем быстро сдвинуть вверх.
: WINDOW-MAX-RESIZE ( -- ? ) { \ x y r b w h mx my flag caption speed -- ? }
    FALSE
    WIN~HWND MAXIMIZED?
    -16 WIN~HWND GetWindowLongA 0x40000 AND 0<> \ #define GWL_STYLE (-16) #define WS_THICKFRAME 0x40000
    AND
    IF
      WIN~HWND WIN-RECT TO x TO y TO r TO b
      r x - TO w
      b y - TO h
      h w b r y x Coordinates2Title

      GetWorkArea TO x TO y TO r TO b
      r x - TO w
      b y - TO h
      40 TO speed \ Чем больше значение тем меньше чувствительность

      TRUE TO flag
      MOUSE-POS 2DUP
      BEGIN VK_#BUTTON KEY-PRESSED? flag AND WHILE
        20 PAUSE
        MOUSE-POS 2DUP 2ROT ROT SWAP - TO my - TO mx
        mx speed 1+ < mx speed 1+ NEGATE > AND
        my speed 1+ < my speed 1+ NEGATE > AND AND TO flag
      REPEAT

      flag 0=
      IF    \ на стеке: false и координаты мыши x0 y0 x y
        2OVER DROP x w 3 / x + WITHIN \ Мышь была нажата на левой трети заголовка.
        IF
          1 TO caption
        ELSE
          2OVER DROP r w 3 / - r WITHIN \ Мышь была нажата на правой трети заголовка.
          IF 3 TO caption  THEN
        THEN

        my ABS speed >
        IF
          caption 1 = IF w 2 / TO w x w + TO r THEN
          caption 3 = IF w 2 / TO w r w - TO x THEN
          my speed > IF h 2 / TO h b h - TO y THEN
          my speed NEGATE < IF h 2 / TO h y h + TO b THEN
        THEN

        mx speed > IF w 2 / TO w r w - TO x THEN
        mx speed NEGATE < IF w 2 / TO w x w + TO r THEN

        1 WIN~HWND ShowWindow DROP \ #define SW_SHOWNORMAL 1
        -1 h w y x WIN~HWND MoveWindow DROP
      THEN
      D- OR 0 <> NIP
    THEN
    WinRestoreTitle
;

\ Выполняется или WINDOW-DRAG-RESIZE или WINDOW-MAX-RESIZE
\ Возвращает ноль если мышь не перемещалась, иначе не ноль.
: WINDOW-DRAG-MAX-RESIZE ( -- ? )
    WINDOW-DRAG-RESIZE WINDOW-MAX-RESIZE OR
;

\ ---------------------------------------------
\ Volume
\ ---------------------------------------------

\ Изменить общую громкость (нажать и сдвигать мышь).
\ Возвращает ноль если мышь на том же месте, иначе не ноль.
\ Эмулирует нажатие виртуальных клавиш VK_VOLUME_DOWN VK_VOLUME_UP
: Mixer-Mouse ( -- ? ) { \ mx my -- ? }
    MOUSE-POS 2DUP
    BEGIN VK_#BUTTON KEY-PRESSED? WHILE
      20 PAUSE
      MOUSE-POS 2DUP 2ROT ROT SWAP - TO my - TO mx   \ my . mx . CR
      mx my OR
      IF
        my ABS mx ABS > IF my ELSE mx THEN
        0 > IF Volume_up ELSE Volume_down THEN
          S"   Громкость" >ZPAD
          WinSetTitle
      THEN
    REPEAT
    D- OR 0 <>
    WinRestoreTitle
;

\ Изменить общую громкость (нажать и сдвигать мышь).
\ Возвращает ноль если мышь на том же месте, иначе не ноль.
: Mixer-Mouse-XP ( -- ? ) { \ mx my -- ? }
    MIXER-STATE IFNOT 0 MIXER-VOLUME! MIXER-UNMUTE THEN
    MOUSE-POS 2DUP
    BEGIN VK_#BUTTON KEY-PRESSED? WHILE
      20 PAUSE
      MOUSE-POS 2DUP 2ROT ROT SWAP - TO my - TO mx
      mx my OR
      IF
        my ABS mx ABS > IF my my ABS ELSE mx mx ABS THEN
        DUP 20 < IF / ELSE / 10 * THEN MIXER+ \ При быстром передвижении мыши шаг 10%
          S"   Громкость Общая: " >ZPAD
          MIXER-VOLUME@ N>S +ZPAD
          WinSetTitle
      THEN
    REPEAT
    D- OR 0 <>
    WinRestoreTitle
;

\ Изменить общую громкость (нажать и сдвигать мышь).
\ Возвращает ноль если мышь на том же месте, иначе не ноль.
: MIXER-MOUSE ( -- ? )
    Win-XP? IF Mixer-Mouse-XP ELSE Mixer-Mouse THEN
;


WINAPI: waveOutSetVolume winmm.dll
WINAPI: waveOutGetVolume winmm.dll

\ nnlib.zip\~nn\lib\win\mm\mixer.f
\ : */R DUP 2/ >R */MOD SWAP R> > IF 1+ THEN ;
: */Ro DUP 2/ >R */MOD SWAP R> < 1+ + ;

: (waveOutGetVolume) ( -- vol ) 0 SP@ 0 waveOutGetVolume DROP ;
\ Младшее слово - громкость левого канала, старшее — правого.
\ http://compress.ru/article.aspx?id=10882&part=part011ext1#47
\ http://compress.ru/article.aspx?id=10882

: WAVEOUT-SETVOLUME ( % -- )
    0xFFFF 100 */Ro (waveOutGetVolume) 0x0000FFFF AND + 0xFFFF MIN 0 MAX
    DUP 16 LSHIFT OR 0 waveOutSetVolume DROP
;

: WAVEOUT-LGETVOLUME ( -- % ) (waveOutGetVolume) 0x0000FFFF AND 100 0xFFFF */Ro ;

: WAVEOUT-RGETVOLUME ( -- % ) (waveOutGetVolume) 16 RSHIFT 100 0xFFFF */Ro ;


: WAVEOUT-LSETVOLUME ( % -- )
    0xFFFF 100 */Ro (waveOutGetVolume)
    DUP >R 0x0000FFFF AND + 0xFFFF MIN 0 MAX
        R> 0xFFFF0000 AND OR 0 waveOutSetVolume DROP
;

: WAVEOUT-RSETVOLUME ( % -- )
    0xFFFF 100 */Ro (waveOutGetVolume)
    DUP >R 16 RSHIFT + 0xFFFF MIN 0 MAX 16 LSHIFT
        R> 0x0000FFFF AND OR 0 waveOutSetVolume DROP
;

\ Изменить громкость "Wave" (нажать и сдвигать мышь).
\ Возвращает ноль если мышь на том же месте, иначе не ноль.
: Waveout-Mouse-XP ( -- ? ) { \ mx my -- ? }
    MOUSE-POS 2DUP
    BEGIN VK_#BUTTON KEY-PRESSED? WHILE
      20 PAUSE
      MOUSE-POS 2DUP 2ROT ROT SWAP - TO my - TO mx
      mx my OR
      IF
        my ABS mx ABS > IF my my ABS ELSE mx mx ABS THEN
        DUP 20 < IF / ELSE / 10 * THEN WAVEOUT-SETVOLUME \ При быстром передвижении мыши шаг 10%
          S"   Громкость Звук: " >ZPAD
          WAVEOUT-LGETVOLUME N>S +ZPAD
          WinSetTitle
      THEN
    REPEAT
    D- OR 0 <>
    WinRestoreTitle
;

\ Изменить громкость "Wave" (нажать и сдвигать мышь).
\ В Vista и выше не работает.
: WAVEOUT-MOUSE ( -- ? )
    Win-XP? IF Waveout-Mouse-XP ELSE FALSE THEN
;

\ Регулировка отдельно левого и правого каналов "Wave" (нажать и сдвигать мышь).
\ Возвращает ноль если мышь на том же месте, иначе не ноль.
: Waveout-Balance-Mouse-XP ( -- ? ) { \ mx my percent -- ? }
    MOUSE-POS 2DUP
    BEGIN VK_#BUTTON KEY-PRESSED? WHILE
      20 PAUSE
      MOUSE-POS 2DUP 2ROT ROT SWAP - TO my - TO mx
      mx my OR
      IF
        my ABS mx ABS > IF my my ABS ELSE mx mx ABS THEN
        DUP 20 < IF / ELSE / 10 * THEN TO percent \ При быстром передвижении мыши шаг 10%
        VK_LMENU KEY-PRESSED?
        IF
          percent WAVEOUT-RSETVOLUME WAVEOUT-RGETVOLUME
            S"   Громкость Правый: " >ZPAD
            N>S +ZPAD
            WinSetTitle
        THEN
        VK_LCONTROL KEY-PRESSED?
        IF
          percent WAVEOUT-LSETVOLUME WAVEOUT-LGETVOLUME
            S"   Громкость Левый: " >ZPAD
            N>S +ZPAD
            WinSetTitle
        THEN
      THEN
    REPEAT
    D- OR 0 <>
    WinRestoreTitle
;

\ Регулировка отдельно левого и правого каналов "Wave" (нажать и сдвигать мышь).
\ В Vista и выше не работает.
: WAVEOUT-BALANCE-MOUSE ( -- ? )
    Win-XP? IF Waveout-Balance-Mouse-XP ELSE FALSE THEN
;

\ Звук ВКЛ\ВЫКЛ
: Mixer-On-Off-XP ( -- )
    MIXER-STATE
    IFNOT
      MIXER-UNMUTE S"   Звук: ВКЛ."
    ELSE
      MIXER-MUTE S"   Звук: ВЫКЛ."
    THEN
    >ZPAD
    WinSetTitle
    500 PAUSE
    WinRestoreTitle
;

\ Звук ВКЛ\ВЫКЛ
\ Эмулирует нажатие виртуальной клавиши VK_VOLUME_MUTE
: Mixer-On-Off ( -- )
    Volume_mute
    S"   Звук: ВКЛ/ВЫКЛ" >ZPAD
    WinSetTitle
    500 PAUSE
    WinRestoreTitle
;

\ Звук ВКЛ\ВЫКЛ
: MIXER-ON-OFF ( -- )
    Win-XP? IF Mixer-On-Off-XP ELSE Mixer-On-Off THEN
;

\ ---------------------------------------------
\ Transparency
\ ---------------------------------------------

WINAPI: GetLayeredWindowAttributes USER32.DLL

\ Получить текущую прозрачность окна.
: GET-ALPHA ( hwnd -- u )
    >R 0 SP@ 0 SWAP 0 R> GetLayeredWindowAttributes DROP
;

\ Прозрачность окна (нажать и сдвигать мышь).
\ На правой кнопке работает не так как надо.
\ Возвращает ноль если мышь на том же месте, иначе не ноль.
: WIN-TRANSPARENCY-MOUSE ( -- ? ) { \ tr -- ? }
    MOUSE-POS DROP DUP
    WIN~HWND GET-ALPHA
    DUP IF 255 XOR THEN TO tr
    BEGIN VK_#BUTTON KEY-PRESSED? WHILE
      50 PAUSE
      MOUSE-POS DROP DUP ROT - ?DUP
      IF
        tr + 200 MIN 0 MAX TO tr \ Вместо 200 можно и 255
        WIN~HWND tr (WIN-TRANSPARENCY)
          S"   Прозрачность: " >ZPAD
          tr N>S +ZPAD
          WinSetTitle
      THEN
    REPEAT
    - 0 <>
    WinRestoreTitle
;

\ ---------------------------------------------
\ Taskbar
\ ---------------------------------------------

\ Параметры сообщения WM_COMMAND для панели задач.
\ 305 Меню "Пуск"
\ 401 Меню "Пуск" Выполнить...
\ 402 Меню "Пуск" Выход из системы (с запросом)
\ 403 Окна каскадом
\ 404 Окна сверху вниз
\ 405 Окна слева направо
\ 407 Свернуть все окна
\ 408 Настройка даты/времени
\ 413 Свойства панели задач
\ 415 Свернуть все окна
\ 416 Отменить Свернуть все, Каскадом, Окна рядом
\ 419 Свернуть все окна
\ 420 Диспетчер задач
\ 421 Настройка уведомлений
\ 424 Закрепить панель задач (ON/OFF)
\ 503 Центр справки и поддержки
\ 505 Панель управления
\ 506 Завершение работы
\ 510 Принтеры и факсы

\ Отправить сообщение WM_COMMAND  \ #define WM_COMMAND 273
: SEND-WM-COMMAND ( n hwnd -- )
   >R 0 SWAP 273 R> SendMessageA DROP
;

\ Открепить/закрепить панель задач.
: TASKBAR-LOCK-UNLOCK ( -- ) { \ x y r b -- }
    Taskbar TO WIN~HWND
    424 WIN~HWND SEND-WM-COMMAND \ Открепить/закрепить.
    WIN~HWND WIN-RECT TO x TO y TO r TO b
\ Помещаем курсор на рамку изменения размера панели задач.
    y
    IF
      MOUSE-POS DROP y MOUSE-MOVE \ Панель снизу
    ELSE
      x
      IF
        x MOUSE-POS NIP MOUSE-MOVE \ Панель справа
      ELSE
        b r >
        IF
          r 1- MOUSE-POS NIP MOUSE-MOVE \ Панель слева
        ELSE
          r b >
          IF
            MOUSE-POS DROP b 1- MOUSE-MOVE \ Панель сверху
          THEN
        THEN
      THEN
    THEN
    VK_CAPITAL WAIT-KUP
;

\ : WIN-CASCADE      ( -- ) 403 Taskbar SEND-WM-COMMAND ; \ Окна каскадом
\ : WIN-MINIMIZE-ALL ( -- ) 415 Taskbar SEND-WM-COMMAND ; \ Свернуть все окна
\ : WIN-UNDO-ALL     ( -- ) 416 Taskbar SEND-WM-COMMAND ; \ Отменить Свернуть все, Каскадом, Рядом

\ -------------------------------------------------
\ Фильтр окон
\ -------------------------------------------------

\ WINAPI: GetWindow USER32.DLL

: WIN-VALID? ( hwnd -- ? ) { hwnd -- ? }
    FALSE
    hwnd VISIBLE?       \ visible window only
    IF
\      4 hwnd GetWindow \ top level window only    \ #define GW_OWNER 4
\      IFNOT
\        hwnd Progman?
\        IFNOT
          hwnd GetWindowTextLengthA    \ windows with title text only
          IF
            -16 hwnd GetWindowLongA 0xCF0000 AND \ #define GWL_STYLE (-16) \ #define WS_OVERLAPPEDWINDOW 0xCF0000
            IF
              hwnd WIN-RECT ROT - -ROT - OR \ окна ненулевого размера ("2x2 Калькулятор", "InqSoft Window Scanner"...)
              IF
                DROP TRUE
              THEN
            THEN
          THEN
\        THEN
\      THEN
    THEN
;
\ FOR-WINDOWS находит не все окна которые появляются на панели задач.
\ WIN-VALID? выбирает и диалоговые (модальные) окна.

: WIN-HIDE? ( hwnd -- ? ) { hwnd -- ? }
    FALSE
    hwnd IsWindow
    IF
      hwnd VISIBLE?
      IFNOT
        hwnd GetWindowTextLengthA
        IF
          -16 hwnd GetWindowLongA 0xCF0000 AND \ #define GWL_STYLE (-16) \ #define WS_OVERLAPPEDWINDOW 0xCF0000
          IF
            hwnd WIN-RECT ROT - -ROT - OR \ окна ненулевого размера
            IF
              DROP TRUE
            THEN
          THEN
        THEN
      THEN
    THEN
;


\ ---------------------------------------------
\ Список окон
\ ---------------------------------------------
VARIABLE wincounter
VARIABLE DetailMenuWinList
0 VALUE winlist

: N>HEX ( n -- a u )  \ DECIMAL to HEX
    BASE @ SWAP HEX
    S>D <# # # # # # # # # #>
    ROT BASE !
;

: +winlist ( a u -- ) winlist +ZPLACE ;

: WinText2List ( a u hwnd -- )
    DUP >R
    N>S    +winlist \ В начае каждой строки пишем hwnd окна это будет ID пункта меню.
    S" _"  +winlist
    wincounter 1+! wincounter @
    N>S     +winlist
    S"   "  +winlist
    100 MIN +winlist \ Длинные заголовки укорачиваем до 100 символов.
    HTAB    +winlist
    DetailMenuWinList @
    IF
      WIN-VER 6 <   \ ОС по разному делает выравнивание после табуляции, в XP по левому краю, в 7 по правому.
      IF \ Если XP и ниже.
        R@ N>HEX +winlist \ Пишем hwnd
        S"   "  +winlist
      THEN
      S" ("  +winlist
      R@ MINIMIZED?
      IF
        S" --" +winlist
      ELSE
        R@ MAXIMIZED?
        IF
          S" +" +winlist
        ELSE
          R@ WIN~RECT \ Пишем координаты окна.
          N>S     +winlist
          S" , "  +winlist
          N>S     +winlist
          S" )-(" +winlist
          N>S     +winlist
          S" , "  +winlist
          N>S     +winlist
        THEN
      THEN
      S" )" +winlist
      R@ WIN-SIZE SWAP
      S"  " +winlist
      N>S   +winlist
      S" x" +winlist
      N>S   +winlist
      R@ TOPMOST? IF S"   T  " ELSE S"      " THEN +winlist
      WIN-VER 5 >
      IF R@ N>HEX +winlist THEN \ Пишем hwnd
    THEN RDROP
    CRLF    +winlist
;

:NONAME { xt hwnd -- }
    hwnd WIN-VALID?
    IF
      256 PAD hwnd GetWindowTextA
      PAD SWAP hwnd xt EXECUTE
    THEN
    TRUE
; WNDPROC: WinEnumProc

: WIN~ENUM ( -- )
    ['] WinText2List ['] WinEnumProc EnumWindows DROP
;

: WINLIST-BUILD ( -- )
\                      winlist 0<> IF S" winlist no FREE" TYPE CR THEN \ отладка
    10 Kb ALLOCATE THROW TO winlist
    winlist OFF
    wincounter OFF
    WIN~ENUM
;

: WINLIST-DEL ( -- )
    winlist ?DUP IF FREE THROW 0 TO winlist THEN
;

\ ---------------------------------------------
\ Управление окнами
\ ---------------------------------------------

\ Файловая переменная для сохранения идентификаторов окон скрытых с помощью слова WINDOW-HIDE
fVAR hide_windows

: WINHLST-BUILD ( -- )
\                      winlist 0<> IF S" winlist no FREE" TYPE CR THEN \ отладка
    10 Kb ALLOCATE THROW TO winlist
    winlist OFF
    wincounter OFF
    LE-GET 2>R
    LE-WIN
    hide_windows OVER >R
    FOR-LINES
      FOUND-LINE NIP
      IF
        FOUND-LINE S>NUM DUP WIN-HIDE? IF DUP GET-WTEXT ROT WinText2List
        ELSE DROP S" bad  " +winlist FOUND-LINE +winlist CRLF +winlist THEN \ Недоделано.
      THEN
    ;FOR-LINES
    R> FREE DROP
    2R> LE-SET
;

\ Прячет (скрывает) активное окно.
: WINDOW-HIDE ( -- )
    hide_windows NIP 0= IF S" " TO hide_windows THEN
    0 WIN~HWND ShowWindow DROP  \ #define SW_HIDE 0
    WIN~HWND N>S CRLF hide_windows
    OVER >R
    >ZPAD +ZPAD +ZPAD ZPAD> TO hide_windows
    R> FREE DROP
;

\ Восстанавливает на экране окна, скрытые с помощью слова WINDOW-HIDE
: WINDOW-SHOW ( hwnd -- )
    DUP >R WIN-HIDE?
    IF
\      9 R@ ShowWindow DROP  \ #define SW_RESTORE 9 \ Некоторые окна неправильно перерисовываются.
      5 R@ ShowWindow DROP  \ #define SW_SHOW 5
      R@ WinActivate
    THEN
    hide_windows
    2DUP R@ N>S CropFromString 2- >ZPAD
    2DUP R> N>S LCropAfterString +ZPAD
    ZPAD> TO hide_windows
    DROP FREE DROP
;

\ Закрыть все окна
\ Закрываются только те окна, которые есть на панели задач или в диспетчере задач (хинты nnCron).
\ Окна свернутые в трей не закрываются.
\ Окна которые закрываются через подтверждение - ждут подтверждения.
: WIN-CLOSE-ALL ( -- )
    S" Закрыть все окна на рабочем столе?" >ZPAD 2CRLF +ZPAD
    S" Несохраненные данные будут потеряны!" +ZPAD
    4132 Z" Задача управления окнами" ZPAD> DROP 0 MessageBoxA
    6 = IF
    WINLIST-BUILD
    LE-GET 2>R
    LE-WIN
    winlist ASCIIZ>
    FOR-LINES
      FOUND-LINE S>NUM WIN~CLOSE
    ;FOR-LINES
    2R> LE-SET
    WINLIST-DEL
    THEN
;

: SHOW-WIN-ALL ( n -- )
    WINLIST-BUILD
    LE-GET 2>R
    LE-WIN
    winlist ASCIIZ>
    FOR-LINES
      FOUND-LINE S" _" LCropAfterString S" nnCron HINT window" COMPARE \ Хинты nnCron не трогаем.
      IF DUP FOUND-LINE S>NUM ShowWindow DROP THEN
    ;FOR-LINES
    2R> LE-SET
    DROP
    WINLIST-DEL
;

\ Развернуть все окна
: WIN-MAXIMIZE-ALL ( -- ) 3 SHOW-WIN-ALL ; \ #define SW_MAXIMIZE 3
\ Свернуть все окна
: WIN-MINIMIZE-ALL ( -- ) 6 SHOW-WIN-ALL ; \ #define SW_MINIMIZE 6
\ Восстановить все окна
: WIN-RESTORE-ALL ( -- )  9 SHOW-WIN-ALL ; \ #define SW_RESTORE 9
\ Сделать всем окнам нормальный размер
: WIN-NORMAL-ALL ( -- ) 1 SHOW-WIN-ALL ; \ #define SW_SHOWNORMAL 1

 WINAPI: CascadeWindows USER32.DLL

 : WIN-CASCADE ( -- )  0 0 0 2 0 CascadeWindows DROP ; \ #define MDITILE_SKIPDISABLED 2

\ Поверх всех окон ON\OFF
: WIN-TOP-NOTOP ( -- )
    WIN~HWND DUP TOPMOST?
    IF
      WIN-NOTOPMOST
      S"   NO TOPMOST"
    ELSE
      WIN-TOPMOST
      S"   TOPMOST"
    THEN
    >ZPAD
    WinSetTitle
    VK_#BUTTON WAIT-KUP
    WinRestoreTitle
;

\ Диалог выбора окна.
\ В XP нет Ctrl+Alt+Tab есть только Alt+Tab.
: CTRL-ALT-TAB ( -- )
    VK_#BUTTON WAIT-KUP
    WinG7? IF Ctrl( Alt( Tab )Alt )Ctrl THEN
;

\ Заголовок окна копировать в буфер обмена.
: WIN-TITLE2CLIPBOARD ( -- )
    WIN~TITLE CLIPBOARD!
    S"   Заголовок скопирован." >ZPAD
    WinSetTitle
    VK_#BUTTON WAIT-KUP
    WinRestoreTitle
;

\ Дескриптор окна (HWND) копировать в буфер обмена.
: WIN-HWND2CLIPBOARD ( -- )
    WIN~HWND N>HEX 2DUP CLIPBOARD!
    S"   Дескриптор скопирован  " >ZPAD +ZPAD
    WinSetTitle
    VK_#BUTTON WAIT-KUP
    WinRestoreTitle
;

\ ---------------------------------------------
\ Menu
\ ---------------------------------------------

0 VALUE disable-create-menu

\ Перед вызовом меню проверяем завершилось ли предыдущее меню.
: disable-create-menu? ( -- ? )
    10 0 DO disable-create-menu 0= IF LEAVE THEN 10 PAUSE ( I . CR) LOOP
    disable-create-menu DUP 0= IF TRUE TO disable-create-menu THEN
;

\ Всплывающее меню - Стандартные.
: Menu-Accessories ( -- )
    VK_#BUTTON WAIT-KUP
    VK_LMENU WAIT-KUP \ При нажатой Alt меню сразу закрывается.
    [NONAME
    POPUPMENU
      S" Блокнот" Z" notepad.exe" MENUITEM
      S" Калькулятор" Z" calc.exe" MENUITEM
      S" Таблица символов" Z" %windir%\system32\charmap.exe" MENUITEM
      S" Экранная клавиатура" Z" start osk.exe" MENUITEM  \ Z" osk.exe" ICONITEM
      S" Paint" Z" mspaint.exe" MENUITEM
      S" Громкость" Win-XP? IF Z" sndvol32.exe" ELSE Z" sndvol.exe" THEN MENUITEM
      WinG7? IF S" Записки" OSx64? IF Z" %windir%\Sysnative\StikyNot.exe" ELSE Z" StikyNot.exe" THEN MENUITEM THEN
      Win-XP? IF S" Универсальный проигрыватель" Z" mplay32.exe" MENUITEM THEN
      Win-XP? IF S" Буфер обмена" Z" clipbrd.exe" MENUITEM THEN
      MENUSEPARATOR
      S" Проводник" Z" explorer.exe" MENUITEM
      S" Командная строка" Z" cmd.exe" MENUITEM
      S" Диспетчер задач" Z" taskmgr.exe" MENUITEM
      S" Редактор реестра" Z" regedit.exe" MENUITEM
      S" Конфигурация системы" OSx64? IF Z" %windir%\Sysnative\msconfig.exe" ELSE Z" msconfig.exe" THEN MENUITEM
      Win-XP? IFNOT S" Монитор ресурсов" Z" resmon.exe" MENUITEM THEN
      S" Очистка диска" Z" cleanmgr.exe" MENUITEM
\      S" Настройка звука" Z" RTHDCPL.exe" MENUITEM
\      S" Настройка звука" Z" RTLCPL.exe" MENUITEM
      MENUSEPARATOR
      S" Help по командной строке" Z" hh.exe ntcmds.chm::/ntcmds.htm#X" MENUITEM
      S" Glossary Windows" Z" hh.exe Glossary.chm" MENUITEM
      S" Справка Windows" Z" hh.exe windows.chm" MENUITEM
    END-MENU
    RunMenu ?DUP IF START-APP-LAUNCH THEN
    FALSE TO disable-create-menu
    NONAME]
    disable-create-menu? IF DROP EXIT THEN
    EXECUTE-LAUNCH
;

\ Всплывающее меню - Список окон.
: Menu-WinList ( -- )
    VK_#BUTTON WAIT-KUP
    VK_LMENU WAIT-KUP \ При нажатой Alt меню сразу закрывается.
    [NONAME
    WINLIST-BUILD
    POPUPMENU
      LE-GET 2>R
      LE-WIN
      winlist  ASCIIZ>
      FOR-LINES
        FOUND-LINE S" _" LCropAfterString >ZPAD ZPAD> FOUND-LINE S>NUM MENUITEM
      ;FOR-LINES
      WINLIST-DEL
      MENUSEPARATOR
      S" Свернуть все окна" 10 MENUITEM
      S" Развернуть все окна" 15 MENUITEM
      S" Восстановить все окна" 20 MENUITEM
      S" Закрыть все окна" 25 MENUITEM
\      S" Нормальный размер" 30 MENUITEM
\      S" Каскадом" 35 MENUITEM
      MENUSEPARATOR
      S" Переключить меню" 40 MENUITEM
      MENUSEPARATOR
      WINHLST-BUILD
      winlist  ASCIIZ>
      FOR-LINES
        FOUND-LINE S" _" LCropAfterString >ZPAD ZPAD> FOUND-LINE S>NUM MENUITEM
      ;FOR-LINES
      WINLIST-DEL
      2R> LE-SET
    END-MENU
    RunMenu
    CASE
      0   OF NOOP ENDOF
      10  OF WIN-MINIMIZE-ALL ENDOF
      15  OF WIN-MAXIMIZE-ALL ENDOF
      20  OF WIN-RESTORE-ALL ENDOF
      25  OF WIN-CLOSE-ALL ENDOF
\      30  OF WIN-NORMAL-ALL ENDOF
\      35  OF WIN-CASCADE ENDOF
      40  OF DetailMenuWinList @ INVERT DetailMenuWinList ! ENDOF
      DUP DUP OF DUP VISIBLE? IF WinActivate ELSE WINDOW-SHOW THEN ENDOF
    ENDCASE
    FALSE TO disable-create-menu
    NONAME]
    disable-create-menu? IF DROP EXIT THEN
    EXECUTE-LAUNCH
;

\ Всплывающее меню nnCron
\ В nncron.ini надо назначить хоткей для вызова меню nnCron
\ например:      MenuHotKey: "+{BREAK}"
: Menu-nnCron ( -- )
    VK_#BUTTON WAIT-KUP
    VK_CONTROL KEY-PRESSED?
    VK_SHIFT   KEY-PRESSED? OR
    VK_MENU    KEY-PRESSED? OR
    VK_LWIN    KEY-PRESSED? OR
    IFNOT Shift( Break )Shift THEN
;


\ ---------------------------------------------
\ Обработка нажатий клавиш мыши. http://nncron.ru/help/RU/add_info/tips_n_tricks.htm#nchittest
\ ---------------------------------------------

0 VALUE WinClassName \ Адрес строки.
: SkipWindow: ( "/re-classname/" -- ) C", TO WinClassName ;
: SkipWindow? ( -- ? ) WIN~CLASS WinClassName COUNT RE-MATCH ;

\ Некоторые нестандартные заголовки-окна для некоторых действий будем игнорировать.
: CAPTION-VALID? ( -- ? )
    WIN~CLASS S" nnCron Splash Class" COMPARE \ Хинт nnCron.
    WIN~HWND Taskbar? 0= AND
;


\ ---------------------------------------------
\ Левая клавиша мыши.
\ ---------------------------------------------
\ Если был клик LBM на кнопке [свернуть], [развернуть] или [закрыть], то к моменту выполнения WinSendMsg,
\ под курсором уже может находиться и другое окно и другой элемент, и получим число которое соответствует другому элементу а не нажатой кнопке.
\ Клики LBM на кнопках [свернуть], [развернуть], [закрыть] исключены из обработки.
: MOUSE-LB ( -- )
    VK_LBUTTON TO VK_#BUTTON
    WinSendMsg
    SkipWindow? IF VK_#BUTTON WAIT-KUP DROP EXIT THEN

\ ---LCtrl+LBM---
    VK_LCONTROL KEY-PRESSED?
    IF
      CASE
        0  OF  ENDOF \ курсор на кнопке любого окна в панели задач, какое-либо окно должно быть активным.
        1  OF WINDOW-DRAG DROP ENDOF \ курсор внутри окна
        2  OF CAPTION-VALID? IF WIN-TITLE2CLIPBOARD THEN ENDOF \ курсор в области заголовка
        3  OF  ENDOF \ курсор на значке
        5  OF  ENDOF \ курсор на строке меню
        18 OF  ENDOF \ курсор на рамке окна, чей размер нельзя изменить (на панели задач)
      ENDCASE
      VK_LCONTROL WAIT-KUP
    ELSE

\ ---LShift+LBM---
    VK_LSHIFT KEY-PRESSED?
    IF
      CASE
        0  OF  ENDOF \ курсор на кнопке любого окна в панели задач, какое-либо окно должно быть активным.
        1  OF  ENDOF \ курсор внутри окна
        2  OF CAPTION-VALID? IF WIN-TOP-NOTOP THEN ENDOF \ курсор в области заголовка
        3  OF  ENDOF \ курсор на значке
        5  OF  ENDOF \ курсор на строке меню
        18 OF  ENDOF \ курсор на рамке окна, чей размер нельзя изменить (на панели задач)
      ENDCASE
      VK_LSHIFT WAIT-KUP
    ELSE

\ ---LAlt+LBM---
    VK_LMENU KEY-PRESSED?
    IF
      CASE
        0  OF  ENDOF \ курсор на кнопке любого окна в панели задач, какое-либо окно должно быть активным.
        1  OF WIN~HWND Progman? IF WIN-RESTORE-ALL THEN ENDOF \ курсор внутри окна
        2  OF CAPTION-VALID? IF WIN-HWND2CLIPBOARD THEN ENDOF \ курсор в области заголовка
        3  OF  ENDOF \ курсор на значке
        5  OF  ENDOF \ курсор на строке меню
        18 OF  ENDOF \ курсор на рамке окна, чей размер нельзя изменить (на панели задач)
      ENDCASE
      VK_LMENU WAIT-KUP
      SysMenuClose

    ELSE DROP \ Если не нажата LCtrl или LShift или LAlt

    THEN
    THEN
    THEN
    VK_#BUTTON WAIT-KUP \ Чтобы не запускалось 100 раз MOUSE-LB
;
\ ---------------------------------------------
\ Правая клавиша мыши.
\ ---------------------------------------------
: MOUSE-RB ( -- )
    VK_RBUTTON TO VK_#BUTTON
    WinSendMsg
    SkipWindow? IF VK_#BUTTON WAIT-KUP DROP EXIT THEN

\ ---LCtrl+RBM---
    VK_LCONTROL KEY-PRESSED?
    IF
      CASE
        0  OF  ENDOF \ курсор на кнопке любого окна в панели задач, какое-либо окно должно быть активным.
        1  OF WINDOW-DRAG SysMenuClose IFNOT NOOP THEN ENDOF \ курсор внутри окна
        2  OF CAPTION-VALID? IF SysMenuClose WAVEOUT-BALANCE-MOUSE IFNOT NOOP THEN THEN ENDOF \ курсор в области заголовка
        3  OF  ENDOF \ курсор на значке
        5  OF  ENDOF \ курсор на строке меню
        8  OF  ENDOF \ курсор на кнопке [свернуть]
        9  OF  ENDOF \ курсор на кнопке [развернуть]
        20 OF  ENDOF \ курсор на кнопке [закрыть]
        18 OF  ENDOF \ курсор на рамке окна, чей размер нельзя изменить (на панели задач)
      ENDCASE
      VK_LCONTROL WAIT-KUP
    ELSE

\ ---LShift+RBM---
    VK_LSHIFT KEY-PRESSED?
    IF
      CASE
        0  OF  ENDOF \ курсор на кнопке любого окна в панели задач, какое-либо окно должно быть активным.
        1  OF  ENDOF \ курсор внутри окна
        2  OF CAPTION-VALID? IF SysMenuClose WAVEOUT-MOUSE IFNOT MIXER-ON-OFF THEN THEN ENDOF \ курсор в области заголовка
        3  OF  ENDOF \ курсор на значке
        5  OF  ENDOF \ курсор на строке меню
        8  OF  ENDOF \ курсор на кнопке [свернуть]
        9  OF  ENDOF \ курсор на кнопке [развернуть]
        20 OF  ENDOF \ курсор на кнопке [закрыть]
        18 OF  ENDOF \ курсор на рамке окна, чей размер нельзя изменить (на панели задач)
      ENDCASE
      VK_LSHIFT WAIT-KUP
    ELSE

\ ---LAlt+RBM---
    VK_LMENU KEY-PRESSED?
    IF
      CASE
        0  OF  ENDOF \ курсор на кнопке любого окна в панели задач, какое-либо окно должно быть активным.
        1  OF  ENDOF \ курсор внутри окна
        2  OF CAPTION-VALID? IF WAVEOUT-BALANCE-MOUSE IFNOT NOOP THEN THEN ENDOF \ курсор в области заголовка
        3  OF  ENDOF \ курсор на значке
        5  OF  ENDOF \ курсор на строке меню
        8  OF  ENDOF \ курсор на кнопке [свернуть]
        9  OF  ENDOF \ курсор на кнопке [развернуть]
        20 OF  ENDOF \ курсор на кнопке [закрыть]
        18 OF  ENDOF \ курсор на рамке окна, чей размер нельзя изменить (на панели задач)
      ENDCASE
      VK_LMENU WAIT-KUP
    ELSE

\ ---RBM---
    CASE
      0  OF  ENDOF \ курсор на кнопке любого окна в панели задач, какое-либо окно должно быть активным.
      1  OF  ENDOF \ курсор внутри окна
      2  OF CAPTION-VALID? IF SysMenuClose MIXER-MOUSE IFNOT Menu-Accessories THEN THEN ENDOF \ курсор в области заголовка
      3  OF Menu-nnCron ENDOF \ курсор на значке
      5  OF  ENDOF \ курсор на строке меню
      8  OF WIN~TITLE WIN-TO-TRAY ENDOF \ курсор на кнопке [свернуть]
      9  OF WINDOW-HIDE ENDOF \ курсор на кнопке [развернуть]
      20 OF WIN-MINIMIZE-ALL ENDOF \ курсор на кнопке [закрыть]
      18 OF  ENDOF \ курсор на рамке окна, чей размер нельзя изменить (на панели задач)
    ENDCASE

    THEN
    THEN
    THEN
    VK_#BUTTON WAIT-KUP
;
\ ---------------------------------------------
\ Средняя клавиша мыши.
\ ---------------------------------------------
0 VALUE DesktopSizeX
0 VALUE DesktopSizeY

: MOUSE-MB  ( -- )
    VK_MBUTTON TO VK_#BUTTON
\ Если курсор находится в каком либо углу экрана то открываем меню без дополнительных условий.
    MOUSE-POS
    2DUP 10 < SWAP 10 < AND IF 2DROP CTRL-ALT-TAB EXIT THEN     \ Левый верхний угол (0,0)
    GetDesktopSize TO DesktopSizeY TO DesktopSizeX
    2DUP      10 < DesktopSizeX ROT - 10 < AND IF 2DROP Menu-WinList EXIT THEN     \ Правый верхний угол.
    2DUP SWAP 10 < DesktopSizeY ROT - 10 < AND IF 2DROP Menu-Accessories EXIT THEN \ Левый нижний угол.
    DesktopSizeY SWAP - 10 <  DesktopSizeX ROT - 10 < AND IF Menu-nnCron EXIT THEN \ Правый нижний угол.

    WinSendMsg
    SkipWindow? IF VK_#BUTTON WAIT-KUP DROP EXIT THEN

\ ---LCtrl+MBM---
    VK_LCONTROL KEY-PRESSED?
    IF
      CASE
        0  OF  ENDOF \ курсор на кнопке любого окна в панели задач, какое-либо окно должно быть активным.
        1  OF  ENDOF \ курсор внутри окна
        2  OF  ENDOF \ курсор в области заголовка
        3  OF  ENDOF \ курсор на значке
        5  OF  ENDOF \ курсор на строке меню
        8  OF  ENDOF \ курсор на кнопке [свернуть]
        9  OF  ENDOF \ курсор на кнопке [развернуть]
        20 OF  ENDOF \ курсор на кнопке [закрыть]
        18 OF  ENDOF \ курсор на рамке окна, чей размер нельзя изменить (на панели задач)
      ENDCASE
      VK_LCONTROL WAIT-KUP
    ELSE

\ ---LShift+MBM---
    VK_LSHIFT KEY-PRESSED?
    IF
      CASE
        0  OF  ENDOF \ курсор на кнопке любого окна в панели задач, какое-либо окно должно быть активным.
        1  OF  ENDOF \ курсор внутри окна
        2  OF  ENDOF \ курсор в области заголовка
        3  OF  ENDOF \ курсор на значке
        5  OF  ENDOF \ курсор на строке меню
        8  OF  ENDOF \ курсор на кнопке [свернуть]
        9  OF  ENDOF \ курсор на кнопке [развернуть]
        20 OF  ENDOF \ курсор на кнопке [закрыть]
        18 OF  ENDOF \ курсор на рамке окна, чей размер нельзя изменить (на панели задач)
      ENDCASE
      VK_LSHIFT WAIT-KUP
    ELSE

\ ---LAlt+MBM---
    VK_LMENU KEY-PRESSED?
    IF
      CASE
        0  OF  ENDOF \ курсор на кнопке любого окна в панели задач, какое-либо окно должно быть активным.
        1  OF  ENDOF \ курсор внутри окна
        2  OF CAPTION-VALID? IF WIN-TRANSPARENCY-MOUSE DROP THEN ENDOF \ курсор в области заголовка
        3  OF  ENDOF \ курсор на значке
        5  OF  ENDOF \ курсор на строке меню
        8  OF  ENDOF \ курсор на кнопке [свернуть]
        9  OF  ENDOF \ курсор на кнопке [развернуть]
        20 OF  ENDOF \ курсор на кнопке [закрыть]
        18 OF  ENDOF \ курсор на рамке окна, чей размер нельзя изменить (на панели задач)
      ENDCASE
      VK_LMENU WAIT-KUP
    ELSE

\ ---MBM---
    CASE
      0  OF  ENDOF \ курсор на кнопке любого окна в панели задач, какое-либо окно должно быть активным.
      1  OF WINDOW-DRAG IFNOT WIN~HWND Progman? IF Menu-Accessories THEN THEN ENDOF \ курсор внутри окна
      2  OF CAPTION-VALID? IF WINDOW-DRAG-MAX-RESIZE IFNOT Menu-WinList THEN THEN ENDOF \ курсор в области заголовка
      3  OF CTRL-ALT-TAB ENDOF \ курсор на значке
      5  OF  ENDOF \ курсор на строке меню
      8  OF  ENDOF \ курсор на кнопке [свернуть]
      9  OF  ENDOF \ курсор на кнопке [развернуть]
      20 OF  ENDOF \ курсор на кнопке [закрыть]
      18 OF  ENDOF \ курсор на рамке окна, чей размер нельзя изменить (на панели задач)
    ENDCASE

    THEN
    THEN
    THEN
    VK_#BUTTON WAIT-KUP
;
\ ---------------------------------------------
\ Клавиатура.
\ ---------------------------------------------
: KB-CAPSL ( -- )
    VK_CAPITAL KEY-PRESSED?
    VK_CONTROL KEY-PRESSED? AND       \ Перемещение окна стрелками.
    IF GET-WIN WINDOW-MOVE-KBD THEN \ Ctrl+CapsLock и удерживая CapsLock нажимать стрелки.

    VK_CAPITAL KEY-PRESSED?
    VK_SHIFT KEY-PRESSED? AND       \ Изменение размеров окна.
    IF GET-WIN WINDOW-RESIZE THEN \ Shift+CapsLock и удерживая CapsLock двигать мышью.

    VK_CAPITAL KEY-PRESSED?
    VK_LWIN KEY-PRESSED? AND
    IF TASKBAR-LOCK-UNLOCK THEN \ LWin+CapsLock  Открепить/закрепить панель задач.
;


\ ---------------------------------------------

VARIABLE ExitWinCraft
VARIABLE LogoOsd

: LOGO-OSD
    LogoOsd @ ExitWinCraft @ NOT AND
    IF
      400 300 OSD-POS
      16 1 DO
        S" Arial" 50 I 4 Kb * OSD-FONT
        S" WinCraft" OSD 20 PAUSE
      LOOP OSD-CLEAR
    THEN
;

USER wPause
USER wDepth \ Глубина стека.
USER wActive \ Переключатель режима работы задачи (активный/пассивный).

\ VARIABLE icon-id

\ Переключение режима по хоткею LWin+ScrollLock
\ Выход из задачи по хоткею LWin+RShift+ScrollLock
: Check-HotKey-Start-Stop ( -- )
    VK_SCROLL KEY-PRESSED?
    IF
      VK_LWIN KEY-PRESSED?
      IF
        VK_RSHIFT KEY-PRESSED?
        IF
          TQUERY: "WinCraft%CRLF%Выйти из задачи?" 10 No
          IF ExitWinCraft ON THEN
          EXIT
        THEN
        VK_SCROLL WAIT-KUP VK_RWIN WAIT-KUP
        wActive @ INVERT wActive ! tweet \ или 100 PAUSE
        Win( ScrollLock )Win \ Восстановить состояние ScrollLock (можно без Win если ScrollLock не хоткей на что-то ещё).
        wActive @ 150 * 200 + wPause ! \ Пауза 50 в активном режиме, 200 в пассивном.

\        0 BalloonIcon !
\        S" WinCraft" wActive @ IF S" Active" ELSE S" No Active" THEN BALLOON

\        wActive @  \ Если добавить иконку в трей то при откреплении
\        IF       \ панели задач задача зависает.
\          S" active" 32512 0 LoadIconA ADD-TI icon-id !
\        ELSE
\          icon-id @ DEL-TI
\        THEN
      wActive @ IF LOGO-OSD THEN
      THEN
    THEN
;

: WaitConsole ( -- )
    Console @ RemConsole @ AND UPTIME-NNCRON 10 < AND \ Чтобы задача тут не застряла если, закрыть консоль и перечитать кронтабы.
    IF \ Ждем пока запустится консоль.
      BEGIN  RemConsoleIsStarted @ 0= WHILE 1000 PAUSE REPEAT
      BEGIN  1000 PAUSE S" nnCron console*" WIN-EXIST? UNTIL
      5000 PAUSE
    THEN
    500 PAUSE LOGO-OSD
;

%>



#( CLASSIC-TASK-#-WinCraft \ можно поиграть
SingleInstance NoLog NoActive
Rule: ExitWinCraft @ 0=
Action:
    DEPTH wDepth !
    WaitConsole
    50 wPause !
    wActive ON
    BEGIN
      Check-HotKey-Start-Stop
      wActive @
      IF
        VK_MBUTTON KEY-PRESSED? IF MOUSE-MB THEN
        VK_RBUTTON KEY-PRESSED? IF MOUSE-RB THEN
        VK_LBUTTON KEY-PRESSED? IF MOUSE-LB THEN
        VK_CAPITAL KEY-PRESSED? IF KB-CAPSL THEN
      THEN
      wPause @ PAUSE
      DEPTH wDepth @ -
      IF ExitWinCraft ON ( TMSG: "%CUR-TASK-NAME%: Ошибка стека" 5) THEN
      ExitWinCraft @
    UNTIL
)#



<%

\ mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
\ Настройки

ExitWinCraft OFF \ Если ON то задача не будет запущена автоматически.
DetailMenuWinList OFF \ Показывает в Menu-WinList координаты и тп. (можно переключать из меню).
LogoOsd OFF \ Показывает OSD при старте задачи.


\ Неправильные окна, которые задача будет игнорировать для мышиных действий.
\ Окна у которых все элементы кроме рамок определяются как клиентская область.
\ Фильтрация по классу окна.
SkipWindow: "/.*(YandexBrowser)|(MozillaWindowClass).*/"
\ mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm



\ Безусловный запуск задачи.
: WinCraft ( -- )
    ExitWinCraft OFF
    CLASSIC-TASK-#-WinCraft LAUNCH
;

\ Автоматический запуск при старте nnCron и при перечитывании кронтабов (если ExitWinCraft OFF).
CLASSIC-TASK-#-WinCraft LAUNCH

%>





:roll:
Подключить плагины keystate.spf windows.spf win2tray.spf extwords.spf sendinput.spf read-by-line.spf

Подключить кронтаб nncron_extwords2.tab лежит в следующем сообщении ниже.
Last edited by dothen on Tue, 28 Mar 2017, 22:08, edited 17 times in total.
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

nncron_extwords2.tab

Postby dothen » Fri, 27 May 2016, 21:59

Кронтаб nncron_extwords2.tab это дополнительные слова которые используются в разных задачах.
Code: Select all
# Файл:       nncron_extwords2.tab
# Автор:      dothen
# Дата:       07.05.2017
# Версия:     1.05
# Описание:   Сборник различных полезных слов и задач.

# ---------------------------------------------
# : D> 2SWAP D< ; \ Числа двойной длины.
# Это слово определено в плагине lists.spf также используется в плагине read-by-line.spf
# Если плагин lists.spf не используется(отключен) то это определение надо добавить в начало файла nncron.ini (до плагина read-by-line.spf)
# ---------------------------------------------

<%

\ Запись в лог для CLASSIC-TASK-#- задач.
: CRON~LOG ( a u -- )
    CUR-TASK-NAME CLASSIC?
    IF S" TASK: %CUR-TASK-NAME%" CRON-LOG THEN
    CRON-LOG
    50 500 BEEP
;

\ Запись в лог только если не включена опция NoLog
: ?CRON~LOG ( a u -- )
    CUR-NODE      \ CUR-NODE=0 если ?CRON~LOG или вызываюшее его слово выполняется не в задаче (например в консоли).
    IF
      CF-LOGGING? IF CRON~LOG ELSE 2DROP THEN
    ELSE
      S" NOTASK:" CRON-LOG CRON-LOG
    THEN
;


\ Буфер для сложения коротких строк, например для формирования заголовка окна, или пункта меню.
\ PAD не всегда подходит для этого. Например, чтобы GET-WTEXT сложить с GET-WCLASS или ACTIVE-WINDOW нужен другой буфер.
USER-CREATE ZPAD 260 USER-ALLOT
\ Не 256 а 260 - это страховка от PLACE0 и +PLACE0 при максимальной длине строки (там нет проверки).
\ 255 CONSTANT MAXCOUNTED
: >ZPAD ( a u -- ) "CLIP" ZPAD ZPLACE ;
: +ZPAD ( a u -- ) 0 MAX MAXCOUNTED ZPAD ASCIIZ> NIP - MIN ZPAD +ZPLACE ;
: ZPAD> ( -- a u ) ZPAD ASCIIZ> ;

\ ---------------------------------------------
\ Дата, время
\ ---------------------------------------------

\ Кладет на стек количество секунд, прошедших с момента старта nnCron.
: UPTIME-NNCRON ( -- sec )
    FT-CUR SWAP SP@ DUP FileTimeToLocalFileTime ERR THROW
    SWAP
    0 0 SP@ START-TIME SystemTimeToFileTime ERR THROW
    SWAP D- FT>SEC D>S
;

\ Миллисекунды.
: mSec@ ( -- msec ) LTIME wMilliseconds W@ ;

: mss ( -- a u ) GET-CUR-TIME mSec@ S>D <# # # # #> ;


\ ---------------------------------------------
\ Меню
\ ---------------------------------------------

WINAPI: GetMenuStringA USER32.DLL

USER-CREATE <MENUITEM-TEXT> 256 USER-ALLOT

: GetMenuItemText ( id hmenu -- a u )
    2>R 0 255 <MENUITEM-TEXT> 2R> GetMenuStringA DROP   \ #define MF_BYCOMMAND  0x00000000
;

: MENUITEM-TEXT ( -- a u ) <MENUITEM-TEXT> ASCIIZ> ; \ Текст выбранного(нажатого) пункта меню.

USER-VALUE MENUITEM-ID \ Идентификатор выбранного(нажатого) пункта меню

\ WINAPI: SwitchToThisWindow user32.dll

\ Текущее окно должно быть приоритетным окном прежде, чем приложение вызовет функцию TrackPopupMenuEx.
\ В противном случае, меню не будет исчезать, когда пользователь щелкает кнопкой мыши вне меню.
\ Система ограничивает число процессов, которые могут устанавливать приоритетное окно.
\ Функция SetForegroundWindow работает правильно если вызывающий её процесс является активным
\ (какой либо поток этого процесса обрабатывает пользовательский ввод).
\ В общем после события(сообщения) ввода, процесс получает право
\ забрать себе передний план используя функцию SetForegroundWindow.
: RunMenu ( hmenu -- id ) { hmenu \ hwnd -- id }
    SEND-KEYS: "{NUMLOCK}{NUMLOCK}"  \ Событие ввода.
    WITH TrayIcon Z" Static" 0 0 Window TO hwnd ENDWITH
    10 BEGIN 1- DUP 0= hwnd SetForegroundWindow OR 50 PAUSE UNTIL \ Делаем максимум 10 попыток
    IF
      0 hwnd CalcMenuYX 260 hmenu TrackPopupMenuEx \ #define TPM_RETURNCMD 256 + #define TPM_CENTERALIGN 4
      DUP TO MENUITEM-ID        \ Запомнить идентификатор пункта меню.
      DUP hmenu GetMenuItemText \ Запомнить текст пункта меню.
      hmenu DestroyMenu DROP
    ELSE
      0 S" Error: RunMenu" ?CRON~LOG
    THEN
;


\ ---------------------------------------------
\ Окна
\ ---------------------------------------------

WINAPI: IsZoomed   USER32.DLL
WINAPI: PtInRect   USER32.DLL

: MAXIMIZED? ( hwnd -- ? ) IsZoomed ;

\ Определить, находится ли курсор внутри заданного прямоугольника.
: CURSOR-INRECT? { b r y x -- ? } MOUSE-POS SWAP AT x PtInRect 0<> ;

\ Координаты рабочего стола минус панель задач.
: GetWorkArea ( -- b r y x )
    0 0 0 0 SP@ 0 SWAP 0 48 SystemParametersInfoA DROP \ #define SPI_GETWORKAREA 48
;

\ Реальные координаты прямоугольника окна (r и b меньше на 1).
\ В ОС точка на правой или нижней стороне считается вне прямоугольника.
\ https://msdn.microsoft.com/en-us/library/windows/desktop/ms633519(v=vs.85).aspx
\ https://msdn.microsoft.com/en-us/library/windows/desktop/dd162882(v=vs.85).aspx
: WIN~RECT ( hwnd -- b r y x) WIN-RECT 2SWAP 1- SWAP 1- SWAP 2SWAP ;
\ Проверка:(переместить курсор мыши в правый нижний угол окна)
\ 1) GetForegroundWindow WIN-RECT 2DROP SWAP MOUSE-MOVE     \ Курсор вне окна
\ 2) GetForegroundWindow WIN~RECT 2DROP SWAP MOUSE-MOVE     \ Курсор в углу окна

\ Получить ширину и высоту окна.
: WIN-SIZE ( hwnd -- width height ) WIN-RECT ROT SWAP - -ROT - ;

\ Получить относительные координаты окна.
: WIN-WINRECT ( hwnd -- height width 0 0 ) WIN-SIZE SWAP 0 0 ;

\ Получить координаты рабочей области окна.
: WIN-CLIENTRECT ( hwnd -- height width 0 0 )  >R 0 0 0 0 SP@ R> GetClientRect DROP ;

\ Отправить активному окну сообщение WM_NCHITTEST
: SEND-WM_NCHITTEST ( hwnd -- n )
    >R MOUSE-POS 16 LSHIFT OR 0 132 R> SendMessageA  \ #define WM_NCHITTEST 132
;

\ Закрывает окно с указанным hwnd
: WIN~CLOSE ( hwnd -- )
   >R 0 0 16 R> PostMessageA DROP \ #define WM_CLOSE 16
;

\ Закрывает первое найденное окно с точно указанным текстом и классом.
: WIN-NAME-CLOSE ( azWindowName azClassName -- )
    OVER 0= OVER 0= OR IF 2DROP EXIT THEN
    FindWindowA ?DUP IF WIN~CLOSE ELSE 2DROP THEN
;

\ Закрывает все окна с точно указанным текстом и классом.
: WIN-NAME-CLOSE-ALL ( azWindowName azClassName -- )
    OVER 0= OVER 0= OR IF 2DROP EXIT THEN
    BEGIN
      2DUP FindWindowA DUP IF DUP WIN~CLOSE THEN 0=
    UNTIL 2DROP
;
\ Слова
\ WIN-EXIST?
\ WIN-CLOSE
\ WIN-SET-TITLE
\ WIN-DESTROY
\ WIN-MINIMIZE
\ WIN-MAXIMIZE
\ WIN-RESTORE
\ WIN-HIDE
\ WIN-SHOW
\ WIN-ACTIVATE
\ реализованы через FOR-WINDOWS
\ а FOR-WINDOWS игнорирует окна созданные процессом nnCron.exe (WIN-INPUT-TEXT: MSG: TMSG: и т.п.)

\ Возвращает ID процесса который создал указанное окно.
: WIN-PID ( hwnd -- pid )
   >R 0 SP@ R> GetWindowThreadProcessId DROP
;


\ ---------------------------------------------
\ Версия операционной системы.
\ ---------------------------------------------

\ WinXP? возвращает TRUE даже если не XP но выше. (spf4-20.rar\devel\~nn\lib\winver.f)

: WinVersion ( -- n ) WinVerMajor 10 * WinVerMinor + ;

: Win-2k? ( -- ? ) WinNT? WinVersion 50 = AND ; \ TRUE если Win 2000 (Windows NT 5.0)
: Win-XP? ( -- ? ) WinNT? WinVersion 51 = WinVersion 52 = OR AND ; \ TRUE если XP (Windows NT 5.1 или 5.2)
: WinGXP? ( -- ? ) WinNT? WinVersion 50 > AND ; \ TRUE если XP или выше.
: Win-VI? ( -- ? ) WinNT? WinVersion 60 = AND ; \ TRUE если Vista (Windows NT 6.0)
: WinGVI? ( -- ? ) WinNT? WinVersion 59 > AND ; \ TRUE если Vista или выше.
: Win-7?  ( -- ? ) WinNT? WinVersion 61 = AND ; \ TRUE если Win7 (Windows NT 6.1)
: WinG7?  ( -- ? ) WinNT? WinVersion 60 > AND ; \ TRUE если Win7 или выше.
: Win-8?  ( -- ? ) WinNT? WinVersion 62 = AND ; \ TRUE если Win8 (Windows NT 6.2)
: WinG8?  ( -- ? ) WinNT? WinVersion 61 > AND ; \ TRUE если Win8 или выше.
: Win10?  ( -- ? ) WinNT? WinVersion 100 = AND ; \ TRUE если Win10 (Windows NT 10.0)


\ ---------------------------------------------
\ Строки
\ ---------------------------------------------

\ Горизонтальная табуляция.
\ В диалогах или меню иногда требуется сделать отступы или выравнивание текста с помощью табуляции,
\ а при копировании кода из сообщений на форуме, явная табуляция автоматически заменяется на пробелы.
CREATE <HTAB> 9 C, 0 C,
: HTAB <HTAB> 1 ;

: N>HEX ( n -- a u )  \ DECIMAL to HEX
    BASE @ SWAP HEX
    S>D <# # # # # # # # # S" 0x" HOLDS #>
    ROT BASE !
;

\ Удаляет начало строки 1 до конца строки 2 (для первого совпадения с начала строки).
: LCropAfterString ( a1 u1  a2 u2 -- a3 u3 )
\    DUP >R SEARCH IF R@ - SWAP R@ + SWAP THEN RDROP
    DUP >R SEARCH IF R@ /STRING THEN RDROP
;

\ Получить первое слово строки.
\ Т.е. получить кусок строки от начала до первого пробела, тбуляции или перевода строки.
: CropAfterWord ( a1 u1 -- a2 u2 )
    OVER
    BEGIN
      2DUP C@ 32 > AND
    WHILE
      1+ SWAP 1- SWAP
    REPEAT
    NIP OVER -
;

\ Удаляет пробелы из начала строки.
: LTRIM-BL ( a1 u1 -- a2 u2 )
    BEGIN
      OVER C@ 32 = OVER AND
    WHILE
      1- SWAP 1+ SWAP
    REPEAT
;

\ Удаляет из начала строки пробелы, тбуляции, переводы строк.
: LTRIM ( a1 u1 -- a2 u2 )
    BEGIN
      OVER C@ 33 < OVER AND
    WHILE
      1- SWAP 1+ SWAP
    REPEAT
;

\ Удаляет из конца строки пробелы, тбуляции, переводы строк.
: RTRIM ( a1 u1 -- a2 u2 )
    BEGIN
      2DUP 1- 0 MAX + C@ 33 < OVER AND
\      2DUP DUP 0> + + C@ 33 < OVER AND
    WHILE
      1-
    REPEAT
;


\ Расширение для SCASE(строковый CASE) из плагина extwords.spf
\ Поддерживает работу с масками используя символы * и ?
: WCSOF ( a1 u1 a2-pat u2-pat -- )
    POSTPONE 2OVER POSTPONE 2SWAP POSTPONE WC-COMPARE
    [COMPILE] IF POSTPONE 2DROP
; IMMEDIATE
\ Пример:  S" *.txt"  WCSOF ... ENDSOF

\ Сравнивает без учета регистра.
: ISOF
    POSTPONE 2OVER POSTPONE ICOMPARE
    [COMPILE] IFNOT POSTPONE 2DROP
; IMMEDIATE

\ Строковая константа.
\ Сначала строке делается EVAL-SUBST, если развернутая строка длинная,
\ то укорачивается до 255 байт, и компилируется в виде строки со счетчиком и с нулем в конце.
: STRCONSTANT ( "name" "текст до конца строки" -- )
    CREATE
    to-eol EVAL-SUBST "CLIP" S", 0 C,
    DOES> COUNT
;
\ Пример:
\ STRCONSTANT userfile.txt %ModuleDirName%user\%USERNAME%\userfile.txt
\ userfile.txt MsgBox
\ ' userfile.txt  >BODY COUNT DUMP CR


\ ---------------------------------------------
\ Клавиатура
\ ---------------------------------------------

 WINAPI: GetAsyncKeyState USER32.DLL

: KEY~PRESSED? ( vk -- ? ) GetAsyncKeyState 0x8000 AND? ;

\ Ждать поднятия кнопки с кодом VK если она нажата.
: WAIT~KUP ( vk -- )
    BEGIN DUP KEY~PRESSED? WHILE
      50 PAUSE
    REPEAT DROP
;


\ ---------------------------------------------
\ Разное
\ ---------------------------------------------

\ ---------------------------
\ В Win7 размер буфера для структуры SYSTEM_PERFORMANCE_INFORMATION не 312 а 328
\ поэтому слово CPU-USAGE работает неправильно.
WinGVI?
[IF]
    328 ' /SYSTEM_PERFORMANCE_INFORMATION >BODY !
[THEN]
\ : GetSizeBuf ( -- ) \ В XP не возвращает требуемый размер буфера.
\    0 SP@ 0 0 2 NtQuerySystemInformation DROP . CR    \ 2 CONSTANT SystemPerformanceInformation
\ ;
\ ---------------------------

WINAPI: ActivateKeyboardLayout user32.dll
\ Функция ActivateKeyboardLayout устанавливает идентификатор языка ввода
\ для текущего потока или текущего процесса (в данном случае для nnCron).
\ SEND-KEYS: "@(+)"    так nnCron сам себя не переключает.

: LngActivate ( id -- )  256 SWAP ActivateKeyboardLayout DROP ; \ #define KLF_SETFORPROCESS 256
\ Пример:   RUS LngActivate
\ Коды языков определены как константы в плагине kbd_layout.spf

: pip 50 1000 BEEP ;
: tweet 10 0 DO 10 I 200 * 2000 + BEEP LOOP ;


%>




# --------------------------------------------------------
# Запуск приложений и выполнение слов из отдельной задачи.
# --------------------------------------------------------
# Запуск приложений.
# http://www.nncron.ru/forums/viewtopic.php?f=5&t=1380
# http://www.nncron.ru/forums/viewtopic.php?f=5&t=12928#p34586

# При выполнении слов из полноценной отдельной задачи, выявляется больше ошибок
# в отличие от ['] word TASK 0 SWAP START DROP   или  START-TASK
# например при ошибке стека нет никакой реакции.

#( CLASSIC-TASK-#-LAUNCH
NoActive \ NoLog
0 VALUE launchflag
0 VALUE launchargument
Action:
    launchargument
    launchflag 0 TO launchargument
    IF
      GetDesktopWindow PUSH-WINDOW DROP \ Чтобы окно запущенного приложения открылось на переднем плане.
      ASCIIZ> START-APP
    ELSE
      EXECUTE
    THEN
)#


<%

\ Т.к. аргумент глобальный то изменять его можно только если он не занят.
: X-LAUNCH ( az|xt flg -- )
    20 0 DO launchargument 0= IF LEAVE THEN 20 PAUSE LOOP
    launchargument 0=
    IF
      TO launchflag
      TO launchargument
      CLASSIC-TASK-#-LAUNCH LAUNCH
    ELSE
      2DROP
      S" Error: X-LAUNCH" ?CRON~LOG
    THEN
;

: START-APP-LAUNCH ( az -- ) TRUE  X-LAUNCH ;
: EXECUTE-LAUNCH   ( xt -- ) FALSE X-LAUNCH ;

\ #( Primer
\ NoActive
\ : slovo TMSG: "%hh%:%mm%:%ss%" 1 ;
\ Action:
\     4 0 DO slovo LOOP \ Сообщения выводятся последовательно.
\     4 0 DO ['] slovo EXECUTE-LAUNCH LOOP \ Сообщения выводятся параллельно.
\ )#
%>



И еще:
Code: Select all
: D> 2SWAP D< ; \ Числа двойной длины.
Это слово определено в плагине lists.spf также используется в плагине read-by-line.spf
Если плагин lists.spf не используется(отключен) то это определение надо добавить в начало файла nncron.ini
Last edited by dothen on Sun, 07 May 2017, 16:48, edited 9 times in total.
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

Re: Задача управления окнами

Postby dothen » Mon, 30 May 2016, 04:21

Добавлены слова для изменения громкости и баланса "Wave"
WAVEOUT-MOUSE ( -- ? ) \ (LShift+RBM на заголовке окна)
WAVEOUT-BALANCE-MOUSE ( -- ? ) \ (LCtrl+RBM и LAlt+RBM на заголовке окна)
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

Re: Задача управления окнами

Postby Dimsok » Mon, 30 May 2016, 16:23

У меня не работает 2 пункта:
1. # Всплывающее меню nnCron (LShift+RBM на строке меню, на заголовке, внутри окна)
2. # Изменение прозрачности окна (LAlt+MBM на заголовке)

До этого пользовался вот этим:

Code: Select all
#########################################################################################################################
#( Окна:_Управление_мышью                                     \ задача: использование клавиш мыши для управления окнами
SingleInstance
WINAPI: GetWindowTextA USER32.DLL
CREATE win_title 250 ALLOT
2VARIABLE Окна:_Буфер_обмена
VARIABLE  Окна:_Управление_мышью
VARIABLE  Окна:_Прозрачность
VARIABLE  Окна:_Триггер_поверх_всех
Action:
    BEGIN                                                     \ цикл проверки положения курсора и нажатий кнопок мыши
        VK_LBUTTON KEY-PRESSED? VK_MBUTTON KEY-PRESSED? OR VK_RBUTTON KEY-PRESSED? OR  \ одна из клавиш мыши нажата
        IF
            Окна:_Управление_мышью @ MOUSE-POS 16 LSHIFT OR 0 132 GetForegroundWindow SendMessageA
\ ЛЕВАЯ кнопка мыши ->                                             
            VK_LBUTTON KEY-PRESSED?                                                 
            IF
             CASE
                    DUP  0 OF DROP                                                     \ курсор в фоновой области
               ENDOF                                               
                    DUP  1 OF DROP                                                     \ курсор внутри окна
               ENDOF                                             
                    DUP  2 OF DROP                                                     \ курсор в области заголовка
               ENDOF                                               
                    DUP  3 OF DROP                                                     \ курсор на значке
               ENDOF                                             
                    DUP  5 OF DROP                                                     \ курсор на строке меню
               ENDOF                                               
                    DUP  8 OF DROP                                                     \ курсор на кнопке: свернуть
               ENDOF                                             
                    DUP  9 OF DROP                                                     \ курсор на кнопке: развернуть
               ENDOF                                             
                    DUP 10 OF DROP                                                     \ курсор на левой границе
               ENDOF                                             
                    DUP 11 OF DROP                                                     \ курсор на правой границе
               ENDOF                                             
                    DUP 12 OF DROP                                                     \ курсор на верxней границе
               ENDOF                                             
                    DUP 13 OF DROP                                                     \ курсор в левом верхнем углу
               ENDOF                                             
                    DUP 14 OF DROP                                                     \ курсор в правом верхнем углу
               ENDOF                                             
                    DUP 15 OF DROP                                                     \ курсор на нижней границе
               ENDOF                                             
                    DUP 16 OF DROP                                                     \ курсор в левом нижнем углу
               ENDOF                                             
                    DUP 17 OF DROP                                                     \ курсор в правом нижнем углу
               ENDOF                                             
                    DUP 20 OF DROP                                                     \ курсор на кнопке: закрыть
               ENDOF                                             
                ENDCASE
            ELSE
\ СРЕДНЯЯ кнопка мыши ->
                VK_MBUTTON KEY-PRESSED?                                             
                IF
               CASE                                                                       
                        DUP  0 OF DROP ENDOF                                           \ курсор в фоновой области
                        DUP  1 OF DROP                                                 \ курсор внутри окна ->
                            WIN-ACTIVE: "Program Manager" NOT                          \ -> окно не Рабочий стол ?
                     IF                         
                                CLIPBOARD Окна:_Буфер_обмена 2!                        \ -> запоминаем буфер обмена ->
                                SEND-KEYS: "^(c)"
                        SEND-KEYS: "^({INSERT})"
                        PAUSE: 200                           \ -> копирование в буфер обмена ->
                                Окна:_Буфер_обмена 2@ CLIPBOARD  D=                    \ ->проверка буфера обмена на изменения->
                                IF                                                     \ -> если изменений не обнаружено
                             SEND-KEYS: "^(v)"
                                    HINT-POS: 0 0 0x7EC0EE 0x000000 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                                    THINT: "Вставлено." 2
                                ELSE                                                   \ -> если есть изменения в буфере обмена
                                    HINT-POS: 0 0 0xB3EE3A 0x000000 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                                    THINT: "Копировано." 2
                                THEN
                            ELSE
                                S" Shell_TrayWnd" WIN-EXIST?
                         IF
                             0 416 273 WIN-HWND SendMessageA DROP
                                    HINT-POS: 0 0 0xEEE9BF 0x000000 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                                    THINT: "Все окна развернуты." 2                           
                         THEN
                            THEN
                     PAUSE: 500
                  ENDOF
                        DUP  2 OF DROP                                                 \ курсор в области заголовка ->
                            0 Окна:_Прозрачность !                                     \ -> установка прозрачности 0
                            ACTIVE-WINDOW Окна:_Прозрачность @ WIN-TRANSPARENCY        \ -> установка окна непрозрачным ->
                     PAUSE: 1000       
                            BEGIN
                         VK_MBUTTON KEY-PRESSED? Окна:_Прозрачность @  230 < AND  \ -> если клавиша еще нажата ->
                            WHILE                                                      \ -> цикл увел. прозрачности на N ед.
                                HINT-POS: 835 709 0x8DEEEE 0x000000 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                                THINT: "Прозрачность: %Окна:_Прозрачность @% ед." 1
                                PAUSE: 1300 Окна:_Прозрачность @ 30 + Окна:_Прозрачность !               
                                ACTIVE-WINDOW Окна:_Прозрачность @ WIN-TRANSPARENCY
                            REPEAT
                            HINT-POS: 0 0 0x8DEEEE 0x000000 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                            THINT: "Прозрачность: %Окна:_Прозрачность @% ед." 2
                            PAUSE: 500
                  ENDOF 
                        DUP  3 OF DROP                                                 \ курсор на значке ->
                            250 win_title COUNT SWAP GetForegroundWindow GetWindowTextA DROP
                            win_title COUNT CLIPBOARD!                                 \ -> название окна->буфер обмена
                            HINT-POS: 0 0 0xB3EE3A 0x000000 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                            THINT: "( %CLIPBOARD% ) копировано." 2
                     PAUSE: 500
                  ENDOF
                        DUP  5 OF DROP                                                 \ курсор на строке меню
                      TMSG: "VK_MBUTTON: 5   Запрограммируйте действия" 1
                  ENDOF   
                        DUP  8 OF DROP                                                 \ курсор на кнопке: свернуть ->
                            HINT-POS: 0 0 0xEEE9BF 0x000000 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                            THINT: "%ACTIVE-WINDOW%-сворачивается в Tray " 3
                            PAUSE: 1000
                            WIN-TO-TRAY: %ACTIVE-WINDOW%                               \ активное окно сворачивается в трей и трей обновляется
                     PAUSE: 2000
                     TRAY-REFRESH     
                  ENDOF             
                        DUP  9 OF DROP                                                 \ курсор на кнопке: развернуть
                            Окна:_Триггер_поверх_всех @ 1 =                            \ если окно поверх всех ->
                            IF                                                                   
                                HINT-POS: 0 0 0xFFA54F 0x000000 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                                THINT: "%ACTIVE-WINDOW%-НЕ поверх всех окон" 3
                                WIN-NOTOPMOST: "%ACTIVE-WINDOW%"                       \ активное окно становится "НЕ поверх всех"
                                0 Окна:_Триггер_поверх_всех !
                            ELSE                                                       \ если окно НЕ поверх всех ->
                                HINT-POS: 0 0 0xFFA54F 0x000000 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                                THINT: "%ACTIVE-WINDOW%-Поверх всех окон" 3
                                WIN-TOPMOST: "%ACTIVE-WINDOW%"                         \ активное окно становится "Поверх всех"
                                1 Окна:_Триггер_поверх_всех !
                            THEN
                     PAUSE: 500
                  ENDOF
                        DUP 10 OF DROP                                                 \ курсор на левой границе
                      TMSG: "VK_MBUTTON: 10  Запрограммируйте действия" 1
                  ENDOF   
                        DUP 11 OF DROP                                                 \ курсор на правой границе ->
                            MIXER-STATE 0=
                     IF
                        MIXER-UNMUTE
                      THEN
                     3 MIXER-DOWN                                               \ -> уменьшение громкости на 5 ед.
                            HINT-POS: 0 0 0x8B4513 0x00FF00 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                            THINT: "Громкость: %MIXER-VOLUME@% ед." 2
                     PAUSE: 200
                  ENDOF
                        DUP 12 OF DROP                                                 \ курсор на верxней границе ->
                            SEND-KEYS: "{F5}"                                          \ -> F5 (обновление страницы)
                  ENDOF
                        DUP 13 OF DROP \ курсор в левом верхнем углу
                      TMSG: "VK_MBUTTON: 13  Запрограммируйте действия" 1
                  ENDOF   
                        DUP 14 OF DROP                                                 \ курсор в правом верхнем углу
                      TMSG: "VK_MBUTTON: 14  Запрограммируйте действия" 1
                  ENDOF   
                        DUP 15 OF DROP                                                 \ курсор на нижней границе
                      TMSG: "VK_MBUTTON: 15  Запрограммируйте действия" 1
                  ENDOF   
                        DUP 16 OF DROP                                                 \ курсор в левом нижнем углу
                      TMSG: "VK_MBUTTON: 16  Запрограммируйте действия" 1 
                  ENDOF   
                        DUP 17 OF DROP                                                 \ курсор в правом нижнем углу
                      TMSG: "VK_MBUTTON: 17  Запрограммируйте действия" 1
                  ENDOF     
                        DUP 20 OF DROP                                                 \ курсор на кнопке: закрыть ->
                      S" Shell_TrayWnd" WIN-EXIST? IF 0 415 273 WIN-HWND SendMessageA DROP THEN  \ -> сворач-ние окон
                      HINT-POS: 0 0 0xEEE9BF 0x000000 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                            THINT: "Все окна свернуты. " 2
                            PAUSE: 500
                  ENDOF   
                    ENDCASE
                ELSE
\ ПРАВАЯ кнопка мыши ->
                    VK_RBUTTON KEY-PRESSED?
                    IF
                   CASE                                                                       
                            DUP  0 OF DROP                                             \ курсор в фоновой области
                     ENDOF                                                       
                            DUP  1 OF DROP                                             \ курсор внутри окна
                     ENDOF                                                       
                            DUP  2 OF DROP                                             \ курсор в области заголовка
                         TMSG: "VK_RBUTTON: 2   Запрограммируйте действия" 1
                     ENDOF   
                            DUP  3 OF DROP                                             \ курсор на значке
                         TMSG: "VK_RBUTTON: 3   Запрограммируйте действия" 1
                     ENDOF   
                            DUP  5 OF DROP                                             \ курсор на строке меню
                         TMSG: "VK_RBUTTON: 5   Запрограммируйте действия" 1
                     ENDOF     
                            DUP  8 OF DROP                                             \ курсор на кнопке: свернуть
                         TMSG: "VK_RBUTTON: 8   Запрограммируйте действия" 1
                     ENDOF   
                            DUP  9 OF DROP                                             \ курсор на кнопке: развернуть
                         TMSG: "VK_RBUTTON: 9   Запрограммируйте действия" 1
                     ENDOF     
                            DUP 10 OF DROP                                             \ курсор на левой границе
                         TMSG: "VK_RBUTTON: 10  Запрограммируйте действия" 1
                     ENDOF   
                            DUP 11 OF DROP                                             \ курсор на правой границе ->
                                MIXER-STATE 0=
                        IF
                            MIXER-UNMUTE
                        THEN
                        3 MIXER-UP                                             \ -> увеличение громкости на 5 ед.
                                HINT-POS: 0 0 0x8B4513 0x00FF00 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                                THINT: "Громкость: %MIXER-VOLUME@% ед." 2
                        PAUSE: 200
                     ENDOF
                            DUP 12 OF DROP                                             \ курсор на верxней границе
                         TMSG: "VK_RBUTTON: 12  Запрограммируйте действия" 1
                     ENDOF   
                            DUP 13 OF DROP                                             \ курсор в левом верхнем углу
                         TMSG: "VK_RBUTTON: 13  Запрограммируйте действия" 1
                     ENDOF   
                            DUP 14 OF DROP                                             \ курсор в правом верхнем углу
                         TMSG: "VK_RBUTTON: 14  Запрограммируйте действия" 1
                     ENDOF   
                            DUP 15 OF DROP                                             \ курсор на нижней границе
                         TMSG: "VK_RBUTTON: 15  Запрограммируйте действия" 1
                     ENDOF   
                            DUP 16 OF DROP                                             \ курсор в левом нижнем углу
                         TMSG: "VK_RBUTTON: 16  Запрограммируйте действия" 1
                     ENDOF   
                            DUP 17 OF DROP                                             \ курсор в правом нижнем углу
                         TMSG: "VK_RBUTTON: 17  Запрограммируйте действия" 1
                     ENDOF   
                            DUP 20 OF DROP                                             \ курсор на кнопке: закрыть
                                MIXER-STATE 0=
                                IF
                            MIXER-UNMUTE                                       \ -> либо включаем звук
                                    HINT-POS: 0 0 0x00FF00 0x000000 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                                    THINT: "Звук: ВКЛ." 1                                               
                                ELSE
                            MIXER-MUTE                                         \ -> либо отключаем звук
                                    HINT-POS: 0 0 0xFF3030 0x000000 HINT-COLOR S" Times New Roman" 20 HINT-FONT
                                    THINT: "Звук: ВЫКЛ." 1
                                THEN
                        PAUSE: 500
                     ENDOF 
                        ENDCASE
                    THEN
            THEN     
         THEN
            Окна:_Управление_мышью OFF                                                 \ флаг идентификатора задачи -> OFF
        ELSE
            Окна:_Управление_мышью ON                                                  \ флаг идентификатора задачи -> ON
        THEN
        PAUSE: 200                                                                     \ пауза цикла проверки
    AGAIN
)#
#########################################################################################################################


С ним прозрачность работала. Но решил отказаться от него, потому что там всплывающие сообщения при выполнении появлялись, и заголовок окна в буфер не копировался. Можете из него функцию установки прозрачности адаптировать к вашему скрипту, если у меня одного она не работала.
Dimsok
 
Posts: 28
Joined: Sat, 28 May 2016, 16:37

Re: Задача управления окнами

Postby Dimsok » Mon, 30 May 2016, 16:35

Ааа, сорри, про прозрачность не сообразил, что надо ещё мышкой двигать, думал, будет, как в приведённом скрипте, при удержании средней кнопки.
Dimsok
 
Posts: 28
Joined: Sat, 28 May 2016, 16:37

Re: Задача управления окнами

Postby Dimsok » Mon, 30 May 2016, 16:53

Свернуть/развернуть все окна (RBM на кнопке [закрыть])

А как можно развернуть все окна при RBM на кнопке закрыть, если они при этом только сворачиваются? В том скрипте на рабочем столе при щелчке средней кнопки они все разворачиваются. Думаю, это разумней, а тут развернуть их никак не получается.
Dimsok
 
Posts: 28
Joined: Sat, 28 May 2016, 16:37

Re: Задача управления окнами

Postby dothen » Mon, 30 May 2016, 18:39

Исправлен запуск меню
было: TASK START
стало: TASK 0 SWAP START DROP

Добавлено:
LShift+LBM на рабочем столе - Отменить Свернуть все, Каскадом.


Dimsok wrote:У меня не работает 2 пункта:
1. # Всплывающее меню nnCron (LShift+RBM на строке меню, на заголовке, внутри окна)
2. # Изменение прозрачности окна (LAlt+MBM на заголовке)


Всплывающее меню nnCron
В nncron.ini надо назначить хоткей для вызова меню nnCron
например: MenuHotKey: "+{BREAK}"

Да прозрачность и громкость изменяется при перемещении нажатой мыши.
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

Re: Задача управления окнами

Postby Dimsok » Mon, 30 May 2016, 19:06

Что-то вы то убираете, то добавляете beep. По мне так без него лучше.
Shift+левый щелчок мышью для разворачивания окон - не самая удачная комбинация. Вдруг после сворачивания понадобится выделить ярлыки. Можно, например, alt вместо shift использовать.

# Индикация в заголовке окна (координаты окна, громкость ...)
Каким образом этого добиться? Клавиши не указаны.

Да, а можно добавить возможность закрытия всех окон? Только какую-нибудь замысловатую комбинацию, чтобы случайно нельзя было нажать.

И ещё вопрос. Я редактирую POPUPMENU. exe добавляются, а как добавить элементы контрольной панели? Например, "C:\Program Files\Realtek AC97\ALSndMgr.cpl" Жму пункт, никакой реакции.
Dimsok
 
Posts: 28
Joined: Sat, 28 May 2016, 16:37

Re: Задача управления окнами

Postby dothen » Tue, 31 May 2016, 03:54

Dimsok, ну "гудки" конечно уберём (они для отладки),
если снова будут "пикать" то надо просто везде закомментировать или удалить слово "pip"

Да, комбинацию для разворачивания окон надо переделать.

Индикация в заголовке окна, отображается автоматически, при выполнении некоторых команд.

Dimsok wrote:Да, а можно добавить возможность закрытия всех окон? Только какую-нибудь замысловатую комбинацию, чтобы случайно нельзя было нажать.

Ну если другие могут (CloseAll) то nnCron тоже может.

Dimsok wrote:И ещё вопрос. Я редактирую POPUPMENU. exe добавляются, а как добавить элементы контрольной панели? Например, "C:\Program Files\Realtek AC97\ALSndMgr.cpl" Жму пункт, никакой реакции.

Можно же сразу Z" RTLCPL.exe"

А для *.cpl надо так Z" start name.cpl"
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

Re: Задача управления окнами

Postby VoidVolker » Tue, 31 May 2016, 09:34

dothen wrote:Свернуть все окна

В семерке и выше в углу таскбара эта кнопочка есть, в ХР - в панели рядом с пуском.
Win + D
dothen wrote:Перемещение окна стрелками.

Alt + Пробел -> П
dothen wrote:Окна каскадом

Win + Tab (семерка и выше)
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: Задача управления окнами

Postby Dimsok » Tue, 31 May 2016, 11:04

dothen wrote:если снова будут "пикать" то надо просто везде закомментировать или удалить слово "pip"


Я просто сделал так: 0 BEEP
Dimsok
 
Posts: 28
Joined: Sat, 28 May 2016, 16:37

Re: Задача управления окнами

Postby dothen » Tue, 31 May 2016, 13:36

VoidVolker, конечно все эти штуки уже есть в ОС, но мы же хотим чтобы было ещё удобнее и быстрее :)
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

Re: Задача управления окнами

Postby Dimsok » Tue, 31 May 2016, 13:53

dothen wrote:VoidVolker, конечно все эти штуки уже есть в ОС, но мы же хотим чтобы было ещё удобнее и быстрее :)

К тому же, у меня, к примеру, XP.
Dimsok
 
Posts: 28
Joined: Sat, 28 May 2016, 16:37

Re: Задача управления окнами

Postby Dimsok » Tue, 31 May 2016, 14:33

А нельзя ли в меню по правому щелчку организовать подменю?
Dimsok
 
Posts: 28
Joined: Sat, 28 May 2016, 16:37

Re: Задача управления окнами

Postby dothen » Tue, 31 May 2016, 17:52

Да только это меню сделано просто для примера,
и только для запуска приложений, т.е. строка с командой передаётся слову START-APP

Подменю делается так:
Code: Select all
    POPUPMENU
      S" Громкость" Z" sndvol32.exe" MENUITEM
      S" Блокнот" Z" notepad.exe" MENUITEM
      ...
      POPUP
        S" Калькулятор" Z" calc.exe" MENUITEM
        S" Буфер обмена" Z" clipbrd.exe" MENUITEM
        S" Пример подменю"
      END-POPUP
      ...
      S" Справка Windows" Z" hh.exe windows.chm" MENUITEM
    END-MENU
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

Next

Return to nnCron forum (Russian)

Who is online

Users browsing this forum: No registered users and 2 guests

cron