;=================================================================== ; 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