Что нового

Некорректная работа элемента на пользовательском обработчике

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Доброго времени суток!
Заранее приношу свои извинения за столь ужасный вид примера, набросал его вырывая куски из проекта.

Попробуйте потянуть за ползунок в Edit ( или управляющие скроллом стрелки ), желательно несколько раз.
Происходит следующее:
1) Тянем ползунок, функция _Wnd_Proc повисает пока не отпустим клавишу ( работает стандартный обработчик CallWindowProc ).
2) Отпускаем ползунок, обработчик освобождает выполнение и мой завершается.
3) И тут начинается самое веселое: В тот момент, когда мы тянули ползунок - сообщения о перерисовке окна должен был принимать CallBack, однако AutoIt их не вызывает до тех пор, пока не завершит работу CallWindowProc.
4) После завершения работы CallWindowProc он оставляет ( предыдущие вызовы ) у себя в памяти, а самое странное -
не выполняет их.
5) При получении нового вызова - он выполняет не его, а первый в порядке приоритета из повисших!

Схема ( как видно - происходит сдвиг в вызове, зачем их AutoIt вообще коллекционирует? ):
Код:
1>>Кнопка мыши зажата на ползунке ( ПРИНЯТО ).
2>>Ползунок сдвинут, перерисовать окно ( НЕ ПРИНЯТО ).
3>>Ползунок сдвинут, перерисовать окно ( НЕ ПРИНЯТО ).
4>> Кнопку мыши отпустили ( ПРИНЯТО "2" )
5>>Сообщение любому другому элементу ( ПРИНЯТО "3" )

Может у кого есть идеи как можно совместить все обработчики и заставить их корректно отрабатывать?
*Для контрола и окна отдельные Callback функции не решают проблему.
*GUICreate ( внутренний обработчик AutoIt ) решает проблему, но к сожалению ее использование не допускается.

Код:
#include <GuiEdit.au3>
#include <WinAPIEx.au3>
#include <APIConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>

Global $fExit, $WndHandle, $hCtrl_DbgEdit, $sText, _
	$iWndW = 220, $iWndX = ( @DesktopWidth / 2 ) - ( $iWndW / 2 ), _
	$iWndH = 260, $iWndY = ( @DesktopHeight/ 2 ) - ( $iWndH / 2 )

For $Idx = 1 To 999 Step 1
	$sText &= "Line" & $Idx & @CRLF
Next

$User32Dll = DllOpen( 'user32.dll' )
$hModule = _WinAPI_GetModuleHandle( 0 )
$hFont = _WinAPI_GetStockObject( 17 )
$hBrush = _WinAPI_CreateSolidBrush( 0xeeeeee )
$hCursor = _WinAPI_LoadCursor( 0, 32512 )
$hWndProc = DllCallbackRegister( '_Wnd_Proc', 'lresult', 'hwnd;uint;wparam;lparam' )
; *
$sClass = "ExampleClass"
$sName = "ExampleName"
; ---
$tClass = DllStructCreate( 'wchar[' & StringLen( $sClass ) + 1 & ']' )
	DllStructSetData( $tClass, 1, $sClass )

$tWndClassEx = DllStructCreate( $tagWNDCLASSEX )
	DllStructSetData( $tWndClassEx, 'Size', DllStructGetSize( $tWndClassEx ) )
	DllStructSetData( $tWndClassEx, 'Style', 0 )
	DllStructSetData( $tWndClassEx, 'hWndProc', DllCallbackGetPtr( $hWndProc ) )
	DllStructSetData( $tWndClassEx, 'ClsExtra', 0 )
	DllStructSetData( $tWndClassEx, 'WndExtra', 0 )
	DllStructSetData( $tWndClassEx, 'hInstance', $hModule )
	DllStructSetData( $tWndClassEx, 'hIcon', 0 )
	DllStructSetData( $tWndClassEx, 'hCursor', $hCursor )
	DllStructSetData( $tWndClassEx, 'hBackground', $hBrush )
	DllStructSetData( $tWndClassEx, 'MenuName', 0 )
	DllStructSetData( $tWndClassEx, 'ClassName', DllStructGetPtr( $tClass ) )
	DllStructSetData( $tWndClassEx, 'hIconSm', 0 )
; *
DllCall( $User32Dll, 'dword', 'RegisterClassExW', 'ptr', DllStructGetPtr( $tWndClassEx ) )
$WndHandle = DllCall( $User32Dll, 'hwnd', 'CreateWindowExW', 'dword', 0x00050181, 'wstr', $sClass, 'str', $sName, 'dword', 0x94CB00CC, _
	'int', $iWndX, 'int', $iWndY, 'int', $iWndW, 'int', $iWndH, 'hwnd', 0, 'hwnd', 0, 'hwnd', $hModule, 'ptr', 0 )
$WndHandle = $WndHandle[0]

$hCtrl_DbgEdit = _WinAPI_CreateWindowEx( 0x00000200, "Edit", "", 0x50210844, 5, 5, 205, 225, $WndHandle, 10000 )
$hCtrl_DefProc = _WinAPI_SetWindowLong( $hCtrl_DbgEdit, $GWL_WNDPROC, DllCallbackGetPtr( $hWndProc ) )
_WndEdit_AppendText( $hCtrl_DbgEdit, $sText )

While Not $fExit And Sleep( 10 )
	WEnd
; < Cleanup
_WinAPI_DestroyWindow( $hCtrl_DbgEdit )
_Wnd_Proc( $WndHandle, $WM_CLOSE, 1, 1 )
_WinAPI_DestroyCursor( $hCursor )
DllCall( $User32Dll, 'dword', 'UnregisterClassW', 'wstr', $sClass, 'ptr', $hModule )
DllCallbackFree( $hWndProc )

Func _Wnd_Proc($hWnd, $iMsg, $wParam, $lParam)
	Switch $hWnd
		Case $WndHandle
			Switch $iMsg
				Case $WM_CLOSE
					If Not $wParam Or Not $lParam Then
						$fExit = True
						Return
					Else
						$wParam = 0
						$lParam = 0
					EndIf
			EndSwitch
		Case $hCtrl_DbgEdit
			Return _WinAPI_CallWindowProc( $hCtrl_DefProc, $hWnd, $iMsg, $wParam, $lParam )
	EndSwitch
	Return _WinAPI_DefWindowProc($hWnd, $iMsg, $wParam, $lParam)
EndFunc

Func _WndEdit_AppendText( $hWnd, $sText )
	Local $iLength = _SendMessage( $hWnd, 0x000E ) ;WM_GETTEXTLENGTH
	; ---
	_SendMessage( $hWnd, $EM_SETSEL, $iLength, $iLength )
	_SendMessage( $hWnd, $EM_REPLACESEL, True, $sText & @CRLF, 0, "wparam", "wstr" )
EndFunc   ;==>_GUICtrlEdit_AppendText


P.S. Есть идея:
1)Ставить хук $WH_CALLWNDPROC
2)Фильтровать на нужные сообщения
3)Если сообщения подходят - ставить контролу свой обработчик
4)CallNextHook
5)Ловить это сообщение в обработчике
5-1)Вернуть стандартный обработчик
5-2)Сделать необходимые действия.

Но сами понимаете - такие дебри я буду использовать в последнюю очередь, надеюсь на вашу помощь.
 
Верх