Autorun

Обсуждение только плагинов и утилит для Total Commander.

Модераторы: Avada, CaptainFlint, Nik, d-view, Моторокер

AkulaBig
Сообщения: 639
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Orion9 писал(а):Чем меньше пользовательских кнопок, тем больше пустого, зияющего пространства справа, что само по себе некрасиво, на мой взгляд.
Можно конечно все стандартные иконки показать. Но ведь мне потом с этим работать. Сборка-то у меня рабочая, а не на выставку. И так некоторые иконки я раз в год использую.
Orion9 писал(а):По той же причине верхнее меню должно иметь больше пунков
Это мое принципиальное значение - никакого расширенного меню.
Orion9 писал(а):пустое пространство заголовка ТС просто само просит, чтобы его чем-то заполнили.
Ну это-же у меня сделано.
Loopback
Сообщения: 1646
Зарегистрирован: Пн сен 07, 2009 09:29

Сообщение Loopback »

Orion9 писал(а):Ну как там багофиксы продвигаются, конец виден?
Последние три недели как-то не было возможности всем этим заниматься. Но DllCall и Callback исправил, ориентировочно завтра выложу минорную версию.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

AkulaBig писал(а):Можно конечно все стандартные иконки показать.
Да нет. Дело не в стандартных иконках, а в том, что кнопок накопилось много за годы использования, особенно в последнее время. А стандартных иконок на всей панели у меня может процентов 10 от общего количества, не больше.
AkulaBig писал(а):Это мое принципиальное значение - никакого расширенного меню.
А я бы не спешил. Многие программы в своем интерфейсе используют такую фишку, как "режим эксперта" и "режим простого пользователя", и это, на мой взгляд, правильно. Если бы я делал публичную сборку, я бы точно использовал такой подход. Но поскольку я делаю только для себя, то у меня всего одно расширенное меню как раз на пол экрана )
Loopback писал(а):DllCall и Callback исправил, ориентировочно завтра выложу минорную версию.
Класс. Спасибо. Ждём.
Loopback писал(а):- узнать, включены ли значки
- узнать их размер
- получить панель, над которой находится курсор (ItemAtCursor)
- получить хэндл панели (RequestInfo)
- получить координаты этой панели (WinGetPos)
- вычислить прямоугольник, где может находиться курсор, с помощью размера значка
- получить координаты курсора (MouseGetPos)
- проверить, находится ли курсор в границах прямоугольника
Нет, всё-таки не мог я дать такому алгоритму пропасть. Немного сделал по-другому, но основная идея та же.

Код: Выделить всё

If FieldIndex = 1 Then
    
       Local x, y, w, h, mx, my
       Local hWnd = RequestInfo(ItemAtCursor("panel"))
       WinGetPos("", "", "w", "h", hWnd)
       If w > 0 Then
          MouseGetPos("x","y")          
          Static buf = Buffer(8)	# POINT
          buf.Zero()
          buf.SetNum(0, "long", x, "long", y)
          DllCall("ScreenToClient", "hwnd", hWnd, "ptr", buf.ptr)
          x = buf.GetNum(0)
          MediaInfoNum = 1
          Switch Round(x/w*100,0)
             Case 1 To 10
                b_CTRL = 1
                b_SHIFT = 1
             Case 10 To 90
                b_CTRL = 1
             Case 90 To 100
                MediaInfoNum = 4                
          EndSwitch          
       EndIf
Как видите, строк совсем немного, но какой эффект! Я бы назвал это волшебным хинтом ) Панель делится на три части. Первые 10% слева выводят один хинт, 80% посередине выводят второй, последние 10% справа - третий. Счастью нет предела.

Строка If FieldIndex = 1 Then из тела рабочей функции JointHint, полный код которой привести не могу, так как он сильно завязан на множество других функций. Но для работоспособности любого кода необходимые параметры нужно задать в Switch...EndSwitch.
Loopback
Сообщения: 1646
Зарегистрирован: Пн сен 07, 2009 09:29

Сообщение Loopback »

Версия Autorun 2.2.19.1 beta

* обновленная версия китайского перевода и справки
- исправлена проблема DllCall с вызовом функции по адресу на x64
* реорганизация и чистка старого кода в работе функций
- DllCall не работала при указании полного пути библиотеки
- исправлена работоспособность Callback с двумя и более параметрами

