enumなんとかをfor..inで、その2
できた…眠いので解説しません。ソース貼って終わり。
type TWindowEnumerator = class(TObject) caller_ebx, caller_esi, caller_edi, caller_ebp, caller_eip: Pointer; enum_ebx, enum_esi, enum_edi, enum_esp, enum_eip: Pointer; save_esp, save_eip: Pointer; base_esp: Pointer; FState: (Enumerating, Terminated, Ended); FNext, FCurrent: HWND; procedure BeforeDestruction; override; function MoveNext: Boolean; function GetCurrent: HWND; property Current: HWND read GetCurrent; end; function Each(Wnd: HWND; Self: TWindowEnumerator): Boolean cdecl; asm mov edx, Wnd mov eax, Self push ebp mov TWindowEnumerator[eax].FNext, edx mov TWindowEnumerator[eax].enum_ebx, ebx mov TWindowEnumerator[eax].enum_esi, esi mov TWindowEnumerator[eax].enum_edi, edi mov TWindowEnumerator[eax].enum_esp, esp mov TWindowEnumerator[eax].enum_eip, offset @Next mov ebx, TWindowEnumerator[eax].caller_ebx mov esi, TWindowEnumerator[eax].caller_esi mov edi, TWindowEnumerator[eax].caller_edi mov edx, TWindowEnumerator[eax].caller_eip mov ebp, TWindowEnumerator[eax].caller_ebp jmp edx @Next: pop ebp mov eax, Self mov al, TWindowEnumerator[eax].FState end; function TWindowEnumerator.MoveNext: Boolean; asm {FCurrent := FNext} mov edx, TWindowEnumerator[eax].FNext mov TWindowEnumerator[eax].FCurrent, edx {終了判定} mov dl, TWindowEnumerator[eax].FState test dl, dl jnz @Terminated {コンテキスト保存} pop ecx mov TWindowEnumerator[eax].save_esp, esp mov TWindowEnumerator[eax].save_eip, ecx {スイッチ} mov TWindowEnumerator[eax].caller_ebx, ebx mov TWindowEnumerator[eax].caller_esi, esi mov TWindowEnumerator[eax].caller_edi, edi mov TWindowEnumerator[eax].caller_ebp, ebp mov TWindowEnumerator[eax].caller_eip, offset @Next mov ebx, TWindowEnumerator[eax].enum_ebx mov esi, TWindowEnumerator[eax].enum_esi mov edi, TWindowEnumerator[eax].enum_edi mov esp, TWindowEnumerator[eax].enum_esp mov edx, TWindowEnumerator[eax].enum_eip jmp edx @Next: {コンテキスト復帰} mov esp, TWindowEnumerator[eax].save_esp mov ecx, TWindowEnumerator[eax].save_eip push ecx mov al, 1 ret @Terminated: cmp dl, Terminated jne @End mov TWindowEnumerator[eax].FState, Ended mov al, 1 ret @End: mov al, 0 end; function TWindowEnumerator.GetCurrent: HWND; begin Result := FCurrent end; procedure TWindowEnumerator.BeforeDestruction; asm mov dl, TWindowEnumerator[eax].FState test dl, dl jnz @Exit {終了フラグ} mov TWindowEnumerator[eax].FState, Terminated {コンテキスト保存} pop ecx mov TWindowEnumerator[eax].save_eip, ecx mov TWindowEnumerator[eax].save_esp, esp {スイッチ} mov TWindowEnumerator[eax].caller_ebx, ebx mov TWindowEnumerator[eax].caller_esi, esi mov TWindowEnumerator[eax].caller_edi, edi mov TWindowEnumerator[eax].caller_ebp, ebp mov TWindowEnumerator[eax].caller_eip, offset @Next mov ebx, TWindowEnumerator[eax].enum_ebx mov esi, TWindowEnumerator[eax].enum_esi mov edi, TWindowEnumerator[eax].enum_edi mov esp, TWindowEnumerator[eax].enum_esp mov edx, TWindowEnumerator[eax].enum_eip jmp edx @Next: {コンテキスト復帰} mov esp, TWindowEnumerator[eax].save_esp mov ecx, TWindowEnumerator[eax].save_eip push ecx {スタック巻き戻し} mov eax, TWindowEnumerator[eax].base_esp lea edx, [eax - 24] {BeforeDestruction, @BeforeDestruction(pop*2), Destroy, Finally} mov eax, esp mov ecx, 24 push edx call System.Move pop esp @Exit: end; type TEnumWindows = record function GetEnumerator: TWindowEnumerator; end; function TEnumWindows.GetEnumerator: TWindowEnumerator; const VMT: TClass = TWindowEnumerator; asm {コンストラクタ呼び出し} mov dl, 1 mov eax, [VMT] call TWindowEnumerator.Create {フィールド代入} lea edx, [esp + 4] mov TWindowEnumerator[eax].base_esp, edx mov TWindowEnumerator[eax].caller_ebx, ebx mov TWindowEnumerator[eax].caller_esi, esi mov TWindowEnumerator[eax].caller_edi, edi mov TWindowEnumerator[eax].caller_ebp, ebp mov edx, [esp] mov TWindowEnumerator[eax].caller_eip, edx {Self保存} push ebx mov ebx, eax {呼び出し} mov edx, eax mov eax, offset Each call EnumerateWindows {Self復帰} mov eax, ebx pop ebx {デストラクタから来たならデストラクタへ戻る} mov dl, TWindowEnumerator[eax].FState test dl, dl jz @Exit mov edx, TWindowEnumerator[eax].caller_eip mov ebp, TWindowEnumerator[eax].caller_ebp jmp edx @Exit: {終了フラグ} mov TWindowEnumerator[eax].FState, Terminated end;