;-----------------------------------------
;   Banner.asm -- A Banner animation
;   based on "C" code from Herbert Schildt's 
;   "Advanced Windows 95 Programming"
; 
;   Translated into assembly 26/4/99 by
;   Ron Thomas Ron_Thom@Compuserve.com	
;-----------------------------------------

; Animated banner that makes use of idle cycles - this method is MUCH faster

.386				; 32 bit when .386 appears before .MODEL
.MODEL FLAT,STDCALL

include windows.inc

include user32.inc
include kernel32.inc
include gdi32.inc

includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib

WinMain		PROTO :DWORD, :DWORD, :DWORD, :SDWORD
run		PROTO STDCALL :DWORD

.data

ClassName db "SimpleWinClass",0
AppName   db "Animated Banner",0

animdim		RECT		<>	; Use for animation area
tm		TEXTMETRIC	<>	;

X		dd	0		; Current output location
Y		dd	0

maxX		dd	?		; Screen dimensions
maxY		dd	?

memdc		HDC	?		; Store virtual device handle
hbrush		HBRUSH	?
hbit		HBITMAP	?		; Store vitual bitmap handle
 
btext	BYTE	'Win32 programming using assembly is great',0
	
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
;---------------------------------------------------------------------------
.code
start:
	invoke GetModuleHandle, NULL
	mov    hInstance,eax
	invoke GetCommandLine
        invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
	invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:SDWORD

	LOCAL wc:WNDCLASSEX
	LOCAL msg:MSG
        LOCAL hwnd:HWND

	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  hInstance
        pop   wc.hInstance
	mov   wc.hbrBackground,COLOR_WINDOW+1
	mov   wc.lpszMenuName,NULL
	mov   wc.lpszClassName,OFFSET ClassName
        invoke LoadIcon,NULL,IDI_APPLICATION
	mov   wc.hIcon,eax
        mov   wc.hIconSm,0
        invoke LoadCursor,NULL,IDC_ARROW
	mov   wc.hCursor,eax 
        invoke RegisterClassEx, addr wc

        INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
           hInst,NULL
        mov   hwnd,eax
        INVOKE ShowWindow, hwnd,SW_SHOWNORMAL
        INVOKE UpdateWindow, hwnd
        .WHILE TRUE
                INVOKE GetMessage, ADDR msg,NULL,0,0
                .BREAK .IF (!eax)
                INVOKE TranslateMessage, ADDR msg
                INVOKE DispatchMessage, ADDR msg
	        invoke run, hwnd			;Cycle the animation
        .ENDW
        mov     eax,msg.wParam
        ret
WinMain endp

WndProc proc   hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

        LOCAL  hdc:HDC
        LOCAL  ps:PAINTSTRUCT
		  		
	mov    eax,uMsg

	.IF	eax==WM_CREATE

	  invoke  GetSystemMetrics, SM_CXSCREEN
	  mov	  maxX,eax
	  invoke  GetSystemMetrics, SM_CYSCREEN
	  mov	  maxY,eax

;	Create a compatible bitmap

	  invoke  GetDC, hWnd
	  mov	  hdc,eax
	  invoke  CreateCompatibleDC, hdc
	  mov	  memdc,eax
	  invoke  CreateCompatibleBitmap, hdc, maxX, maxY
	  mov	  hbit,eax
	  invoke  SelectObject, memdc, hbit
	  invoke  GetStockObject, WHITE_BRUSH
	  mov	  hbrush,eax
	  invoke  SelectObject, memdc, hbrush
	  invoke  PatBlt, memdc, 0, 0, maxX, maxY, PATCOPY

;	Get text metrics

	  invoke  GetTextMetrics, hdc, ADDR tm

	  mov	  eax,X
	  mov	  animdim.left,eax
	  add	  eax,maxX	
	  mov	  animdim.right,eax		; set to maxX + X
 
	  mov	  eax,Y
	  mov	  animdim.top,eax
	  add	  eax,tm.tmHeight
	  mov	  animdim.bottom,eax		; set to tm.tmHeight + Y

	  invoke  lstrlen, ADDR btext
	  invoke  TextOut, memdc, X, Y, ADDR btext, eax	; Output to memory

	  invoke  ReleaseDC, hWnd, hdc
	  invoke  InvalidateRect, hWnd, NULL, 1

        .ELSEIF eax==WM_PAINT

          invoke  BeginPaint, hWnd, ADDR ps	; Get DC

          mov	hdc,eax	 ; Get handle to device context before selecting GDI object into it

;	Copy virtual window onto screen

	  mov	eax,ps.rcPaint.right
	  sub	eax,ps.rcPaint.left
	  mov	ecx,ps.rcPaint.bottom
	  sub	ecx,ps.rcPaint.top
	
	  invoke  BitBlt, hdc,   ps.rcPaint.left, ps.rcPaint.top, eax, ecx, \ 
			  memdc, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY

          invoke  EndPaint, hWnd, ADDR ps

	.ELSEIF eax==WM_DESTROY

          invoke  DeleteDC, memdc
          invoke  PostQuitMessage,NULL

        .ELSE

            invoke  DefWindowProc, hWnd, uMsg, wParam, lParam
            ret

	.ENDIF
        xor    eax,eax
	ret

WndProc endp

run	Proc	hWnd:HWND

;	Move left edge to the right end

	mov	eax,maxX
	dec	eax			; maxX-1
	push	eax			; save copy

	invoke  BitBlt, memdc, eax, Y, 1, tm.tmHeight, memdc, 0, Y, SRCCOPY
	
;	Move remaining edge left

	pop	eax
	invoke	BitBlt, memdc, 0, Y, eax, tm.tmHeight, memdc, 1, Y, SRCCOPY

	invoke	InvalidateRect, hWnd, ADDR animdim,0

	ret
run	ENDP

        end start