На полную версию пока изменений не хватает :)
Последний раз редактировалось Loopback Вт июн 24, 2025 12:17, всего редактировалось 2 раза.
Аватара пользователя
yozhik
Сообщения: 353
Зарегистрирован: Вс май 04, 2014 20:34
Откуда: Электросталь

Сообщение yozhik »

Loopback писал(а):На полную версию пока изменений не хватает
Добавьте StrRegexReplace :roll:
Amo ergo sum
Loopback
Сообщения: 1646
Зарегистрирован: Пн сен 07, 2009 09:29

Сообщение Loopback »

yozhik
Регэкспы в todo :wink:
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

Loopback писал(а):На полную версию пока изменений не хватает
Зато хватает, чтобы потестировать объект Callback )

[cut]

Код: Выделить всё

RegisterCommand 60025 "WindowTest"

Static hWnd = 0

Const PBM_SETPOS      =  1026, _
      PBM_SETRANGE    =  1025, _
      PBS_MARQUEE     =  0x08, _
      PBM_SETMARQUEE  =  1034

Const TD_WARNING_ICON      = 65535, _
      TD_ERROR_ICON        = 65534, _
      TD_INFORMATION_ICON  = 65533, _
      TD_SHIELD_ICON       = 65532
      
Const TDCBF_OK_BUTTON      = 1, _
      TDCBF_YES_BUTTON     = 2, _
      TDCBF_NO_BUTTON      = 4, _
      TDCBF_CANCEL_BUTTON  = 8, _
      TDCBF_RETRY_BUTTON   = 0x10, _
      TDCBF_CLOSE_BUTTON   = 0x20     

Global g_WndProc, g_Task = 0
Global oWP = Callback("TestWinProc", "hwnd;uint;wparam;lparam")
                   
Func WindowTest()
    RunThread WinTest
EndFunc

Func TestWinProc(hWnd, uMsg, wParam, lParam)
    Static WM_CLOSE = 0x0010
    #OutputDebugString("Autorun: " & uMsg)
    If uMsg = WM_CLOSE Then
       If DllCall("DestroyWindow", "handle", hWnd) Then 
          g_Task = 0
       EndIf   
       Return 0
    EndIf
    Return DllCall("CallWindowProcW", _
                   "ptr", g_WndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc
              
Func WinTest()
    If hWnd > 0 Then
       If WinGetState(1, hWnd) Then
          SendMessage(hWnd, 0x0010, 0, 0)
          Return
       EndIf   
       hWnd = 0
    Endif    
    hWnd = DllCall("CreateWindowExW", _
                   "dword", 0, _
                   "wstr", "msctls_progress32", _
                   "wstr", "", _
                   "dword", 0x10C80000, _
                   "int", 200, "int", 100, "int", 300, "int", 50, _
                   "handle", AUTORUN_TCHANDLE, _
                   "handle", 0, "handle", 0, "ptr", 0, _
                   "handle")
    
    If hWnd = 0 Then Return
    
    g_WndProc = DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), _
                        "hwnd", hWnd, _
                        "int", -4, _
                        "long_ptr", oWP.Ptr)
    
    #DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), "hwnd", hWnd, "int", -16, "long_ptr", 0x10C00000)  
    
    hIco = SendMessage(AUTORUN_TCHANDLE, 0x7f, 2, 0)                     
    SendMessage(hWnd, 0x80, 0, hIco)       
                   
    WinSetStyle(PBS_MARQUEE, 2, hWnd)
    WinSetText("Estimating...", hWnd)
    
    g_Task = 1
    SendMessage(hWnd, PBM_SETMARQUEE, 1, 0)
    For i = 1 to 15
        Sleep(100)
        If g_Task = 0 Then Break
    Next
    If g_Task > 0 Then
       SendMessage(hWnd, PBM_SETMARQUEE, 0, 0)    
       WinSetStyle(PBS_MARQUEE, 4, hWnd) 
       SendMessage(hWnd, PBM_SETPOS, 0, 0)   
       For i = 1 to 10
           SendMessage(hWnd, PBM_SETPOS, i*10, 0) 
           WinSetText("Processed " & i*10 & "%", hWnd)
           Sleep(300)
           If g_Task = 0 Then Break
       Next 
    EndIf   
    If g_Task = 0 Then 
       MsgBox("Операция прервана", "", 48)
    Else       
       If DllCall("DestroyWindow", "handle", hWnd) Then hWnd = 0
       MsgBox("Операция успешно завершена", "", 64)       
    EndIf   
