101

Re: AHK: Пишем удобный менеджер буфера обмена

teadrinker пишет:

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

Тогда, видимо, напрашивается вкладка Избранное.

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

102 (изменено: Irbis, 2015-02-21 16:01:05)

Re: AHK: Пишем удобный менеджер буфера обмена

Потестировал, удобно. Но, конечно, есть что добавить в wish-list, как без него.

Опционально:
- Одно из основных. Отправлять не по нажатию ЛКМ, а при отжатии. Для чего? Например, чтобы при помощи click'n'drag выделить несколько ячеек для групповой вставки или их быстрого удаления. Развивая идею, можно дополнительно сделать выделение по Ctrl+ЛКМ, чтобы затем вставить в порядке выделения, хотя это может и лишнее.

- Кнопка "Удалить" - рядом с каждой ячейкой. Не обязательно иконкой, будет слишком "пёстро", лучше плоская кнопка с "Х". А лучше при подсвечивании ячейки показывать кнопку.

+ фотошоп ))

http://savepic.su/5174740.png

Upd: ПКМ по кнопке -> отправить и удалить, меньше лишних действий.

- Настраиваемая прозрачность при потере фокуса. Плюс опция - возможность не только прятать окно, а сворачивать до пределов заголовка или плавающей иконки при потере фокуса или по хоткею.

- Block/unblock по хоткею, при этом изменять заголовок или иконку (из предыдущего пункта), а также иконку в трее.

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

- Авто-разворачивание главного окна при получении фокуса целевым окном.

- Идея с со списком постоянных шаблонов годная, подумал об этом же в первую-вторую очередь. Реализовать можно, например так: окно поделено по горизонтали, при блокировании шаблона он "уходит вниз", в постоянный список. Оба списка прокручиваются и редактируются независимо. Другой вариант - заблокированный шаблон остается на месте при добавлении новых и при удалении имеющихся. Пример - блокируем ячейки #2 и #5, при копировании они не сдвигаются, #4 -> #6, #3 -> #4, #1 -> #3.
   Другой подход - разные шаблоны в разных вкладках. Tab'ы отображать не обязательно, если 2 типа шаблонов, можно переключаться между ними циклически, колесом мыши на заголовке окна. И если сделать настройку цвета для каждого окна по отдельности, будет наглядней.

И, last but not least, что в основом сподвигло создать сей пост, и чего категорически не хватает - быстрого последовательного копирования/вставки без обращения к окну менеджера буфера обмена. Все-таки предыдущие пункты касаются эргономики при обращении с большим количеством элементов, а при работе часто бывает более простая задача - в одном окне несколько раз скопировать (например, Ф.И.О, адрес, прочие данные), затем в другом вставить это в несколько полей ввода. И тут FIFO-шный буфер удобней стека, мозг подсознательно против обратной польской нотации .
Можно такие данные хранить в одной ячйке, для разделения использовать спец.символы.

В общем, идей для апгрейда можно еще найти на пару-тройку отдельных программ.

103

Re: AHK: Пишем удобный менеджер буфера обмена

Обдумаю!

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

104

Re: AHK: Пишем удобный менеджер буфера обмена

в одном окне несколько раз скопировать (например, Ф.И.О, адрес, прочие данные), затем в другом вставить это в несколько полей ввода.

Тоже давно хотел добавить в свой. Думаю пока о 2 вариантах. При выводе своего тултипа с содержимым ячейки, строки подсвечиваются, то есть могут быть выбраны. Или добавить в ячейки пункт - сделать каждую строку отдельной ячейкой.

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

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

105

Re: AHK: Пишем удобный менеджер буфера обмена

serzh82saratov пишет:

большой текст выводится очень долго.

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

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

106 (изменено: Malcev, 2015-02-21 23:56:22)

Re: AHK: Пишем удобный менеджер буфера обмена

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

107

Re: AHK: Пишем удобный менеджер буфера обмена

Иконка не льется. Вручную тоже.

108

Re: AHK: Пишем удобный менеджер буфера обмена

Всё равно программа пока не завершена.

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

109

Re: AHK: Пишем удобный менеджер буфера обмена

А галки есть для того чтобы выделенные пункты не "тонули", а всегда были в топе?

110

Re: AHK: Пишем удобный менеджер буфера обмена

А можно сделать "бип" если скопированный текст уже есть в базе?

111

Re: AHK: Пишем удобный менеджер буфера обмена

Проект заброшен?

112

Re: AHK: Пишем удобный менеджер буфера обмена

Не-а, отложен.

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

113 (изменено: teadrinker, 2015-11-03 01:54:51)

Re: AHK: Пишем удобный менеджер буфера обмена

Пока пользуюсь таким вариантом:

;********************************** Описание **************************************
Readme =
(
Скрипт сохраняет определённое в настройках количество состояний буфера обмена
(только текстовые данные, включая пути к скопрованным файлам) и даёт возможность
вводить их повторно.

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

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

По умолчанию текст вводится в активное окно (само окно скрипта всегда неактивно).
Это поведение можно изменить через меню «Настройки».

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

Если содержимое ячейки не видно полностью, посмотреть его можно, нажав над ней
колесо мыши.

Окно скрипта не имеет кнопки на панели задач. Чтобы восстановить свёрнутое окно,
можно воспользоваться меню «Показать» иконки скрипта в трее, либо просто один раз
кликнуть по ней. Кроме того, есть возможность задать горячую клавишу для
показа/скрытия окна в меню «Настройки».

Скрипт регистрирует в системе сообщение "WM_INFO", чтобы можно было заблокировать
его работу извне на время. Для получения информации о текущем состоянии блокировки
окна отправьте любому окну скрипта сообщение "WM_INFO" с wp = 1, в ответ придёт,
если заблокировано — 1, если разблокировано — 0. Для блокировки окна отпрвьте
"WM_INFO" c lp = 1, для разблокировки lp = 0.

При завершении работы скрипт сохраняет все данные в файл `%A_ScriptDir`%\data, и
загружает их из него в следующей сессии.

Для корректной работы скомпилированного варианта из exe-файла все дефолтные иконки
должны быть удалены, вместо них должны быть добавлены иконки из dll-файла в том же
порядке, первая с именем 159 и далее.
Если файловая система NTFS, скомпилированный скрипт пишет сохраняемые данные не в
отдельный файл, а в NTFS-поток по адресу `%A_ScriptFullPath`%:data

Если вы используете в Windows 7 тему "Классика", при выделении ячейки цветом может
происходить неприятное мелькание текста. В этом случае через меню «Вид» можно
указать цвет выделения равный цвету фона ячейки, тогда при наведении курсора на
ячейку её цвет меняться не будет.

Вопросы по работе скрипта можно задать здесь:
http://forum.script-coding.com/viewtopic.php?id=10385

© teadrinker
)
/*
***************************** Структура файла "data" *****************************

UChar          // Количество блоков с данными из "скопированного"
Блоки с данными
{
   UInt        // Длина строки данных
   Str         // Строка данных
}

UChar          // Количество блоков с данными из "вставленного"
Блоки с данными
{
   UInt        // Длина строки данных
   Str         // Строка данных
}

UShort         // X-координата окна
UShort         // Y-координата окна
UShort         // ширина клиентской части окна
UShort         // высота клиентской части окна

UChar          // SendVariant, возможные значения 1, 3, 4
UChar          // Длина строки с названием и классом связанного окна
Str            // Строка с названием и классом связанного окна
UChar          // Длина строки с Match Mode
Str            // Строка с Match Mode, возможные значения: "1", "2", "3", "RegEx"

UChar          // Длина строки с названием шрифта
Str            // Строка с названием шрифта
UChar          // Размер шрифта, возможные значения: 8 - 15
UChar          // Качество рендеринга, возможные значения 0 - 5
UInt           // Цвет шрифта в RGB

UChar          // Количество строк в ячейке
UChar          // Общее количество ячеек

UInt           // Цвет основного фона окна
UInt           // Цвет фона ячеек
UInt           // Цвет выделения ячеек
UInt           // Цвет области кнопок
UChar          // Стиль рамки, возможные значения:
               //   7 (SS_BLACKFRAME), 8 (SS_GRAYFRAME), 9 (SS_WHITEFRAME)
UChar          // AlwaysPlaceIntoClipboard, возможные значения 0 и 1
UChar          // HideAfterSend, возможные значения 0 и 1

UChar          // Длина строки с названием горячей клавиши для показа/скрытия окна
Str            // Строка с названием горячей клавиши для показа/скрытия окна

UChar          // LoadOnStartup, возможные значения 0 и 1
UChar          // ToggleToSaved, возможные значения 0 и 1

**********************************************************************************
*/

#NoEnv
#SingleInstance, Off

if FileExist(A_ScriptDir "\BufferIcons.dll")
   FileDelete, % A_ScriptDir "\BufferIcons.dll"

