Listing Viewer is a sample program for Windows which uses Graphic User Interface (GUI).
It displays the listing file produced by EuroAssembler and enhances its divisions (dump, source, messages) with different background colours.
The viewed file name may be provided by several methods:
lstview mysource.htm.lst
when the program is launched from console,mysource.htm.lst
.Listing viewer can be assembled in ANSI and WIDE version by changing the boolean option
EUROASM Unicode=
specified in header
. No other intervention is necessary and both version work the same way.
This should demonstrate EuroAssembler's ability to select ANSI|WIDE
variant of string macros, string definitions and WinAPI invocations depending on UNICODE= option.
Nevertheless, the viewed listing file is always assumed in UTF-8 encoding only.
..\objlib\winapi.libyet,
prowin32subdirectory with command
euroasm dll2lib.htm
. euroasm lstview.htm
lstview.exe "Source.htm.lst"
or associate the program with
*.lstfiles and doubleclick on the listing file in Explorer.
The header defines program format, imported and linked libraries, dynamic memory management.
GUI programs use lot of dynamically linked functions from graphic librariescomctl32.dll,gdi32.dlland others. Instead of tediously IMPORTing each used function individually, it's more convenient to LINK those DLLs directly from the system where the program is being created, or use their import libraries. €ASM will pick up only those DLL function names, which were actually used in the program.
If you don't have the linked import librarywinapi.lib, you can create it with sample project DLL2LIB.
Memory variables are allocated statically in the segment [.bss]
and they are initialized to zero in bulk at the beginning.
Due to the potentially unlimited size of displayed files this program uses
dynamically allocated memory provided by macrolibrary
memory.htm
, too. This library requires system macros SysAlloc, SysFree,
which are defined here in the header.
EUROASM Unicode=off lstview PROGRAM Format=PE, Subsystem=GUI, Width=32, Entry=WinMain, IconFile="easm.ico" LINK winapi.lib INCLUDE winapi.htm, wins.htm, winsgui.htm, winscon.htm, \ winsdlg.htm, winsreg.htm, winssec.htm, winf32.htm, \ stdcal32.htm, cpuext32.htm, cpuext.htm, string32.htm, memory.htm ; Definition of three system macros required by library "memory.htm": SysAlloc %MACRO BlockSize PUSH ECX,EDX WinAPI VirtualAlloc, 0, EDX, MEM_COMMIT, PAGE_READWRITE TEST EAX POP EDX,ECX %ENDMACRO SysAlloc ; Returns ZF on error, otherwise EAX=pointer to allocatd block. SysFree %MACRO BlockAddress PUSH ECX,EDX WinAPI VirtualFree, %BlockAddress, 0, MEM_RELEASE POP EDX,ECX %ENDMACRO SysFree SysGetAllocationGranularity %MACRO MOV EAX,64K %ENDMACRO SysGetAllocationGranularity ; Debugging macro for simplified error report. AbortIf %MACRO cc,SourceLine %IF "%cc" == "FALSE" TEST EAX JNZ Abort%.: %ELSE J%!cc,Abort%.: %ENDIF MOV EBX,%SourceLine ; Error occured at "lstview.htm"{%^SourceLine}. JMP Abort@RT: ; Go to report error and terminate program. [.text] Abort@RT:PROC1 SUB ESP,40 MOV EDI,ESP MOV ESI,AbortText MOV ECX,34 REP MOVSB WinAPI GetLastError LEA EDI,[ESP+6] StoH EDI,Size=8 MOV EAX,EBX LEA EDI,[ESP+23] StoD EDI,Size=8 XOR EAX,EAX STOSB MOV ESI,ESP WinAPI MessageBoxA,0,ESI,=B"%^SourceName%^SourceExt",MB_OK|MB_ICONERROR TerminateProgram Errorlevel=8 [.data] AbortText D B "Error XXXXXXXXh at line DDDDDDDD" ; 0....5...10...15...20...24....30 ENDPROC1 Abort@RT: Abort%.: %ENDMACRO AbortIf
This is the main program entry procedure.
Command line argument specifies a listing file to view.
Listing is expected in UTF-8 encoding.
When no valid file was provided,
the viewer will show HelpText instead,
which is also expected in UTF-8 | plain ASCII.
User can also use standard OpenFile dialog [Ctrl~O] or drag the file icon to the viewer window.
[.data] HelpTitle DB "LstView keys:",0 HelpText DB " ",10,10, \ Top padding lines. " LstView - EuroAssembler listing viewer ",10,10, \ "Help - this overview [Ctrl~H] or [F1]",10, \ "Open a listing file [Ctrl~O] or [F3]",10, \ "Associate *.lst with this viewer [F4]",10, \ "Modify optimal window size [Ctrl~M] or [F5]",10, \ "Restore default font size [Ctrl~0] or [F6]",10, \ "Decrease font size [Ctrl~-] or [F7]",10, \ "Increase font size [Ctrl~+] or [F8]",10, \ "Skip to the previous message [Shift~Tab] [F11]",10, \ "Skip to the next message [Tab] [F12]",10, \ "Move in row | columns steps [arrows]",10, \ "Move in page steps [PgUp|PgDn|Home|End]",10, \ "Accelerate the movement [Ctrl]",10, \ "Quit the viewer [Ctrl~Q] or [Esc]",10, \ 10, 0 ; Bottom padding lines. NotFoundText DB "Error reading the specified file.",0 [.bss] Msg D MSG ; Window message. LstFileName D MAX_PATH_SIZE * UNICHAR ; Name of the selected listing file. [.text] WinMain Procedure hInstance, hPrevInstance, szCmdLine, iCmdShow Clear SEGMENT# [.bss], Size=SIZE# [.bss] ; Make sure to start with zeroed memory. CALL WndCreate ; Initialize the program window. GetArg 1 ; Return the filename argument in ESI,ECX, if provided. StripQuotes ESI,ECX; Remove double quotes from filename. AND ECX,0x000001FF ; Limit filename size to 255 characters. MOV EDI,LstFileName REP MOVSB CALL LstCreate ; Load and index the listing file specified on command line. CALL WndModify ; Shrink|expand window to the optimal size. WinAPI RedrawWindow,[hWindow],0,0,RDW_FRAME | RDW_INTERNALPAINT | RDW_INVALIDATE .MsgLoop: WinAPI GetMessage, Msg,0,0,0 TEST EAX JZ .MsgQuit: ; Message WM_QUIT - terminate program. WinAPI TranslateMessage, Msg ; Remap character keys from national keyboards. WinAPI DispatchMessage, Msg ; Let Windows call our WndProc. JMP .MsgLoop: ; Wait for another message. .MsgQuit: CALL LstDestroy ; Release allocated dynamic memory. TerminateProgram Errorlevel=[Msg.wParam] EndProcedure WinMain
SB_VERT_THUMBTRACK EQU SB_THUMBTRACK SB_HORZ_THUMBTRACK EQU SB_THUMBTRACK CtrlStep EQU 5 ; Cursor keys move the screen by 1, or by CtrlStep characters when Ctrl is pressed. FontSizeMin EQU 10 ; Acceptable character-box height in pixels. FontSizeMax EQU 48 FontSizeDef EQU 16 ; Standard font height to begin with. WheelPerLine EQU 40 ; wParamHigh = 120 or -120 to scroll 3 rows up or down. [.bss] WheelCnt D D ; Accumulated WheelPerLine value when mouse wheel is rolled. PseudoCapture D D ; Nonzero while the left mouse button is down. OldPos D D ; lParam with mouse client coordinates on left button pressed. xClientCnt D D ; Accumulated x-difference in pixels on mouse drag. yClientCnt D D ; Accumulated y-difference in pixels on mouse drag. cxChar D D ; Glyph box dimensions of one unproportional character in pixels. cyChar D D FontSize D D ; Height of character glyph box in pixels. hFont D D ; Handle of the used font. [.text] WndProc Procedure hWnd, uMsg, wParam, lParam MOV EBX,[%hWnd] MOV EAX,[%uMsg] MOV ESI,[%wParam] MOV EDI,[%lParam] ; Load msg attributes for handler's convenience. ; Fork message uMsg=EAX to its handler using macro Dispatch: Dispatch EAX, WM_VSCROLL, WM_HSCROLL, \ Scroll events. WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_LBUTTONDOWN, WM_LBUTTONUP, \ Mouse events. WM_KEYDOWN, WM_CHAR, \ Keyboard events. WM_PAINT, WM_DROPFILES, WM_SIZE, WM_CREATE, WM_DESTROY ; Other events. .Def:WinAPI DefWindowProc,[%hWnd],[%uMsg],[%wParam],[%lParam] ; Ignored events. JMP .Ret: ; EndProcedure WndProc with value EAX returned from DefWindowProc. ; Message handlers terminate with a jump to .Def: or .Ret0:. .WM_CREATE: ; Window is being created by WndCreate. WinAPI DragAcceptFiles,EBX,1 JMP .Ret0: .WM_SIZE: ; User changed window dimensions. CALL WndSize JMP .Ret0: .WM_PAINT: ; Window needs repaint. CALL WndPaint JMP .Ret0: .WM_DESTROY: ; Program terminates. WinAPI DragAcceptFiles,EBX,0 ; Stop accepting dragged files. WinAPI DeleteObject,[hFont] ; Free the allocated font memory. WinAPI PostQuitMessage,0 ; Tell Windows to quit with errorlevel 0. JMP .Ret0: .WM_DROPFILES: ; User dropped a file icon to our window. WinAPI DragQueryFile,ESI,0,LstFileName,MAX_PATH_SIZE ; Retrieve new LstFileName. CALL LstDestroy ; Deallocate previous file. CALL LstCreate JMP .Ret0: ; Mouse event handlers. .WM_MOUSEWHEEL: ; Rolled. SAR ESI,16 ; ESI is now +120 or -120 on mouse-wheel roll. ADD [WheelCnt],ESI ; Accumulate scroll requests. MOV EDI,[WheelCnt] .RollUp: CMP EDI,WheelPerLine JL .RollDown: SUB EDI,WheelPerLine MOV [WheelCnt],EDI WinAPI SendMessage,EBX,WM_VSCROLL,SB_LINEUP,0 JMP .RollUp: .RollDown: CMP EDI,0 JGE .Ret0: ADD EDI,WheelPerLine MOV [WheelCnt],EDI WinAPI SendMessage,EBX,WM_VSCROLL,SB_LINEDOWN,0 JMP .RollDown: .WM_LBUTTONDOWN: ; Left mouse button pressed. Window contents will be dragged. MOV [PseudoCapture],1 MOV [OldPos],EDI ; Mouse capture begins. CALL WndTitleLoc ; Calculate and show character-coordinates on title bar. JMP .Ret0: .WM_MOUSEMOVE: CMP [PseudoCapture],0 JE .Ret0: TEST ESI,MK_LBUTTON JNZ .Drag: ; If mouse button is still pressed, continue drag. .WM_LBUTTONUP: ; Window contents was dragged from [OldPos] to the position in lParam=EDI. MOV [PseudoCapture],0 ; End of mouse capture. CALL WndTitle ; Stop displaying character-coordinates in window title strip. .Drag: MOV EAX,0x0000_FFFF ; Accumulate the difference between [OldPos] and current position EDI. MOV ECX,EAX AND EAX,EDI AND ECX,[OldPos] SUB EAX,ECX ADD [xClientCnt],EAX MOV EAX,EDI MOV ECX,[OldPos] SHR EAX,16 SHR ECX,16 SUB EAX,ECX ADD [yClientCnt],EAX MOV [OldPos],EDI SUB ESI,ESI .DragDown: CMP [yClientCnt],ESI JGE .DragUp: MOV EAX,[cyChar] ADD [yClientCnt],EAX WinAPI SendMessage,EBX,WM_VSCROLL,SB_LINEDOWN,0 JMP .DragDown: .DragUp: CMP [yClientCnt],ESI JLE .DragRight: MOV EAX,[cyChar] SUB [yClientCnt],EAX WinAPI SendMessage,EBX,WM_VSCROLL,SB_LINEUP,0 JMP .DragUp: .DragRight: CMP [xClientCnt],ESI JGE .DragLeft: MOV EAX,[cxChar] ADD [xClientCnt],EAX WinAPI SendMessage,EBX,WM_HSCROLL,SB_LINERIGHT,0 JMP .DragRight: .DragLeft: CMP [xClientCnt],ESI JLE .Ret0: MOV EAX,[cxChar] SUB [xClientCnt],EAX WinAPI SendMessage,EBX,WM_HSCROLL,SB_LINELEFT,0 JMP .DragLeft: ; Helper subprocedures for keyboard and scrollbox event handlers. .GetCtrl2ECX PROC ; Returns ECX=1 when Ctrl is pressed, otherwise ECX=0. EAX,EDX undefined. WinAPI GetKeyState,VK_CONTROL XOR ECX,ECX SAL AX,1 RCL ECX,1 ; Virtual key handlers receive ECX=1 when Ctrl was pressed, otherwise ECX=0. RET ENDP .GetCtrl2ECX .GetShift2ECX PROC ; Returns ECX=1 when Shift is pressed, otherwise ECX=0. EAX,EDX undefined. WinAPI GetAsyncKeyState,VK_SHIFT XOR ECX,ECX SAL AX,1 RCL ECX,1 ; Virtual key handlers receive ECX=1 when Shift was pressed, otherwise ECX=0. RET ENDP .GetShift2ECX .ScrollVer: PROC ; Scroll vertically until TopRow=ESI. ; Saturate proposed signed TopRow=ESI to the acceptable range 0..MaxRowNr-NrRowsCl. TEST ESI JNS .v1: SUB ESI,ESI .v1:MOV EDX,[MaxRowNr] SUB EDX,[NrRowsCl] JAE .v3: SUB EDX,EDX .v3:CMP ESI,EDX JLE .v5: XCHG ESI,EDX .v5:MOV [TopRow],ESI WinAPI SetScrollPos,[hWindow],SB_VERT,ESI,1 WinAPI InvalidateRect,[hWindow],0,0 RET ENDP .ScrollVer: .ScrollHor: PROC ; Scroll horizontally until LeftCol=ESI. ; Saturate proposed signed LeftCol=ESI to the acceptable range 0..MaxLineLen-NrColsCl. TEST ESI JNS .h1: SUB ESI,ESI .h1:MOV EDX,[MaxLineLen] SUB EDX,[NrColsCl] JGE .h3: SUB EDX,EDX .h3:CMP ESI,EDX JLE .h5: XCHG ESI,EDX .h5:MOV [LeftCol],ESI WinAPI SetScrollPos,[hWindow],SB_HORZ,ESI,1 WinAPI InvalidateRect,[hWindow],0,0 RET ENDP .ScrollHor: ; Scrollbox event handlers. .WM_VSCROLL: ; User scrolled the window vertically. CALL .GetCtrl2ECX MOV EAX,0x0000_FFFF AND EAX,ESI ; EAX is now scroll box action. SHR ESI,16 ; ESI is now scroll box position. Dispatch EAX,SB_LINEUP,SB_LINEDOWN,SB_PAGEUP,SB_PAGEDOWN,SB_VERT_THUMBTRACK JMP .Def: .WM_HSCROLL: ; User scrolled the window horizontally. CALL .GetCtrl2ECX MOV EAX,0x0000_FFFF AND EAX,ESI ; EAX is now scroll box action. SHR ESI,16 ; ESI is now scroll box position. Dispatch EAX,SB_LINELEFT,SB_LINERIGHT,SB_PAGELEFT,SB_PAGERIGHT,SB_HORZ_THUMBTRACK JMP .Def: ; Keyboard event handlers. .WM_CHAR: ; Character key mapped by WinAPI TranslateMessage to wParam=ESI was pressed. ADD ESI,0x0000_0040 ; Convert Ctrl~X to 'X'. Dispatch ESI,'H','O','M','Q' ; Jump to labels .H:, .O:, .M:, .Q: (Help, OpenFile, ModifySize, Quit). JMP .Def: ; Pass other character keys. .WM_KEYDOWN: ; Non-character key ESI=wParam was pressed. Set ECX=0 if [Ctrl] is not pressed. CALL .GetCtrl2ECX ; Test if [Ctrl] was pressed. Dispatch ESI, VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT, \ VK_LEFT, VK_RIGHT, VK_HOME, VK_END,\ VK_ADD, VK_SUBTRACT, VK_NUMPAD0, \ VK_ESCAPE, VK_TAB, \ VK_F1, VK_F3, VK_F4, VK_F5, VK_F6, \ VK_F7, VK_F8, VK_F11, VK_F12 JMP .Def: ; Pass unhandled keys to WinAPI DefWindowProc. .SB_LINEDOWN: ; Vertical scrollbox line down. .VK_DOWN: ; Down arrow. MOV ESI,[TopRow] INC ESI JECXZ .SB_VERT_THUMBTRACK: ; If Ctrl not pressed. ADD ESI,CtrlStep .SB_VERT_THUMBTRACK: ; User dragged the tumbtrack to the position ESI. CALL .ScrollVer: JMP .Ret0: .SB_LINEUP: ; Vertical scrollbox line up. .VK_UP: ; Up arrow. MOV ESI,[TopRow] DEC ESI JECXZ .SB_VERT_THUMBTRACK: ; If Ctrl not pressed. SUB ESI,CtrlStep JMP .SB_VERT_THUMBTRACK: .SB_PAGEDOWN: ; Vertical scrollbox page down. .VK_NEXT: ; PageDown MOV ESI,[TopRow] DEC ESI,ESI ADD ESI,[NrRowsCl] JECXZ .SB_VERT_THUMBTRACK: ; If Ctrl not pressed. MOV ESI,[MaxRowNr] ; Set ESI to maximum on Ctrl-PgDown. JMP .SB_VERT_THUMBTRACK: .SB_PAGEUP: ; Vertical scrollbox page up. .VK_PRIOR: ; PageUp MOV ESI,[TopRow] INC ESI,ESI SUB ESI,[NrRowsCl] JECXZ .SB_VERT_THUMBTRACK: ; If Ctrl not pressed. SUB ESI,ESI ; Set ESI to minimum on Ctrl-PgUp. JMP .SB_VERT_THUMBTRACK: .SB_LINERIGHT: ; Horizontal scrollbox column right. .VK_RIGHT: ; Right arrow. MOV ESI,[LeftCol] INC ESI JECXZ .SB_HORZ_THUMBTRACK: ADD ESI,CtrlStep .SB_HORZ_THUMBTRACK: CALL .ScrollHor: JMP .Ret0: .SB_LINELEFT: ; Horzintal scrollbox column left. .VK_LEFT: ; Up arrow. MOV ESI,[LeftCol] DEC ESI JECXZ .SB_HORZ_THUMBTRACK: SUB ESI,CtrlStep JMP .SB_HORZ_THUMBTRACK: .SB_PAGERIGHT: ; Horizontal scrollbox page right. .VK_END: ; End MOV ESI,[LeftCol] DEC ESI,ESI ADD ESI,[NrColsCl] JECXZ .SB_HORZ_THUMBTRACK: MOV ESI,[MaxLineLen] ; Set ESI to maximum on Ctrl-End. JMP .SB_HORZ_THUMBTRACK: .SB_PAGELEFT: ; Horizontal scrollbox page left. .VK_HOME: ; Home MOV ESI,[LeftCol] INC ESI,ESI SUB ESI,[NrColsCl] JECXZ .SB_HORZ_THUMBTRACK: SUB ESI,ESI ; Set ESI to minimum on Ctrl-Home. JMP .SB_HORZ_THUMBTRACK: .Q: ; Ctrl-Q Quit the program. .VK_ESCAPE: ; Esc WinAPI SendMessage,EBX,WM_DESTROY,0,0 JMP .Ret0: .H: ; Ctrl-H Display ANSI HelpText. .VK_F1: ; F1 WinAPI MessageBoxA,EBX,HelpText,HelpTitle,MB_OK|MB_ICONINFORMATION JMP .Ret0: .VK_F4: ; F4 Register association. CALL Register JMP .Ret0: .O: ; Ctrl-O Open dialog for selection of another file. .VK_F3: ; F3 CALL LstSelect JZ .Ret0: ; If the OpenFile dialog was cancelled with Esc. .M: ; Ctrl-M Modify window size. .VK_F5: ; F5 CALL LstDestroy ; Deallocate previous file. CALL LstCreate ; Load and index the new listing file. JMP .Ret0: .VK_NUMPAD0: ; Ctrl-0 ; Restore default font size. .VK_F6: ; F6 MOV EDI,FontSizeDef .SetFontEDI: MOV [FontSize],EDI CALL WndFont WinAPI GetClientRect,EBX,ClientRect MOV EAX,[ClientRect.bottom] SUB EAX,[ClientRect.top] MOV EDI,[ClientRect.right] SUB EDI,[ClientRect.left] SHL EAX,16 OR EDI,EAX CALL WndSize ; Consequence of changed cxChar,cyChar will be recalculation of NrColsCl,NrRowsCl. WinAPI InvalidateRect,[hWindow],0,0 ; Redraw client area with the new font. JMP .Ret0: .VK_SUBTRACT: ; Ctrl - Decrease font size. .VK_F7: ; F7. MOV EDI,[FontSize] DEC EDI CMP EDI,FontSizeMin JL .Ret0: JMP .SetFontEDI: .VK_ADD: ; Ctrl + Increase font size .VK_F8: ; F6 MOV EDI,[FontSize] INC EDI CMP EDI,FontSizeMax JG .Ret0: JMP .SetFontEDI: .VK_F11: ; F11 Previous message. MOV ECX,1 JMP .SkipMsg: .VK_F12: ; F12 Next message. XOR ECX,ECX JMP .SkipMsg: .VK_TAB: CALL .GetShift2ECX .SkipMsg: ; Scroll window to the next or previous listing message. ; ECX= 0 or 1 to scroll down or up. MOV EAX,[NrRowsCl] MOV ESI,[TopRow] SHR EAX,1 ADD EAX,ESI ; EAX is now "cursor" line number (in vertical center of client). SHL EAX,4 ; Multiply by SIZE#INDEX=16. MOV EDI,[IndexBeg] ADD EDI,EAX ; EDI now points to the index of "cursor" line. MOV EAX,SIZE# INDEX SHL ECX,1 ; ECX is now 0 or 2. NOT ECX ; ECX is now -1 or -3. ADD ECX,2 ; ECX is now +1 or -1. IMUL ECX ; EAX is now +SIZE#INDEX or -SIZE#INDEX. .SkipLine: ADD EDI,EAX ; The next line (forward or backward). ADD ESI,ECX ; The next TopRow (INC or DEC). CMP EDI,[IndexBeg] JB .ColorInfo: ; Stop at the top of listing. CMP EDI,[IndexEnd] JNB .ColorInfo: ; Stop at the bottom of listing. MOV EDX,[EDI+INDEX.Color] ; The €ASM message is identified by its background color. Dispatch EDX,ColorErr,ColorWarn,ColorInfo JMP .SkipLine: ; Continue searching when the line is not a message. .ColorErr: .ColorWarn: .ColorInfo: ; Move up or down to the new "cursor" line indexed by ESI. CALL .ScrollVer: ; Scroll to the TopRow=ESI. ; JMP .Ret0: .Ret0:XOR EAX,EAX .Ret: MOV [%ReturnEAX],EAX EndProcedure WndProc
lstview.exeuses one and only graphical window. Procedure WndCreate creates the window class and window object.
[.data] WndClassName D "LSTVIEW",0 [.bss] WndClassEx DS WNDCLASSEX ; Definition of the window class structure. hWindow D D ; Handle of the window object. hPen D D ; Handle of the pen. PaintStruct DS PAINTSTRUCT VScrollInfo DS SCROLLINFO HScrollInfo DS SCROLLINFO cxScreen D D ; Width (cx*) and height (cy*) of screen objects. cyScreen D D ; Screen resolution. cxClient D D ; Inner area of the window. cyClient D D cxScroll D D ; Thicknes of the scrollbar. cyScroll D D cxBorder D D ; Thicknes of the window border. cyBorder D D cyCaption D D ; Height of window title bar. NrRowsCl EQU VScrollInfo.nPage ; How many characters are visible in the window row. MaxRowNr EQU VScrollInfo.nMax ; How many physical lines are in the listing file. NrColsCl EQU HScrollInfo.nPage ; How many rows are visible in the window. MaxLineLen EQU HScrollInfo.nMax ; How many characters are in the longest listing line. [.text] WndCreate PROC ; Register class LSTVIEW for the main window. MOV [WndClassEx.cbSize],SIZE# WNDCLASSEX MOV [WndClassEx.lpszClassName],WndClassName MOV [WndClassEx.style],CS_HREDRAW|CS_VREDRAW MOV [WndClassEx.lpfnWndProc],WndProc WinAPI GetModuleHandle,0 MOV [WndClassEx.hInstance],EAX WinAPI LoadIcon,EAX,1 ; The 1st and only icon from [.rsrc] section. MOV [WndClassEx.hIcon],EAX WinAPI LoadCursor,0,IDC_HAND MOV [WndClassEx.hCursor],EAX WinAPI GetStockObject,WHITE_BRUSH ; Default window background colour. MOV [WndClassEx.hbrBackground],EAX WinAPI GetStockObject,NULL_PEN MOV [hPen],EAX WinAPI RegisterClassEx,WndClassEx ; Inquire system metrics. WinAPI GetSystemMetrics,SM_CXSCREEN MOV [cxScreen],EAX WinAPI GetSystemMetrics,SM_CYSCREEN MOV [cyScreen],EAX WinAPI GetSystemMetrics,SM_CXVSCROLL MOV [cxScroll],EAX WinAPI GetSystemMetrics,SM_CYHSCROLL MOV [cyScroll],EAX WinAPI GetSystemMetrics,SM_CXBORDER MOV [cxBorder],EAX WinAPI GetSystemMetrics,SM_CYBORDER MOV [cyBorder],EAX WinAPI GetSystemMetrics,SM_CYCAPTION MOV [cyCaption],EAX ; Create the main window. WinAPI CreateWindowEx, WS_EX_ACCEPTFILES|WS_EX_CLIENTEDGE, \ WndClassName, DefTitle, WS_OVERLAPPEDWINDOW, \ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, \ 0, 0, [WndClassEx.hInstance], 0 MOV [hWindow],EAX MOV EBX,EAX MOV [VScrollInfo.cbSize], SIZE# SCROLLINFO MOV [VScrollInfo.fMask], SIF_RANGE | SIF_PAGE WinAPI SetScrollInfo, EBX, SB_VERT, VScrollInfo, 1 MOV [HScrollInfo.cbSize], SIZE# SCROLLINFO MOV [HScrollInfo.fMask], SIF_RANGE | SIF_PAGE WinAPI SetScrollInfo, EBX, SB_HORZ, HScrollInfo, 1 WinAPI ShowWindow, EBX, SW_SHOWNORMAL WinAPI UpdateWindow, EBX MOV [FontSize], FontSizeDef CALL WndFont CALL WndTitle RET ENDP WndCreate
This is a procedure which repaints the client area with listing contents.
Indexed listing is virtually formated to a character text-rectangle MaxLineLen × MaxRowNr
(in LstCreate
), this includes white top&bottom margin rows and left&right margin columns.
Visible part of text-client rectangle NrRowsCl × NrColsCl
is manipulated by user interactions which are transformed to changes of
LeftCol & TopRow
values (in WndProc) and then it is repainted here..
Each listing line consists of five spans 0..4 described by its index:
Span | Background | Pointer | Length in chars | Remark |
---|---|---|---|---|
0 | ColorMrg | StuffPtr | 1 | Left margin. |
1 | INDEX.Color | INDEX.Ptr | INDEX.Len1 | Dump column. |
2 | ColorSrc | INDEX.Ptr+2*INDEX.Len1 | INDEX.Len2 | Source column, color changed only when INDEX.length2>0. |
3 | unchanged | StuffPtr | MaxLineLen-INDEX.Len1-INDEX.Len2 | Extends the line to MaxLineLen. |
4 | ColorMrg | StuffPtr | 1 | Right margin. |
Margin spans 0 and 4 are one character (space) wide.
Dump and source span length in characters is specified by INDEX.Len1 and INDEX.Len2.
Stuff length is calculated on the fly and it fills each line with spaces
up to the MaxLineLen-1, which was learnt in LstCreate.
Only rows and spans potentionally visible in the client window are being painted.
[.bss] hDC D D ; Device context handle. xClient D D ; Client pixel position of TextOut. 0..[cxClient]. ColClient D D ; Number of characters already painted in client. TopRow D D ; Number of listing lines hidden above the top edge of client area (topmost lineNr). LeftCol D D ; Number of characters hidden on the left side of client area (leftmost colNr). [.text] WndPaint:: PROC MOV ESI,[IndexBeg] MOV EAX,SIZE# INDEX TEST ESI ; If index is not created yet. JZ .90: MUL [TopRow] ; MUL by the number of line which is displayed in the 1st client row. ADD ESI,EAX ; Index of topmost row. CMP ESI,[IndexBeg] JB .90: WinAPI BeginPaint, [hWindow], PaintStruct MOV [hDC],EAX WinAPI SelectObject, EAX, [hFont] WinAPI SelectObject, [hDC], [hPen] SUB EDI,EDI ; Begin to paint rows on client y-coordinate EDI=0. MOV ECX,[NrRowsCl] .10:CMP ESI,[IndexEnd] JNB .50: PUSH ECX CALL .RowPaint: POP ECX ADD EDI, [cyChar] ; Height of character box. ADD ESI, SIZE# INDEX ; Index of the next row. DEC ECX JNZ .10: .50:CMP EDI,[cyClient] JAE .60: WinAPI Rectangle,[hDC],0,EDI,[cxClient],[cyClient] ; Erase garbage on the bottom. .60:MOV EAX,[xClient] CMP EAX,[cxClient] JAE .80: WinAPI Rectangle,[hDC],EAX,0,[cxClient],[cyClient] ; Erase garbage on the right. .80:WinAPI EndPaint, [hWindow], PaintStruct .90:RET .RowPaint PROC ; Paint one line described by INDEX record ESI at yClient=EDI. ESI,EDI are preserved. SUB EBX,EBX MOV [xClient],EBX MOV [ColClient],EBX CMP EBX,[LeftCol] JNE .10: ; Paint span0 margin. WinAPI SetBkColor, [hDC], ColorMrg INC EBX WinAPI TextOutW, [hDC], 0, EDI, [StuffPtr], EBX MOV EAX,[cxChar] ADD [xClient],EAX .10:MOV [ColClient],EBX ; 0 or 1. ; Paint span1 dump. WinAPI SetBkColor, [hDC], [ESI+INDEX.Color] MOV EDX,[ESI+INDEX.Ptr] MOV ECX,[ESI+INDEX.Len1] MOV EAX,[LeftCol] LEA EAX,[EAX+EBX-1] SUB ECX,EAX JB .15: SAL EAX,1 ADD EDX,EAX ADD [ColClient],ECX WinAPI TextOutW, [hDC], [xClient], EDI, EDX, ECX ; Paint dump span of ECX characters. MOV EAX,[cxChar] MUL [ColClient] MOV [xClient],EAX CMP EAX,[cxClient] JAE .80: .15:MOV ECX,[ESI+INDEX.Len2] JECXZ .30: ; Paint span2 source. WinAPI SetBkColor,[hDC],ColorSrc MOV EDX,[ESI+INDEX.Len1] LEA EBX,[EDX+EDX] ADD EBX,[ESI+INDEX.Ptr] MOV EAX,[LeftCol] INC EDX MOV ECX,[ESI+INDEX.Len2] SUB EAX,EDX JB .20: SUB ECX,EAX SAL EAX,1 ADD EBX,EAX .20:ADD [ColClient],ECX WinAPI TextOutW, [hDC], [xClient], EDI, EBX, ECX ; Paint source span of ECX characters. MOV EAX,[cxChar] MUL [ColClient] MOV [xClient],EAX CMP EAX,[cxClient] JAE .80: .30:; Paint span3 stuff. MOV ECX,[MaxLineLen] SUB ECX,[ESI+INDEX.Len1] SUB ECX,[ESI+INDEX.Len2] SUB ECX,2 JBE .40: ADD [ColClient],ECX WinAPI TextOutW, [hDC], [xClient], EDI, [StuffPtr], ECX ; Paint stuff span of ECX characters. MOV EAX,[cxChar] MUL [ColClient] MOV [xClient],EAX CMP EAX,[cxClient] JAE .80: .40: ; Paint span4 margin. WinAPI SetBkColor, [hDC], ColorMrg WinAPI TextOutW, [hDC], [xClient], EDI, [StuffPtr], 1 ; Paint right margin space. .80:RET ENDP .RowPaint: ENDP WndPaint
[.text] WndSize:: PROC MOV EAX,0x0000FFFF ; Width is in lower WORD of lParam. AND EAX,EDI MOV ECX,[cxChar] JECXZ .End: ; If font is not loaded yet. MOV [cxClient],EAX CDQ DIV ECX INC EAX MOV [NrColsCl],EAX ; How many characters fits in client width. WinAPI SetScrollInfo,[hWindow], SB_HORZ, HScrollInfo, 1 MOV EAX,EDI ; Client height is in higher WORD of lParam. SHR EAX,16 MOV ECX,[cyChar] MOV [cyClient],EAX JECXZ .End: CDQ DIV ECX INC EAX MOV [NrRowsCl],EAX ; How many rows fits in client height. WinAPI SetScrollInfo,[hWindow],SB_VERT, VScrollInfo,1 .End:RET ENDP WndSize::
MarginHor EQU 48 ; Screen margins of max-modified window in pixels. MarginVert EQU 64 [.text] WndModify PROC MOV EAX,[MaxLineLen] ; Calculate maximal useful window width. MUL [cxChar] ADD EAX,[cxScroll] ADD EAX,[cxScroll] XCHG EBX,EAX ; EBX is now required client width to display whole lines. MOV EAX,[cxScreen] SUB EAX,2*MarginHor CMP EAX,EBX JA .xOK: XCHG EAX,EBX ; Screen is not wide enough. .xOK: ; EBX is now the new client width. MOV EAX,[MaxRowNr] MUL [cyChar] ADD EAX,[cyScroll] XCHG EDI,EAX MOV EAX,[cyScreen] SUB EAX,2*MarginVert CMP EAX,EDI JA .yOK: XCHG EAX,EDI ; Screen is not high enough. .yOK: ; EDI is now the new client height. MOV [cxClient],EBX MOV [cyClient],EDI MOV EAX,[cxBorder] ADD EBX,EAX ADD EBX,EAX ADD EDI,[cyBorder] ADD EDI,[cyCaption] WinAPI MoveWindow, [hWindow], MarginHor, MarginVert, EBX, EDI, 1 RET ENDP WndModify
"LstFileName"{rowNr}[colNr]
.
LstView - €ASM listing viewer
.[.bss] LocA D 16*B ; ANSI format. %IF %^UNICODE LocW D 16*U ; WIDE format. %ENDIF [.text] WndTitleLoc PROC PUSHAD MOV EBX,0x0000_FFFF MOV ECX,EDI AND EBX,EDI ; xClient. MOV EDI,LocA MOV AL,'{' STOSB XCHG ECX,EAX SHR EAX,16 ; yClient. CDQ DIV [cyChar] ADD EAX,[TopRow] StoD EDI MOV AX,'}[' STOSW MOV EAX,EBX CDQ DIV [cxChar] ADD EAX,[LeftCol] StoD EDI MOV AX,']' STOSW %IF %^UNICODE ; Convert ANSI string produced by StoD to WIDE string. MOV ESI,LocA MOV EDI,LocW SUB EAX,EAX .50:LODSB STOSW TEST EAX JNZ .50: %ENDIF POPAD CALL WndTitleUpdate RET ENDP WndTitleLoc
"LstFileName"
.
LstView - €ASM listing viewer
.[.text] WndTitle PROC %IF %^UNICODE MOVW [LocW],0 %ELSE MOVB [LocA],0 %ENDIF CALL WndTitleUpdate RET ENDP WndTitle
"LstFileName"{rowNr}[colNr]
or "LstFileName"
.
LstView - €ASM listing viewer
.
The character € defined in ANSI version of string DefTitle is in ANSI codepage and therefore it is misinterpreted in browser.
[.data] %IF %^UNICODE ; DefTitle contains non-ASCII character, CODEPAGE is required. EUROASM CODEPAGE=UTF-8 DefTitle DU " LstView - �,�ASM listing viewer",0 %ELSE EUROASM CODEPAGE=WINDOWS-1252 DefTitle DB " LstView - ?ASM listing viewer",0 %ENDIF [.bss] Title D MAX_PATH_SIZE + 16 * U [.text] WndTitleUpdate PROC PUSH EBX,EDI %IF %^UNICODE MOV EBX,LocW %ELSE MOV EBX,LocA %ENDIF CMPB [LstFileName],0 JNZ .NoFile: Concat$ Title,DefTitle JMP .ShowTitle: .NoFile: Concat$ Title,='"', LstFileName, ='"', EBX, DefTitle .ShowTitle: WinAPI SetWindowText,[hWindow],Title POP EDI,EBX RET ENDP WndTitleUpdate
Display standard OpenFileName dialogue for selection of the listing file to view.
[.data] OpenFilter D "Listing files *.lst",0,"*.lst",0, "All files *.*",0,"*.*",0,0 [.bss] OpenDialog DS OPENFILENAME ; Standard Windows open-file dialogue. [.text] LstSelect PROC MOV [LstFileName],0 MOV [OpenDialog.lStructSize],SIZE#OPENFILENAME MOV [OpenDialog.lpstrFilter],OpenFilter MOV [OpenDialog.lpstrFile],LstFileName MOV [OpenDialog.nMaxFile],SIZE# LstFileName MOV [OpenDialog.Flags],OFN_FILEMUSTEXIST WinAPI GetOpenFileName,OpenDialog TEST EAX RET ENDP LstSelect
LstCreate reserves dynamic memory for Index and for the conversion of UTF-8 listing file to UTF-16.
Listing file specified with LstFileName is open, recoded from UTF-8 to UTF-16 (WIDE), each physical line is parsed and creates one index record, stored to IndexBuffer.
[.bss] LstVarBeg: ; Memory up to LstVarEnd: is cleared in LstDestroy before a new file is loaded. Pool D D ; Pointer to dynamic memory structure POOL. LineBuffer D D ; Pointer to BUFFER for temporary Wide listing line. IndexBuffer D D ; Pointer to BUFFER with INDEX record per each listing line. IndexBeg D D ; Pointer to INDEX record of the first listing line. IndexEnd D D ; Pointer beyond the INDEX record of the last listing line. StuffPtr D D ; Pointer to an empty line of MaxLineLen WIDE spaces. LstFile DS FILE ; FILE object. Index DS INDEX ; Working space for the index. LstVarEnd: [.text] LstCreate PROC PoolCreate AbortIf C,%^SourceLine MOV [Pool],EAX BufferCreate EAX,Size=4K ; Temporary buffer for one Wide listing line span. AbortIf C,%^SourceLine MOV [LineBuffer],EAX BufferCreate [Pool],Size=16K*SIZE#INDEX ; This is enough to store 16K physical lines without reallocation. AbortIf C,%^SourceLine MOV [IndexBuffer],EAX CALL WndTitle MOV EDI,HelpText MOV ECX,SIZE# HelpText CMPB [LstFileName],0 JZ .20: ; If no filename in command line. FileAssign LstFile,LstFileName FileLoad LstFile ; Memory at ESI,EAX now contains the listing in UTF-8 (or plain ASCII). MOV EDI,NotFoundText MOV ECX,SIZE# NotFoundText JC .20: ; If the specified file was not found. MOV EDI,ESI ; Pointer to the loaded listing (encoded in ASCII or UTF-8). MOV ECX,EAX ; Size of the listing file loaded in memory. .20:; Create index of the UTF-8 text EDI,ECX. SUB EAX,EAX MOV [MaxLineLen],EAX MOV [MaxRowNr],EAX ; Create index of top margin empty envelope line. MOV [Index.Color],ColorMrg BufferStore [IndexBuffer],Index, SIZE# Index ; Top envelope line. INCD [MaxRowNr] MOV AL,10 ; LineFeed termination of physical line. .30:; Index the physical line at EDI with remaining file size in ECX. JECXZ .50: MOV ESI,EDI REPNE SCASB MOV EBX,EDI JNE .40: DEC EBX ; Trim LF. .40:Invoke LstIndex,ESI,EBX ; Create index of physical listing line ESI,EBX. JMP .30: .50:MOV ECX,[MaxLineLen] ; Prepare line of stuff (spaces). INC ECX,ECX MOV [MaxLineLen],ECX SHL ECX,1 PoolNew [Pool],ECX,Align=WORD AbortIf C,%^SourceLine MOV EDI,EAX MOV [StuffPtr],EDI MOV AX,0x0020 SHR ECX,1 REP STOSW ; Create index of bottom margin empty envelope line. Clear Index MOV [Index.Color],ColorMrg BufferStore [IndexBuffer],Index, SIZE# Index ; Bottom envelope line. BufferRetrieve [IndexBuffer] MOV [IndexBeg],ESI MOV [IndexEnd],ESI ADD [IndexEnd],ECX ;DIV ECX,SIZE#INDEX SAR ECX,4 ; SIZE# INDEX = 16. MOV [MaxRowNr],ECX FileClose LstFile ; File contents is already converted and indexed on Pool. SUB EAX,EAX MOV [TopRow],EAX MOV [LeftCol],EAX CALL WndModify ; Shrink | expand the window to the optimal size. WinAPI RedrawWindow,[hWindow],0,0,RDW_FRAME | RDW_INTERNALPAINT | RDW_INVALIDATE RET ENDP LstCreate
One INDEX record is created for each physical line of listing file and also for the envelope margin lines (the first and the last).
Each physical line is virtually extended with spaces to MaxLineLen, so all lines will be displayed with the same width.
Procedure LstIndex will parse one physical line into five spans (0..4) with different background colors, see WndPaint.
Line is parsed, decoded from UTF-8 to UTF-16LE and stored on Pool. The Index record is then saved to IndexBuffer.
INDEX STRUC ; Describes one listing line. .Color D D ; Background color of span 1 (as well for span 1..3 when INDEX.Length2=0). .Ptr D D ; Pointer to the first unichar of listing line. .Len1 D D ; Length of span 1. .Len2 D D ; Length of span 2. ENDSTRUC INDEX ; Background color definition for INDEX.Color. ColorMrg EQU 0x00FFFFFF ; Margin line. ColorHtml EQU 0x00FFD0D0 ; Markup comment. ColorDmp EQU 0x00D0D0D0 ; Dump column. ColorSrc EQU 0x00D0FFFF ; Source column. ColorInfo EQU 0x00D0FFD0 ; Info message line. ColorWarn EQU 0x0030FFFF ; Warning message line. ColorErr EQU 0x00D0D0FF ; Error message line. [.text] LstIndex Procedure LinePtr, LineEnd Clear Index MOV [Index.Color],ColorSrc ; Assume no dump column. MOV ESI,[%LinePtr] MOV EDX,[%LineEnd] MOV EBX,ESI MOV ECX,EDX SUB ECX,ESI .White: CMP ESI,EDX JNB .Length: LODSB CMP AL,' ' JBE .White: ; Skip leading white spaces. CMP AL,'|' ; Does dump-column exist? JE .Dmp: CMP AL,'<' ; Is it a markup comment line? > JE .Html: MOV [Index.Color],ColorSrc ; It is a source-only line. BufferClear [LineBuffer] CALL .Decode MOV [Index.Ptr],EAX SHR ECX,1 MOV [Index.Len1],ECX JMP .Length: .Decode:PROC ; Convert the input string from UTF-8 to UTF-16 and store it on [Pool]. ; Input: EBX,ECX is input string ; Output: EAX,ECX is output string (size in ECX is doubled). PUSH ESI DecodeUTF8 EBX, Size=ECX, .W: ; Macro from string32.htm. .W:PROC1 ; Store decoded Wide character to LineBuffer. CMP AX,0x0020 JAE .WS: MOV AX,0x0020 ; Convert white-space to space. .WS:BufferStoreWord [LineBuffer],EAX RET ENDP1 .W: BufferRetrieve [LineBuffer] ; Into ESI,ECX. PoolStore [Pool],ESI,ECX POP ESI RET ENDP .Decode: .Html: MOV [Index.Color],ColorHtml BufferClear [LineBuffer] CALL .Decode MOV [Index.Ptr],EAX SHR ECX,1 MOV [Index.Len1],ECX JMP .Length: .Dmp: ; AL='|', EBX=LinePtr, ESI=beyond 1st '|', EDX=LineEnd. MOV EDI,ESI MOV ECX,EDX SUB ECX,EDI REPNE SCASB ; Search for the 2nd '|'. JNE .Msg: ; EBX EDI EDX ; | | | ; |1234:5678| Source MOV [Index.Color],ColorDmp BufferClear [LineBuffer] MOV ECX,EDI SUB ECX,EBX CALL .Decode SHR ECX,1 MOV [Index.Len1],ECX MOV EBX,EDI MOV ECX,EDX SUB ECX,EBX CALL .Decode MOV [Index.Ptr],EAX SHR ECX,1 SUB ECX,[Index.Len1] MOV [Index.Len2],ECX JMP .Length: .Msg: ; EBX=LinePtr, ESI=beyond 1st '|', EDX=LineEnd. ; ESI EDI ;EBX| EDX ; || | ; |## W1234 Warning MOV AL,'#' MOV ECX,ColorDmp CMP [ESI+0],AL JNE .SetColor: MOV ECX,ColorInfo CMP [ESI+1],AL JNE .SetColor: MOV ECX,ColorWarn CMP [ESI+2],AL JNE .SetColor: MOV ECX,ColorErr .SetColor: MOV [Index.Color],ECX BufferClear [LineBuffer] MOV ECX,EDX SUB ECX,EBX CALL .Decode MOV [Index.Ptr],EAX SHR ECX,1 MOV [Index.Len1],ECX .Length: MOV EAX,[Index.Len1] ADD EAX,[Index.Len2] CMP EAX,[MaxLineLen] JNA .Store: MOV [MaxLineLen],EAX .Store: BufferStore [IndexBuffer], Index, SIZE# Index EndProcedure LstIndex
[.text] LstDestroy PROC PoolDestroy [Pool] ; Free the memory if Pool was already created before. Clear LstVarBeg, Size=LstVarEnd-LstVarBeg WinAPI UpdateWindow,[hWindow] RET ENDP LstDestroy
[.bss] %IF %^UNICODE ; Properties of the used font. TextMetric DS TEXTMETRICW %ELSE TextMetric DS TEXTMETRICA %ENDIF ClientRect DS RECT ; Client area of the window. [.text] WndFont PROC MOV ECX,[hFont] JECXZ .10: WinAPI DeleteObject,ECX .10:WinAPI CreateFont, [FontSize], 0, 0, 0, FW_DONTCARE, 0, 0, 0, ANSI_CHARSET, \ OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DRAFT_QUALITY, \ FIXED_PITCH | FF_SWISS, 0 AbortIf FALSE,%^SourceLine MOV [hFont],EAX MOV EBX,[hWindow] WinAPI GetDC,EBX MOV EDI,EAX ; Device context, WinAPI SelectObject,EDI,[hFont] WinAPI GetTextMetrics,EDI,TextMetric WinAPI ReleaseDC,EBX,EDI MOV EAX,[TextMetric.tmHeight] MOV ECX,[TextMetric.tmAveCharWidth] ADD EAX,[TextMetric.tmExternalLeading] MOV [cxChar],ECX MOV [cyChar],EAX RET ENDP WndFont
*.lstfiles with this viewer in MS Windows registry.
[.data] Listing D "lstview.exe",0 ; Name of file type in registry classes. RegHelp D 'Associate "*.lst" files to always open with',10 Command D MAX_PATH_SIZE + 4 * UNICHAR 0 [.bss] hKey D D ; Handle of registry key. RegName D D ; Pointer to the filename in ExeSelf. Not used. ExeSelf D MAX_PATH_SIZE * U ; Full path to "lstview.exe". [.text] Register PROC WinAPI SearchPath, 0, ="lstview.exe", 0, MAX_PATH_SIZE, ExeSelf, RegName AbortIf FALSE,%^SourceLine Concat$ Command, ='"', ExeSelf, ='" "%%1"' WinAPI MessageBox, [hWindow], RegHelp, ="Associate *.lst", \ Ask for confirmation. MB_OKCANCEL | MB_ICONASTERISK | MB_DEFBUTTON1 CMP EAX,IDOK JNE .Cancel: ; Create keyHKCU\Software\Classes\.lstwith value (Default) REG_SZ "lstview.exe". WinAPI RegCreateKeyEx, HKEY_CURRENT_USER, ="Software\Classes\.lst", 0, \ ="", 0, KEY_ALL_ACCESS, 0, hKey, 0 WinAPI RegSetValueEx, [hKey], 0, 0, REG_SZ, Listing, SIZE#Listing WinAPI RegCloseKey, [hKey] ; Create keyHKCU\Software\Classes\Applications\lstview.exe\shell\open\command. WinAPI RegCreateKeyEx, HKEY_CURRENT_USER, ="Software\Classes\Applications\lstview.exe\shell\open\command", 0, \ ="", 0, KEY_ALL_ACCESS, 0, hKey, 0 GetLength$ Command INC ECX,ECX WinAPI RegSetValueEx, [hKey], 0, 0, REG_SZ, Command, ECX WinAPI RegCloseKey, [hKey] WinAPI SHChangeNotify, SHCNE_ASSOCCHANGED,SHCNF_IDLIST, 0, 0 ; Remind MS Windows. .Cancel: RET ENDP Register
ENDPROGRAM lstview