EndFunc
[/cut]
Сделано, конечно, немножко криво, но это только для теста. Всё работает. Однако TCx64 при вызове WindowTest валится. В чём может быть проблема?

Также сделал функцию на волшебный хинт в целях демонстрации, но TCx64 при его вызове тоже валится, хотя в 32-битной версии всё работает. Валится на третьем шаге, т.е. на вызове функции из DLL по адресу, а не по имени:
[cut]

Код: Выделить всё

Func MagicHint(FileName, FieldIndex, UnitIndex)
    Local bCaps = DllCall("GetKeyState", "int", 0x14, "short")
    Local b_CTRL = BitAND(bCaps, 1), b_Shift = IsPressed(0x10)
    
    If Not b_CTRL then b_CTRL = IsPressed (0x11)
    If Not b_CTRL Then Return
    
    Static Pipe, Idx = 0, _
           sPath = COMMANDER_PATH & "\Ini\Tools\Libs", _
           sLang ="file://" & sPath & "ru.csv", _         
           sHint ="file://" & sPath & "hint.txt", _             
           sLib = "MediaInfo" & (auX64 ? "" : "_i386") & ".dll", _
           hLib = DllCall("LoadLibrary", "Wstr",  sPath & sLib, "Ptr"), _
           pNew, pOpen, pDel, pOpt, pInfo
    
    OutputDebugString("Autorun: 1")
           
    If hLib = 0 And FieldIndex > 1 Then Return
    
    If FieldIndex = 1 Then
    
       If hLib = 0 Then Return "Error LoadLibrary " & sLib
       
       Idx = 0
       pNew = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_New", "Ptr")
       pOpen = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Open", "Ptr")
       pDel = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Delete", "Ptr")
       pOpt = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Option", "Ptr")
       pInfo = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_Inform", "Ptr")
       
       OutputDebugString("Autorun: 2")
       
       Local hMI = DllCall(pNew, "Ptr")
       If hMI = 0 Then Return "MediaInfo_New couldn't create new object"
       
       OutputDebugString("Autorun: 3")
       
       If DllCall(pOpen, 'Ptr', hMI, "Wstr", FileName, "Uint") <> 1 Then
          DllCall(pDel, "Ptr", hMI)        
          Return "MediaInfo_Open couldn't open file " &  FileName
       EndIf
       
       OutputDebugString("Autorun: 4")

       Local x, y, w, bHint = 0
       Local hWnd = RequestInfo(ItemAtCursor("panel"))
       WinGetPos("", "", "w", "", hWnd)
       If w > 0 Then
          MouseGetPos("x","y")          
          Static buf = Buffer(8)	# POINT
          buf.Zero()
          buf.SetNum(0, "long", x, "long", y)
          DllCall("ScreenToClient", "hwnd", hWnd, "ptr", buf.ptr)
          x = buf.GetNum(0)
          Switch Round(x/w*100,0)
             Case 1 To 10
                b_SHIFT = 1
             Case 10 To 90
                
             Case 90 To 100
                bHint = true              
          EndSwitch          
       EndIf                         

       DllCall(pOpt, 'Ptr', hMI, "Wstr", "Language", "Wstr", sLang, "Wstr")      
       If b_Shift Then 
          DllCall(pOpt, 'Ptr', hMI, "Wstr", "Complete", "Wstr", "1", "Wstr")
       Else
          DllCall(pOpt, 'Ptr', hMI, "Wstr", "Complete", "Wstr", "0", "Wstr")       
       EndIf
       If bHint Then
          DllCall(pOpt, "Ptr", hMI, "Wstr", "Output", "Wstr", sHint, "Wstr")           
       Else
          DllCall(pOpt, "Ptr", hMI, "Wstr", "Output", "Wstr", "", "Wstr")    
       EndIf              
       Pipe = DllCall(pInfo, 'Ptr', hMI, "Uint", 0, "Wstr")
       DllCall(pDel, "Ptr", hMI)
       If IsPressed(0x5B) Then Idx = 50
    Endif
    Return TrimSpaces(StrPart(Pipe, auLF, FieldIndex + Idx))
EndFunc
[/cut]
А так всё работает. Код стал более компактным и чистым. Для работы требуется прописать в autorun.cfg поля:
[cut]

Код: Выделить всё

