This is a variation on an idea that Erol suggested some years ago, using macros as prototypes to get the arg count correct and not using "invoke" or similar to call an API but call it directly by its name. I don't personally care as I like the format of ML64 without prototypes but it is technically possible if the arg count is known when automating the production of the macros.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
OPTION DOTNAME ; required for macro files
option casemap:none ; case sensitive
includelib \masm32\lib64\kernel32.lib
includelib \masm32\lib64\user32.lib
PPROC TYPEDEF PTR PROC
externdef __imp_MessageBoxA:PPROC
externdef __imp_ExitProcess:PPROC
include \masm32\macros64\macros64.inc
MessageBox MACRO hndl:REQ, tmsg:REQ, dttl:REQ, dstyle:REQ
IFNDEF __UNICODE__
invoke __imp_MessageBoxA,hndl,tmsg,dttl,dstyle
ELSE
invoke __imp_MessageBoxW,hndl,tmsg,dttl,dstyle
ENDIF
ENDM
ExitProcess MACRO ecode:REQ
invoke __imp_ExitProcess,0
ENDM
rt MACRO args:VARARG
args
EXITM <rax>
ENDM
.data
tmsg db "Text Message",0
tttl db "Title",0
pmsg dq tmsg
pttl dq tttl
.code
function_format equ <0>
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
STACKFRAME
entry_point proc
IF function_format
; ---------------
; function format
; ---------------
LOCAL mbrv :QWORD
LOCAL eprv :QWORD
mov mbrv, rt(MessageBox 0,pmsg,pttl,0)
mov eprv, rt(ExitProcess 0)
ELSE
; ----------------
; statement format
; ----------------
MessageBox 0,pmsg,pttl,0
ExitProcess 0
ENDIF
ret
entry_point endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end