Orion9

|
Posted: Tue Jun 10, 2025 17:46 Post subject: |
|
|
Loopback wrote: | Не представляю, как сюда блокировку притянуть. |
Как вы, наверное, догадались, данную статейку я почитал на досуге, чтобы лучше понимать механизм сообщений, но она меня навела на одну мысль.
Если откинуть баги Гислера и Lazarus, остается только один вариант: сообщение с IDCANCEL посылается специально и с определенной целью. Быть может, в работе ТСх64 есть некий критичный момент, когда появление диалогового окна нежелательно и может привести к проблемам, именно поэтому сразу посылается сообщение о закрытии.
Например, AkulaBig недавно писал, что при использовании TCFS2 значок Тотала на панели задач пропадает, а потом опять появляется. Я тоже заметил этот "прикол", характерный только для ТСх64. Но дело не только в TCFS2. Такое происходит и при отправке сообщений окну ТС из Autorun. То есть, складывается впечатление, что ТСх64, обрабатывыая полученные сообщения и выполняя какие-то внутренние операции, скрывает главное окно и повторно его инициализирует. По крайней мере, так выглядит визуально на панели задач.
А теперь допустим, что в такой момент что-то произойдет и значок на панели задач так и не появится. Вот именно о таком критичном моменте я и говорил. Но это только мысли, которые к реальности могут не иметь никакого отношения.
Loopback wrote: | Экземпляр контрола штука не всегда надёжная. Он постоянен только тогда, когда количество созданных контролов в процессе работы не изменяется, т.е. они не удаляются и не создаются новые. |
Спасибо за объяснения. Теперь я, кажется, стал это лучше понимать.
Loopback wrote: | Для получения хэндлов элементов главного окна лучше пользоваться RequestInfo. |
Да, забыл о таком, думал с хэндлами прокатит. Но этот вариант действительно представляется более надежным. Только я не совсем понял, какой именно индекс заменяет TMyPanel6 в ТСх86, потому что именно в это окно я хотел рисовать вентихлятор )
Обновленная функция, которая не требует отдельных файлов с иконками (иконка берется из основного окна ТС сообщением 0x7f и поворачивается вызовом функции PlgBlt из gdi32.dll)
 Hidden text Code: | RegisterCommand 62016 "RotateIcon"