Pragma AutorunPluginFields "C1:::MagicHint" "C2:::MagicHint" "C3:::MagicHint" "C4:::MagicHint" "C5:::MagicHint" "C6:::MagicHint" "C7:::MagicHint" "C8:::MagicHint" "C9:::MagicHint" "C10:::MagicHint" "C11:::MagicHint" "C12:::MagicHint" "C13:::MagicHint" "C14:::MagicHint" "C15:::MagicHint" "C16:::MagicHint" "C17:::MagicHint" "C18:::MagicHint" "C19:::MagicHint" "C20:::MagicHint" "C21:::MagicHint" "C22:::MagicHint" "C23:::MagicHint" "C24:::MagicHint" "C25:::MagicHint" "C26:::MagicHint" "C27:::MagicHint" "C28:::MagicHint" "C29:::MagicHint" "C30:::MagicHint" "C31:::MagicHint" "C32:::MagicHint" "C33:::MagicHint" "C34:::MagicHint" "C35:::MagicHint" "C36:::MagicHint" "C37:::MagicHint" "C38:::MagicHint" "C39:::MagicHint" "C40:::MagicHint" "C41:::MagicHint" "C42:::MagicHint" "C43:::MagicHint" "C44:::MagicHint" "C45:::MagicHint" "C46:::MagicHint" "C47:::MagicHint" "C48:::MagicHint" "C49:::MagicHint" "C50:::MagicHint" "C51:::MagicHint" "C52:::MagicHint" "C53:::MagicHint" "C55:::MagicHint" "C55:::MagicHint" "C56:::MagicHint" "C57:::MagicHint" "C58:::MagicHint" "C59:::MagicHint" "C60:::MagicHint"
[/cut]
И две вспомогательные функции:
[cut]

Код: Выделить всё

Func TrimSpaces(String)
    Local a, b
    If Not StrPos(String, ":") Then Return String
    
    a = StrPart(String, ":", 1)
    b = StrPart(String, ":", 2) & StrPart(String, ":", 3)
    
    Return StrTrim(a) & ":  " & FixCP(StrTrim(b)) 
EndFunc

Func FixCP(String)
   If MediaInfoLock = 0 Then Return String
   Local bUsedRepl
   Local nSize = StrLen(String)
   Local buf = Buffer(nSize)
   buf.Zero()

   # iso-8859-1 = 28591
   DllCall("WideCharToMultiByte", _
           "uint", 28591, _
           "dword", 0, _
           "wstr", String, _
           "int", -1, _
           "ptr", 0, _
           "int", 0, _
           "ptr", 0, _
           "bool*", @bUsedRepl)
   If bUsedRepl Then Return String

   DllCall("WideCharToMultiByte", _
           "uint", 28591, _
           "dword", 0, _
           "wstr", String, _
           "int", -1, _
           "ptr", buf.ptr, _
           "int", nSize, _
           "ptr", 0, _
           "ptr", 0)
   Local fixed = buf.GetStr(0, nSize, "ANSI")
   Free(buf)
   Return fixed
EndFunc
[/cut]
А также файл hint.txt положить в папку MediaInfo и путь в скрипте поменять:
[cut]

Код: Выделить всё

General;Name: %FileName%.%FileExtension%\r\nSize: %FileSize/String4%\r\n[Duration: %Duration%]\r\n[Duration: %Duration/String1%]\r\n[Duration: %Duration/String5%]\r\n[General: %BitRate/String%][(%BitRate_Mode%)][, %Format%][(%Format/Family%)]$if(%Cover%,\, Cover)[, %Width%x%Height%pix][, AR:%AspectRatio%=~%AspectRatio/String%][, %Channel(s)%ch][, %Resolution/String%][, %FrameRate/String%][, %SamplingRate/String%][, %Bits-(Pixel*Frame)%bpf][, %Language%]\r\n

Video;Video #%StreamKindID%: [%Width%x%Height%pix][, AR:%AspectRatio%=~%AspectRatio/String%][, %Resolution/String%][, %FrameRate/String%][, %BitRate/String%][(%BitRate_Mode%)][, %Bits-(Pixel*Frame)%bpf][, %Format%][(%Format/Family%)][, %Language%][, %Channel(s)%ch][, %SamplingRate/String%]\r\n

