;===================================================================
; ESF DEMO - Eliminating Screen Flicker
;===================================================================
;===================================================================
; ABOUT THIS DEMO PROGRAM
;===================================================================
;
; This demo program is part of a tutorial on eliminating the
; screen flicker that is typically found in an application.
;
; The tutorial contains first, an HTML document describing the
; methods we will use to eliminate the flicker, and detailing
; step-by-step how to achive this. Second, is the demo program
; that allows you to compare the two methods. Finally, this
; document -- the source code -- is included. Although I have
; many snippets of code in the HTML document, I wanted you
; to be able to see for yourself the entire picture. You
; may use whatever code you would like in your own programs,
; or, if you prefer, just use this as a guide for your own
; applications. The source code is in HTML format so it can be
; viewed anywhere on anything that has a browser. Just copy
; and paste what you need.
;
; With that stated a few notes about the source code for this
; application are in order...
;
; 1 -- I have used the same routine to paint the
; screen for both the flicker and non-flicker
; versions. I pass in a TRUE/FALSE value that
; says use, or don't use, a backbuffer.
;
; 2 -- My coding convention for the WM_PAINT procedure
; is a little different than most peoples. First,
; I do not bother with only updating the invalid
; portions, I update the entire screen. Second, I
; choose to paint my own controls if I have enough
; stuff to draw that warrants using a backbuffer.
; Finally, I like to do everything in it's own
; routine instead of in the normal WM_PAINT
; message.
;
; 3 -- This code is heavily commented, as are all of
; my applications. So, you should not have any
; trouble with this code. But, if you do, please
; feel free to contact me:
; Http://www.fastsoftware.com
; chobbs@fastsoftware.com
;
; 4 -- Finally, I use a back buffer to do the normal
; screen updates for this application. The only
; time the flickering update is used is when the
; user clicks the "Update w/ Flicker" button.
;
;===================================================================
;===================================================================
;###########################################################################
;###########################################################################
; THE COMPILER OPTIONS
;###########################################################################
;###########################################################################
.386
.MODEL flat, stdcall
OPTION CASEMAP :none ; case sensitive
;###########################################################################
;###########################################################################
; THE INCLUDES SECTION
;###########################################################################
;###########################################################################
INCLUDE \masm32\include\windows.inc
INCLUDE \masm32\include\comctl32.inc
INCLUDE \masm32\include\comdlg32.inc
INCLUDE \masm32\include\shell32.inc
INCLUDE \masm32\include\user32.inc
INCLUDE \masm32\include\kernel32.inc
INCLUDE \masm32\include\gdi32.inc
INCLUDELIB \masm32\lib\comctl32.lib
INCLUDELIB \masm32\lib\comdlg32.lib
INCLUDELIB \masm32\lib\shell32.lib
INCLUDELIB \masm32\lib\gdi32.lib
INCLUDELIB \masm32\lib\user32.lib
INCLUDELIB \masm32\lib\kernel32.lib
;###########################################################################
;###########################################################################
; LOCAL MACROS
;###########################################################################
;###########################################################################
;========================================
; This macro creates a local string
;========================================
szText MACRO Name, Text:VARARG
LOCAL lbl
JMP lbl
Name DB Text,0
lbl:
ENDM
;========================================
; This macro swaps the values of two
; variables by using the stack
;========================================
m2m MACRO M1, M2
PUSH M2
POP M1
ENDM
;========================================
; Places the return value into eax
; and then returns from the procedure
;========================================
return MACRO arg
MOV EAX, arg
RET
ENDM
;========================================
; This macro creates an RGB triplet from
; the threee specified colors
;========================================
RGB MACRO red, green, blue
XOR EAX,EAX
MOV AH,blue
SHL EAX,8
MOV AH,green
MOV AL,red
ENDM
;#################################################################################
;#################################################################################
; THE PROTOTYPES
;#################################################################################
;#################################################################################
;==================================
; Main Program Procedures
;==================================
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
;====================================
; The Update Manager
;====================================
ManageUpdate PROTO :BYTE
;====================================
; Drawing Procedures
;====================================
PaintScreen PROTO :BYTE
DrawWindow PROTO :DWORD
;====================================
; MISC Procedures
;====================================
AboutProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
MiscCenterWnd PROTO :DWORD,:DWORD
PushButton PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
;#################################################################################
;#################################################################################
; BEGIN INITIALIZED DATA
;#################################################################################
;#################################################################################
.DATA
;==============================
;Text for the Window Title
;==============================
szDisplayName DB "Eliminating Screen Flicker by Lightning Software",0
;==============================
;Windows handles and Misc
;==============================
msg MSG <?> ; For message handling
CommandLine DD 0 ; for the commandline params
hMainWnd DD 0 ; Handle to the main window
hInst DD 0 ; Handle to an Instance
;========================================================
; This is the buffer for wvsprintfA it can hold up to
; 40 characters inlcuding the NULL
;========================================================
szBuffer DB 40 dup (0)
;========================================================
; This is used to pass arguments to wvsprintfA it can
; hold up to 4 different args
;========================================================
dwArgs DD 4 dup (0)
;===============================================
; Current Screen Update Number
;===============================================
CurUpdate DD 0
;===========================================
; These are the rects fro the placement
; of text and colors on the window
;===========================================
Rect_DEMO RECT <1,1,419,94> ; Left, top, right, bottom
Rect_HOWTO RECT <1,142,419,208> ; Left, top, right, bottom
Rect_CURNUM RECT <1,207,419,249> ; Left, top, right, bottom
Rect_RED1 RECT <184,93,235,144> ; Left, top, right, bottom
Rect_RED2 RECT <184,248,235,299> ; Left, top, right, bottom
;===========================================
; These are the rects fro the placement
; of the buttons in the window
;===========================================
Rect_NOFLICK RECT <12,102,172,135> ; Left, top, right, bottom
Rect_FLICK RECT <248,102,408,135> ; Left, top, right, bottom
Rect_ABOUT RECT <12,256,172,289> ; Left, top, right, bottom
Rect_EXIT RECT <248,256,408,289> ; Left, top, right, bottom
;===============================
; Strings for the application
;===============================
szClassName DB "ESF_Class",0
szNoHomePage DB "Unable to open www.fastsoftware.com!",0
szHomepage DB "Http://www.fastsoftware.com/",0
szCurNumber DB "Current Update Number: %d",0
szDemo DB "A simple demo showing screen updates with ",
"flicker and screen updates without the flicker!",0
szHowTo DB "Click on one of the two update buttons above to see ",
"the screen updated 500 times. One performs this update ",
"with normal methods, the other uses the flicker-less method.",0
;===============================
; Captions for the buttons
;===============================
NOFLICK_Cap DB "Update w/o Flicker",0
FLICK_Cap DB "Update w/ Flicker",0
ABOUT_Cap DB "About this Demo",0
EXIT_Cap DB "Exit this Demo",0
;=====================================================
;Initialize the Font structure for generic app then
; change what is necessary before calls
;=====================================================
Font LOGFONT <11,0,0,0,FW_NORMAL,\
0,0,0,ANSI_CHARSET,OUT_STRING_PRECIS,\
CLIP_STROKE_PRECIS,DEFAULT_QUALITY,\
DEFAULT_PITCH OR FF_DONTCARE,"MS Sans Serif">
; Height Values for the font
; 11 = size 8
; 13 = size 10
; -16 = size 12
; -19 = size 14
; 24 = size 18
; -32 = size 24
;#################################################################################
;#################################################################################
; BEGIN EQUATES
;#################################################################################
;#################################################################################
;=================
;Utility Equates
;=================
FALSE EQU 0
TRUE EQU 1
;================
; Button ID's
;================
ID_FLICKER EQU 850 ; Updatye with flicker
ID_NOFLICKER EQU 875 ; Update without flicker
ID_ABOUT EQU 885 ; The about app button
ID_EXIT EQU 895 ; The exit button
;================
; resource IDs
;================
IDI_ICON EQU 01h
IDD_ABOUT EQU 04h
;#################################################################################
;#################################################################################
; BEGIN THE CODE SECTION
;#################################################################################
;#################################################################################
.CODE
start:
;==================================
; Obtain the instance for the
; application
;==================================
INVOKE GetModuleHandle, NULL
MOV hInst, EAX
;==================================
; Is there a commandline to parse?
;==================================
INVOKE GetCommandLine
MOV CommandLine, EAX
;==================================
; Call the WinMain procedure
;==================================
INVOKE WinMain,hInst,NULL,CommandLine,SW_SHOWDEFAULT
;==================================
; Leave the program
;==================================
INVOKE ExitProcess,EAX
;########################################################################
; WinMain Function
;########################################################################
WinMain PROC hInstance :DWORD,
hPrevInst :DWORD,
CmdLine :DWORD,
CmdShow :DWORD
;====================
; Put LOCALs on stack
;====================
LOCAL wc :WNDCLASS
LOCAL Wwd :DWORD
LOCAL Wht :DWORD
LOCAL hFont :DWORD
;==================================================
; Fill WNDCLASS structure with required variables
;==================================================
MOV wc.style,CS_HREDRAW OR CS_VREDRAW \
OR CS_BYTEALIGNWINDOW
MOV wc.lpfnWndProc,OFFSET WndProc
MOV wc.cbClsExtra,NULL
MOV wc.cbWndExtra,NULL
m2m wc.hInstance,hInst ;<< NOTE: macro not mnemonic
MOV wc.hbrBackground,COLOR_WINDOW
MOV wc.lpszMenuName,NULL
MOV wc.lpszClassName,OFFSET szClassName
INVOKE LoadIcon, hInst, IDI_ICON ; icon ID
MOV wc.hIcon,EAX
INVOKE LoadCursor,NULL,IDC_ARROW
MOV wc.hCursor,EAX
;================================
; Register our class we created
;================================
INVOKE RegisterClass, ADDR wc
;================================
; Create window at following size
;================================
MOV Wwd, 429
MOV Wht, 327
;===========================================
; Create the main screen
;===========================================
INVOKE CreateWindowEx,NULL,
ADDR szClassName,
ADDR szDisplayName,
WS_OVERLAPPEDWINDOW XOR WS_MAXIMIZEBOX,
0,0,Wwd,Wht,
NULL,NULL,
hInst,NULL
;===========================================
; Put the window handle in for future uses
;===========================================
MOV hMainWnd, EAX
;==========================================
; Create the font we want for the buttons
;==========================================
MOV Font.lfWeight, FW_BOLD
MOV Font.lfHeight, -16
INVOKE CreateFontIndirect, OFFSET Font
MOV hFont, EAX
;=================================
; Create our 4 buttons
;=================================
INVOKE PushButton,ADDR NOFLICK_Cap,hMainWnd,12,102,160,33,ID_NOFLICKER
INVOKE SendMessage,EAX,WM_SETFONT,hFont,0
INVOKE PushButton,ADDR FLICK_Cap,hMainWnd,248,102,160,33,ID_FLICKER
INVOKE SendMessage,EAX,WM_SETFONT,hFont,0
INVOKE PushButton,ADDR ABOUT_Cap,hMainWnd,12,256,160,33,ID_ABOUT
INVOKE SendMessage,EAX,WM_SETFONT,hFont,0
INVOKE PushButton,ADDR EXIT_Cap,hMainWnd,248,256,160,33,ID_EXIT
INVOKE SendMessage,EAX,WM_SETFONT,hFont,0
;========================================
; Set the current Update number to zero
;========================================
MOV CurUpdate, 0
;================================
; Center the window
;================================
INVOKE GetDesktopWindow
INVOKE MiscCenterWnd, hMainWnd, EAX
;================================
; Show the window
;================================
INVOKE ShowWindow,hMainWnd,SW_SHOWNORMAL
;===================================
; Loop until PostQuitMessage is sent
;===================================
.WHILE TRUE
INVOKE GetMessage, ADDR msg, NULL, 0, 0
.BREAK .IF (!eax)
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
.ENDW
;===========================
; Delete the font object
;===========================
INVOKE DeleteObject, hFont
;===========================
; We are through
;===========================
return msg.wParam
WinMain endp
;########################################################################
; End of WinMain Procedure
;########################################################################
;########################################################################
; Main Window Callback Procedure -- WndProc
;########################################################################
WndProc PROC hWin :DWORD,
uMsg :DWORD,
wParam :DWORD,
lParam :DWORD
;========================================
; LOCAL VARIABLES
;=========================================
LOCAL Pt :POINT
LOCAL PS :PAINTSTRUCT
LOCAL LastX :DWORD
LOCAL LastY :DWORD
.IF uMsg == WM_COMMAND
;========== COMMAND BUTTONS =========================================================
.IF wParam == ID_FLICKER
;====================================
; Code to update the display with the
; normal method of drawing right on
; the main window
;====================================
INVOKE ManageUpdate, FALSE
.ELSEIF wParam == ID_NOFLICKER
;====================================
; Code to update the window with the
; backbuffer method to elimiante the
; flicker on the screen
;====================================
INVOKE ManageUpdate, TRUE
.ELSEIF wParam == ID_ABOUT
;====================================
; Code to display the about dialog
;====================================
INVOKE DialogBoxParam, hInst, IDD_ABOUT, hMainWnd, ADDR AboutProc, NULL
.ELSEIF wParam == ID_EXIT
;====================================
; Code to quit this demo
;====================================
INVOKE SendMessage,hWin,WM_SYSCOMMAND,SC_CLOSE,NULL
.ENDIF
;======================== Command Buttons =============================
.ELSEIF uMsg == WM_ERASEBKGND
;===========================
; Say we handled it
;===========================
return 1
.ELSEIF uMsg == WM_ACTIVATE
;===========================
; Call to Paint the screen
;===========================
INVOKE PaintScreen, TRUE
.ELSEIF uMsg == WM_PAINT
;=====================================
; Let windows know we took care of it
;=====================================
INVOKE BeginPaint, hMainWnd, ADDR PS
INVOKE EndPaint, hMainWnd, ADDR PS
INVOKE PaintScreen, TRUE
;====================================
; Return just to make sure
;====================================
return 1
.ELSEIF uMsg == WM_DESTROY
;===========================
; Kill the application
;===========================
INVOKE PostQuitMessage,NULL
return 0
.ENDIF
;=================================================
; Let the default procedure handle the message
;=================================================
INVOKE DefWindowProc,hWin,uMsg,wParam,lParam
RET
WndProc endp
;########################################################################
; End of Main Windows Callback Procedure
;########################################################################
;########################################################################
; ManageUpdate Function
;########################################################################
ManageUpdate PROC UseBackBuffer:BYTE
;============================================
; This will update our display 500 times
; with either the flicker or the no-flicker
; method of updating
;============================================
;================================
; Make sure the count is at zero
;================================
MOV CurUpdate, 0
;========================================
; Loop through 500 times and call the
; PaintScreen procedure each time through
;========================================
.WHILE CurUpdate < 500
;======================
; Increment the count
;======================
INC CurUpdate
;=============================
; Make the proper call based
; on whether or not they want
; to use the backbuffer
;=============================
.IF UseBackBuffer == TRUE
;=================================
; Yes use the flicker free method
;=================================
INVOKE PaintScreen, TRUE
.ELSE
;=================================
; NO use the flickering method
;=================================
INVOKE PaintScreen, FALSE
.ENDIF
.ENDW
done:
;==================
; Return good
;==================
return TRUE
err:
;==================
; Return an error
;==================
return FALSE
ManageUpdate endp
;########################################################################
; END of ManageUpdate
;########################################################################
;########################################################################
; PaintScreen Function
;########################################################################
PaintScreen PROC UseBackBuffer:BYTE
;============================================
; Code to update the display. It is called
; whenever the screen needs painting it takes
; as its only parameter whether or not to
; draw with a backbuffer. This code calls the
; DrawWindow Proc to do the actaul drawing.
;============================================
;============================
; LOCAL VARIABLES
;============================
LOCAL hDC :DWORD
LOCAL hMemDC :DWORD
LOCAL ScreenRect :RECT
LOCAL hBitmap :DWORD
;=================================
; Get the client rectangle
;=================================
INVOKE GetClientRect, hMainWnd, ADDR ScreenRect
;============================
; get the DC
;============================
INVOKE GetDC, hMainWnd
MOV hDC, EAX
;=========================================
; Did they want to use a backbuffer
;=========================================
.IF UseBackBuffer == TRUE
;=========================================
; Yes they want to update without flicker
;=========================================
;============================
; Create a compatible DC
;============================
INVOKE CreateCompatibleDC, hDC
MOV hMemDC, EAX
;==============================
; Now create a Bitmap for that
; offscreen DC
;==============================
MOV EAX, ScreenRect.right
SUB EAX, ScreenRect.left
MOV EBX, ScreenRect.bottom
SUB EBX, ScreenRect.top
INVOKE CreateCompatibleBitmap, hDC, EAX, EBX
MOV hBitmap, EAX
;=============================
; Select that bitmap into the
; object, preserve old
;=============================
INVOKE SelectObject, hMemDC, hBitmap
PUSH EAX
;=============================
; Erase the Background
;=============================
INVOKE GetSysColor, COLOR_WINDOW
INVOKE CreateSolidBrush, EAX
PUSH EAX
INVOKE FillRect, hMemDC, ADDR ScreenRect, EAX
POP EAX
INVOKE DeleteObject,EAX
;====================================
; Draw the stuff onto the backbuffer
;====================================
INVOKE DrawWindow, hMemDC
;===========================
; Copy buffer to actual
;===========================
MOV EAX, ScreenRect.right
SUB EAX, ScreenRect.left
MOV EBX, ScreenRect.bottom
SUB EBX, ScreenRect.top
INVOKE BitBlt,hDC, ScreenRect.left, ScreenRect.top, EAX, EBX,\
hMemDC, 0, 0, SRCCOPY
;============================
; Select old int hMemDC
;============================
POP EAX
INVOKE SelectObject, hMemDC, EAX
;============================
; Delete the Compatible DC
;============================
INVOKE DeleteDC, hMemDC
;===============================
; Delete the Compatible Bitmap
;===============================
INVOKE DeleteObject, hBitmap
.ELSE
;=============================
; No so just update with the
; normal method of drawing on
; the main window DC
;=============================
;=============================
; Erase the Background
;=============================
INVOKE GetSysColor, COLOR_WINDOW
INVOKE CreateSolidBrush, EAX
PUSH EAX
INVOKE FillRect, hDC, ADDR ScreenRect, EAX
POP EAX
INVOKE DeleteObject,EAX
;====================================
; Draw the stuff onto the backbuffer
;====================================
INVOKE DrawWindow, hDC
.ENDIF
;================================
; release the device context
;================================
INVOKE ReleaseDC, hMainWnd, hDC
done:
;==================
; Return good
;==================
return TRUE
err:
;==================
; Return an error
;==================
return FALSE
PaintScreen endp
;########################################################################
; END of PaintScreen
;########################################################################
;########################################################################
; DrawWindow Function
;########################################################################
DrawWindow PROC DC:DWORD
;============================================
; This code performs all of the actal drawing
; for the window
;============================================
;===============================
; Local Variables
;===============================
LOCAL hPen :DWORD
LOCAL hBrush :DWORD
LOCAL hFont :DWORD
;===============================================
; START OUT BY DRAWING THE OUTLINES
;===============================================
;========================================
; Create our new pen of the color black
;========================================
INVOKE CreatePen, PS_SOLID, 3, 0
MOV hPen, EAX
;========================================
; Select our new pen and save the old one
; on the stack for later
;========================================
INVOKE SelectObject, DC, hPen
PUSH EAX
;======================================
; Draw the outlining frame for form
; and the dividers for the palette
;======================================
INVOKE MoveToEx, DC, 1, 1, NULL
INVOKE LineTo, DC, 418, 1
INVOKE LineTo, DC, 418, 298
INVOKE LineTo, DC, 1, 298
INVOKE LineTo, DC, 1, 1
;===============================================
; Now draw the seperating boxes
;===============================================
;==================================
; Make the call to create a
; red brush for the two red boxes
;==================================
RGB 255,0,0
INVOKE CreateSolidBrush, EAX
PUSH EAX
;===============================
; Select the brush into our DC
; and preserve the old object
;===============================
INVOKE SelectObject, DC, EAX
PUSH EAX
;======================================
; Make a call to draw the rectangle
; outlined in the pen color and filled
; in with the brush color
;======================================
INVOKE Rectangle, DC, Rect_RED1.left, Rect_RED1.top,\
Rect_RED1.right, Rect_RED1.bottom
INVOKE Rectangle, DC, Rect_RED2.left, Rect_RED2.top,\
Rect_RED2.right, Rect_RED2.bottom
;===============================
; Select the old object back in
;===============================
POP EAX
INVOKE SelectObject, DC, EAX
;===============================
; Delete our brush we created
;===============================
POP EAX
INVOKE DeleteObject, EAX
;==================================
; Make the call to create a
; green brush for the demo box
;==================================
RGB 0,192,0
INVOKE CreateSolidBrush, EAX
PUSH EAX
;===============================
; Select the brush into our DC
; and preserve the old object
;===============================
INVOKE SelectObject, DC, EAX
PUSH EAX
;======================================
; Make a call to draw the rectangle
; outlined in the pen color and filled
; in with the brush color
;======================================
INVOKE Rectangle, DC, Rect_DEMO.left, Rect_DEMO.top,\
Rect_DEMO.right, Rect_DEMO.bottom
;===============================
; Select the old object back in
;===============================
POP EAX
INVOKE SelectObject, DC, EAX
;===============================
; Delete our brush we created
;===============================
POP EAX
INVOKE DeleteObject, EAX
;==================================
; Make the call to create a blue
; highlight brush for the demo box
;==================================
INVOKE GetSysColor, COLOR_HIGHLIGHT
INVOKE CreateSolidBrush, EAX
PUSH EAX
;===============================
; Select the brush into our DC
; and preserve the old object
;===============================
INVOKE SelectObject, DC, EAX
PUSH EAX
;======================================
; Make a call to draw the rectangle
; outlined in the pen color and filled
; in with the brush color
;======================================
INVOKE Rectangle, DC, Rect_HOWTO.left, Rect_HOWTO.top,\
Rect_HOWTO.right, Rect_HOWTO.bottom
;===============================
; Select the old object back in
;===============================
POP EAX
INVOKE SelectObject, DC, EAX
;===============================
; Delete our brush we created
;===============================
POP EAX
INVOKE DeleteObject, EAX
;==================================
; Make the call to create a blue
; highlight brush for the demo box
;==================================
RGB 255,255,0
INVOKE CreateSolidBrush, EAX
PUSH EAX
;===============================
; Select the brush into our DC
; and preserve the old object
;===============================
INVOKE SelectObject, DC, EAX
PUSH EAX
;======================================
; Make a call to draw the rectangle
; outlined in the pen color and filled
; in with the brush color
;======================================
INVOKE Rectangle, DC, Rect_CURNUM.left, Rect_CURNUM.top,\
Rect_CURNUM.right, Rect_CURNUM.bottom
;===============================
; Select the old object back in
;===============================
POP EAX
INVOKE SelectObject, DC, EAX
;===============================
; Delete our brush we created
;===============================
POP EAX
INVOKE DeleteObject, EAX
;====================================
; Select the old object back in
;====================================
POP EAX
INVOKE SelectObject, DC, EAX
;==================================
; Delete our Pen we created
;==================================
INVOKE DeleteObject, hPen
;===============================================
; Now draw the buttons onto the DC
;===============================================
INVOKE DrawFrameControl, DC, ADDR Rect_FLICK, DFC_BUTTON, DFCS_BUTTONPUSH
INVOKE DrawFrameControl, DC, ADDR Rect_NOFLICK, DFC_BUTTON, DFCS_BUTTONPUSH
INVOKE DrawFrameControl, DC, ADDR Rect_ABOUT, DFC_BUTTON, DFCS_BUTTONPUSH
INVOKE DrawFrameControl, DC, ADDR Rect_EXIT, DFC_BUTTON, DFCS_BUTTONPUSH
;===============================================
; Now text into the boxes we created
;===============================================
;============================
; Set text and bkgnd mode
;============================
INVOKE SetTextColor, DC, 00000000h
INVOKE SetBkMode, DC, TRANSPARENT
;=================================================
; Create and Select the Font preserve old on stack
;=================================================
MOV Font.lfWeight, FW_BOLD
MOV Font.lfHeight, -24
INVOKE CreateFontIndirect, OFFSET Font
MOV hFont, EAX
INVOKE SelectObject, DC, hFont
PUSH EAX
;===================================
; Paint the Demo Text
;===================================
INVOKE DrawText, DC, ADDR szDemo, (SIZEOF szDemo)-1, ADDR Rect_DEMO, \
DT_CENTER OR DT_WORDBREAK
;===============================
; Set the text color
;===============================
RGB 0,0,192
INVOKE SetTextColor, DC, EAX
;===================================
; Print out the Cur Update Number
;===================================
MOV EAX, CurUpdate
MOV dwArgs, EAX
INVOKE wvsprintfA, ADDR szBuffer, ADDR szCurNumber, OFFSET dwArgs
INVOKE DrawText, DC, ADDR szBuffer, EAX, ADDR Rect_CURNUM,\
DT_CENTER OR DT_VCENTER OR DT_SINGLELINE
;===============================
; Restore old object
;===============================
POP EAX
INVOKE SelectObject, DC, EAX
;===============================
; Delete the FONT object
;===============================
INVOKE DeleteObject, hFont
;===============================
; Set text color
;===============================
INVOKE SetTextColor, DC, 0
;=================================================
; Create and Select the Font preserve old on stack
;=================================================
MOV Font.lfHeight, -16
INVOKE CreateFontIndirect, OFFSET Font
MOV hFont, EAX
INVOKE SelectObject, DC, hFont
PUSH EAX
;===================================
; Paint the Text for the buttons
;===================================
INVOKE DrawText, DC, ADDR FLICK_Cap, (SIZEOF FLICK_Cap)-1, ADDR Rect_FLICK, \
DT_CENTER OR DT_SINGLELINE OR DT_VCENTER
INVOKE DrawText, DC, ADDR NOFLICK_Cap, (SIZEOF NOFLICK_Cap)-1, ADDR Rect_NOFLICK, \
DT_CENTER OR DT_SINGLELINE OR DT_VCENTER
INVOKE DrawText, DC, ADDR ABOUT_Cap, (SIZEOF ABOUT_Cap)-1, ADDR Rect_ABOUT, \
DT_CENTER OR DT_SINGLELINE OR DT_VCENTER
INVOKE DrawText, DC, ADDR EXIT_Cap, (SIZEOF EXIT_Cap)-1, ADDR Rect_EXIT, \
DT_CENTER OR DT_SINGLELINE OR DT_VCENTER
;===============================
; Restore old object
;===============================
POP EAX
INVOKE SelectObject, DC, EAX
;===============================
; Delete the FONT object
;===============================
INVOKE DeleteObject, hFont
;============================
; Set the text color
;============================
RGB 255,255,255
INVOKE SetTextColor, DC, EAX
;=================================================
; Create and Select the Font preserve old on stack
;=================================================
MOV Font.lfWeight, FW_NORMAL
MOV Font.lfHeight, -16
INVOKE CreateFontIndirect, OFFSET Font
MOV hFont, EAX
INVOKE SelectObject, DC, hFont
PUSH EAX
;===================================
; Paint the Demo Text
;===================================
INVOKE DrawText, DC, ADDR szHowTo, (SIZEOF szHowTo)-1, ADDR Rect_HOWTO, \
DT_CENTER OR DT_WORDBREAK
;===============================
; Restore old object
;===============================
POP EAX
INVOKE SelectObject, DC, EAX
;===============================
; Delete the FONT object
;===============================
INVOKE DeleteObject, hFont
done:
;==================
; Return good
;==================
return TRUE
err:
;==================
; Return an error
;==================
return FALSE
DrawWindow endp
;########################################################################
; END of DrawWindow
;########################################################################
;########################################################################
; Handle the About Dialog Box
;########################################################################
AboutProc PROC hDlg :DWORD,
uMsg :DWORD,
wParam :DWORD,
lParam :DWORD
;=================================
; The equate for the homepage code
;=================================
IDHOME EQU 0
;=========================
; Get the message into eax
;=========================
MOV EAX, uMsg
.IF (EAX == WM_INITDIALOG)
;=============================
; Center the Dialog Box
;=============================
INVOKE MiscCenterWnd, hDlg, hMainWnd
.ELSEIF (EAX == WM_COMMAND) && (wParam == IDHOME)
;===================================
; Execute our homepage
;===================================
INVOKE ShellExecute,0,0,ADDR szHomepage,0,0,0
.IF EAX <= 32
;======================
; Tell them we can't
; open the homepage
;======================
INVOKE MessageBox, hMainWnd, OFFSET szNoHomePage, NULL, MB_OK
.ENDIF
.ELSEIF (EAX == WM_COMMAND) && (wParam == IDOK)
;========================================
; They are done so End the Dialog Proc
;========================================
INVOKE EndDialog, hDlg, TRUE
.ELSE
;==================================
; Show that we didn't process
;==================================
MOV EAX, FALSE
JMP Return
.ENDIF
;==================================
; Show that we did process
;==================================
MOV EAX, TRUE
;==================================
; Return from this message
;==================================
Return: RET
AboutProc endp
;########################################################################
; END AboutProc
;########################################################################
;########################################################################
; Misc Center Window from SIB by Steve Gibson. Thanks Steve!
;########################################################################
MiscCenterWnd PROC hChild:DWORD,
hParent:DWORD
; Define the local variables
LOCAL rcP:RECT, rcC:RECT, xNew:DWORD, yNew:DWORD
INVOKE GetWindowRect, hParent, ADDR rcP
.IF (eax)
INVOKE GetWindowRect, hChild, ADDR rcC
.IF (eax)
MOV EAX, rcP.right ;center horizontally
SUB EAX, rcP.left ;x=Px+(Pdx-Cdx)/2
SUB EAX, rcC.right
ADD EAX, rcC.left
SAR EAX, 1
ADD EAX, rcP.left
; check if off screen at left
.IF (sign?)
MOV EAX, 0
.ENDIF
MOV xNew, EAX
INVOKE GetSystemMetrics, SM_CXFULLSCREEN
SUB EAX, rcC.right
ADD EAX, rcC.left
; check if off screen at right
.IF (EAX < xNew)
MOV xNew, EAX
.ENDIF
MOV EAX, rcP.bottom ; center vertically
SUB EAX, rcP.top ; y=Py+(Pdy-Cdy)/2
SUB EAX, rcC.bottom
ADD EAX, rcC.top
SAR EAX, 1
ADD EAX, rcP.top
; check if off screen at top
.IF (sign?)
MOV EAX, 0
.ENDIF
MOV yNew,EAX
INVOKE GetSystemMetrics, SM_CYFULLSCREEN
SUB EAX, rcC.bottom
ADD EAX, rcC.top
.IF (EAX < yNew)
MOV yNew, EAX
.ENDIF
INVOKE SetWindowPos, hChild, NULL, xNew, yNew, 0, 0,\
SWP_NOSIZE + SWP_NOZORDER
.ENDIF
.ENDIF
Return: RET
MiscCenterWnd ENDP
;########################################################################
; END MISC CENTER WINDOW
;########################################################################
;########################################################################
; PUSHBUTTON PROCEDURE
;########################################################################
PushButton PROC lpText:DWORD,hParent:DWORD,
a:DWORD,b:DWORD,wd:DWORD,ht:DWORD,ID:DWORD
; PushButton PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
; invoke PushButton,ADDR szCaption,hWnd,20,20,100,25,500
szText btnClass, "BUTTON"
INVOKE CreateWindowEx,0,
ADDR btnClass,lpText,
WS_CHILD OR WS_VISIBLE,
a,b,wd,ht,hParent,ID,
hInst,NULL
RET
PushButton endp
;########################################################################
; END of PUSHBUTTON PROCEDURE
;########################################################################
;######################################
; THIS IS THE END OF THE PROGRAM CODE #
;######################################
END start