Global ROTATE_THREAD = 0
Func RotateIcon()
If ROTATE_THREAD > 0 Then
ROTATE_THREAD = 0
Return
EndIf
RunThread("ThreadRotateIcon", IsPressed(0x11))
EndFunc
Func ThreadRotateIcon(FileIcons)
ROTATE_THREAD = 1
Local hIcon = SendMessage(AUTORUN_TCHANDLE, 0x7f, 2, 0)
While ROTATE_THREAD > 0
Sleep(100)
If FileIcons Then
IconRotateDraw()
Else
RotateDeviceContext()
EndIf
Wend
SendMessage(AUTORUN_TCHANDLE, 0x80, 0, hIcon)
WinRedraw(2)
EndFunc
Func IconRotateDraw()
Static nIco = 0
nIco += 1
If nIco > 4 Then nIco = 1
Local sFile = COMMANDER_PATH & "\Icons\TC\" & nIco & ".ico"
Local hIco = DllCall("shell32\ExtractIconW", _
"ptr", AUTORUN_TCHANDLE, _
"wstr", sFile, _
"uint", 0, _
"ptr")
Local hWnd = WinFind(AUTORUN_TCHANDLE, _
(AUTORUN_TCARCH = 32 ? "TMyPanel" : "Window"), _
(AUTORUN_TCARCH = 32 ? 6 : 10))
#Local hWnd = RequestInfo(15)
Local hDC = DllCall("GetWindowDC", "ptr", hWnd, "ptr")
Local x, y, w, h
WinGetPos("x", "y", "w", "h", hWnd)
DllCall("DrawIconEx", _
"ptr", hDC, _
"int", w - 20, _
"int", 1, _
"ptr", hIco, _
"int", 16, _
"int", 16, _
"uint", 0, _
"ptr", 0, _
"uint", 0x0003)
SendMessage(AUTORUN_TCHANDLE, 0x80, 0, hIco)
SendMessage(AUTORUN_TCHANDLE, 0x80, 1, hIco)
DllCall("ReleaseDC", "ptr", AUTORUN_TCHANDLE, "ptr", hDC)
DllCall("DestroyIcon", "ptr", hIco)
EndFunc
Func RotateDeviceContext()
Static c = 0
c += 1
If c > 4 Then c = 1
Local x, y, w, h
Local hIco = SendMessage(AUTORUN_TCHANDLE, 0x7f, 2, 0)
Local hWnd = WinFind(AUTORUN_TCHANDLE, _
(AUTORUN_TCARCH = 32 ? "TMyPanel" : "Window"), _
(AUTORUN_TCARCH = 32 ? 6 : 10))
#Local hWnd = RequestInfo(15)
Local hdcWndDC = DllCall("GetWindowDC", "ptr", hWnd, "ptr")
Local hdcMemDC = DllCall("CreateCompatibleDC", "ptr", hdcWndDC, "ptr")
Local hdcBltDC = DllCall("CreateCompatibleDC", "ptr", hdcWndDC, "ptr")
Local hbmDB1 = DllCall("CreateCompatibleBitmap", "ptr", hdcWndDC, "int", 16, "int", 16,"ptr")
Local hbmDB2 = DllCall("CreateCompatibleBitmap", "ptr", hdcWndDC, "int", 16, "int", 16,"ptr")
DllCall("SelectObject", "ptr", hdcMemDC, "ptr", hbmDB1, "ptr")
DllCall("SelectObject", "ptr", hdcBltDC, "ptr", hbmDB2, "ptr")
DllCall("DrawIconEx", _
"ptr", hdcMemDC, _
"int", 1, _
"int", 1, _
"ptr", hIco, _
"int", 16, _
"int", 16, _
"uint", 0, _
"ptr", 0, _
"uint", 0x0003)
Local pt = Buffer(24)
pt.Zero()
If c = 1 Then
pt.SetNum(0, "int", 16, "int", 0, _
"int", 0, "int", 0, _
"int", 16, "int", 16)
ElseIf c = 2 Then
pt.SetNum(0, "int", 16, "int", 16, _
"int", 16, "int", 0, _
"int", 0, "int", 16)
ElseIf c = 3 Then
pt.SetNum(0, "int", 0, "int", 16, _
"int", 16, "int", 16, _
"int", 0, "int", 0)
ElseIf c = 4 Then
pt.SetNum(0, "int", 0, "int", 0, _
"int", 0, "int", 16, _
"int", 16, "int", 0)
EndIf
DllCall("PlgBlt", _
"ptr", hdcBltDC, _
"ptr", pt.Ptr, _
"ptr", hdcMemDC, _
"int", 0, _
"int", 0, _
"int", 16, _
"int", 16, _
"ptr", 0, _
"int", 0, "int", 0)
WinGetPos("x", "y", "w", "h", hWnd)
DllCall("BitBlt", _
"ptr", hdcWndDC, _
"int", w - 20, _
"int", 2, _
"int", 16, _
"int", 16, _
"ptr", hdcBltDC, _
"int", 1, _
"int", 1, _
"dword", 13369376)
DllCall("DeleteObject", "ptr", hbmDB1)
DllCall("DeleteObject", "ptr", hbmDB2)
DllCall("DeleteObject", "ptr", hdcMemDC)
DllCall("DeleteObject", "ptr", hdcBltDC)
DllCall("ReleaseDC", "ptr", AUTORUN_TCHANDLE, "ptr", hdcWndDC)
EndFunc |
Старая функция по-прежнему доступна и вызывается с удержнием CTRL.
Loopback wrote: | - узнать, включены ли значки
- узнать их размер
- получить панель, над которой находится курсор (ItemAtCursor)
- получить хэндл панели (RequestInfo)
- получить координаты этой панели (WinGetPos)
- вычислить прямоугольник, где может находиться курсор, с помощью размера значка
- получить координаты курсора (MouseGetPos)
- проверить, находится ли курсор в границах прямоугольника |
Норм алгоритм, но нужно на практике проверить, как он будет работать. Но я не стал бы заморачиваться. Когда приходится дополнительно куда-то целиться, это немного напрягает. |
|