Audio;Audio #%StreamKindID%: [%Channel(s)%ch][, %Resolution/String%][, %SamplingRate/String%][, %BitRate/String%][(%BitRate_Mode%)][, %Format%][(%Format/Family%)][, %Format_Profile%][, %Language%][, %Width%x%Height%pix][, AR:%AspectRatio%=~%AspectRatio/String%][, %FrameRate/String%][, %Bits-(Pixel*Frame)%bpf]\r\n
;
Text;Text #%StreamKindID%: %Format%[(%Format/Family%)][@%Language%][, %StreamSize/String4%][, %BitRate/String%][(%BitRate_Mode%)][, %Width%x%Height%pix][, AR:%AspectRatio%=~%AspectRatio/String%][, %Channel(s)%ch][, %Resolution/String%][, %FrameRate/String%][, %SamplingRate/String%][, %Bits-(Pixel*Frame)%bpf]\r\n

Chapters;Chapters #%StreamKindID%: %Format%[(%Format/Family%)][@%Language%][, %Total% entries][, %StreamSize/String4%][, %BitRate/String%][(%BitRate_Mode%)][, %Width%x%Height%pix][, AR:%AspectRatio%=~%AspectRatio/String%][, %Channel(s)%ch][, %Resolution/String%][, %FrameRate/String%][, %SamplingRate/String%][, %Bits-(Pixel*Frame)%bpf]\r\n
;
Image;Image #%StreamKindID%: [%Width%x%Height%pix][, AR:%AspectRatio%=~%AspectRatio/String%][, %Resolution/String%][, %FrameRate/String%][, %StreamSize/String4%][, %BitRate/String%][(%BitRate_Mode%)][, %Bits-(Pixel*Frame)%bpf][, %Format%][(%Format/Family%)][, %Language%][, %Channel(s)%ch][, %SamplingRate/String%]\r\n
;
Menu;Menu #%StreamKindID%: [%MenuID/String%][, %Duration% Format:%Format/String%]
;
[/cut]
Будут вызываться три разные подсказки в зависимости от позиции указателя на панели. Но данные подсказки выбраны только в качестве демонстрации, на самом деле подсказки могут быть совершенно любыми.
Loopback
Сообщения: 1646
Зарегистрирован: Пн сен 07, 2009 09:29

Сообщение Loopback »

Orion9 писал(а): В чём может быть проблема?
Надо указать тип возвращаемого значения c размером указателя (ptr, long_ptr) для вызова SetWindowLong, сейчас возвращается int, что не подходит для x64.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

Loopback писал(а):сейчас возвращается int, что не подходит для x64
Точно! Торопился, пропустил. Но хорошо, что это мелкая ошибка никак не связанная с плагином.

Теперь бы ещё вот с этим разобраться:

Код: Выделить всё

pNew = DllCall("GetProcAddress", "Ptr", hLib, "Str", "MediaInfo_New", "Ptr")
Local hMI = DllCall(pNew, "Ptr")
Возможно на второй строчке ТСх64 падает.

Я еще попробовал сабклассинг подсказки сделать через SetClassLong, но что-то он не работает:

Код: Выделить всё

Local hTip = WinFind(0, "TToolTip")
g_WndProc = DllCall("SetClassLong" & (auX64 ? "PtrW" : "W"), _
                "hwnd", hTip, _
                "int", -24, _
                "long", oWP.Ptr, "ptr")
OutputDebugString("g_WndProc=" & g_WndProc & " oWP.Ptr=" & oWP.Ptr)
Вообще такое впечатление, что Гислер мониторит адрес оконной процедуры в классе и возвращает значение по умолчанию при его изменении. Хотя в этом я плохо разбираюсь, так что далеко идущих выводов делать, пожалуй, не стоит. Но если повесить на ControlSetHint /F /D:50 28
[cut]

Код: Выделить всё

Func ButtonBarTestHint()
    Local hTip = WinFind(0, "TToolTip")
    g_WndProc = DllCall("SetClassLong" & (auX64 ? "PtrW" : "W"), _
                    "hwnd", hTip, _
                    "int", -24, _
                    "long", oWP.Ptr, "ptr")
    OutputDebugString("g_WndProc=" & g_WndProc & " oWP.Ptr=" & oWP.Ptr)
    Local hDC = DllCall("GetWindowDC", "ptr", hTip, "ptr")
    hIco = SendMessage(AUTORUN_TCHANDLE, 0x7f, 2, 0)
    Local x, y, w, h    
    WinGetPos("x", "y", "w", "h", hTip)    
    DllCall("DrawIconEx", _
                   "ptr", hDC, _
                   "int", 10, _
                   "int", 10, _
                   "ptr", hIco, _
                   "int", 16, _
                   "int", 16,  _
                   "uint", 0, _
                   "ptr", 0,  _
                   "uint", 0x0003)
    DllCall("ReleaseDC", "ptr", AUTORUN_TCHANDLE, "ptr", hDC)                
    WinSetPos(100, "", "", "", 1, hTip)
