Orion9

|
Posted: Fri May 23, 2025 20:34 Post subject: |
|
|
Вот же, а... Случайно отредактировал предыдущий пост, вместо отправки нового.
Loopback, там было про проблему с функцией ClipGet, которая режет текст из буфера. Используя DllCall удалось обойти это ограничение:
Code: | Local hCB, pMem, obg, CF_UNICODETEXT = 13
If DllCall("OpenClipboard", "handle", 0) Then
hCB = DllCall("GetClipboardData", "uint", CF_UNICODETEXT, "handle")
pMem = DllCall("GlobalLock", "handle", hCB, "ptr")
obj = Buffer(1024*500, pMem)
txt = obj.GetStr()
Free(obj)
DllCall("GlobalUnlock ", "handle", hCB)
DllCall("CloseClipboard")
Else
MsgBox("Clipboard Error" )
EndIf |
Но в приведенном коде используется другое ограничение буфера размером в 500 Кб. Правильно я понимаю, что это просто "окно" для чтения из памяти, на самом деле память в таких случаях не выделяется? А как вообще правильно сделать, ведь объем текстовых данных в буфере может быть ещё больше?
Короче, вдохновившись новым лозунгом Autorun "Пока Гислер думает, Autorun делает", соорудил небольшую функцию:
 Hidden text TOTALCMD#BAR#DATA
62015
%COMMANDER_EXE%
Подсчёт колонок|Ctrl - Запуск потока|Ctrl + ESC - Отмена
-1
 Hidden text Code: | RegisterCommand 62015 "Summarize"
Global SUM_THREAD = 0, SUM_MX = 0, SUM_MY = 0
Func Summarize(lParam)
If SUM_THREAD > 0 Then
SUM_THREAD = 0
Sleep(250)
Return
EndIf
If Not IsPressed(0x11) Then
MouseGetPos("SUM_MX", "SUM_MY")
SumUpColumns(1)
Return
EndIf
# CTRL запуск потока
RunThread ThreadSumCustomView
EndFunc
Func ThreadSumCustomView()
Local i
SUM_THREAD = 1
MouseGetPos("SUM_MX", "SUM_MY")
While SUM_THREAD > 0
SumUpColumns(0)
For i = 1 To 10
If SUM_THREAD = 0 Or (IsPressed (0x11) And IsPressed (0x1B)) Then
SUM_THREAD = 0
ShowHint("Операция прервана")
Break
EndIf
Sleep(50)
Next
Wend
SUM_THREAD = 0
EndFunc
Func SumUpColumns(lWait = 0)
Local txt, i, j, T1 = GetUptime()
#If GetSelectedItems(3, 0) = '' And GetCurrentItem(3, 2) = 0 Then
If GetCurrentItem(3, 2) = 0 Then
ShowHint("Index = 0", SUM_MX, SUM_MY, 1000, 1)
Sleep(500)
Return
EndIf
ShowHint("Clipboard Waiting", SUM_MX, SUM_MY, (lWait ? "" : 1000), (lWait ? "" : 1))
Local bReady = false, sMsg
Local aSel = List(), aCol = List(), aVal = List(), aRow = List()
aSel.Count = 0
aCol.Count = 0
aVal.Count = 0
aRow.Count = 0
SendCommand(2090, 0, 1) # cm_CopyHdrFileDetailsToClip
#Sleep(100)
#txt = ClipGet()
Local hCB, pMem, obg, CF_UNICODETEXT = 13
If DllCall("OpenClipboard", "handle", 0) Then
hCB = DllCall("GetClipboardData", "uint", CF_UNICODETEXT, "handle")
pMem = DllCall("GlobalLock", "handle", hCB, "ptr")
obj = Buffer(1024*500, pMem)
txt = obj.GetStr()
Free(obj)
DllCall("GlobalUnlock ", "handle", hCB)
DllCall("CloseClipboard")
Else
sMsg = "Clipboard Error"
EndIf
If StrLen(txt) > 0 Then
bReady = true
aSel.Text = txt
EndIf
If StrPos(aSel[0], auTAB) = 0 Then
bReady = false
sMsg = "Clipboard Data Incorrect"
Endif
#FileWrite(TEMP & "\temp.tmp", txt)
#MsgBox("hCB: " & hCB & auCRLF & "Len: " & StrLen(txt) & auCRLF & "txt")
#Return
If Not bReady Then
If lWait Then
ShowHint(sMsg, SUM_MX, SUM_MY)
Else
ShowHint(sMsg, SUM_MX, SUM_MY, 1000, 1)
Endif
Free(aSel, aCol, aRow, aVal)
Return
Endif
aCol.Split(aSel[0], auTAB)
aVal.Count = aCol.Count
For j = 0 To aVal.Count - 1
aVal[j] = ""
Next
txt = ""
For j = 1 To aSel.Count - 1
aRow.Split(aSel[j], auTAB)
For i = 0 To aRow.Count - 1
If StrPos(aRow[i], Chr(160)) Then
aRow[i] = StrReplace(aRow[i], Chr(160), "")
EndIf
If IsNumber(aRow[i]) Then aVal[i] += aRow[i]
Next
Next
For j = 0 To aCol.Count - 1
txt &= aCol[j] & ": " & aVal[j] & auCRLF
Next
Local TL = Round(GetUptime() - T1, 0) / 1000
txt &= "---" & auCRLF & _
"Selected: " & aSel.Count - 1 & auCRLF & _
"Powered by Autorun.wdx" & auCRLF & _
"Время операции: " & StrFormat("%.3f", TL) & " sec"
Free(aSel, aCol, aRow, aVal)
If lWait Then
ShowHint(StrTrim(txt), SUM_MX, SUM_MY)
Else
ShowHint(StrTrim(txt), SUM_MX, SUM_MY, 1000, 1)
Endif
EndFunc |
Функция еще сырая и абсолютно тестовая, но, кажется, делает то, что от неё требуется. Запуск с CTRL удобен на небольших списках, когда выделенных позиций меньше 100 или где-то около 100, тогда данные обновляются в подсказке в реальном времени. Но чем больше выделено, тем больше тормозов, поэтому на больших списках лучше пользоваться одиночным кликом, так надежнее. Но надо будет с этим что-то придумать.
Добавлено спустя 6 минут:
Ну, что-то у меня совсем не заладилось )
Quote: | по-хорошему этот размер надо получать c помощью GlobalSize. |
Не знаю, успею ли глянуть. А можно пример? Вопрос тот же: ак вообще правильно сделать, ведь объем текстовых данных в буфере может быть ещё больше?
Кстати, были кое-какие проблемы с объектом List. Пока не инициализировал принудительно:
Code: | aSel.Count = 0
aCol.Count = 0
aVal.Count = 0
aRow.Count = 0
|
Были какие-то глюки и непонятные результаты. |
|