Использование клавиш мыши для управления окнами.
Выполнение некоторых действий в один клик по разным участкам окна.
- 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
%>

Подключить плагины keystate.spf windows.spf win2tray.spf extwords.spf sendinput.spf read-by-line.spf
Подключить кронтаб nncron_extwords2.tab лежит в следующем сообщении ниже.