EndFunc
[/cut]
То видно, как подсказка с прорисованной иконкой меняет позицию, а затем исчезает и заменяется новой дефолтной подсказкой. Странное какое-то поведение.

Добавлено спустя 8 минут:

Я имею в виду, что после вызова SetClassLong, который вроде срабатывает:

Код: Выделить всё

Func ButtonBarTestHint()
    Local hTip = WinFind(0, "TToolTip")
    g_WndProc = DllCall("SetClassLong" & (auX64 ? "PtrW" : "W"), _
                    "hwnd", hTip, _
                    "int", -24, _
                    "long", oWP.Ptr, "ptr")
Нет входа в оконную процедуру TestWinProc:

Код: Выделить всё

Global g_WndProc
Global oWP = Callback("TestWinProc", "hwnd;uint;wparam;lparam")
                   
Func TestWinProc(hWnd, uMsg, wParam, lParam)
    Static WM_CLOSE = 0x0010
    OutputDebugString("Autorun: " & uMsg)
    If uMsg = WM_CLOSE Then
       If DllCall("DestroyWindow", "handle", hWnd) Then 
          g_Task = 0
       EndIf   
       Return 0
    EndIf
    Return DllCall("CallWindowProcW", _
                   "ptr", g_WndProc, "hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc
С вызовом SetWindowLong это работает.
Loopback
Сообщения: 1646
Зарегистрирован: Пн сен 07, 2009 09:29

Сообщение Loopback »

Orion9 писал(а):Возможно на второй строчке ТСх64 падает
Да, что-то я пропустил это сообщение. Действительно, неправильно преобразовывался передаваемый адрес под x64. Не стал делать новую версию, заменил во вчерашней, все равно сайт забыл обновить.
Orion9 писал(а):Я еще попробовал сабклассинг подсказки сделать через SetClassLong, но что-то он не работает
Видимо потому, что подсказка Autorun не использует TToolTip, в основе лежит static. Впрочем, SetClassLong и не сработает, поскольку меняет параметры класса для окон, которые будут созданы после её использования, а ControlSetHint создает окно подсказки один раз при первом запуске.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

Loopback писал(а):Не стал делать новую версию, заменил во вчерашней
Теперь всё работает и в 64-битной версии, класс! А с вызовом функций по адресам теперь ещё и быстрее должно быть, хотя визуально это сложно отличить.
Loopback писал(а):подсказка Autorun не использует TToolTip, в основе лежит static
Да, я видел. Ещё по этому поводу хотел спросить у вас, как вы расчет размеров окна делаете, но не стал лишний раз донимать ) Ведь текст static можно легко заменить через WinSetText, например:

Код: Выделить всё

Local hWnd = LAST_HINT_WINDOW
If hWnd > 0 Then
   If WinGetState(1, hWnd) Then
      WinSetText("Тест...." & auCRLF & "Загрузка"& auCRLF & "Загрузка....", hWnd)
      WinSetPos("", "", "", 50, 2, hWnd)      
      WinRedraw(2, hWnd)
   EndIf   
Endif
А вот изменить размер окна под новый текст уже сложнее. Здесь с метрикой шрифта надо заморачиваться, как пишут на сайте microsoft:
The system displays as much text as it can in the static control and clips whatever does not fit. To calculate an appropriate size for the control, retrieve the font metrics for the text. For more information about fonts and font metrics, see Fonts and Text.
https://learn.microsoft.com/en-us/windo ... ic-control
Но с вызовом SetClassLong я хотел добиться другого, если это, конечно, вообще возможно.

Я хотел как раз вот этого:
Loopback писал(а):SetClassLong... меняет параметры класса для окон, которые будут созданы после её использования
Я хотел поменять оконную функцию у гислеровской подсказки, т.е. у всего класса подсказок, называющихся TToolTip. Как я понял, гислеровская подсказка - это обычное дочернее окно, в которое он рисует текст функцией TextOut, превращая его в растровое изображение. Извлечь из этого какую-то пользу вряд ли возможно при таком раскладе, но я просто хотел посмотреть, будет ли работать сабклассинг с функцией обратного вызова, установленной через SetClassLong, хотя это не так важно.

