include header.inc
include constant.inc
DlgProc  PROTO  :DWORD, :DWORD, :DWORD, :DWORD
.data
hInstance equ 400000h
ClassName db 1,2,0
AppName 	db 'Styles',0
wc WNDCLASSEX <sizeof wc,CS_BYTEALIGNWINDOW or CS_DBLCLKS,offset WndProc,\
		0,0,hInstance,0,0,COLOR_BTNFACE+1,0,offset ClassName,0>
include descript.inc
ALIGN 4
CallerEdit dd 0
.data?
msg MSG <>
include handles.inc
include values.inc
CommandLine db 32 dup (?)
.code
start:
	invoke GetCL,1,offset CommandLine
	cmp eax,1 ;not errors?
	jne @F      ;some errors - leave processing of CommandLine
	invoke htodw,offset CommandLine ;convert HEX string to value (assuming that it is hEdit of the Caller)
	mov CallerEdit,eax ;Store the caller hEdit
;-----------------------------------------------------------------------------------------------------------------------------
; Определим не загружено ли уже окно
;-----------------------------------------------------------------------------------------------------------------------------
@@:	invoke FindWindow,offset ClassName,0
	test eax,eax
	je @F ; если не найдено - перейти на основной код
;------------------------------------------------------------------------------------------------------------------------
;Если окно загружено то в зависимости от того минимизировано оно или нет:
;минимизировано: использовать ShowWindow(handle,SW_RESTORE
;нет	            : использовать SetForegroundWindow
;--------------------------------------------------------------------------------------------------------------------------

	mov ebx,eax		;ebx = handle найденого окна
	invoke IsIconic,eax		;minimized?
	test eax,eax
	je @noticonic		;not minimized - proceed to Activation
	invoke ShowWindow,ebx,SW_RESTORE ;else (minized) - restore
	jmp @sendmsg		;jump for passing Caller Edit to 1st copy and exit
@noticonic:
	invoke SetForegroundWindow,ebx ;Activate window if it is not iconic
@sendmsg:
	cmp CallerEdit,0		;if there was handle of edit in CommandLine?
	je @exit			;there was not - just exit
WM_NEWEDIT equ WM_USER+100
	invoke SendMessage,ebx,WM_NEWEDIT,CallerEdit,eax ;else pass the handle to 1st copy
	jmp @exit	
;Загружаем битмапы для лист бокса с классами окон и помещаем хэндлы этих
;битмапов в структуры описывающие эти классы
.data
HelpName 	db 'LbHelp.hlp',0
.data?
FullHelpName db 260 dup (?)
.code
@@:	invoke GetAppPath,offset FullHelpName		;create fullname for hlp file
	invoke szMultiCat,1,offset FullHelpName,offset HelpName

	mov ebx,14	;counter for 14 classes (!)
	mov  esi,Classes	;адрес массива структур описывающих таблицы классов
	mov edi,1	;индекс первого ресурса
@@:	invoke LoadBitmap,hInstance,edi ; загружаем битмап edi = индекс нового битмапа
assume esi:ptr ClassTable	;esi указатель на текущую структуру
	mov [esi].hBmp,eax ; поместим hBmp в DWORD член текущей структуры
	inc edi		; увеличим индекс
	add esi,Sizeof ClassTable ;сместим указатель на размер струтуры что указывал на следующую
	dec ebx		; уменьшим счётчик
	jne @B		; если есть что ещё заполнять - перейти к заполнению
assume esi:nothing
;==================================================================================
;Заполним класс главного окна зарегистрируем его и создадим само окно а также цикл опроса
;==================================================================================
.data?
hBrushM dd ?
.code
	invoke LoadIcon,ebx,IDI_EXCLAMATION	
	mov wc.hIcon,eax
	mov wc.hIconSm,eax
	invoke LoadCursor,ebx,IDC_ARROW
	mov wc.hCursor,eax
	invoke LoadBitmap,hInstance,20 ;bitmap for window skin
	invoke CreatePatternBrush,eax   ;create brush from it
	mov wc.hbrBackground,eax         ;this brush will be used to paint main window
	mov hBrushM,eax
	invoke RegisterClassEx,offset wc
	and eax,0FFFFh
w equ 670
h equ 486
	mov ebx,eax	;атом класса в ebx
	invoke GetSystemMetrics,SM_CXSCREEN
	mov edi,eax
	invoke GetSystemMetrics,SM_CYSCREEN
	sub edi,w
	sub eax,h
	shr edi,1
	shr eax,1
	xor esi,esi
;CONTEXTHELP - our window will receive msgs after user press F1 or clicked by ? some control
	invoke CreateWindowEx,WS_EX_CONTEXTHELP,ebx,offset AppName,
	WS_SYSMENU or WS_CAPTION or WS_VISIBLE,
	edi,eax,w,h,
	esi,esi,hInstance,esi
	mov edi,offset msg
@@:
	invoke GetMessage,edi,esi,esi,esi
	invoke TranslateMessage,edi
	invoke DispatchMessage,edi
	jmp @B
.data
SvinStr db 'Svintus®'
.code
@exit:
	call ExitProcess
WndProc proc uses edi esi ebx hWnd,uMsg,wParam,lParam
LOCAL buffer[1024]:BYTE
	mov eax,uMsg
WM_CASE eax,<DESTROY,CREATE,COMMAND,MEASUREITEM,DRAWITEM,CTLCOLOREDIT,CTLCOLORLISTBOX>
WM_CASE eax,<NEWEDIT,HELP,CHAR,SIZE,PAINT,LBUTTONDBLCLK,VKEYTOITEM,CTLCOLORSTATIC>

	invoke DefWindowProc,hWnd,eax,wParam,lParam
@r:	ret
@@LBUTTONDBLCLK :

	invoke  DialogBoxParam,hInstance,2,hWnd,offset DlgProc,0
	jmp @r
.data?
pnts  PAINTSTRUCT <>
.code
@@PAINT:
	mov ebx,hWnd
	invoke BeginPaint,ebx,offset pnts
	mov eax,1
	invoke FrameGrp,hb31,hb00,eax,eax,eax
	invoke EndPaint,ebx,offset pnts
	jmp @r0
@@CHAR:
	cmp wParam,VK_ESCAPE
	jne @F
	invoke DestroyWindow,hWnd
@@:	jmp @r	
@@HELP:
	mov ebx,lParam
	assume ebx:ptr  HELPINFO
	invoke WinHelp,hWnd,offset FullHelpName,HELP_CONTEXTPOPUP,[ebx].dwContextId
	jmp @r
@@NEWEDIT:
	cmp CallerEdit,0
	mov eax,wParam
	mov CallerEdit,eax
	jne @alreadyenabled
	invoke EnableWindow,hBtnEdit,1
@alreadyenabled:
	jmp @r
@@DESTROY:
	jmp @exit
@@CTLCOLOREDIT:
	mov ebx,wParam
	invoke SetTextColor,ebx,Green
	invoke SetBkColor,ebx,Black
	invoke GetStockObject,BLACK_BRUSH
	jmp @r
@@CTLCOLORLISTBOX:
	mov edx,hDrawListBox
	cmp edx,lParam
	mov ebx,wParam
	je @r0
	invoke SetTextColor,ebx,White
	invoke SetBkColor,ebx,Black
	invoke GetStockObject,BLACK_BRUSH
	jmp @r
@@CTLCOLORSTATIC:
	invoke SetBkMode,wParam,TRANSPARENT
	mov eax,hBrushM
	ret
@@CREATE:
;в create.inc находится код для создания элементов управления
	invoke InitCommonControls
include create.inc
	invoke EnableWindow,hBtnEdit,CallerEdit
	jmp @fillfirst

@@COMMAND:
;=======================================================================
;Определим что за msg к нам пришёл wParam = Notify Code + ID ; lParam = Ctrl hWnd
;=======================================================================

	mov eax,wParam
	mov ebx,lParam	;ebx = hCtrl
	mov edx,eax
	and eax,0FFFFh	;eax = ctrl ID
	shr  edx,16	;edx = Notify msg
	je @btnclk	;if 0 then it was btnclk
	cmp edx,LBN_DBLCLK
	je @dblclk
	cmp edx,LBN_SELCHANGE
	jne @r
@sel:
	cmp eax,LbID3
	je @Lb3Sel	;на обработку бокса выбирающего класс
	xor edi,edi

	;===================================
	;Получим адрес записи выбранного itemа в esi
	;===================================
	invoke SendMessage,ebx,LB_GETCURSEL,edi,edi	;ebx = ListBox handle edi = 0
	invoke SendMessage,ebx,LB_GETITEMDATA,eax,edi	
	mov esi,eax
	;--------------------------------------------------------------------
	invoke SetWindowText,hEdit,0
	invoke SetWindowText,hEdit,[esi+8]	;установим в hEdit текст находящийся по адресу rec.+8
	push ebx				;сохраним list box handle (ebx используется в fastadws)
.data
VStyleText 	db 'Virtual Style',0
SStyleText 	db 'SingleFlagStyle',0
CStyleText 	db 'ComlexFlagsStyle',0
ALIGN 4
TblStyleTypes dd offset VStyleText,offset SStyleText,offset CStyleText
.code
	mov eax,[esi+4]			;в eax значение стиля в текущей записи
	push eax
	xor ebx,ebx	;1
	mov edx,eax	;0
	cmp ebx,eax	;1
	lea ecx,[eax][-1]	;0
	adc ebx,0		;1
	xor edx,ecx	;0
	and edx,eax	;1
	cmp edx,eax	;1
	adc ebx,0		;1
	invoke SendMessage,hStatus,SB_SETTEXT,3,[ebx*4][offset TblStyleTypes]
	pop eax
	invoke fastadws,offset numCurrentV	;преобразуем его Hex строку
	invoke SetWindowText,hNumCurrentV,offset numCurrentV ;покажем полученую строку
	pop ebx				;востановим ebx
	jmp @r

@dblclk:  sub eax,12	;ID - greatest of LB ID +1
	mov edi,hLbClasses
	jns @r   ;in the future - go to other LB handlers
;Проверим от кого пришло сообщение
	cmp edi,ebx	;edi = hLbClasses ebx = Handle of list box we got the msg from
	jne @notCl	;if edi <> ebx then we can use ebx edi as handles of two different
			;List boxes we need exchange data with
			;and handle in ebx is always the handle of window we got msg from
			;so we delete from "ebx" list box end add to "edi" list box
	mov edi,hLbChoosen ;if they are equal then change value of edi to the second option (hLbChoosen)
;ebx = от кого edi = с кем менятся
@notCl:	invoke SendMessage,ebx,LB_GETCURSEL,0,0 ;index in eax
;------------------------------------------------------------ 
	push 0			;parameters to remove string from the sender
	push eax
	push LB_DELETESTRING
	push ebx
;----------------------------------------------------------------
	invoke SendMessage,ebx,LB_GETITEMDATA,eax,0 ;pointer to record of double clicked item
	mov ecx,[eax]		;[pointer + 0] = offset of string of the item
	mov esi,eax		;save pointer to unchangable esi
	invoke SendMessage,edi,LB_ADDSTRING,0,ecx ;add double clicked item to other list box
	invoke SendMessage,edi,LB_SETITEMDATA,eax,esi ;accosiat new item with record
	call SendMessage ;parameters already pushed after @notsel

;=========================================================================
;CumNum - это переменная которая хранит or'ed значения всех выбранных
;классов.
;Когда новое значение добавляется к выбранным стилям технология
;получения нового CumNum простая - просто or новое значение с предидущим
;При удалении же нового значения недостаточно просто AND старое значение с новым
;выставив в 0 выставленые биты удаляемого значения и поставив в 1 остальные
;т.к. некоторые стили(сложенные из нескольких) могут оставаться и иметь те же
;выставленные биты, что и в удаляемом значении. Поэтому, необходимо 
;выполнить полное or всех значений оказавшихся выбранными стилей
;=========================================================================

	mov edi,CumNum		;старое значение в edi
	cmp ebx,hLbClasses	;добавление или удаление?
	mov PrevCumNum,edi	;старое значение в PrevCumNum
	jne @F			;удаление - перейти на полную регенерацию
	mov eax,[esi+4]
	or edi,eax		;просто добавление - зделать or с новым значением
	jmp @convert

;Секция полной регенарации CumNum

@@:	invoke SendMessage,ebx,LB_GETCOUNT,0,0 ;get number of items as counter for or cicles
	test eax,eax ;if no items here
	mov edi,eax
	lea esi,[eax-1] ;set esi as number of items minus 1 so we can use it both for counter and index
	je @convert ;then edi = 0 and go to convert

	xor edi,edi

@@:	invoke SendMessage,ebx,LB_GETITEMDATA,esi,0 ;get offset of item's record
	or edi,[eax+4] ;or edi with value member
	dec esi	       ;next index
	jns @B	       ;if it's less than 0 then we've done
@convert:
	mov CumNum,edi ;new or'ed choosen styles value in CumNum
	invoke udw2str,edi,offset DecDisplayTotal ;convert it to decimal
	invoke SetWindowText,hTotalDec,offset DecDisplayTotal ;display the decimal string
	mov eax,edi ;value in eax for fastadws
	invoke fastadwsz,offset HexDisplayTotal ;convert new or'ed value in hex
	invoke SetWindowText,hTotalHex,offset HexDisplayTotal ;display the hex string
	invoke B2Asciids,edi,offset BitDisplayTotal,1,1 ;convert new or'ed value in Bit String
	inc esi ;esi=0
	invoke SetWindowText,hTotalBit,offset BitDisplayTotal ;display the Bit String
	invoke SendMessage,hLbClasses,LB_GETCOUNT,esi,esi ;Get number of items in hLbClasses
	lea ebx,buffer		;ebx = pointer to the LOCAL buffer
	invoke udw2str,eax,ebx	;convert number of items in hLbClasses into decimal string
	invoke SetWindowText,hNumTotalA,ebx ;display the decimal string
	invoke SendMessage,hLbChoosen,LB_GETCOUNT,esi,esi ;Get number of items in hLbChoosen
	invoke udw2str,eax,ebx	;convert the number into decimal string (ebx = pointer to buffer)
	invoke SetWindowText,hNumTotalC,ebx ;display the number
;We empty desciption and current style value display 'cause after double clicked there
;will be no item selected (previously selected item will be deleted after double click)

	invoke SetWindowText,hEdit,0	;empty hEdit
	invoke SetWindowText,hNumCurrentV,0 ;empty hNumCurrentV

;Change Enable Status of "bit numbers winodws"
@bitenble:
	mov ebx,CumNum ;current number
	mov eax,PrevCumNum ;previous number
	mov edi, ebx	;current number
	xor ebx,eax	;if 0 - all are equal if not changed bits set
	je @r
@@:	bsf ecx,ebx ;find first set bit index
	mov esi,1 ;set first bit in esi
	mov edx,edi ;edi current value of classes
	shl esi,cl	;set bit in esi into position of found bit
	mov eax,[ecx*4][offset hb00] ;eax = handle of window that represents fount bit
	and edx,esi ;edx = 0 if the found bit is 0
	shr edx,cl ;edx = 1 if the found bit is
	xor esi,-1
	invoke EnableWindow,eax,edx
	and ebx,esi
	jne @B
	invoke SendMessage,hStatus,SB_SETTEXT,3,0
	jmp @r

;eax = ctrl ID
;ebx = hCtrl
;edx = 0
;============================================
;Обработка нажатий кнопок форматирующих строку
;============================================

@btnclk: 		cmp eax,22 ;if it is not "String inset buttons" greatest value is 21 if not it sets carry
		mov edi,eax ;save ID for the future
		jnc @r
;Now we need to formate a string
;Определить должна ли строка быть символьной или числовой
;------------------------------------------------------------------------------------------------------------
		invoke SendMessage,hRbSimbol,BM_GETCHECK,edx,edx
		test eax,eax ;if 0 then Numeric type of data is set
		je @numeric ;радио-кнопка hRbSimbol не установлена - значит установлена числовая
;-----------------------------------------------------------------------------------------------------------
;Создание символьной строки
;-----------------------------------------------------------------------------------------------------------
		mov esi,hLbChoosen ;handle of Choosen box
		invoke SendMessage,esi,LB_GETCOUNT,0,0
		test eax,eax ;if zero - nothing to insert
		lea ebx,buffer ;save buffer addr
;edi = ID esi = hChoosen ebx =addr buffer
		je @r ;if no items - exit
		push edi ;в edi index контрола сохраним его - он говорит куда нужно поместить строку
		lea edi,[eax-1] ;edi = counter - 1 dec until -1 will give us array of indexes

;Проводим заполнение следующим образом
;1. Вставляем в буффер строку

@@:		invoke SendMessage,esi,LB_GETTEXT,edi,ebx ;eax = num of caracters

;в eax - количество символов только что вставленых символов 
;значит [ebx][eax] следующий за последним символом адрес
;2. Вставляем туда ' or ' - 4e символа

		mov dword ptr [ebx][eax],20726F20h

;3. уменьшаем index - edi если он меньше 0 значит предидущий индекс было 0 - последний

		dec edi

;4. Корректируем ebx чтобы он показывал на следующий символ после вставки ' or ' [2]

		lea ebx,[ebx][eax][4]

;5. Если уменьшение edi [3] дало отрицательное значение - то конец - иначе новое заполнение [1]

		jns @B

;Востановим в edi индекс кнопки

		pop edi 
;6. ebx указывает на байт следующий за последним ' or ' [2] последний нам не нужен 
; вставляем в его начало 0 чтобы закончить строку

		mov byte ptr [ebx][-4],0
		lea esi,buffer

;7. Завершаем помещение указателя в ebx для последующих операций
; над только что созданной строкой

		sub ebx,esi
		sub ebx,3

;---------------------Lets formate the string ------------------------------------
; Переходим на размещение строки.

		jmp @insertstr		
; Если выбран был numeric то мы можем использовать Hex строку 
; которая формируется нами при выборе пользователем стилей двойным щелчком

@numeric:	mov esi,offset HexDisplayTotal
		mov ebx,sizeof HexDisplayTotal
		
; Теперь определяем куда нужно поместить строку

@insertstr:	cmp edi,20 	;if ID = Clipboard
		jne @edit		;if no : Go to process
		invoke OpenClipboard,hWnd
		invoke EmptyClipboard
		invoke GlobalAlloc,GMEM_FIXED,ebx
		push eax			;Указатель для SetClipboardData
		mov ecx,ebx
		mov edi,eax
		and ebx,3
		shr ecx,2
	rep	movsd
		mov ecx,ebx
	rep	movsb
		push CF_TEXT		;Индекс типа данных для SetClipboardData
		call SetClipboardData
		invoke CloseClipboard
		ret
@edit:	
		invoke SendMessage,CallerEdit,EM_REPLACESEL,1,esi

		jmp @r


@@MEASUREITEM:
	mov ebx,lParam
	assume ebx: ptr MEASUREITEMSTRUCT
	mov [ebx].itemHeight ,34
	assume ebx: nothing
	mov eax,1
	ret
@@DRAWITEM:
.data?
hbmpPicture dd ?
hdcMem dd ?
hbmpOld dd ?
ps PAINTSTRUCT <>
rcBitmap RECT <>
tm  TEXTMETRIC <>
StructAddr dd ?
hStatCurrent dd ?
.code
	cmp wParam,10
	jne @F
	mov ebx,lParam
	assume ebx:ptr DRAWITEMSTRUCT
	invoke CreateCompatibleDC,[ebx].hdc
	mov hdcMem,eax
	invoke SelectObject,eax,hStatCurrent
	mov hbmpOld,eax

	invoke BitBlt,[ebx].hdc,[ebx].rcItem.left,[ebx].rcItem.top,bm.bmWidth,
	bm.bmHeight,hdcMem,0,0,SRCCOPY
	invoke SelectObject,hdcMem,hbmpOld
	invoke DeleteDC,hdcMem
	ret
@@:
	mov ebx,lParam
	assume ebx: ptr DRAWITEMSTRUCT
	cmp [ebx].itemID,-1
	je @r0
	cmp [ebx].itemAction,ODA_FOCUS
	je @r1

;Вычисляем картинку
	mov eax,[ebx].itemID
	shl eax,2
	lea eax,[eax][eax*2]
	lea esi,[eax*2]+Classes ;esi = addr of ClassTable struct
assume esi:ptr ClassTable
	mov eax,[esi].hBmp
	mov StructAddr,esi
	mov hbmpPicture,eax
	invoke CreateCompatibleDC,[ebx].hdc
	mov hdcMem,eax
	invoke SelectObject,eax,hbmpPicture
	mov hbmpOld,eax
	mov edx,[ebx].rcItem.right
	mov ecx,[ebx].rcItem.bottom
assume esi:nothing
	mov esi,[ebx].rcItem.left
	mov edi,[ebx].rcItem.top

	sub edx,esi
	sub ecx,edi

	.IF [ebx].itemAction == ODA_DRAWENTIRE
	invoke BitBlt,[ebx].hdc,esi,edi,edx,ecx,hdcMem,0,0,SRCCOPY
	invoke GetTextMetrics,[ebx].hdc,addr tm
	lea ecx,[edi][edi][34]
	mov eax,StructAddr
assume eax:ptr ClassTable
	sub ecx,tm.tmHeight
	mov edx,[eax].dClass
	shr ecx,1
	mov eax,[eax].dSize
assume eax:nothing
	invoke TextOut,[ebx].hdc,34,ecx,edx,eax
	.ENDIF
	.IF [ebx].itemState == ODS_SELECTED || [ebx].itemAction == ODA_SELECT
	invoke DrawFocusRect,[ebx].hdc,addr [ebx].rcItem
	.ENDIF
	invoke SelectObject,hdcMem,hbmpOld
	invoke DeleteDC,hdcMem

	assume ebx:nothing
@r1:	mov eax,1
	ret
@r0:	xor eax,eax
	ret
@Lb3Sel:
.data
Lb3Current dd -1
.code
	xor ebx,ebx
	invoke SendMessage,lParam,LB_GETCURSEL,ebx,ebx ;ebx=0
	cmp eax,Lb3Current
	mov Lb3Current,eax
	je @r
;1 обнулим 1 и 2ой лист боксы
	invoke SendMessage,hLbClasses,LB_RESETCONTENT,ebx,ebx ;ebx=0
	invoke SendMessage,hLbChoosen,LB_RESETCONTENT,ebx,ebx ;ebx=0
;-------------------------------------------------------------------------------------------------------------------------------------
;Установим в нули основные показатели
;Total choosen ; Total available будет заполнено после нового заполнения
	mov dword ptr numTotalCh,030h
	invoke SendMessage,hNumTotalC,WM_SETTEXT,ebx,offset numTotalCh ;ebx=0
;Заполним нулями окно отражающее  значение текущего выделеного стиля
	invoke SendMessage,hNumCurrentV,WM_SETTEXT,ebx,ebx ;ebx=0
;Choosen classes value
;Dec
	invoke SendMessage,hTotalDec,WM_SETTEXT,ebx,ebx ;ebx=0
;Bit
	invoke SendMessage,hTotalBit,WM_SETTEXT,ebx,ebx ;ebx=0
;Hex
	invoke SendMessage,hTotalHex,WM_SETTEXT,ebx,ebx ;ebx=0
;Обнулим окно описания
	invoke SendMessage,hEdit,WM_SETTEXT,ebx,ebx ;ebx=0
;-------------------------------------------------------------------------------------------------------------------------------------
;Заполним новыми значениями hLbClasses
;-------------------------------------------------------------------------------------------------------------------------------------
	invoke SendMessage,hDrawListBox,LB_GETCURSEL,ebx,ebx ;ebx=0
@fillfirst:
	lea eax,[eax*8]
	lea esi,[eax*2][eax][Classes] ;addr of record for selected item
	cmp esi,Classes+(sizeof ClassTable *3) ;if #recored > 3 status=chip else status = globe
.data?
fSameStat dd ?
.code
	mov ecx,fSameStat ;current Status state
	mov eax,0
	adc eax,0		;eax=1 if chip else eax=0
	cmp eax,ecx	;do we need redraw picture in status, is it differrent?
	je SameStat	;it's not - skip repaint
	mov fSameStat,eax ;save current status
	mov eax,dword ptr [eax*4][offset hStatbmp] ;load into eax hndl of appropiate picture
	mov hStatCurrent,eax	;load it in variable used it status DWRAWITEM code
	invoke SendMessage,hStatus,SB_SETTEXT,SBT_OWNERDRAW,eax ;send msg to status
								;that it needs redraw item
SameStat:
assume esi:ptr ClassTable
	mov edi,[esi].lpdTable ;first record
	mov ebx,[esi].cMembers ;number of records
	invoke SetWindowText,hClassName,[esi].nClass ;display the name of the class
assume esi:nothing
	invoke udw2str,ebx,addr buffer ; convert to string number of styles
	invoke SendMessage,hNumTotalA,WM_SETTEXT,0,addr buffer ;display total number of styles

;Fill the first listbox with names of styles of the class
;-------------------------------------------------------------------------------------
@@:	invoke SendMessage,hLbClasses,LB_ADDSTRING,0,[edi] ;first mbr address of string
	invoke SendMessage,hLbClasses,LB_SETITEMDATA,eax,edi ;accocate with offset of record
	add edi,12 ;shift to next record
	dec ebx 
	jne @B ;all records? not - do again

;----------------------------------------------------------------------------------	
;Disable all hb Windows
;----------------------------------------------------------------------------------

	mov edi,CumNum
	xor eax,eax
	mov PrevCumNum,edi
	mov CumNum,eax ;eax = 0
	invoke SendMessage,hStatus,SB_SETTEXT,3,eax ;eax=0
	jmp @bitenble

@@SIZE:	
	invoke SendMessage,hStatus,WM_SIZE,0,0
	ret

@@VKEYTOITEM:
	cmp word ptr wParam,13
	jne @F
	mov eax,lParam
	mov ecx,10
	cmp eax, hLbClasses
	je @10
	inc ecx
@10:	lea edx,[ecx][LBN_DBLCLK*65536]
	invoke SendMessage,hWnd,WM_COMMAND,edx,eax ;eax = lParam edx hword LBN_DBLCLK, low ID
@@:	mov eax,-1
	jmp @r
WndProc endp

DlgProc proc uses ebx esi edi hWnd,uMsg,wParam,lParam
.data?
hlbVirtual 	dd ?
hlbSingle 	dd ?
hlbComplex 	dd ?
hrbCurrent	dd ?
hrbAll		dd ?
rctn RECT <>
hrbAllDC dd ?
hdc dd ?
hBrush	dd ?
.code
	mov eax,uMsg
WM_CASE eax,<CLOSE,COMMAND,INITDIALOG,PAINT>
	xor eax,eax
	ret
@@PAINT:
	mov edi,hWnd
	invoke BeginPaint,edi,offset pnts
	mov ebx,eax
	invoke FrameGrp,hlbVirtual,hlbComplex,1,2,1
	invoke SelectObject,ebx,hBrush
	invoke Ellipse,ebx,520,15,620,40
	invoke SetTextColor,ebx,Blue
	invoke  SetBkColor,ebx,0000FF80h
	invoke TextOut,ebx,544,20,offset SvinStr,sizeof SvinStr
	invoke EndPaint,edi,offset pnts
	jmp @r	
@@INITDIALOG:
	invoke CreateSolidBrush,0000FF80h
	mov hBrush,eax
	mov ebx,hWnd
	mov esi,offset hlbVirtual
	mov edi,10
@@:
	invoke GetDlgItem,ebx,edi
	mov [esi],eax
	cmp edi,14
	lea esi,[esi+4]
	lea edi,[edi+1]
	jne @B

	mov edi,20
	mov esi,hlf3

@@:	invoke GetDlgItem,ebx,edi
	invoke SendMessage,eax,WM_SETFONT,esi,1
	cmp edi,22
	lea edi,[edi+1]
	jne @B

.data
lblTotalV 	db 'Total virtual flags:'
lblVvalue dd 5 dup (0)
lblTotalB 	db 'Total basic flags:'
lblBvalue db 5 dup (0)
lblTotalA 	db 'Total complex flags:'
lblAvalue db 5 dup (0)
lblAll	db 'All:'
lblAllvalue db 5 dup (0)
lblTbl dd offset lblTotalV,offset lblTotalB,offset lblTotalA,offset lblAll
lblTblV dd offset lblVvalue,offset lblBvalue,offset lblAvalue,offset lblAllvalue
.code
	mov edi,30
@@:	push edi
	invoke GetDlgItem,ebx,edi
	mov ecx,[esp]
	mov edi,eax
	sub ecx,30
	invoke SendMessage,eax,WM_SETTEXT,0,[ecx*4][offset lblTbl]
	invoke SendMessage,edi,WM_SETFONT,esi,1
	cmp dword ptr [esp],33
	pop edi
	lea edi,[edi+1]
	jne @B
	mov CurSelFlag,0FFFEh
	jmp @r
; firsttime
@@COMMAND:
	mov eax,wParam
	mov ebx,lParam
	cmp eax,2
	mov ecx,eax
	je @@exit
	shr ecx,16
	jne @r
.data
Groups dd Current, All
.data?
CurSelFlag dd ?
IfPrevAll dd ?

.code

	invoke SendMessage,hrbAll,BM_GETCHECK,ecx,ecx
	jmp [eax*4][offset Groups]


Current:	
firsttime:	
	invoke SendMessage,hDrawListBox,LB_GETCURSEL,eax,eax
	cmp eax,CurSelFlag
	mov CurSelFlag,eax
	je @r
	cmp eax,LB_ERR
	lea ebx,[eax*8]
	lea eax,[eax*8]
	lea ebx,[eax*2][ebx][Classes]
	jne @F
	mov ebx,offset General

@@:
	assume ebx: ptr ClassTable
	mov edi,2
@@:	invoke SendMessage,[edi*4][offset hlbVirtual],LB_RESETCONTENT,0,0
	dec edi
	jns @B

	mov edi,[ebx].cMembers
	mov esi,[ebx].lpdTable
	assume ebx:nothing
;esi = String esi+4 = Value
@@:	
	mov eax,[esi+4]			;в eax значение стиля в текущей записи
	xor ebx,ebx	;1
	mov edx,eax	;0
	cmp ebx,eax	;1
	lea ecx,[eax][-1]	;0
	adc ebx,0		;1
	xor edx,ecx	;0
	and edx,eax	;1
	cmp edx,eax	;1
	adc ebx,0		;1
	invoke SendMessage,[ebx*4][offset hlbVirtual],LB_ADDSTRING,0,[esi]
	add esi,12
	dec edi
	jne @B
	mov IfPrevAll,0
	mov eax,1
	jmp fillcount
All:
	cmp IfPrevAll,1
	je @r
	mov edi,2
@@:	invoke SendMessage,[edi*4][offset hlbVirtual],LB_RESETCONTENT,0,0
	dec edi
	jns @B

	mov ebx,offset General
OutLoop:	push ebx
	assume ebx: ptr ClassTable
	mov edi,[ebx].cMembers
	mov esi,[ebx].lpdTable
	assume ebx:nothing
;esi = String esi+4 = Value
@@:	
	mov eax,[esi+4]			;в eax значение стиля в текущей записи
	xor ebx,ebx	;1
	mov edx,eax	;0
	cmp ebx,eax	;1
	lea ecx,[eax][-1]	;0
	adc ebx,0		;1
	xor edx,ecx	;0
	and edx,eax	;1
	cmp edx,eax	;1
	adc ebx,0		;1
	invoke SendMessage,[ebx*4][offset hlbVirtual],LB_ADDSTRING,0,[esi]
	add esi,12
	dec edi
	jne @B
	cmp dword ptr [esp],offset General +(sizeof ClassTable * 13) ;*13 means 14 members in ClassTable (!)
	pop ebx
	lea ebx,[ebx + sizeof ClassTable]
	jne OutLoop
	mov CurSelFlag,0FFFFh
	mov IfPrevAll,1
	
fillcount:
	mov ebx,2
	mov edi,32
	xor esi,esi
@@:	invoke SendMessage,[ebx*4][offset hlbVirtual],LB_GETCOUNT,0,0
	add esi,eax
	invoke udw2str,eax,[ebx*4][offset lblTblV]
	invoke SetDlgItemText,hWnd,edi,[ebx*4][offset lblTbl]
	dec edi
	dec ebx
	jns @B
	invoke udw2str,esi,offset lblAllvalue
	invoke SetDlgItemText,hWnd,33,offset lblAll
	jmp @r
@@CLOSE:
@@exit:	mov CurSelFlag,0EFFFh
	mov IfPrevAll,0
	mov ecx,3
@@:	mov edi,dword ptr [ecx*4][offset lblTblV]
	dec ecx
	mov byte ptr [edi],0
	jns @B
	invoke EndDialog,hWnd,1
@r:	mov eax,1
	ret
DlgProc endp
	end start