Downloadez l'exemple ici.
CreateEvent
proto lpEventAttributes:DWORD,\
bManualReset:DWORD,\
bInitialState:DWORD,\
lpName:DWORD
lpEventAttribute-->
Si vous donnez la valeur NULL, l' 'event object' est créé d'une façon par défaut.
bManualReset-->
Si vous souhaitez que Windows désactive automatiquement l'event object (off) après l'appel WaitForSingleObject, vous devez taper 'FALSE' pour ce paramètre. Sinon vous devez le désactiver manuellement avec l'appel ResetEvent.
bInitialState-->
Au moment où il est créé, si vous souhaitez que l'event object soit dans l'état signalé, mettez TRUE pour ce paramètre, sinon l' event object sera créé avec l'état nonsignalé.
lpName
--> C'est le pointer qui repère une chaîne de caractère (ASCIIZ=du texte), laquelle est le nom de l'event object. Ce nom sera employé quand vous voudrez appeler OpenEvent.(pointe sur le nom de l'Event Object)
Si l'appel s'est déroulé avec succès, il renvoie l'handle de l' event object qui vient d'être créé, autrement il renvoie le NULL.
Vous pouvez modifier l'état de l'event object avec deux des appels API : SetEvent et ResetEvent. La fonction SetEvent met l'event object à l'état signalé. ResetEvent fait le contraire.
Après que l'event object soit créé, il vous faut insérez l'appel 'WaitForSingleObject' dans le lien qui dépend de l'état de l'event object. WaitForSingleObject a la syntaxe suivante :
WaitForSingleObject proto hObject:DWORD, dwTimeout:DWORD
hObject
--> L'handle d'un des l'objets de synchronisation. L' event object est un type d'objet de synchronisation.
dwTimeout
--> C'est à vous de fixer (en millisecondes) le temps maximal que cette fonction peut mettre pour que l'objet passe à l'état signalé. Si le temps indiqué est passé et que l'event object est toujours à l'état nonsignalé, alors WaitForSingleObject rend la main à l'interlocuteur. Si vous voulez attendre indéfiniment, vous devez mettre la valeur 'INFINITE' pour ce paramètre.(c'est aussi -1 en décimal ou FFFFFFFF en hexadécimal).
.386
.model
flat,stdcall
option
casemap:none
WinMain
proto :DWORD,:DWORD,:DWORD,:DWORD
include
\masm32\include\windows.inc
include
\masm32\include\user32.inc
include
\masm32\include\kernel32.inc
includelib
\masm32\lib\user32.lib
includelib
\masm32\lib\kernel32.lib
.const
IDM_START_THREAD
equ 1
IDM_STOP_THREAD
equ 2
IDM_EXIT
equ 3
WM_FINISH
equ WM_USER+100h
.data
ClassName
db "Win32ASMEventClass",0
AppName
db "Win32 ASM Event Example",0
MenuName
db "FirstMenu",0
SuccessString
db "The calculation is completed!",0
StopString
db "The thread is stopped",0
EventStop
BOOL FALSE
.data?
hInstance
HINSTANCE ?
CommandLine
LPSTR ?
hwnd
HANDLE ?
hMenu
HANDLE ?
ThreadID
DWORD ?
ExitCode
DWORD ?
hEventStart
HANDLE ?
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain
proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,OFFSET MenuName
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,\
ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,300,200,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
invoke GetMenu,hwnd
mov hMenu,eax
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain
endp
WndProc
proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_CREATE
invoke CreateEvent,NULL,FALSE,FALSE,NULL
mov hEventStart,eax
mov eax,OFFSET ThreadProc
invoke CreateThread,NULL,NULL,eax,\
NULL,0,\
ADDR ThreadID
invoke CloseHandle,eax
.ELSEIF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.if lParam==0
.if ax==IDM_START_THREAD
invoke SetEvent,hEventStart
invoke EnableMenuItem,hMenu,IDM_START_THREAD,MF_GRAYED
invoke EnableMenuItem,hMenu,IDM_STOP_THREAD,MF_ENABLED
.elseif ax==IDM_STOP_THREAD
mov EventStop,TRUE
invoke EnableMenuItem,hMenu,IDM_START_THREAD,MF_ENABLED
invoke EnableMenuItem,hMenu,IDM_STOP_THREAD,MF_GRAYED
.else
invoke DestroyWindow,hWnd
.endif
.endif
.ELSEIF uMsg==WM_FINISH
invoke MessageBox,NULL,ADDR SuccessString,ADDR AppName,MB_OK
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc
endp
ThreadProc
PROC USES ecx Param:DWORD
invoke WaitForSingleObject,hEventStart,INFINITE
mov ecx,600000000
.WHILE ecx!=0
.if EventStop!=TRUE
add eax,eax
dec ecx
.else
invoke MessageBox,hwnd,ADDR StopString,ADDR AppName,MB_OK
mov EventStop,FALSE
jmp ThreadProc
.endif
.ENDW
invoke PostMessage,hwnd,WM_FINISH,NULL,NULL
invoke EnableMenuItem,hMenu,IDM_START_THREAD,MF_ENABLED
invoke EnableMenuItem,hMenu,IDM_STOP_THREAD,MF_GRAYED
jmp ThreadProc
ret
ThreadProc
ENDP
end
start
.IF uMsg==WM_CREATE
invoke CreateEvent,NULL,FALSE,FALSE,NULL
mov hEventStart,eax
mov eax,OFFSET ThreadProc
invoke CreateThread,NULL,NULL,eax,\
NULL,0,\
ADDR ThreadID
invoke CloseHandle,eax
Vous pouvez voir que je crée l'event object ainsi que le lien, pendant le traitement du message WM_CREATE. Je crée l'event object à l'état nonsignalé et avec remis automatique. Après que l'event object soit créé, je crée le lien. Cependant le lien ne se met pas immédiatement au travail parce qu'il attend que l'event object soit mis à l'état 'signalé'. Ci-dessous voici comment le mettre à signalé:
ThreadProc
PROC USES ecx Param:DWORD
invoke WaitForSingleObject,hEventStart,INFINITE
mov ecx,600000000
La première ligne de la procédure de lien est l'appel WaitForSingleObject. Ici on attend infiniment que l'event object passe à l'état signalé avant qu'il ne retourne. Ça signifie que même après que le lien soit créé, nous le mettons dans un état d'inactivité.
Quand l'utilisateur choisit la commande du menu "run thread", nous mettons l'event object dans l'état signalé, comme indiqué ci-dessous :
.if ax==IDM_START_THREAD
invoke SetEvent,hEventStart
L'appel SetEvent met l'event object à l'état signalé, ce qui fait qu'à son tour l'appel WaitForSingleObject nous dirige vers la procédure du lien et le lien commence à travailler. Quand l'utilisateur choisit la commande "stop thread", nous mettons la valeur de la variable globale "EventStop" à TRUE.
.if EventStop==FALSE
add eax,eax
dec ecx
.else
invoke MessageBox,hwnd,ADDR StopString,ADDR AppName,MB_OK
mov EventStop,FALSE
jmp ThreadProc
.endif
Ceci stop le lien et saute de nouveau à l'appel WaitForSingleObject. Remarquez que nous n'avons pas besoin de remettre manuellement l'event object dans l'état nonsignalé puisque nous avons mis le paramètre bManualReset à FALSE (dans l'appel de CreateEvent).