Зато проверил Callback на диалоге задач )
[cut]

Код: Выделить всё

RegisterCommand 60027 "TaskDialogIndirect"

Global TASK_THREAD = 0
Global oTaskWinProc = Callback("TaskWinProc", "hwnd;uint;wparam;lparam;long_ptr")

Func TaskWinProc(hWnd, Msg, wParam, lParam, lpRefData)
    If Msg = 0 Then
       RunThread("ProgressMove", hWnd)
       Return 1
    EndIf
    If Msg = 2 Then
       If wParam = 4 Then
          If TASK_THREAD > 0 Then
             TASK_THREAD = 0
             Return 1
          EndIf   
          RunThread("ProgressMove", hWnd)
          Return 1
       Else
          If TASK_THREAD > 0 Then TASK_THREAD = 0
          Return 0
       EndIf    
    EndIf
EndFunc

Func ProgressMove(hWnd)
    TASK_THREAD = 1
    Local sMsg = "Initializing...", buf = Buffer(64)
    buf.SetStr(sMsg & Chr(0))
    SendMessage(hWnd, 1127, 1, 0)        
    SendMessage(hWnd, 1131, 1, 0)
    SendMessage(hWnd, 1138, 0, buf.ptr)
    For i = 1 to 30
        Sleep(100)
        If i = 7 Then
           sMsg = "Processing..."
        ElseIf i = 20 Then   
           sMsg = "Finishing..."
        EndIf
        If i = 7 Or i = 20 Then
           buf.SetStr(sMsg & Chr(0))
           SendMessage(hWnd, 1138, 0, buf.ptr)
        EndIf
        If TASK_THREAD = 0 Then Break
    Next
    sMsg = "Content"
    buf.SetStr(sMsg & Chr(0))
    SendMessage(hWnd, 1138, 0, buf.ptr)
    Free(buf)
    SendMessage(hWnd, 1131, 0, 0)
    SendMessage(hWnd, 1127, 0, 0)    
    SendMessage(hWnd, 1130, 0, 0)
    If TASK_THREAD = 0 Then 
       MsgBox("Операция прервана", "", 48)
    Else       
       MsgBox("Операция успешно завершена", "", 64)       
    EndIf
    TASK_THREAD = 0
EndFunc

Func TaskDialogIndirect()
   If auX64 Then
      MsgBox("Unsupported version","",48)
      Return
   EndIf
   Local hRes, bn
   Local buf = Buffer(96)
   Local sTitle = "Title"
   Local sInstr = "Instruction"
   Local sContn = "Content"
   Local sExpand = "Expanded text"
   Local sFooter = "Autorun " &  FileGetVersion(AUTORUN_PATH & "\Autorun.wdx", "FileVersion")
   Local ttl = Buffer(StrLen(sTitle)*2+2), _
         ins = Buffer(StrLen(sInstr)*2+2), _
         con = Buffer(StrLen(sContn)*2+2), _
         exp = Buffer(StrLen(sExpand)*2+2), _
         ftr = Buffer(StrLen(sFooter)*2+2)
   ttl.SetStr(sTitle & Chr(0))
   ins.SetStr(sInstr & Chr(0))
   con.SetStr(sContn & Chr(0))
   exp.SetStr(sExpand & Chr(0))
   ftr.SetStr(sFooter & Chr(0))
   buf.Zero()
   buf.SetNum(0, "uint", buf.size, _   
                 "hwnd", AUTORUN_TCHANDLE, _
                 "handle", 0, _
                 "dword", 0x0408, _
                 "dword", 21, _
                 "ptr", ttl.ptr, _
                 "ptr", 65535, _
                 "ptr", ins.ptr, _
                 "ptr", con.ptr, _
                 "uint", 0, _
                 "ptr", 0, _
                 "int", 0, _
                 "uint", 0, _
                 "ptr", 0, _
                 "int", 0, _
                 "ptr", 0, _
                 "ptr", exp.ptr, _
                 "ptr", 0, _
                 "ptr", 0, _
                 "ptr", 65533, _
                 "ptr", ftr.ptr, _
                 "ptr", oTaskWinProc.ptr, _
                 "long_ptr", 0, _
                 "uint", 0)
   hRes = DllCall("TaskDialogIndirect", _
                   "ptr", buf.ptr, _   
                   "int*", @bn, _   
                   "int*", 0, _   
                   "bool*", 0)
