Показать сообщение отдельно
Старый 16.01.2013, 06:08   #25
Platon
Знающий
 
Регистрация: 04.08.2006
Адрес: Россия
Сообщений: 297
Написано 39 полезных сообщений
(для 70 пользователей)
Ответ: Закрытие окна (крестик)

да можно обойтись только средствами winapi, хохо :D
Const PAGE_EXECUTE_READWRITE% = 64

Const GWL_WNDPROC% = -4
Const GWL_USERDATA% = -21

;
; хендл окна и адрес его функции обработки сообщений
;
Global BlitzWindowID% = SystemProperty( "AppHWND" )
Global BlitzWindowProc% = GetWindowLong( BlitzWindowID, GWL_WNDPROC )

; 
; создаем банк, хранящий адрес родной функции окна и флаг
; который будет сигнализировать о получении сообщения закрытия окна WM_CLOSE
;
Global CloseHandlerData% = CreateBank( 5 )
PokeInt( CloseHandlerData, 0, BlitzWindowProc )
PokeByte( CloseHandlerData, 4, False )

;
; устанавливаем окну этот банк как пользовательские данные
; для передачи их в новую оконную функцию
;
SetWindowLong2( BlitzWindowID, GWL_USERDATA, CloseHandlerData )

;
; получаем адреса функций, необходимых для работы оконной функции
;
Local User32Module% = GetModuleHandle( "USER32.DLL" )
Local GetWindowLongAddress% = GetProcAddress( User32Module, "GetWindowLongA" )
Local CallWindowProcAddress% = GetProcAddress( User32Module, "CallWindowProcA" )

;
; создаем банк, хранящий машинный код новой функции обработки сообщений
; эта функция обрабатывает сообщение WM_CLOSE, а остальные отдает родной функции
;
; выглядит следующим образом:
;
; Function CloseHandlerProc%( WindowID%, MessageID%, WParam%, LParam% )
;     Local CloseHandlerData% = GetWindowLongA( WindowID, GWL_USERDATA )
;     If MessageID <> WM_CLOSE Then
;         Return CallWindowProcA( PeekInt( CloseHandlerData, 0 ), WindowID, MessageID, WParam, LParam )
;     End If
;     PokeByte( CloseHandlerData, 4, True )
;     Return 0
; End Function
;
Global CloseHandlerProc% = CreateBank( 92 )
PokeInt( CloseHandlerProc, 0, $0424448B )
PokeInt( CloseHandlerProc, 4, $8908EC83 )
PokeInt( CloseHandlerProc, 8, $44C72404 )
PokeInt( CloseHandlerProc, 12, $FFEB0424 )
PokeInt( CloseHandlerProc, 16, ( ( GetWindowLongAddress And $FF ) Shl 24 ) Or $B8FFFF )
PokeInt( CloseHandlerProc, 20, $FF000000 Or ( ( GetWindowLongAddress Shr 8 ) And $FFFFFF ) )
PokeInt( CloseHandlerProc, 24, $247C83D0 )
PokeInt( CloseHandlerProc, 28, $32741008 )
PokeInt( CloseHandlerProc, 32, $EC83008B )
PokeInt( CloseHandlerProc, 36, $24048914 )
PokeInt( CloseHandlerProc, 40, $1824448B )
PokeInt( CloseHandlerProc, 44, $04244489 )
PokeInt( CloseHandlerProc, 48, $1C24448B )
PokeInt( CloseHandlerProc, 52, $08244489 )
PokeInt( CloseHandlerProc, 56, $2024448B )
PokeInt( CloseHandlerProc, 60, $0C244489 )
PokeInt( CloseHandlerProc, 64, $2424448B )
PokeInt( CloseHandlerProc, 68, $10244489 )
PokeInt( CloseHandlerProc, 72, ( ( CallWindowProcAddress And $FFFFFF ) Shl 8 ) Or $B8 )
PokeInt( CloseHandlerProc, 76, $C2D0FF00 Or ( CallWindowProcAddress Shr 24 ) )
PokeInt( CloseHandlerProc, 80, $40C60010 )
PokeInt( CloseHandlerProc, 84, $C0310104 )
PokeInt( CloseHandlerProc, 88, $900010C2 )
;
; т.к. банк содержит исполняемый код, нужно изменить аттрибут доступа этого блока памяти на исполняемый
;
Local OldProtect% = CreateBank( 4 )
VirtualProtect2( CloseHandlerProc, 92, PAGE_EXECUTE_READWRITE, OldProtect )
FreeBank( OldProtect )
;
; устанавливаем новую функцию обработки сообщения
;
SetWindowLong2( BlitzWindowID, GWL_WNDPROC, CloseHandlerProc )




Graphics( 800, 600, 0, 2 )

Repeat
	
	Cls()
	
	;
	; значение True или 1 означает что была попытка закрыть окно
	;
	If PeekByte( CloseHandlerData, 4 ) = True Then Text( 400, 300, "window close detected", True, True )
	
	Flip()
	
Until KeyDown( 1 )




;
; устанавливаем блицевскому окну обратно его родную функцию для корректного завершения
;
SetWindowLong( BlitzWindowID, GWL_WNDPROC, BlitzWindowProc )

End
в функцию думаю сами оформите если потребуется
а, и соответствующий winapi.decls еще
.lib "KERNEL32.DLL"

GetModuleHandle%( Name$ ) : "GetModuleHandleA"
GetProcAddress%( Module%, Name$ ) : "GetProcAddress"
VirtualProtect2%( MemoryBank*, Size%, NewProtect%, OldProtectBank* ) : "VirtualProtect"

.lib "USER32.DLL"

GetWindowLong%( Window%, Index% ) : "GetWindowLongA"
SetWindowLong%( Window%, Index%, Value% ) : "SetWindowLongA"
SetWindowLong2%( Window%, Index%, Bank* ) : "SetWindowLongA"
(Offline)
 
Ответить с цитированием