IcoDll := A_IsCompiled ? A_ScriptFullPath : A_ScriptDir "\ClipMgrIcons.dll"
if !FileExist(IcoDll)  {
   if !Ping("dropbox.com")  {
      MsgBox, Невозможно загрузить файл с иконками`, проверьте подключение к интернету!
      ExitApp
   }
   URLDownloadToFile, % "http://content.screencast.com/users/teadrinker/folders/Files/media/7d4f94ae-cdd3-467d-b3d1-786f5e8af91c/ClipMgrIcons.dll?downloadOnly=true", % IcoDll
}
if !A_IsCompiled
   Menu, Tray, Icon, %IcoDll%, 1
SetBatchLines, -1
SetWinDelay, 0
CoordMode, Mouse
StringCaseSense, Locale

global HTCAPTION := 2, HTSYSMENU := 3, SC_MAXIMIZE := 0xF030, SC_MINIMIZE := 0xF020
     , SS_BLACKFRAME := 0x7, SS_GRAYFRAME := 0x8, SS_WHITEFRAME := 0x9, WS_EX_NOACTIVATE := 0x8000000
     , IMAGE_CURSOR := 2, OCR_HAND := 32649, LR_SHARED := 0x8000, LR_DEFAULTSIZE := 0x40
     , WM_SETCURSOR := 0x20, WM_NCMOUSEMOVE := 0xA0, WM_VSCROLL := 0x115, WS_VSCROLL := 0x200000, WM_MOUSEMOVE := 0x200
     , TargetWindow, AssociatedWindow, MatchMode, SendVariant, ScrollHeight, LastActiveWindowID
     , AlwaysPlaceIntoClipboard, HideAfterSend, ColorCell, ColorSelect
     , FontName, FontSize, FontQuality, FontColor, RowNumber
     , hMain, hBack, hSetWindow, hSetFont, hSetNumber, hSetColor, hReadme, hSetHotkey
     , hCursorHand := LoadCursorHand(), hBall, TextH, DisplayHkPrev
     , Block := 1, TopWork := 5, VisibleCell := 8, AllCell, oSaved := [], oEntered := [], CurrentContent := "Saved"
     , oQual := [ "DEFAULT_QUALITY"          , "DRAFT_QUALITY"        , "PROOF_QUALITY"
                , "NONANTIALIASED_QUALITY", "ANTIALIASED_QUALITY", "CLEARTYPE_QUALITY" ]
   
SB_LINEUP := 0, SB_LINEDOWN := 1
HKM_SETHOTKEY := 0x401
HOTKEYF_ALT := 0x4, HOTKEYF_CONTROL := 0x2, HOTKEYF_EXT := 0x80, HOTKEYF_SHIFT := 0x1
EM_SETCUEBANNER := 0x1501, EM_SETSEL := 0xB1, OBJID_VSCROLL := 0xFFFFFFFB
STATE_SYSTEM_INVISIBLE := 0x8000
oFonts := GetCyrillicFontNames()

VarSetCapacity(SBI, 60)
NumPut(60, SBI)
DriveGet, FIleSystem, FS, % SubStr(A_ScriptDir, 1, 2)
DataFile := A_ScriptDir "\" . ((FIleSystem = "NTFS" && A_IsCompiled) ? A_ScriptName . ":" : "") . "data"
param = %1%

if !FileExist(DataFile)
   MatchMode := 2, SendVariant := 3
   , PrevFontName    := FontName    := "Arial"
   , PrevFontSize    := FontSize    := 10
   , PrevFontQuality := FontQuality := 5
   , PrevFontColor   := FontColor   := 0
   , PrevRowNumber   := RowNumber   := 3
   , PrevAllCell     := AllCell     := 24
   , PrevColorBack   := ColorBack   := 0xFFFFFF
   , PrevColorCell   := ColorCell   := 0xFFFFFF
   , PrevColorSelect := ColorSelect := 0xFFFEAF
   , PrevColorButton := ColorButton := 0xD0D0D0
   , PrevFrameStyle  := FrameStyle  := SS_GRAYFRAME
   , AlwaysPlaceIntoClipboard := HideAfterSend := 0
   , Hk := DisplayHkPrev := "Нет"
   , LoadOnStartup := 0
   , ToggleToSaved := 1
else
{
   oFile := FileOpen(DataFile, "r", "UTF-16-RAW")
   Loop % oFile.ReadUChar()
      bytes := oFile.ReadUInt()
      , oSaved.Insert(oFile.Read(bytes))
      
   Loop % oFile.ReadUChar()
      bytes := oFile.ReadUInt()
      , oEntered.Insert(oFile.Read(bytes))

   MainGuiX := oFile.ReadUSHort(), MainGuiY := oFile.ReadUSHort()
   MainGuiW := oFile.ReadUSHort(), MainGuiH := oFile.ReadUSHort()

   SendVariant := oFile.ReadUChar()
   bytes := oFile.ReadUChar()
   AssociatedWindow := oFile.Read(bytes)
   bytes := oFile.ReadUChar()
   MatchMode := oFile.Read(bytes)
   
   Fontbytes := oFile.ReadUChar()
   PrevFontName    := FontName    := oFile.Read(Fontbytes)
   PrevFontSize    := FontSize    := oFile.ReadUChar()
   PrevFontQuality := FontQuality := oFile.ReadUChar()
   PrevFontColor   := FontColor   := oFile.ReadUInt()
   
   PrevRowNumber   := RowNumber   := oFile.ReadUChar()
   PrevAllCell     := AllCell     := oFile.ReadUChar()
   
   PrevColorBack   := ColorBack   := oFile.ReadUInt()
   PrevColorCell   := ColorCell   := oFile.ReadUInt()
   PrevColorSelect := ColorSelect := oFile.ReadUInt()
   PrevColorButton := ColorButton := oFile.ReadUInt()
   PrevFrameStyle  := FrameStyle  := oFile.ReadUChar()
   
   AlwaysPlaceIntoClipboard := oFile.ReadUChar()
   HideAfterSend := oFile.ReadUChar()
   
   bytes := oFile.ReadUChar()
   Hk := oFile.Read(bytes)
   DisplayHkPrev := GetDisplayHk(Hk)
   
   LoadOnStartup := oFile.ReadUChar()
   ToggleToSaved := oFile.ReadUChar()
   
   oFile.Close()

   if (MainGuiX = "" || MainGuiX > A_ScreenWidth - 50)
      Error .= "Ошибка чтения данных MainGuiX`nБудет присвоено значение по умолчанию`n`n", MainGuiX := ""
   if (MainGuiY = "" || MainGuiY > A_ScreenHeight - 50)
      Error .= "Ошибка чтения данных MainGuiY`nБудет присвоено значение по умолчанию`n`n", MainGuiY := ""
   if (MainGuiW = "" || MainGuiW > A_ScreenWidth)
      Error .= "Ошибка чтения данных MainGuiW`nБудет присвоено значение по умолчанию`n`n", MainGuiW := ""
   if (MainGuiH = "" || MainGuiH > A_ScreenHeight)
      Error .= "Ошибка чтения данных MainGuiH`nБудет присвоено значение по умолчанию`n`n", MainGuiH := ""
   if SendVariant not in 1,3,4
      Error .= "Ошибка чтения данных SendVariant`nБудет присвоено SendVariant := 3 (Посылать в активное окно)`n`n", SendVariant := 3
   if MatchMode not in 1,2,3,RegEx
      Error .= "Ошибка чтения данных MatchMode`nБудет присвоено MatchMode := 2`n`n", MatchMode := 2
   for k, font in (oFonts)
      if (FontName = font && Success := 1)
         break
   if !Success
      Error .= "Ошибка чтения данных FontName`nБудет присвоено FontName := ""Arial""`n`n", FontName := "Arial"
   if (FontSize < 8 || FontSize > 15)
      Error .= "Ошибка чтения данных FontSize`nБудет присвоено FontSize := 10`n`n", FontSize := 10
   if FontQuality not between 1 and 5
      Error .= "Ошибка чтения данных FontQuality`nБудет присвоено FontQuality := 5`n`n", FontQuality := 5
   if (FontColor > 0xFFFFFF || FontColor = "")
      Error .= "Ошибка чтения данных FontColor`nБудет присвоено FontColor := 0x000000`n`n", FontColor := 0
   if RowNumber not between 1 and 5
      Error .= "Ошибка чтения данных RowNumber`nБудет присвоено RowNumber := 3`n`n", RowNumber := 3
   if AllCell not between 8 and 64
      Error .= "Ошибка чтения данных AllCell`nБудет присвоено AllCell := 24`n`n", AllCell := 24
   if (ColorBack > 0xFFFFFF || ColorBack = "")
      Error .= "Ошибка чтения данных ColorBack`nБудет присвоено ColorBack := 0xFFFFFF`n`n", ColorBack := 0xFFFFFF
   if (ColorCell > 0xFFFFFF || ColorCell = "")
      Error .= "Ошибка чтения данных ColorCell`nБудет присвоено ColorCell := 0xFFFFFF`n`n", ColorCell := 0xFFFFFF
   if (ColorSelect > 0xFFFFFF || ColorSelect = "")
      Error .= "Ошибка чтения данных ColorSelect`nБудет присвоено ColorSelect := 0xFFFEAF`n`n", ColorSelect := 0xFFFEAF
   if (ColorButton > 0xFFFFFF || ColorButton = "")
      Error .= "Ошибка чтения данных ColorButton`nБудет присвоено ColorButton := 0xD0D0D0`n`n", ColorButton := 0xD0D0D0
   if FrameStyle not in 7,8,9
      Error .= "Ошибка чтения данных FrameStyle`nБудет присвоено FrameStyle := 0x8`n`n", FrameStyle := 8
   if AlwaysPlaceIntoClipboard not in 0,1
      Error .= "Ошибка чтения данных AlwaysPlaceIntoClipboard`nБудет присвоено AlwaysPlaceIntoClipboard := 0`n`n", AlwaysPlaceIntoClipboard := 0
   if HideAfterSend not in 0,1
      Error .= "Ошибка чтения данных HideAfterSend`nБудет присвоено HideAfterSend := 0`n`n", HideAfterSend := 0
   if Hk = ""
      Error .= "Ошибка чтения данных Hk`nБудет присвоено Hk := ""Нет""`n`n", Hk := "Нет"
   if LoadOnStartup not in 0,1
   {
      LoadOnStartup := param = "Hide"
      Error .= "Ошибка чтения данных LoadOnStartup`nБудет присвоено LoadOnStartup := " . LoadOnStartup . "`n`n"
   }
   if ToggleToSaved not in 0,1
      Error .= "Ошибка чтения данных ToggleToSaved`nБудет присвоено ToggleToSaved := 1`n`n", ToggleToSaved := 1
   
   if Error
      MsgBox, % Trim(Error, "`n")
   Error := Success := ""
}

Menu, Tray, NoStandard
Menu, Tray, Add, Открыть новое окно, OpenNewWindow
Menu, Tray, Add, % "Скрыть окно" . (DisplayHkPrev = "Нет" ? "" : A_Tab . DisplayHkPrev), HideShowMainWindow
If !A_IsCompiled
   Menu, Tray, Add, Reload, Reload
Menu, Tray, Add, Выход, MainGuiClose

Menu, Actions, Add, Удалить, Delete
Menu, Actions, Icon, Удалить, %IcoDll%, 2
Menu, Actions, Add, Отправить             LButton, Send
Menu, Actions, Icon, Отправить             LButton, %IcoDll%, 3

Menu, Settings, Add, Указать связанное окно, SetAssociatedWindow
Menu, Settings, Add, Выбрать целевое окно правой кнопкой, SelectWindow
Menu, Settings, Add
Menu, Settings, Add, Посылать в связанное окно, SendToAssociatedWindow
Menu, Settings, Add, Посылать в целевое окно, SendToTargetWindow
Menu, Settings, Add, Посылать в активное окно, SendToActiveWindow
Menu, Settings, Add, Только помещать в буфер обмена, SendOnlyIntoClipboard
Menu, Settings, Check, % SendVariant = 1 ? "Посылать в связанное окно"
                       : SendVariant = 3 ? "Посылать в активное окно" : "Только помещать в буфер обмена"
Menu, Settings, Add
Menu, Settings, Add, Всегда помещать в буфер обмена, AlwaysPlaceIntoClipboard
if AlwaysPlaceIntoClipboard
   Menu, Settings, Check, Всегда помещать в буфер обмена

Menu, Settings, Add, Скрывать после вставки и вывода курсора за пределы окна, HideAfterSend
if HideAfterSend
   Menu, Settings, Check, Скрывать после вставки и вывода курсора за пределы окна

Menu, Settings, Add, Переключать на «Скопированное» при изменении буфера обмена, ToggleToSaved
if ToggleToSaved
   Menu, Settings, Check, Переключать на «Скопированное» при изменении буфера обмена

Menu, Settings, Add
Menu, Settings, Add, % "Указать горячую клавишу для показа/скрытия окна" A_Tab DisplayHkPrev, SetHotkey
Menu, Settings, Add
Menu, Settings, Add, Загружать при старте системы, LoadOnStartup
if LoadOnStartup
   Menu, Settings, Check, Загружать при старте системы
Menu, Settings, Add
Menu, Settings, Add, Readme, ShowReadme
Menu, Settings, Icon, Readme, %IcoDll%, 7

Menu, View, Add, Выбрать шрифт, SetFont
Menu, View, Icon, Выбрать шрифт, %IcoDll%, 4
Menu, View, Add, Количество строк и ячеек, SetNumber
Menu, View, Icon, Количество строк и ячеек, %IcoDll%, 5

Menu, View, Add, Настройки цвета, SetColor
Menu, View, Icon, Настройки цвета, %IcoDll%, 6

Menu, Content, Add, Скопированное, ShowSaved
Menu, Content, Add, Вставленное, ShowEntered
Menu, Content, Check, Скопированное

Menu, MenuBar, Add, Настройки, :Settings
Menu, MenuBar, Add, Вид, :View
Menu, MenuBar, Add, Содержимое, :Content

Gosub, CreateMainWindow

OnMessage(WM_SETCURSOR  , "WM_MOUSEMOVE")
OnMessage(WM_NCMOUSEMOVE, "WM_MOUSEMOVE")
OnMessage(0x0A1, "WM_NCLBUTTONDOWN")
OnMessage(0x0A2, "WM_NCLBUTTONUP")
OnMessage(0x0A3, "WM_NCLBUTTONDBLCLK")
OnMessage(0x102, "WM_CHAR")
OnMessage(0x112, "WM_SYSCOMMAND")
OnMessage(0x115, "WM_VSCROLL")
OnMessage(0x200, "WM_MOUSEMOVE")
OnMessage(0x205, "WM_RBUTTONUP")
OnMessage(0x207, "WM_MBUTTONDOWN")
OnMessage(0x404, "AHK_NOTIFYICON")
OnMessage(DllCall("RegisterWindowMessage", Str, "WM_INFO"), "WM_INFO")
SetTimer, Unblock, -1000
OnExit, SaveData
if (Hk = "Нет" || Hk = "")
   Return

try  {
   Hotkey, If
   Hotkey, %Hk%, HideShowMainWindow, On
}
catch e  {
   Menu, Settings, Rename, % "Указать горячую клавишу для показа/скрытия окна" A_Tab DisplayHkPrev
                         , % "Указать горячую клавишу для показа/скрытия окна" A_Tab DisplayHkPrev := "Нет"
   Menu, Tray, Rename, % "Скрыть окно" . (DisplayHkPrev = "Нет" ? "" : A_Tab . DisplayHkPrev), Скрыть окно
   MsgBox, 16, Ошибка установки горячей клавиши, % e.Message "`nГорячая клавиша """ . Hk . """ для показа/скрытия окна не установлена!"
}
Return

CreateMainWindow:
   Gui, Main: New, +hwndhMain +AlwaysOnTop +E%WS_EX_NOACTIVATE% +Owner +Resize +MinSize218x -DPIScale
   Gui, Main: Menu, MenuBar
   Gui, Main: Color, % Format("{:X}", ColorButton)

   Gui, Back: +ParentMain -Caption +Border +hwndhBack +%WS_VSCROLL% -DPIScale
   Gui, Back: Color, % Format("{:X}", ColorBack)
   Loop % AllCell
   {
      Gui, Work%A_Index%: Default
      Gui, +ParentBack -Caption -DPIScale
      Gui, Margin, 0, 0
      Gui, Color, % Format("{:X}", ColorCell)
      Gui, Add, Text, vBorder +%FrameStyle% x0 y0 w208
      Gui, Font, s%FontSize% q%FontQuality%, % FontName
         
      Gui, Add, Text, % "vText gSend_ x2 y2 w204 r" . RowNumber . " BackgroundTrans -Wrap c" . Format("{:X}", FontColor)
      GuiControlGet, Text, Pos
      GuiControl, Move, Border, % "h" TextH + 4
      Gui, Show, % "x5 y" 5 + (A_Index - 1) * (TextH + 8) " w208 h" TextH + 4 " Hide"
   }
   Gui, Back: Show, % "NA x-1 y0 w218 h" (TextH + 8)*VisibleCell + 6

   Gui, Main: Default
   Gui, Font, s10, Verdana
   Gui, Add, Button, % "x6 y" (TextH + 8)*VisibleCell + 18 " w101 h22", Clear
   Gui, Add, Button, gBlock vBlock x+5 yp wp hp, Block
   
   SetContent()
   GuiControl, Work1: Focus, Static1
   ((MainGuiW = "" || MainGuiH = "") && (MainGuiW := 218) && (MainGuiH := (TextH + 8)*VisibleCell + 40))
   Bool := (MainGuiX != "" && MainGuiY != "")
   Gui, Show, % (Bool ? "x" MainGuiX " y" MainGuiY " " : "") . (param = "Hide" ? "Hide" : "NA") . " w" MainGuiW " h" MainGuiH, Скопированное
   
   if (param = "Hide")  {
      TrayMenuPostFix := DisplayHkPrev = "Нет" ? "" : A_Tab . DisplayHkPrev
      Menu, Tray, Rename, % "Скрыть окно" . TrayMenuPostFix, % "Показать окно" . TrayMenuPostFix
      param := ""
   }
   Return

MainGuiSize:
   DllCall("GetScrollBarInfo", Ptr, hBack, UInt, OBJID_VSCROLL, Ptr, &SBI)
   , delta := NumGet(&SBI + 12, "UInt") - NumGet(&SBI + 4, "UInt")
   
   Gui, Back:Show, % "NA x-1 y0 w" A_GuiWidth - delta " h" A_GuiHeight - 36
   Loop % AllCell
   {
      Gui, Work%A_Index%: Default
      Gui, Show, % "NA x5 y" TopWork + (A_Index - 1) * (TextH + 8) " w" w := A_GuiWidth - 10
      GuiControlGet, Text
      if (Text = "")
         Gui, Show, Hide
      GuiControl, MoveDraw, Border, % "w" w " h" TextH + 4
      GuiControl, Move, Text, % "w" w - 4 " h" TextH
   }
   GuiControl, Main:MoveDraw, Button1, % "y" A_GuiHeight - 28
   GuiControl, Main:MoveDraw, Button2, % "x" A_GuiWidth - 101 - 6 " y" A_GuiHeight - 28
   UpdateScrollBar(hBack, ScrollHeight)
   GuiW := A_GuiWidth, GuiH := A_GuiHeight
   Return
   
ShowSaved:
ShowEntered:
   if (CurrentContent = SubStr(A_ThisLabel, 5))
      Return
   
   Menu, Content, UseErrorLevel
   Menu, Content, UnCheck, Вставленное
   Menu, Content, UnCheck, Скопированное
   Menu, Content, Check, % A_ThisMenuItem
   CurrentContent := SubStr(A_ThisLabel, 5)
   
   SetContent()
   Gui, Main:Show, NA, % A_ThisMenuItem
   Return

Reload:
   Reload
   Return

HideShowMainWindow:
   b := WinExist("ahk_id" hMain)
   Gui, Main:Show, % b ? "Hide" : "NA"
   TrayMenuPostFix := DisplayHkPrev = "Нет" ? "" : A_Tab . DisplayHkPrev
   Menu, Tray, Rename, % (b ? "Скрыть окно" : "Показать окно") . TrayMenuPostFix
                     , % (b ? "Показать окно" : "Скрыть окно") . TrayMenuPostFix
   Return

OpenNewWindow:
   Run, % A_ScriptFullPath,,, PID
   WinWait, ahk_pid %PID%
   WinGetPos, X, Y
   Loop 15
   {
      Sleep, 20
      WinMove, X - 15 < 0 ? (X + A_Index) : (X - A_Index), Y + A_Index
   }
   Return
   
SetFont:
   oDDL := GetDDLstrings(FontName, oFonts, FontQuality, FontSize)
   Gui, SetFont:New, +ToolWindow +OwnerMain +AlwaysOnTop +LastFound +hwndhSetFont -DPIScale
   Gui, SetFont:Default
   Gui, Margin, 15, 15
   Gui, Font,, Tahoma
   
   Gui, Add, Text,, Название шрифта:
   Gui, Add, DDL, vFontName x+25 yp-3 w153 r20 Sort, % oDDL.Font
   GuiControlGet, FontName, Pos

   Gui, Add, Text, x15 y+14, Качество рендеринга:
   Gui, Add, DDL, x%FontNameX% yp-3 w%FontNameW% vQuality, % oDDL.Qual
   
   Gui, Add, Text, x15 y+15, Размер шрифта:
   Gui, Add, DDL, x%FontNameX% yp-3 w38 vFontSize, % oDDL.Size
   
   Gui, Add, Button, vDef gDef x+5 yp-1 hp+2, Сбросить всё
   GuiControlGet, Def, Pos
   GuiControl, Move, Def, % "x" FontNameX + FontNameW - DefW
   Gui, Add, Button, % "vCancel x" FontNameX " y+20 hp w" FontNameW//2 - 2, Применить
   Gui, Add, Button, % "vOk x" FontNameX + FontNameW - (FontNameW//2 - 2) " yp hp wp Default", OK
   Gui, Add, Button, % "vApply x" FontNameX - FontNameW//2 - 4 " yp hp wp", Отмена
   
   ShowOwnerWindow("Шрифт", hSetFont)
   Return
   
Def:
   oDDL := GetDDLstrings("Arial", oFonts, 5, 10)
   Gui, SetFont: Default
   GuiControl,, FontName, % "|" . oDDL.Font
   GuiControl,, Quality , % "|" . oDDL.Qual
   GuiControl,, FontSize, % "|" . oDDL.Size
   Return
   
SetFontButtonПрименить:
SetFontButtonOK:
   Gui, SetFont:Submit, NoHide
   for k, v in oQual  {
      if (v = Quality)  {
         FontQuality := k - 1
         break
      }
   }

SetFontButtonОтмена:
SetFontGuiClose:
SetFontGuiEscape:
   if (A_ThisLabel != "SetFontButtonПрименить")
   {
      Gui, SetFont:Destroy
      WinActivate, ahk_id %LastActiveWindowID%
   }
   if (FontName = PrevFontName && FontSize = PrevFontSize && FontQuality = PrevFontQuality)
      Return
   
   if A_ThisLabel in SetFontButtonOK,SetFontButtonПрименить
   {
      MainGuiW := GuiW, MainGuiH := GuiH
      WinGetPos, MainGuiX, MainGuiY,,, ahk_id %hMain%
      Gui, SetFont: -OwnerMain
      Gosub, CreateMainWindow
      Gui, SetFont: +OwnerMain
   }
   PrevFontName := FontName, PrevFontSize := FontSize, PrevFontQuality := FontQuality
   Return
   
SetNumber:
   oDDL := GetDDLstrings(RowNumber, AllCell)
   Gui, SetNumber:New, +ToolWindow +OwnerMain +AlwaysOnTop +LastFound +hwndhSetNumber -DPIScale
   Gui, SetNumber:Default
   Gui, Margin, 15, 15
   Gui, Font,, Tahoma

   Gui, Add, Text,, Количество строк в ячейке:
   Gui, Add, DDL, vRowNumber x+20 yp-4 w40, % oDDL.Rows
   GuiControlGet, RowNumber, Pos

   Gui, Add, Text, x15 y+13, Общее количество ячеек:
   Gui, Add, DDL, vAllCell x%RowNumberX% yp-4 w40, % oDDL.Cells
   
   ButtonWidth := (RowNumberX + RowNumberW - 10 - 15)//3
   Gui, Add, Button, % "x15 y+20 w" ButtonWidth + 1 " h23", Отмена
   Gui, Add, Button, x+5 yp wp hp, Применить
   Gui, Add, Button, x+5 yp wp hp Default, OK
   ShowOwnerWindow("Количество строк и ячеек", hSetNumber)
   Return
   
SetNumberButtonПрименить:
SetNumberButtonOK:
   Gui, SetNumber:Submit, NoHide

SetNumberButtonОтмена:
SetNumberGuiClose:
SetNumberGuiescape:
   if (A_ThisLabel != "SetNumberButtonПрименить")
   {
      Gui, SetNumber: Destroy
      WinActivate, ahk_id %LastActiveWindowID%
   }
   if (RowNumber = PrevRowNumber && PrevAllCell = AllCell)
      Return
   
   if A_ThisLabel in SetNumberButtonOK,SetNumberButtonПрименить
   {
      oSaved.Remove(AllCell + 1, oSaved.MaxIndex())
      oEntered.Remove(AllCell + 1, oEntered.MaxIndex())
      MainGuiW := GuiW, MainGuiH := GuiH
      WinGetPos, MainGuiX, MainGuiY,,, ahk_id %hMain%
      Gui, SetNumber: -OwnerMain
      Gosub, CreateMainWindow
      Gui, SetNumber: +OwnerMain
   }
   PrevRowNumber := RowNumber, PrevAllCell := AllCell
   Return
   
ControlsCreate(var, text)
{
   global
   Gui, Add, Text, x15 y+15, % text
   Gui, Add, Edit, v%var% gChangeColor x+8 yp-3 w62 Limit6 Uppercase Center, % Format("{:06X}", %var%)
   GuiControlGet, %var%, Pos
   GuiControl, Move, % var, x%ColorBackX%
   ColoredGuiShow(var, "SetColor", %var%, "ColorChoose", ColorBackW, ColorBackH)
}
   
SetColor:
   Gui, SetColor:New, +ToolWindow +OwnerMain +AlwaysOnTop +LastFound +hwndhSetColor -DPIScale
   Gui, SetColor:Default
   Gui, Margin, 15, 15
   Gui, Font, s8, Tahoma
   
   ControlsCreate("ColorBack"  , "Цвет общего фона ячеек:")
   ControlsCreate("ColorCell"  , "Цвет фона ячейки:")
   ControlsCreate("ColorSelect", "Цвет выделения ячейки:")
   ControlsCreate("FontColor"  , "Цвет шрифта:")
   ControlsCreate("ColorButton", "Цвет фона кнопок:")
   
   Gui, Add, Text, x15 y+15, Цвет рамки ячейки:
   Gui, Add, Radio, % "x+15 yp" . (FrameStyle = SS_BLACKFRAME ? " Checked" : "") . " vRadio", Black
   Gui, Add, Radio, % "x+5 yp"  . (FrameStyle = SS_GRAYFRAME  ? " Checked" : ""), Gray
   Gui, Add, Radio, % "x+5 yp"  . (FrameStyle = SS_WHITEFRAME ? " Checked" : ""), White
   GuiControlGet, White, Pos, White
   
   Gui, Add, Button, vApply x15 y+20, Применить
   Gui, Add, Button, xp yp wp, Сбросить
   Gui, Add, Button, vCancel x+3 yp wp, Отмена
   GuiControlGet, Cancel, Pos
   GuiControl, Move, Apply, % "x" CancelX + CancelW + 3
   
   Gui, Add, Button, % "vOK x" CancelX + CancelW*2 + 6 " yp wp Default", OK
   GuiControlGet, OK, Pos
   
   ControlMetr := WhiteX + WhiteW > OKX + OKW ? "White" : "OK"
   ColorGuis := "ColorBack|ColorCell|ColorSelect|FontColor|ColorButton"
   Loop, parse, ColorGuis, |
      Gui, %A_LoopField%:Show, % "NA x" %ControlMetr%X + %ControlMetr%W - %A_LoopField%W - 1 " y" %A_LoopField%Y
   
   GuiControl, Focus, Static1
   ShowOwnerWindow("Настройки цвета в RGB", hSetColor)
   Return

ChangeColor:
   GuiControlGet, Color, SetColor:, %A_GuiControl%
   Gui, %A_GuiControl%: Color, % "0x" Color
   Return
   
ColorChoose:
   GuiControlGet, Color, SetColor:, %A_Gui%
   if (Color := ChooseColor("0x" . Color, hSetColor)) = -1
      Return
   
   Gui, %A_Gui%:Color, % Color
   GuiControl, SetColor:, %A_Gui%, % SubStr("00000" . SubStr(Color, 3), -5)
   Return
   
SetColorButtonСбросить:
   Gui, SetColor:Default
   GuiControl,, Edit1, FFFFFF
   GuiControl,, Edit2, FFFFFF
   GuiControl,, Edit3, FFFEAF
   GuiControl,, Edit4, 000000
   GuiControl,, Edit5, D0D0D0
   GuiControl,, Gray, 1
   Return

SetColorButtonОтмена:
SetColorGuiEscape:
SetColorGuiClose:
   Gui, SetColor:Destroy
   WinActivate, ahk_id %LastActiveWindowID%
   Return

SetColorButtonOK:
SetColorButtonПрименить:
   Gui, SetColor:Submit, NoHide
   Loop, parse, ColorGuis, |
      %A_LoopField% := "0x" . %A_LoopField%
   FrameStyle := [SS_BLACKFRAME, SS_GRAYFRAME, SS_WHITEFRAME][Radio]
   
   if ( ColorBack   != PrevColorBack
     || ColorCell   != PrevColorCell
     || ColorSelect != PrevColorSelect
     || FontColor   != PrevFontColor
     || ColorButton != PrevColorButton
     || FrameStyle  != PrevFrameStyle )
   {
      MainGuiW := GuiW, MainGuiH := GuiH
      WinGetPos, MainGuiX, MainGuiY,,, ahk_id %hMain%
      Gui, SetColor: -OwnerMain
      Gosub, CreateMainWindow
      Gui, SetColor: +OwnerMain
      PrevColorBack := ColorBack, PrevColorCell := ColorCell, PrevColorSelect := ColorSelect
      PrevFontColor := FontColor, PrevColorButton := ColorButton, PrevFrameStyle := FrameStyle
   }
   
   if (A_ThisLabel = "SetColorButtonOK")
      Gosub, SetColorGuiClose
   Return
   
SetAssociatedWindow:
   Gui, SetWindow:New, +ToolWindow +OwnerMain +AlwaysOnTop +LastFound +hwndhSetWindow -DPIScale
   Gui, SetWindow:Default
   Gui, Margin, 12, 12
   Gui, Add, Link, y10, Укажите <a href="http://ahkscript.org/docs/misc/WinTitle.htm">заголовок и класс</a> связанного окна:
   Gui, Add, Edit, y+10 wp h21 hwndhEdit vAssociatedWindow

   Gui, Add, Link, y+25, <a href="http://ahkscript.org/docs/commands/SetTitleMatchMode.htm">Match Mode:</a>
   Gui, Add, Radio, vMatchMode x+15 yp, 1
   GuiControlGet, Radio1, pos, Button1
   
   Gui, Add, Radio, x+7 yp, 2
   Gui, Add, Radio, x+7 yp, 3
   Gui, Add, Radio, x+7 yp, RegEx
   oRadio := {1: "Button1", 2: "Button2", 3: "Button3", RegEx: "Button4"}
   GuiControl,, % oRadio[MatchMode], 1
   GuiControlGet, Radio4, pos, Button4
   
   Gui, Add, GroupBox, % "x" (xGr := Radio1X - 9) " y" Radio1Y - 17
                      . " w" (wGr := Radio4X - Radio1X + 9 + Radio4W + 4) " h" Radio4H + 29
   GuiControl, Move, Edit1, % "w" xGr - 12 + wGr
   
   Gui, Add, Button, % "vSetWindow x" xGr + wGr - 90 " y+12 w90 h23 Default", OK
   Gui, Add, Button, gSetWindowGuiCancel xp-95 yp wp hp, Указать позже
   GuiControl, Focus, Button2
   if !AssociatedWindow
      PostMessage, EM_SETCUEBANNER, 0, " Блокнот ahk_class Notepad",, ahk_id %hEdit%
   else
   {
      GuiControl,, AssociatedWindow, % AssociatedWindow
      PostMessage, EM_SETSEL, 0, -1,, ahk_id %hEdit%
      GuiControl, Focus, Edit1
   }
   
   ShowOwnerWindow("Связанное окно", hSetWindow)
   Return
   
SetWindowButtonOK:
   Gui, SetWindow:Submit, NoHide
   (MatchMode = 4 && MatchMode := "RegEx")
   if (AssociatedWindow = "")
   {
      MsgBox, 4144,, Укажите связанное окно в поле редактирования!
      Return
   }
   Gosub, SendToAssociatedWindow

SetWindowGuiEscape:
SetWindowGuiCancel:
SetWindowGuiClose:
   Gui, SetWindow:Destroy
   WinActivate, ahk_id %LastActiveWindowID%
   Return
   
SendToAssociatedWindow:
SendToTargetWindow:
SendToActiveWindow:
SendOnlyIntoClipboard:
   oSendVariant := { SendToAssociatedWindow: {Variant: 1, Menu: "Посылать в связанное окно"}
                   , SendToTargetWindow:     {Variant: 2, Menu: "Посылать в целевое окно"}
                   , SendToActiveWindow:     {Variant: 3, Menu: "Посылать в активное окно"}
                   , SendOnlyIntoClipboard:  {Variant: 4, Menu: "Только помещать в буфер обмена"} }
   
   SendVariant := oSendVariant[A_ThisLabel].Variant
   for k, v in oSendVariant
      Menu, Settings, % k = A_ThisLabel ? "Check" : "UnCheck", % v.Menu
   Return

Send_:
   Send(A_Gui)
   Return

SelectWindow:
   CrossHair(), CrossHair := 1
   Hotkey, If
   Hotkey, RButton Up, Choice, On
   Return
   
Choice:
   CrossHair(0), CrossHair := ""
   Hotkey, RButton Up, Off
   MouseGetPos,,, TargetWindow
   if (TargetWindow = hMain)
      Goto, SendToActiveWindow
   Send, {Click}
   Gosub, SendToTargetWindow
   TargetWndShow(TargetWindow)
   Return
   
AlwaysPlaceIntoClipboard:
   Menu, Settings, ToggleCheck, Всегда помещать в буфер обмена
   AlwaysPlaceIntoClipboard := !AlwaysPlaceIntoClipboard
   Return
   
HideAfterSend:
   Menu, Settings, ToggleCheck, Скрывать после вставки и вывода курсора за пределы окна
   HideAfterSend := !HideAfterSend
   Return
   
ToggleToSaved:
   Menu, Settings, ToggleCheck, Переключать на «Скопированное» при изменении буфера обмена
   ToggleToSaved := !ToggleToSaved
   Return
   
SetHotkey:
   PrevHk := Hk, wParam := "", HIBYTE := 0, oMods := {"!": HOTKEYF_ALT, "+": HOTKEYF_SHIFT, "^": HOTKEYF_CONTROL}
   RegExMatch(Hk, "^(([!\+\^]+)|)(.*)", match)
   Loop, parse, match2
      HIBYTE |= oMods[A_LoopField]
   wParam := (HIBYTE << 8)|GetKeyVK(match3)
   
   Gui, SetHotkey:New, +ToolWindow +OwnerMain +AlwaysOnTop +LastFound +hwndhSetHotkey -DPIScale
   Gui, SetHotkey:Default
   Gui, Margin, 15, 15
   Gui, Font,, Tahoma
   
   Gui, Add, Text,, Введите горячую клавишу:
   Gui, Add, Hotkey, vHk gHk hwndhHk x+15 yp-3 w110
   GuiControlGet, Hk, Pos
   Gui, Add, Text, x15 y+7, Или напечатайте
   Gui, Add, Link, x15 y+2, в <a href="http://ahkscript.org/docs/Hotkeys.htm">AHK-совместимом формате</a>:
   Gui, Add, Edit, vEdit x%HkX% yp-8 w%HkW%
   
   Gui, Add, Button, vCancel x15 y+17, Отмена
   GuiControlGet, Cancel, Pos
   (CancelW < 80 && CancelW := 80)
   
   Gui, Add, Button, x15 yp, OK
   GuiControl, Move, OK, % "x" HkX + HkW - CancelW " w" CancelW
   GuiControl, Move, Cancel, % "x" HkX + HkW - CancelW*2 - 5 " w" CancelW
   
   ShowOwnerWindow("Горячая клавиша для показа/скрытия окна", hSetHotkey)

   SendMessage, HKM_SETHOTKEY, wParam,,, ahk_id %hHk%
   GuiControlGet, Hk
   Gosub, Hk
   Return
   
Hk:
   RegExMatch(Hk, "[A-Z]$", found)
   StringReplace, Hk, Hk, % found, % "vk" . Format("{:X}", GetKeyVK(found))
   RegExMatch(Hk, "Numpad.+$", found)
   StringReplace, Hk, Hk, % found, % "sc" . Format("{:X}", GetKeySC(found))
   GuiControl, SetHotkey:, Edit, % Hk
   Return

SetHotkeyButtonOK:
   GuiControlGet, Edit, SetHotkey:
   if InStr(Edit, " & ")  {
      MsgBox, Горячие клавиши с символом "&" не поддерживаются!
      Return
   }
   try  {
      Hotkey, If
      Hotkey, %Edit%, HideShowMainWindow, On
   }
   catch e  {
      Hk := PrevHk
      MsgBox, 16, Ошибка установки горячей клавиши, % e.Message "`nНовая горячая клавиша для показа/скрытия окна не установлена!"
                                                              . "`nОстаётся в силе горячая клавиша """ . DisplayHkPrev . """"
      Return
   }
   
   Hk := Edit
   if !(PrevHk = "Нет" || PrevHk = "" || PrevHk = Hk)
      Hotkey, %PrevHk%, Off
   DisplayHk := GetDisplayHk(Edit)
   Menu, Settings, UseErrorLevel
   Menu, Settings, Rename, % "Указать горячую клавишу для показа/скрытия окна" A_Tab DisplayHkPrev
                         , % "Указать горячую клавишу для показа/скрытия окна" A_Tab DisplayHk
   PrevTrayMenuName := WinExist("ahk_id" hMain) ? "Скрыть окно" : "Показать окно"
   Menu, Tray, Rename, % PrevTrayMenuName . (DisplayHkPrev = "Нет" ? "" : A_Tab . DisplayHkPrev)
                     , % PrevTrayMenuName . (DisplayHk = "Нет" ? "" : A_Tab . DisplayHk)
   DisplayHkPrev := DisplayHk
   
SetHotkeyButtonОтмена:
   if (A_ThisLabel = "SetHotkeyButtonОтмена")
      Hk := PrevHk
   Gui, SetHotkey:Destroy
   WinActivate, ahk_id %LastActiveWindowID%
   Return
   
LoadOnStartup:
   if !(LoadOnStartup := !LoadOnStartup)
      FileDelete, %A_Startup%\ClipboardMgr.lnk
   else  {
      try FileCreateShortcut, % A_ScriptFullPath, %A_Startup%\ClipboardMgr.lnk,, Hide
      catch  {
         MsgBox, 16, Ошибка создания ярлыка, Не удалось создать ярлык в папке автозагрузки
         LoadOnStartup := 0
         Return
      }
   }
   Menu, Settings, ToggleCheck, Загружать при старте системы
   Return
   
MainButtonClear:
   o%CurrentContent% := [], SetContent()
   Return

Block:
   GuiControl,, Block, % (Block := !Block) ? "Unblock" : "Block"
   Return

Unblock:
   Block := ""
   Return

OnClipboardChange:
   if Block || (Clipboard == oSaved[1] && StrLen(Clipboard) = StrLen(oSaved[1])) || A_EventInfo != 1
      Return
   
   RemoveExistingAddNew(oSaved, Clipboard)
   if (CurrentContent = "Entered")  {
      (ToggleToSaved && ChangeContent())
      Return
   }
   
   SetContent()
   Return

MainGuiClose:
   ExitApp
   
ShowReadme:
   Gui, Readme:New, +ToolWindow +OwnerMain +AlwaysOnTop +LastFound +hwndhReadme -DPIScale
   Gui, Readme:Default
   Gui, Color, White
   Gui, Margin, 0, 0
   Gui, Font, s9, Tahoma
   Gui, Add, Edit, ReadOnly, % Readme
   ShowOwnerWindow("Readme", hReadme)
   PostMessage, EM_SETSEL, 0, 0, Edit1
   Return
   
ReadmeGuiClose:
   Gui, Readme:Destroy
   WinActivate, ahk_id %LastActiveWindowID%
   Return
   
SaveData:
   DllCall("DestroyCursor", Ptr, hCursorHand)
   (CrossHair && CrossHair(0))
   
   oFile := FileOpen(DataFile, "w", "UTF-16-RAW")
   oFile.WriteUChar(oSaved.MaxIndex())
   for k, v in oSaved
      oFile.WriteUInt(StrLen(oSaved[A_Index]))
      , oFile.Write(oSaved[A_Index])
      
   oFile.WriteUChar(oEntered.MaxIndex())
   for k, v in oEntered
      oFile.WriteUInt(StrLen(oEntered[A_Index]))
      , oFile.Write(oEntered[A_Index])
   
   DetectHiddenWindows, On
   WinGetPos, X, Y,,, ahk_id %hMain%
   oFile.WriteUSHort(X), oFile.WriteUSHort(Y)
   oFile.WriteUSHort(GuiW), oFile.WriteUSHort(GuiH)
   
   (SendVariant = 2 && SendVariant := 3)
   oFile.WriteUChar(SendVariant)
   
   oFile.WriteUChar(StrLen(AssociatedWindow))
   oFile.Write(AssociatedWindow)
   
   oFile.WriteUChar(StrLen(MatchMode))
   oFile.Write(MatchMode)
   
   oFile.WriteUChar(StrLen(FontName))
   oFile.Write(FontName)
   
   oFile.WriteUChar(FontSize)
   oFile.WriteUChar(FontQuality)
   oFile.WriteUInt(FontColor)
   
   oFile.WriteUChar(RowNumber)
   oFile.WriteUChar(AllCell)
   
   oFile.WriteUInt(ColorBack)
   oFile.WriteUInt(ColorCell)
   oFile.WriteUInt(ColorSelect)
   oFile.WriteUInt(ColorButton)
   oFile.WriteUChar(FrameStyle)
   oFile.WriteUChar(AlwaysPlaceIntoClipboard)
   oFile.WriteUChar(HideAfterSend)

   oFile.WriteUChar(StrLen(Hk))
   oFile.Write(Hk)
   
   oFile.WriteUChar(LoadOnStartup)
   oFile.WriteUChar(ToggleToSaved)
   
   oFile.Close()
   ExitApp

#If MouseOverGui()
WheelDown::
WheelUp::
   Loop 4
      WM_VSCROLL(A_ThisHotkey = "WheelUp" ? SB_LINEUP : SB_LINEDOWN, 0, WM_VSCROLL, hBack)
   Return
   
WM_MOUSEMOVE(wp, lp, msg)
{
   static PrevColored, PrevGui
   
   if (msg = WM_MOUSEMOVE && ColorCell != ColorSelect)
   {
      if (A_Gui = PrevGui)
         Return
      
      if InStr(A_Gui, "Work")
      {
         if PrevColored
            Gui, %PrevColored%: Color, % Format("{:X}", ColorCell)
         Gui, %A_Gui%: Color, % Format("{:X}", ColorSelect)
         PrevColored := A_Gui
         SetTimer, WhiteColor, 100
      }
      else if PrevColored
      {
         Gui, %PrevColored%: Color, % Format("{:X}", ColorCell)
         PrevColored := ""
      }
      PrevGui := A_Gui
   }
   
   if (msg = WM_NCMOUSEMOVE)
   {
      if PrevColored  {
         Gui, %PrevColored%: Color, % Format("{:X}", ColorCell)
         PrevColored := PrevGui := ""
      }
      
      (wp = HTSYSMENU && DllCall("SetCursor", Ptr, hCursorHand))
   }
   
   if (msg = WM_SETCURSOR)
      if A_Gui in ColorBack,ColorCell,ColorSelect,FontColor,ColorButton
         Return DllCall("SetCursor", Ptr, hCursorHand)
   Return
   
WhiteColor:
   MouseGetPos,,, WinID
   if (WinID != hMain)
   {
      SetTimer, WhiteColor, Off
      if PrevColored
         Gui, %PrevColored%: Color, % Format("{:X}", ColorCell)
      PrevColored := ""
   }
   Return
}

WM_NCLBUTTONDOWN(wp)
{
   static HTMENU := 5, HTMINBUTTON := 8, HTLEFT := 10, HTRIGHT := 11
      , HTTOP := 12, HTTOPLEFT := 13, HTTOPRIGHT := 14, HTBOTTOM := 15
      , HTBOTTOMLEFT := 16, HTBOTTOMRIGHT := 17, HTCLOSE := 20
      
   if (A_Gui != "Main")
      Return
   
   if wp in %HTCAPTION%,%HTLEFT%,%HTRIGHT%,%HTTOP%,%HTBOTTOM%,%HTTOPLEFT%,%HTTOPRIGHT%,%HTBOTTOMLEFT%,%HTBOTTOMRIGHT%
   {
      LastActiveWindowID := WinExist("A")
      SetTimer, MouseWatch, 100
      WinActivate, ahk_id %hMain%
      if (wp != HTCAPTION)
      {
         ControlGetPos,, TopWork,,, AutoHotkeyGUI1, ahk_id %hBack%
         TopWork -= 1
      }
   }
   if (wp = HTMENU)
   {
      LastActiveWindowID := WinExist("A")
      WinActivate, ahk_id %hMain%
      SendInput, {LButton Down}
      Sleep, 100
      if WinExist("ahk_id" hSetWindow) || WinExist("ahk_id" hSetFont) || WinExist("ahk_id" hSetNumber)
       || WinExist("ahk_id" hSetColor) || WinExist("ahk_id" hReadme) || WinExist("ahk_id" hSetHotkey)
         WinActivate
      else
         WinActivate, ahk_id %LastActiveWindowID%
   }
   if (wp = HTMINBUTTON)
   {
      Gosub, HideShowMainWindow
      Return 1
   }
   if (wp = HTSYSMENU)
      Return 1
   
   if (wp = HTCLOSE && A_Gui = "Main")
      ExitApp
   Return
   
MouseWatch:
   if GetKeyState("LButton", "P")
      Return
   SetTimer, MouseWatch, Off
   WinActivate, ahk_id %LastActiveWindowID%
   Return
}

WM_NCLBUTTONUP(wp)
{
   (wp = HTSYSMENU && ChangeContent() && DllCall("SetCursor", Ptr, hCursorHand))
}

WM_NCLBUTTONDBLCLK(wp)
{
   if (A_Gui = "Main" && wp = HTSYSMENU)
      Return 1
   
   if (A_Gui != "Main" || wp != HTCAPTION)
      Return
   
   WM_SYSCOMMAND(SC_MAXIMIZE)
   Return 1
}

WM_CHAR(wp)
{
   CoordMode, Caret
   WinClose, ahk_id %hBall%
   if (A_Gui != "SetColor")
      Return
   
   GuiControlGet, Focus, %A_Gui%:Focus
   if !InStr(Focus, "Edit")
      Return

   if wp in 3,8,24,26   ; обработка Ctrl + C, BackSpace, Ctrl + X, Ctrl + Z
      Return

   if wp = 22   ; обработка Ctrl + V
   {
      Loop, parse, Clipboard
      {
         Text .= A_LoopField
         if A_LoopField not in 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,A,B,C,D,E,F
         {
            ShowBall("Буфер обмена содержит недопустимые символы."
               . "`nДопустимые символы:`n0123456789ABCDEF", "Ошибка!")
            Return 1
         }
      }
      Control, EditPaste, % Text, % Focus, Настройки цвета в RGB
      Return 1
   }

   Char := Chr(wp)
   if Char not in 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,A,B,C,D,E,F
   {
      ShowBall("Допустимые символы:`n0123456789ABCDEF", Char " — недопустимый символ")
      Return 1
   }
   Return
}

WM_SYSCOMMAND(wp)
{
   static YPrev, HPrev, SB_TOP := 6
   if (A_Gui != "Main")
      Return
   
   WinGetPos,,,,  H_Tray, ahk_class Shell_TrayWnd
   if (wp = SC_MAXIMIZE)
   {
      WinExist("ahk_id" hMain)
      WinGetPos,, Y,, H
      WM_VSCROLL(SB_TOP, 0, WM_VSCROLL, hBack)
      if (Y = 0 && H = A_ScreenHeight - H_Tray && YPrev != "" && HPrev != "")
         WinMove,,,, YPrev,, HPrev
      else
      {
         YPrev := Y, HPrev := H
         WinMove,,,, 0,, A_ScreenHeight - H_Tray
      }
      Return 1
   }
   
   if (wp = SC_MINIMIZE)
   {
      Gosub, HideShowMainWindow
      Return 1
   }
}

WM_VSCROLL(wParam, lParam, msg, hwnd)
{
   static SIF_ALL=0x17, SCROLL_STEP=10
   bar := msg=0x115 ; SB_HORZ=0, SB_VERT=1

   VarSetCapacity(si, 28, 0)
   NumPut(28, si, "UInt") ; cbSize
   NumPut(SIF_ALL, si, 4, "UInt") ; fMask
   if !DllCall("GetScrollInfo", Ptr, hwnd, Int, bar, Ptr, &si)
     return

   VarSetCapacity(rect, 16)
   DllCall("GetClientRect", Ptr, hwnd, Ptr, &rect)

   new_pos := NumGet(si, 20, "UInt") ; nPos

   action := wParam & 0xFFFF
   if action = 0 ; SB_LINEUP
     new_pos -= SCROLL_STEP
   else if action = 1 ; SB_LINEDOWN
     new_pos += SCROLL_STEP
   else if action = 2 ; SB_PAGEUP
     new_pos -= NumGet(rect, 12, "Int") - SCROLL_STEP
   else if action = 3 ; SB_PAGEDOWN
     new_pos += NumGet(rect, 12, "Int") - SCROLL_STEP
   else if (action = 5 || action = 4) ; SB_THUMBTRACK || SB_THUMBPOSITION
     new_pos := wParam>>16
   else if action = 6 ; SB_TOP
     new_pos := NumGet(si, 8, "Int") ; nMin
   else if action = 7 ; SB_BOTTOM
     new_pos := NumGet(si, 12, "Int") ; nMax
   else
     return

   min := NumGet(si, 8, "Int") ; nMin
   max := NumGet(si, 12, "Int") - NumGet(si, 16, "UInt") ; nMax-nPage
   new_pos := new_pos > max ? max : new_pos
   new_pos := new_pos < min ? min : new_pos

   old_pos := NumGet(si, 20, "Int") ; nPos

   y := old_pos-new_pos
   ; Scroll contents of window and invalidate uncovered area.
   DllCall("ScrollWindow", Ptr, hwnd, Int, 0, Int, y, UInt, 0, UInt, 0)

   ; Update scroll bar.
   NumPut(new_pos, si, 20, "Int") ; nPos
   DllCall("SetScrollInfo", Ptr, hwnd, Int, bar, Ptr, &si, Int, 1)
}

WM_RBUTTONUP()
{
   static GuiNum, GuiName
   if !InStr(A_Gui, "Work")
      Return
   
   GuiNum := SubStr(A_Gui, 5)
   Menu, Actions, Show
   Return
   
Delete:
   o%CurrentContent%.Remove(GuiNum)
   SetContent()
   Return
   
Send:
   Send(GuiName)
   Return
}

Send(GuiName)
{
   PrevBlock := Block, Block := 1
   SendText := o%CurrentContent%[SubStr(GuiName, 5)]
   if !(oEntered[1] == SendText)  {
      RemoveExistingAddNew(oEntered, SendText)
      if (CurrentContent = "Entered")
         SetContent()
   }
   
   if (SendVariant = 1)
   {
      if AssociatedWindow  {
         SetTitleMatchMode, % MatchMode
         IfWinExist, % AssociatedWindow
            WinActivate
         else
            Return ToolTipShowAndDel("Связанное окно не найдено! Укажите связанное окно.")
      }
      else
         Return ToolTipShowAndDel("Связанное окно не указано!")
   }
   
   if (SendVariant = 2)
   {
      if TargetWindow  {
         IfWinExist, ahk_id %TargetWindow%
            WinActivate
         else
            Return ToolTipShowAndDel("Целевое окно не найдено! Измените выбор.")
      }
      else
         Return ToolTipShowAndDel("Целевое окно не указано!")
   }
   
   if (SendVariant = 3 && WinExist("A") = hMain)
      Return ToolTipShowAndDel("Активное окно не найдено!")
   
   if (SendVariant = 4)
   {
      Clipboard := SendText
      Sleep, 200
      Block := PrevBlock
      ToolTipShowAndDel("Текст помещён в буфер обмена", 800)
   }

   if SendVariant in 1,2,3
   {
      TempClip := ClipboardAll
      Clipboard := SendText
      Sleep, 100
      SendInput, ^{vk56}   ; Ctrl + V
      if !AlwaysPlaceIntoClipboard  {
         Sleep, 100
         Clipboard := TempClip
      }
      Sleep, 200
      Block := PrevBlock, TempClip := ""
   }
   
   if HideAfterSend
      SetTimer, MouseTrack, 100
   Return
   
MouseTrack:
   MouseGetPos,,, WinID
   if (WinID != hMain)  {
      Gui, Main:Show, Hide
      TrayMenuPostFix := DisplayHkPrev = "Нет" ? "" : A_Tab . DisplayHkPrev
      Menu, Tray, Rename, % "Скрыть окно" . TrayMenuPostFix, % "Показать окно" . TrayMenuPostFix
      SetTimer, MouseTrack, Off
   }
   Return
}

ToolTipShowAndDel(text, time = 1500)
{
   ToolTip % text
   Sleep time
   ToolTip
}

WM_MBUTTONDOWN()
{
   if !InStr(A_Gui, "Work")
      Return
   
   ToolTip, % RegExReplace(o%CurrentContent%[SubStr(A_Gui, 5)], A_Tab, "    ")
   KeyWait, MButton
   ToolTip
}

AHK_NOTIFYICON(wp, lp)
{
   static WM_LBUTTONUP := 0x202, WM_LBUTTONDBLCLK := 0x203, Time
   if (lp = WM_LBUTTONUP)
   {
      if (Time && A_TickCount - Time < 350)
         Return 1
      Gosub, HideShowMainWindow
      Time := A_TickCount
   }
   
   if (lp = WM_LBUTTONDBLCLK)
      Return 1
}

WM_INFO(wp, lp)
{
   (wp = 0 && PrevBlock := Block)
   if !(lp = "")  {
      Block := lp
      GuiControl, Main:, Block, % Block ? "Unblock" : "Block"
   }
   Return PrevBlock
}

UpdateScrollBar(hGui, ScrollHeight)
{
   static SIF_RANGE := 0x1, SIF_PAGE := 0x2, SB_VERT := 1
   i := 0
   Loop % AllCell
   {
      GuiControlGet, Visible, Work%A_Index%:Visible, Text
      (Visible && i++)
   } until !Visible
   
   WinGetPos,,,, GuiHeight, ahk_id %hGui%
   VarSetCapacity(si, 28, 0)
   NumPut(28, si) ; cbSize
   NumPut(SIF_RANGE | SIF_PAGE, si, 4)
   NumPut(ScrollHeight, si, 12) ; nMax
   NumPut(GuiHeight, si, 16) ; nPage
   DllCall("SetScrollInfo", Ptr, hGui, UInt, SB_VERT, Ptr, &si, UInt, 1)

   ControlGetPos,, Top,,, AutoHotkeyGUI1, ahk_id %hBack%
   Top -= 6
   if (Top >= 0)
      Return
   
   ControlGetPos,, y,, h, AutoHotkeyGUI%i%, ahk_id %hBack%
   Bottom := y + h + 6
   if (Top < 0 && Bottom < GuiHeight)
   {
      y := (a := Abs(Top)) > (b := GuiHeight-Bottom) ? b : a
      DllCall("ScrollWindow", Ptr, hGui, Int, 0, Int, y, Ptr, 0, Ptr, 0)
      TopWork += y
   }
}

CrossHair(OnOff=1)
{
   static IDC_CROSS := 32515, SPI_SETCURSORS := 0x57
      , hCursor := DllCall("LoadCursor", Ptr, 0, UInt, IDC_CROSS, Ptr)
      , sys_cursors := [32512,32513,32514,32516,32642,32643,32644,32645,32646,32648,32649,32650]
   
   if !OnOff
      DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0)
   else
      for k, cursor in sys_cursors
         hCopy := DllCall("CopyImage", Ptr, hCursor, UInt, 2, Int, 0, Int, 0, UInt, 0)
         , DllCall("SetSystemCursor", Ptr, hCopy, UInt, cursor)
}

TargetWndShow(TargetWnd)
{
   VarSetCapacity(WI, 60)
   DllCall("GetWindowInfo", Ptr, TargetWnd, Ptr, &WI)
   X := NumGet(WI, 20, "UInt"), Y := NumGet(WI, 24, "UInt")
   W := NumGet(WI, 28, "UInt") - X, H := NumGet(WI, 32, "UInt") - Y
   Gui, Flash:Default
   Gui, +LastFound -Caption +AlwaysOnTop +Disabled +Owner +hwndID3
   Gui, Color, Red
   Gui, Show, x%X% y%Y% w%W% h%H% hide
   th := 5, w1 := w - th, h1 := h - th
   WinSet, Region, 0-0 %w%-0 %w%-%h% 0-%h% 0-0 %th%-%th% %w1%-%th% %w1%-%h1% %th%-%h1% %th%-%th%
   Loop 3
   {
      Gui, Show, NA
      Sleep, 300
      Gui, Show, Hide
      Sleep, 300
   }
   Gui, Destroy
}

MouseOverGui()
{
   MouseGetPos,,, ID
   Return ID = hMain
}

ShowBall(Text, Title="")
{
   global
   WinClose, ahk_id %hBall%
   hBall := TrackToolTip(Text, A_CaretX+1, A_CaretY+15, Title)
   SetTimer, BallDestroy, -2000
   Return

BallDestroy:
   WinClose, ahk_id %hBall%
   Return
}

ChooseColor(Color := 0, hWnd := 0, Flags := 3)   ; Flags := CC_RGBINIT=1 | CC_FULLOPEN=2
{
   static CustColors, CHOOSECOLOR
   Color := RGB_BGR(Color)   ; RGB -> BGR

   if !CHOOSECOLOR
   {
      VarSetCapacity(CustColors, 64)
      Loop 16
         NumPut(0xFFFFFF, CustColors, (A_Index - 1)*4, "UInt")

      VarSetCapacity(CHOOSECOLOR, Size := A_PtrSize*9, 0)
      NumPut(Size, CHOOSECOLOR)
      NumPut(&CustColors, CHOOSECOLOR, A_PtrSize*4)
   }
   NumPut(Flags, CHOOSECOLOR, A_PtrSize*5)
   NumPut(hWnd, CHOOSECOLOR, A_PtrSize)
   NumPut(Color, CHOOSECOLOR, A_PtrSize*3)
   
   if !DllCall("comdlg32\ChooseColor", Str, CHOOSECOLOR)
      Return -1
   
   PrevFormat := A_FormatInteger
   SetFormat, IntegerFast, H
   RGB := RGB_BGR(NumGet(&CHOOSECOLOR + A_PtrSize*3, "UInt")) . ""
   SetFormat, IntegerFast, % PrevFormat
   Return RGB
}

TrackToolTip( sText
            , x = ""   ; если не указаны, то вблизи курсора
            , y = ""
            , sTitle = ""
            , h_icon = 0   ; h_icon — 0: None, 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon
            , CloseButton = 0
            , nColorBack = 0xFFFFE1
            , nColorText = 0
            , BallonTip = 0   ; BalloonTip — это ToolTip с хвостиком
            , w = 400 )  ; максимальная ширина
{
   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80

   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|(CloseButton ? TTS_CLOSE : 0)|(BallonTip ? TTS_BALLOON : 0)
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , Ptr, 0, Ptr, 0, Ptr, 0, Ptr, 0)

   if (x != "" && y != "")
      xtt := x, ytt := y
   else
   {
      CoordMode, Mouse
      MouseGetPos, xtt, ytt
      xtt := x = "" ? xtt + 10 : x
      ytt := y = "" ? ytt + 10 : y
   }

   NumPut(VarSetCapacity(TOOLINFO, A_PtrSize = 4 ? 48 : 72, 0), TOOLINFO, "UInt")
   NumPut(0x20, TOOLINFO, 4, "UInt")      ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, A_PtrSize = 4 ? 36 : 48, "UInt")

   DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%

   WM_USER := 0x400
   SendMessage, WM_USER + 24,, w         ; TTM_SETMAXTIPWIDTH
   SendMessage, WM_USER + (A_IsUnicode ? 50 : 4),, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, WM_USER + 19, RGB_BGR(nColorBack)   ; TTM_SETTIPBKCOLOR
   SendMessage, WM_USER + 20, RGB_BGR(nColorText)   ; TTM_SETTIPTEXTCOLOR
   SendMessage, WM_USER + (A_IsUnicode ? 33 : 32), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, WM_USER + (A_IsUnicode ? 57 : 12),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW
   SendMessage, WM_USER + 18,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
   SendMessage, WM_USER + 17, 1, &TOOLINFO ; TTM_TRACKACTIVATE

   if BallonTip
      xMax := A_ScreenWidth, yMax := A_ScreenHeight
   else
   {
      WinGetPos,,, W, H
      xMax := A_ScreenWidth - W - 10
      yMax := A_ScreenHeight - H - 10
   }
   
   if (xtt > xMax || ytt > yMax)
   {
      WinHide
      xtt := xtt > xMax ? xMax : xtt
      ytt := ytt > yMax ? yMax : ytt
      SendMessage, 1042,, xtt|(ytt<<16)   ; TTM_TRACKPOSITION
      WinShow
   }

   DetectHiddenWindows, % DHW
   Return hWnd
}

RGB_BGR(color)
{
   Return (color & 0xFF000000) | (color & 0xFF) << 16 | (color & 0xFF00) | (color >> 16)
}

GetCyrillicFontNames()
{
   hDC := DllCall("GetDC", UInt, 0, Ptr)
   VarSetCapacity(LOGFONT, 92, 0)
   NumPut(RUSSIAN_CHARSET := 204, &LOGFONT + 23, "UChar")
   DllCall("EnumFontFamiliesEx", Ptr, hDC
                               , Ptr, &LOGFONT
                               , Ptr, RegisterCallback("EnumFontFamExProc", "F", 4)
                               , Ptr, pFonts := Object(oFonts := [])
                               , UInt, 0)
   ObjRelease(pFonts), DllCall("ReleaseDC", Ptr, 0, Ptr, hDC)
   Return oFonts
}

EnumFontFamExProc(lpelfe, lpntme, FontType, lParam)
{
   if font := StrGet(lpelfe + 28)
      Return Object(lParam).Push(font)
}

ShowOwnerWindow(Title, hWnd)
{
   WinGetPos, X_Main, Y_Main, W_Main,, ahk_id %hMain%
   Gui, Show, Hide, % Title
   DetectHiddenWindows, On
   WinGetPos,,, W,, ahk_id %hWnd%
   Gui, Show, % "Hide x" X_Main - W " y" Y_Main
   WinGetPos, X, Y, W, H, ahk_id %hWnd%
   (X < 0 && X := X_Main + W_Main)
   (X + W > A_ScreenWidth && X := A_ScreenWidth - W)
   (Y < 0 && Y := 0)
   (Y + H > A_ScreenHeight && Y := A_ScreenHeight - H)
   WinMove, ahk_id %hWnd%,, X, Y, W, H
   Gui, Show
}

GetDDLstrings(param*)         
{                              
   if (param.MaxIndex() = 2)      ; RowNumber, AllCell
   {
      Loop 5
         RowStr .= (A_Index = 1 ? "" : "|") . A_Index . (A_Index = param[1] ? "|" : "")
      
      Loop 57
         CellStr .= (A_Index = 1 ? "" : "|") . (A_Index + 7) . (A_Index + 7 = param[2] ? "|" : "")
      
      Return { Rows: RegExReplace(RowStr, "\|$", "||")
            , Cells: RegExReplace(CellStr, "\|$", "||") }
   }
      
   if (param.MaxIndex() = 4)      ; FontName, oFonts, FontQuality, FontSize
   {
      for k, font in param[2]
         Fonts .= (A_Index = 1 ? "" : "|") . font . (font = param[1] ? "|" : "")

      for k, v in oQual
         Qual .= (A_Index = 1 ? "" : "|") . v . (k - 1 = param[3] ? "|" : "")
      
      Sizes := "8|9|10|11|12|13|14|15"
      Loop, parse, Sizes, |
         NewSizes .= (A_Index = 1 ? "" : "|") . A_LoopField . (A_LoopField = param[4] ? "|" : "")
      
      Return { Font: RegExReplace(Fonts, "\|$", "||")
             , Qual: RegExReplace(Qual, "\|$", "||")
             , Size: RegExReplace(NewSizes, "\|$", "||") }
   }
}

ColoredGuiShow(GuiName, Parent, Color, Label, W, H)
{
   Gui, %GuiName%: +Parent%Parent% -Caption -DPIScale
   Gui, %GuiName%: Color, % Format("{:X}", Color)
   Gui, %GuiName%: Add, Text, x0 y0 w%W% h%H% g%Label% +%SS_GRAYFRAME%
   Gui, %GuiName%: Show, NA w%W% h%H%
}

LoadCursorHand()
{
   Return DllCall("LoadImage", Ptr, 0
                             , UInt, OCR_HAND
                             , UInt, IMAGE_CURSOR
                             , Int, 0, Int, 0
                             , UInt, LR_DEFAULTSIZE|LR_SHARED, Ptr)
}

Ping(strHost)
{
   Loop 2
      bRet := ComObjGet("winmgmts:").Get("Win32_PingStatus.address='" . strHost . "'").StatusCode = 0
   until bRet
   return bRet
}

GetDisplayHk(Hk)
{
   if (Hk = "Нет" || Hk = "")
      Return "Нет"
   
   StringReplace, DisplayHk, Hk, ^, % "Ctrl@"
   StringReplace, DisplayHk, DisplayHk, +, % "Shift@"
   StringReplace, DisplayHk, DisplayHk, !, % "Alt@"
   StringReplace, DisplayHk, DisplayHk, @, +, All
   RegExMatch(DisplayHk, "i)(vk|sc)[0-9A-F]+$", found)
   StringReplace, DisplayHk, DisplayHk, % found, % GetKeyName(found)
   Return DisplayHk
}

SetContent()
{
   i := 0
   Loop % AllCell  {
      content := o%CurrentContent%[A_Index], clip := ""
      Loop, parse, content, `n, `r
         clip .= (A_Index = 1 ? "" : "`n`r") . A_LoopField
      until A_Index = RowNumber
      
      (clip != "" && i++)
      GuiControl, Work%A_Index%:, Text, % RegExReplace(clip, A_Tab, "    ")
      Gui, Work%A_Index%: Show, % clip = "" ? "Hide" : "NA"
   }
   UpdateScrollBar(hBack, ScrollHeight := 10 + (TextH + 8) * i - 3)
}

RemoveExistingAddNew(obj, data)
{
   for k, v in obj
      if (v == data && ExistSuchClip := 1)
         break
      
   (ExistSuchClip && obj.Remove(k))
   obj.Insert(1, data), obj.Remove(AllCell + 1, obj.MaxIndex())
}

ChangeContent()
{
   b := CurrentContent = "Saved"
   Menu, Content, UnCheck, % b ? "Скопированное" : "Вставленное"
   Menu, Content, Check, % b ? "Вставленное" : "Скопированное"
   CurrentContent := b ? "Entered" : "Saved"
   
   SetContent()
   Gui, Main:Show, % WinExist("ahk_id" hMain) ? "NA" : "Hide", % b ? "Вставленное" : "Скопированное"
   Return 1
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

114 (изменено: dredj, 2015-09-14 10:00:10)

Re: AHK: Пишем удобный менеджер буфера обмена

teadrinker, можете скинуть "ClipMgrIcons.dll" отдельно? Линк на дропбокс в скрипте сломался по моему.

115

Re: AHK: Пишем удобный менеджер буфера обмена

Всё вместе.

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

116

Re: AHK: Пишем удобный менеджер буфера обмена

А окно так должно выглядеть?
http://ic.pics.livejournal.com/the_bestseller/49384395/13775/13775_original.png

В прошлой версии отступа справа не было.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

117

Re: AHK: Пишем удобный менеджер буфера обмена

Нет, у меня так:

https://cloclo19.cloud.mail.ru/weblink/thumb/w3/53Q21oTgiDyU/2015.09.14-17.12.47.4.jpg

Наоборот, в прошлой версии после какого-то обновления AHK сбилась полоса прокрутки, поэтому сейчас и выложил эту, она только исправлением скроллбара отличается. Так что можно старую использовать, если она почему-то лучше работает.

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

118 (изменено: serzh82saratov, 2015-09-14 18:28:12)

Re: AHK: Пишем удобный менеджер буфера обмена

Сейчас обновил AutoHotkey, и началась мистика, полоса стала в 2 раза меньше, но иногда её нет. То есть как повезёт. Ощущение что место иногда резервируется под скролл.

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

В старой версии у меня тоже какие то глюки с полосой прокрутки, она то появляется, то нет.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

119

Re: AHK: Пишем удобный менеджер буфера обмена

Тоже обновил, у меня ничего не изменилось. На х32 тоже пробовал.

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

120

Re: AHK: Пишем удобный менеджер буфера обмена

Может появились какие то конфликты с DPIScale...

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

121

Re: AHK: Пишем удобный менеджер буфера обмена

Отличная программа, но не обнаружил возможности вставки текста по горячей клавише. Это не предусмотрено или недоглядел?

Нуждаюсь в возможности вставить последний скопированный в буфер текст при том, что после его копирования также копировался и файл. Т.е. копируем текст (Ctrl+C), копируем файл (Ctrl+C). Далее вставляем файл (Ctrl+V), вставляем последний скопированный текст (например, Ctrl+Shift+V). Как это можно реализовать посредством AHK?

122

Re: AHK: Пишем удобный менеджер буфера обмена

becauseim пишет:

не обнаружил возможности вставки текста по горячей клавише

Какого именно текста?

после его копирования также копировался и файл

На данный момент программа не вставляет скопированные файлы, копируется только путь, который можно потом вставить, как текст.

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

123 (изменено: Alectric, 2015-09-19 08:21:23)

Re: AHK: Пишем удобный менеджер буфера обмена

Актуальная версия в посте №1?

Error:  Can't load icon.

Specifically: D:\Doc\Work\ahkwork\experim\ClipMgrIcons.dll

Line#
119: {
120: MsgBox,Невозможно загрузить файл с иконками, проверьте подключение к интернету!
121: ExitApp
122: }
123: URLDownloadToFile,"https://dl.dropboxusercontent.com/s/lsuumcs9f5orag6/ClipMgrIcons.dll",IcoDll
124: }
125: if !A_IsCompiled 
---> 126: Menu,Tray,Icon,%IcoDll%,1
127: SetBatchLines,-1
128: SetWinDelay,0
129: CoordMode,Mouse
130: StringCaseSense,Locale
132: HTCAPTION := 2
132: HTSYSMENU :

Я бы добавил:

Menu,Tray,UseErrorLevel

После "Выбрать целевое окно правой кнопкой" - курсор не меняется на заданный в системе.

Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

124

Re: AHK: Пишем удобный менеджер буфера обмена

teadrinker пишет:

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

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

125

Re: AHK: Пишем удобный менеджер буфера обмена

А можно предоставить выбор на то, как вставляется информация из менеджера в программу?
Мне, например, надо не Ctrl+v, а Ctrl+Shift+v.

126

Re: AHK: Пишем удобный менеджер буфера обмена

А смысл? Как манагер узнает какую именно запись ты хочешь скопировать? Т.к. последняя запись итак будет в буфере.

Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

127

Re: AHK: Пишем удобный менеджер буфера обмена

becauseim пишет:

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

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

Malcev пишет:

А можно предоставить выбор на то, как вставляется информация из менеджера в программу?
Мне, например, надо не Ctrl+v, а Ctrl+Shift+v.

Так там вообще пока нет никакой горячей клавиши для вставки текста. Просто, если стоит в настройках отмечена галка «Всегда помещать в буфер обмена», тогда в буфер будет помещаться последний отправленный кликом текст, и тогда его можно после этого вставлять виндосовской комбинацией Ctrl + V.

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

128

Re: AHK: Пишем удобный менеджер буфера обмена

Alectric пишет:

После "Выбрать целевое окно правой кнопкой" - курсор не меняется на заданный в системе.

В смысле, не меняется после клика по нужному окну правой кнопкой?

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

129

Re: AHK: Пишем удобный менеджер буфера обмена

Уже не помню... (не до этого, если честно) возможно я закрыл окно скрипта так и не нажав правую кнопку.

Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

130

Re: AHK: Пишем удобный менеджер буфера обмена

Так там вообще пока нет никакой горячей клавиши для вставки текста.

А как же целевое окно? Или там посылается оконное сообщение?

131

Re: AHK: Пишем удобный менеджер буфера обмена

Не понял вопроса. Целевое окно — что?

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

132

Re: AHK: Пишем удобный менеджер буфера обмена

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

133

Re: AHK: Пишем удобный менеджер буфера обмена

Всё равно не понял, а какой из вариантов должен посылаться по Ctrl+Shift+v ?

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

134 (изменено: Malcev, 2015-09-21 14:59:22)

Re: AHK: Пишем удобный менеджер буфера обмена

На который кликаешь мышкой.
Я имею в виду. Кликаешь мышкой на вариант и в окно посылается Ctrl+Shift+v.
То есть дать пользователю возможность выбора, как будет посылаться клипбоард в связанное окно.

135

Re: AHK: Пишем удобный менеджер буфера обмена

А как целевое окно узнает, что по этой комбинации оно должно получить буфер обмена? Все окна в Виндовс заточены под Ctrl+V.

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

136

Re: AHK: Пишем удобный менеджер буфера обмена

Не все. Например Adobe Premiere по Ctrl+V вставляет одну информацию из буфера обмена (вставляются клипы), а по Ctrl+Shift+v другую (вставляются фильтры этих клипов).

137

Re: AHK: Пишем удобный менеджер буфера обмена

Хотя нет, можно и Ctrl+Shift+v, просто не пользовался этим. Ну, это у тебя узкоспециальный интерес, по-моему. Нет смысла добавлять это в программу для общего пользования, и так меню перегружено. Ну, или если выяснится, что это нужно многим.

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

138

Re: AHK: Пишем удобный менеджер буфера обмена

Ну этот шорткат еще используется для вставки неформатированного текста в ворде.
А подсказать можешь, где это можно подправить в коде?

139

Re: AHK: Пишем удобный менеджер буфера обмена

Строка

SendInput, ^{vk56}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

140 (изменено: OmTatSat, 2015-11-03 01:20:27)

Re: AHK: Пишем удобный менеджер буфера обмена

Error: Can't load icon.
В окне с ошибкой, указатель указывает на 126-ую строку.
Попробовал вручную скачать по адресу с 123 строки, нет доступа.
После попытки запуска скрипта возле него появляется файл ClipMgrIcons.dll .
Как решить проблему?

141

Re: AHK: Пишем удобный менеджер буфера обмена

Например вписать перед

if !A_IsCompiled

вот это:

IcoDll := ""

142

Re: AHK: Пишем удобный менеджер буфера обмена

Отредактирован первый пост, теперь работает.

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

143

Re: AHK: Пишем удобный менеджер буфера обмена

Malcev спасибо, вставил 125 строкой IcoDll := "" и скрипт заработал.
teadrinker скрипт с первого поста без выше упомянутой правки показывал туже ошибку, что и вчера.

144

Re: AHK: Пишем удобный менеджер буфера обмена

Хотел поменять размер окна, в итоге окно сжалось, рабочая зона вообще пропала, при попытке растянуть, окно как бы резиновое и возвращается назад в супер минимальный размер. Как его теперь развернуть? Перезапуск и переименование файла не помогают.

145

Re: AHK: Пишем удобный менеджер буфера обмена

Удалите файл "data", и все установки вернутся к состоянию «по умолчанию».

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

146

Re: AHK: Пишем удобный менеджер буфера обмена

Решил проблему с помощью Anvir Task Manager. Он создал контекстное меню по ПКМ заголовка окна "Изменить размер".
Файл "data" в папке с скриптом не нашел, где он должен быть? П.С. Скрытые и системные файлы отображаются.

147

Re: AHK: Пишем удобный менеджер буфера обмена

Если скрипт не скомпилирован, файл "data" должен быть в папке со скрипом, если скомпилирован, тогда пишется прямо в его файл.

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

148

Re: AHK: Пишем удобный менеджер буфера обмена

Скрипт скомпилирован, сбросить настройки можно только компиляцией нового файла?

149

Re: AHK: Пишем удобный менеджер буфера обмена

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

150

Re: AHK: Пишем удобный менеджер буфера обмена

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

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

151 (изменено: mozers, 2017-03-29 13:30:46)

Re: AHK: Пишем удобный менеджер буфера обмена

teadrinker
Простите, если ошибаюсь, но мне кажется что в код надо добавить FileInstall и исправить строчку

IcoDll := A_IsCompiled ? A_ScriptFullPath : A_ScriptDir "\ClipMgrIcons.dll"

Другой вариант (ИМХО лучший) - код оставить как есть, но заменить ClipMgrIcons.dll на AutoHotkeySC.bin, предварительно всунув в него все нужные иконки. Результат, конечно, можно опять обозвать ClipMgrIcons.dll.
Просто сейчас после компиляции получается неработоспособный exe-шник.

UPD: Добавил AutoHotkeySC.bin (v 1.1.25.01) с иконками из Вашего ClipMgrIcons.dll

Post's attachments

ClipMgrIcons.dll 860.5 kb, 3 downloads since 2017-03-29 

You don't have the permssions to download the attachments of this post.

152

Re: AHK: Пишем удобный менеджер буфера обмена

Да нет, на данный момент уже лучше просто добавить иконки в скрипт текстом в base64. На данный момент — в смысле, уже испытано и алгоритм понятен.

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

153

Re: AHK: Пишем удобный менеджер буфера обмена

100кБ нечитабельного текста в коде - это имхо, чересчур. Хотя, разве что в отдельном файле...
Кстати, на оф.форуме нашел Ahk2Exe, позволяющий при компиляции указать какие иконки (и др.ресурсы) добавить/изменить в exe-шнике.

154

Re: AHK: Пишем удобный менеджер буфера обмена

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

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

155 (изменено: danxak70, 2017-06-05 18:37:15)

Re: AHK: Пишем удобный менеджер буфера обмена

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

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

1. В дополнительном окошке, где можно указать связанное окно, желательно добавить для указания также строку ввода окна источника, и в крипте внести поправку - если окно источника указано, то при копировании содержимого была возможность вставить содержание в связанное окно и после этого тут же вернуться в окно источника.
Требуется это для так называемого конвеейрного копирования.
Очень удобная и нужная штука бывает.
Если не трудно, поправьте скрипт?!
При этом в дополнительном окне рядом со строкой данных окна источника можно было бы добавить чекбокс для указания - если стоит в нём галочка отметки, то после ввода содержимого в связанное окно была бы возвращаться в окно источника, а если галочки в чекбоксе нет, то можно этого не делать.

2. В дополнительном окне в строке, где вводятся имя окна и ahk_class, желательно предусмотреть возможность сохранения текущего выбора связанного окна и в дальнейшем возможность быстрого возврата к этим настройкам уже из списка часто используемых окон.
Я уже думал, как это можно реализовать с данным скриптом... возможно можно попробовать использовать ini-файл для сохранения как раз в нём данных окон, и затем стандартные параметры этих данных уже выбирать из них.
Это добавит универсальности и удобство в работе с различными связанными окнами.

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

156

Re: AHK: Пишем удобный менеджер буфера обмена

danxak70, спасибо за вашу оценку скрипта!
В этом топике накопилось достаточно много пожеланий, большую часть из которых я считаю интересными и полезными. Я сам пользуюсь этим скриптом, и заинтересован в добавлении нового функционала, но пока не могу выделить на это время. Надеюсь, летом дело сдвинется с мертвой точки.

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

157

Re: AHK: Пишем удобный менеджер буфера обмена

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

158

Re: AHK: Пишем удобный менеджер буфера обмена

svoboden, совсем не понял, о чём вы. Скрипт не производит никаких звуков.

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

159

Re: AHK: Пишем удобный менеджер буфера обмена

teadrinker, а как узнать - скопировался ли текст в буфер обмена или нет?

160

Re: AHK: Пишем удобный менеджер буфера обмена

А почему он может не скопироваться, если вы его выделили и нажали Ctrl + C ? В каких случаях такое может произойти? Если окно не скрыто, скопирванный текст появляется в самом верху.

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

161 (изменено: svoboden, 2017-06-05 21:23:33)

Re: AHK: Пишем удобный менеджер буфера обмена

Может, кнопка плохо нажмется, а не ясно - поступили ли данные в буфер обмена или нет.

162

Re: AHK: Пишем удобный менеджер буфера обмена

Ясно, с таким не сталкивался. Но идею понял, можно будет потом добавить, как опцию — звуковой сигнал при изменении буфера обмена, которую можно включать и отключать.

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

163

Re: AHK: Пишем удобный менеджер буфера обмена

Ок.

164 (изменено: danxak70, 2017-06-06 17:57:27)

Re: AHK: Пишем удобный менеджер буфера обмена

Ребята!
Кончайте троллить тему поверхностными претензиями к автору ни о чём!?!!

Автор выше написал: "Я сам пользуюсь этим скриптом, и заинтересован в добавлении нового функционала, но пока не могу выделить на это время."
Этот ответ можно понимать по разному, но... Ну если нету у автора времени на программу, то откуда у него время на этот ненужный детский трёп о каких-то звуках из ниоткуда?!

Напоминаю всем о том, что тема вообще-то называется "Пишем удобный менеджер буфера обмена"
То есть пишем вместе. Ну раз уж автору некогда!?!
Вот и давайте писать.
В начале этой темы я отметил то, что в ней присутствуют те, кто достаточно хорошо понимают язык AHK, и одновременно неплохо разобрался в алгоритме и технике написания программы.
Выше я предложил внести удобные исправления в программу.
Автор говорит что у него нет времени на дальнейшую разработку.
Ну неужели больше никто из разработчиков на AHK не может подсказать, как осуществить эти исправления на языке программы?!

Давайте обсуждать программу, а не звуки от каких-то "пришельцев"?!

165

Re: AHK: Пишем удобный менеджер буфера обмена

danxak70, там почти 2000 строк кода.
Подождите лучше лета.

166

Re: AHK: Пишем удобный менеджер буфера обмена

Malcev пишет:

там почти 2000 строк кода.

И что?!
Хотите сказать, что никакой структуры в ней нет, и что она написана, как бог послал?!

Лето при этом можно долго ждать. А оно может и не прийти в нынешнем технологическом экстриме "неправильной" цивилизации.

167

Re: AHK: Пишем удобный менеджер буфера обмена

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

168

Re: AHK: Пишем удобный менеджер буфера обмена

ИМХО самое оптимальное будет подбодрить автора.
Возможно и лето тогда наступит быстрее.

169 (изменено: danxak70, 2017-06-07 14:04:12)

Re: AHK: Пишем удобный менеджер буфера обмена

ypppu пишет:

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

Да. Признаю. Хорошая штука - эта система подбадривания.
Но... я живу в России, а это сегодня - депрессивная страна в силу наличия санкций и отсутствия как раз станков для производства собственных подбодрительных элементов (в народе их называют купюрами...).
В этой ситуации самого бы кто подбодрил...!!!

Но уж больно сильно вчера зацепила меня сама идея реализации потокового копирования, о котором я написал выше.
К тому же по характеру я очень люблю получать решение своих задумок здесь и сейчас.
А в таких случая я бываю очень упёртый. Не зря же мой первый начальник присвоил мне кличку - "Бульдог"!

Короче...
Очень мне уже вчера захотелось тепла и лета, и я не стал откладывать в долгий ящик, сходил в магазин и сам простимулировал себя, и уже сегодня с утра нашёл для себя временное решение для организации того потокового копирования, о котором я писал вчера.
Написал маленький скриптик на AHK для вставки и возврата в программу источника, и пока играюсь с ним, походу вспоминая уже известные мне методы программирования на AHK и осваивая новые....
Скрипт пока простенький и совсем сырой... даже без формы... поэтому пока его выкладывать сюда не буду. Любой желающий и упёртый в принципе сам его может написать без особого труда. Но походу у меня возникло ещё множество задумок по применению методов, уже реализованных мною в этом скрипте, для решения задач в более конкретной работе с документами и с конкретными программами.
Когда добью скрипт до более-менее красивой формы со всеми нынешними мыслями, то позже может быть и выложу, организовав отдельную тему. Здесь не хочу мешать автору, он и без этого - молодец...! Узбехов ему!
А меня что-то прям прёт сегодня самостоятельно реализовать свою задумку в более красивом оформлении.
Наверное я просто хорошо вчера подбодрился. Если не отвлекут, может что-то и получится более приемлемое.

Вобщем снова убеждаюсь - хорошая всё-же это штука - AHK.
Особенно когда ты вдруг смог подбодриться!
Спасибо всем! Автору и разработчику этого скрипта - отдельное спасибо!!!
Ну и естественно модератору тоже не хворать и находить всё более и более приемлемые для разных болванов типа меня методы мотивации! ))
Удачи всем!

И кстати... для информации - не знаю, как там у кого, а у нас уже сегодня с утра выглянуло Солнышко.
Лето стучится в двери. Плевать оно хотело на чьи-то климатические санкции!!! ))