EndFunc
[/cut]
Поскольку под x64 нужно отдельно структуру высчитывать, я не стал с этим заморачиваться. Но на 32-битном ТС всё отлично работает. Прикольный муляж, кстати, получился )

Так что Callback нормально работает. Спасибо за багофикс. Это открывает теперь большие возможности.
Loopback
Сообщения: 1646
Зарегистрирован: Пн сен 07, 2009 09:29

Сообщение Loopback »

Orion9 писал(а):Здесь с метрикой шрифта надо заморачиваться, как пишут на сайте microsoft:
Верно, шрифт необходимо учитывать. Для расчёта в функции DrawText есть замечательный флаг DT_CALCRECT. Перед расчётом нужно для DC с SelectObject выбрать шрифт, который будет использоваться для отрисовки.
Orion9 писал(а):Как я понял, гислеровская подсказка - это обычное дочернее окно, в которое он рисует текст функцией TextOut, превращая его в растровое изображение.
TToolTip - похоже что самописный контрол подсказки, т.к. в дельфи такого класса нет. Как именно и на основе чего он сделан и как отрисовывается не знаю, но принципы везде одинаковы.
Orion9 писал(а): Прикольный муляж, кстати, получился )
Да, симпатично выглядит.
Аватара пользователя
Orion9
Сообщения: 1283
Зарегистрирован: Пн янв 01, 2024 17:18

Сообщение Orion9 »

Loopback писал(а):Для расчёта в функции DrawText есть замечательный флаг DT_CALCRECT. Перед расчётом нужно для DC с SelectObject выбрать шрифт, который будет использоваться для отрисовки.
Спасибо. Сейчас много дел навалилось, но когда освобожусь, посмотрю.
Loopback писал(а):TToolTip - похоже что самописный контрол подсказки, т.к. в дельфи такого класса нет. Как именно и на основе чего он сделан и как отрисовывается не знаю, но принципы везде одинаковы.
Я в этом плохо разбираюсь, но "имхо" уже писал. Гислер для класса TToolTip, по всей видимости, использует обычное дочернее окно, в клиенсткую область которого текст рисуется функцией TextOut, тем самым превращая его в изображение. Кстати, и панели инструментов он свои по тому же принципу создаёт (класс TButtonBar), т.е. напрямую рисует в клиентскую область значки и хранит эти параметры для расчета координат. Поэтому ему и сложно реализовать drag-and-drop внутри панели, а не потому, что он якобы заботится о безопасности неуклюжего пользователя.
Loopback писал(а):Да, симпатично выглядит.
Согласен. Вещь прикольная и однозначно пригодится. Мне только не нравится, что при появлении диалога звук системный проигрывается и что реализация диалога сложная. Скорее всего буду пользоваться первым вариантом, где окно создаётся через CreateWindowExW с классом msctls_progress32. Но и это вариант буду держать на примете.
Loopback
Сообщения: 1646
Зарегистрирован: Пн сен 07, 2009 09:29

Сообщение Loopback »

Orion9 писал(а):Поэтому ему и сложно реализовать drag-and-drop внутри панели, а не потому, что он якобы заботится о безопасности неуклюжего пользователя.
Да, панель инструментов рисованный контрол, однако сам этот факт совершенно не означает каких-то чрезмерных сложностей в реализации перетаскивания. Хотя какие-то сложности другого рода, несомненно, могут быть.

Однако резон в опасении случайного перетаскивания на самом деле есть. Понятно, что это вроде не критично, кнопку можно переместить обратно, но лично меня бы такое раздражало. Я совсем не против фичи, было бы удобно, но лучше если бы режим перетаскивания не был по умолчанию, а включался, скажем, из контекстного меню.
AkulaBig
Сообщения: 639
Зарегистрирован: Ср дек 03, 2008 11:48

Сообщение AkulaBig »

Попробовал оба варианта записи. Не раскрывается COMMANDER_PATH и все тут. Как все-таки правильно запись делать?

Код: Выделить всё

		# Local Buttonbar = IniRead("~/R", ini_Buttonbar, "Buttonbar", "Buttonbar", "")
		Local Buttonbar
		IniRead /R Buttonbar %ini_Buttonbar% "Buttonbar" "Buttonbar" ""
Ответить