The MASM Forum

General => The Workshop => Topic started by: jj2007 on January 28, 2017, 08:51:02 PM

Title: Event-driven programming
Post by: jj2007 on January 28, 2017, 08:51:02 PM
There is a remarkably poor Wikipedia page on Event-driven programming (https://en.wikipedia.org/wiki/Event-driven_programming), therefore here a few examples on how it can be done in assembly, using the MasmBasic library (http://masm32.com/board/index.php?topic=94.0).

Example #0: a full-fledged window with a menu, its event handler, and a message monitor
GuiParas equ "Event-driven programming in Assembly", x500, y20, w200, h200, cblack, b00FFFFD0h
GuiMenu equ @File, &Open, &Save, -, E&xit, @Edit, Undo, Copy, Paste
include \masm32\MasmBasic\Res\MbGui.asm

Event Menu ; this event returns MenuID
  Switch_ MenuID
  Case_ 0
MsgBox 0, "You clicked Open", "Hi", MB_OK ; first menu item has MenuID 0
  Default_
MsgBox 0, Str$("You clicked menu #%i", MenuID), "Hi", MB_OK ; MenuID=0, 1, 2, ...
  Endsw_

Event Message ; this event returns hWnd, uMsg, lParam, wParam
  inc msgCount ; if the internal msgCount variable
  deb 4, "msg", chg:msgCount ; changes, deb shows the current uMsg

GuiEnd


The code above creates a small window (w200, h200) with a menu. Every message passing the Event Message handler is being displayed in the console. As the screenshot below shows, in this specific moment mainly menu messages appeared.
Title: Event-driven programming
Post by: jj2007 on January 28, 2017, 08:53:58 PM
Example #1 uses simple handlers for the WM_PAINT and WM_KEYDOWN messages:
include \masm32\MasmBasic\Res\MbGui.asm ; no GuiParas, no GuiMenu: defaults will be used
SetGlobals lastkey ; define a global variable

Event Key ; returns VKey, e.g. VK_A, VK_DOWN, ...
  mov lastkey, VKey
  If_ VKey==VK_F1 Then call You_Hit_F1
  GuiRefresh ; force a Paint event

Event Paint ; returns PtDC (=esi)
  invoke TextOut, PtDC, 20, 20, chr$("size the window or press a key to see how the ticks change"), 58
  invoke TextOut, PtDC, 20, 50, str$(rv(GetTickCount)), 10 ; str$ is a standard Masm32 macro; length 10 is guessed
  GuiText 20, 80, Str$("The last key was %i ", lastkey)         ; the GuiText macro provides more features then TextOut
  GuiText 150, 80, Chr$(" or rather: ", lastkey, " ") ; display the char pressed (may not work for special keys)
EndOfEvents ; put user procs below this line

You_Hit_F1:
  MsgBox 0, "No help, sorry...", "Hi", MB_OK
  ret
GuiEnd


When the user presses any key, the key event is triggered; if the key happens to be F1, an "external" routine placed after the events but before the end of the program (GuiEnd) is called.

During Event Key, the variable VKey (internally: edi), plus the booleans KeyCtrl, KeyAlt and KeyShift are available for the coder to decide any specific action, such as calling You_Hit_F1.

In the example above, the Paint event is being used to display the current ticks and the last pressed key, using both the standard Windows API TextOut and the GuiText macro.
Title: Event-driven programming
Post by: jj2007 on January 28, 2017, 09:26:16 PM
Example #3 creates a window with a listbox and a richedit control that accepts dropped files and displays their content:
GuiParas equ "Dropping files is simple"
include \masm32\MasmBasic\Res\MbGui.asm

  GuiControl FilesBox, "listbox", w=200, x1000-175, +WS_BORDER
  GuiControl Content, "richedit", w=800

Event DropFiles
  SetListbox Files$()
  wMsgBox 0, wCat$(wStr$("%i files dropped, first one is\n[", Files$(?))+wRec$(Files$(0))+"], last one is "+CrLf$+"["+wRec$(Files$(Files$(?)-1))+"]"), "Event Dropfiles:", MB_OK or MB_TOPMOST

Event Notify
  .if NotifyCode==LBN_SELCHANGE
mov ecx, Files$(LbSel) ; get the name of the selected file
SetWin$ hContent=FileRead$(ecx) ; put its content into the richedit control
  .endif
GuiEnd


As the screenshot demonstrates, Unicode file names are no problem.

Attached is a single source with all examples. Open in RichMasm, select GuiParas and hit F6 to build them.
Title: Re: Event-driven programming
Post by: hutch-- on January 28, 2017, 10:44:47 PM
Its an old terminology for a UI application that sets up a window, a message loop to dispatch system messages and a message processing procedure. The message handling procedure "WndProc" is the gate to manage "events" to which an action (click on a button etc ...) produces an event which you write code to respond to. It is the architecture of Windows 3.0 and later UI code.

The layout of a basic window is an application that sits idling until the system sends it a message to which it can respond. If the system sends a message to a window the message loop activates, passes the message to the WndProc which funnels it to the processing code.
Title: Re: Event-driven programming
Post by: TWell on January 29, 2017, 12:05:20 AM
WndProc was since Windows 1.0 ;)
Title: Re: Event-driven programming
Post by: BlameTroi on January 29, 2017, 12:27:26 AM
Right after structures/pointers (dsects in my world), event-driven programming seemed to be the most difficult thing for new programmers to grasp. "Where's the mainline?"
Title: Re: Event-driven programming
Post by: jj2007 on January 29, 2017, 02:41:41 AM
Quote from: hutch-- on January 28, 2017, 10:44:47 PM
Its an old terminology for a UI application that sets up a window, a message loop to dispatch system messages and a message processing procedure. The message handling procedure "WndProc" is the gate to manage "events" to which an action (click on a button etc ...) produces an event which you write code to respond to. It is the architecture of Windows 3.0 and later UI code

Right. See e.g. Events (Visual Basic) (https://msdn.microsoft.com/en-us/library/ms172877.aspx) of July 2015. Why it has to be so horribly complicated in VB, no idea. Micros**t 8)

GuiParas equ "Key events only", x50, y50, w100, h60, s0
include \masm32\MasmBasic\Res\MbGui.asm

GuiControl MyStatic, "static"

Event Key
  mov esi, VKey
  SetWin$ hMyStatic=Chr$("You pressed ", esi)
GuiEnd
Title: Re: Event-driven programming
Post by: jj2007 on December 21, 2017, 02:30:50 AM
New beta version of the Gui** macros attached, replacing \Masm32\MasmBasic\Res\MbGui.asm
Building the attached SkelGuiGroup.asc requires a) the new macros and b) a current MasmBasic installation, i.e. version 19 December 2017 (http://masm32.com/board/index.php?topic=94.0) or later.

Tested so far on Win7-64, it looks OK. I know the colours can cause eye cancer, but the red & green is meant to check if the margins are OK. Grateful for feedback on other systems, especially fonts, margins, behaviour when resizing etc...

The timer event shows the current time with millisecond precision. Check with Task Manager if that causes a high cpu usage.
Title: Re: Event-driven programming
Post by: hutch-- on December 21, 2017, 07:54:17 AM
Looks fine here on my Win10 Pro. I don't mind the colours, in small areas is looks fine. One whinge, put a manifest in the resources, gives you the later appearance and gives crappy AV scanners less reason to squark about your exe.
Title: Re: Event-driven programming
Post by: Siekmanski on December 21, 2017, 09:15:06 AM
Works perfect on Win 8.1, smoothly resizing the windows and fonts are perfect too.
Task manager shows 0.0% cpu load.
Title: Re: Event-driven programming
Post by: LiaoMi on December 21, 2017, 10:59:51 AM
Hi,

if you type a string with a space, then the selection of the full line doesnt work, only a part before the space is selected. Maybe it was so programmed, the rest works  :t
Title: Re: Event-driven programming
Post by: jj2007 on December 21, 2017, 11:16:43 AM
Thanks, Marinus :icon14:

Quote from: hutch-- on December 21, 2017, 07:54:17 AMput a manifest in the resources, gives you the later appearance

Can you see any difference?? The progressbar behaves differently, see attachment, but the rest looks identical to me ::)

Quote from: LiaoMi on December 21, 2017, 10:59:51 AMif you type a string with a space, then the selection of the full line doesnt work, only a part before the space is selected.

I tried that now, but if I click left of the string, the whole line gets selected. No such problem here, or do you mean something else?

One thing that puzzles me is the look of the progressbar. With manifest (version 6.16), it has always the PBS_SMOOTH look, whether the style is specified or not ::)
Title: Re: Event-driven programming
Post by: hutch-- on December 21, 2017, 01:56:57 PM
>  it has always the PBS_SMOOTH look, whether the style is specified or not

You can thank Microsoft for this loss of choice. I prefer the later one but its typical Microsoft.
Title: Re: Event-driven programming
Post by: jj2007 on December 21, 2017, 05:42:19 PM
Quote from: hutch-- on December 21, 2017, 01:56:57 PM
>  it has always the PBS_SMOOTH look, whether the style is specified or not

You can thank Microsoft for this loss of choice. I prefer the later one but its typical Microsoft.

The old 'blocky' progressbar is somewhat clearer - if it advances, you recognise immediately what it is. But you are right that choices are really limited here. What did you mean with "newer look & feel"? Even with a Win7 manifest, I can't see a difference on Win7, while a test on Win10 shows tiny differences:
- the reset button changes colour when hovering over it
- same for the MsgBox OK button (press 'A' to see it)
- the progressbar is green and continuous

I vaguely remember that I once saw MsgBox buttons that had a gradient fill, but no idea how to arrive there :(

P.S.: I found the culprit - apparently the newer styles are visible in Win7 only when you enable that ugly "Aero" thing!
See How To Get Windows 7 Look For Controls? (https://stackoverflow.com/questions/5663091/programming-in-c-win-api-how-to-get-windows-7-look-for-controls) and the messy MSDN article Enabling Visual Styles (https://msdn.microsoft.com/en-us/library/bb773175.aspx#ignore_top_level).
(http://www.webalice.it/jj2006/pics/GuiGroupAero.png)
Title: Re: Event-driven programming
Post by: jj2007 on December 22, 2017, 07:13:36 AM
New version attached, including a date & time picker and a trackbar. Code is now a whopping 75 lines long ;-)
Title: Re: Event-driven programming
Post by: hutch-- on December 22, 2017, 10:35:01 AM
This one will not run, it pops a message box saying it could not open MbSnippets.asc for Recall FileRead$.
Title: Re: Event-driven programming
Post by: jj2007 on December 22, 2017, 05:38:33 PM
Oops, I forgot that this file is present only in MasmBasic installations :bgrin:

Try attached version 4 then. You can drag a plain text or RTF file over the exe to see its content in the edit control. The included source SkelGuiGroup.asc will do, for example. If you max the window, it even becomes a source viewer, but beware, clicking on some other control (case, full word, date, time) will use the edit control.

Note that, as a demo, the trackbar resets the progressbar. The trackbar control has a very odd way to communicate its status, it sends a WM_HSCROLL message:

Event Message
  .if uMsg_==WM_HSCROLL                 ; horizontal trackbar sends this message
        mov eax, lParam_
        .if eax==hTrack
                mov ticks, rv(GetTickCount)             ; try to sync with progressbar ;-)
                shl rv(SendMessage, lParam_, TBM_GETPOS, 0, 0), 9
                sub ticks, eax
        .endif
  .elseif uMsg==WM_CLOSE ...
Title: Re: Event-driven programming
Post by: LiaoMi on December 22, 2017, 07:01:44 PM
Quote from: jj2007 on December 21, 2017, 11:16:43 AM

Quote from: LiaoMi on December 21, 2017, 10:59:51 AMif you type a string with a space, then the selection of the full line doesnt work, only a part before the space is selected.

I tried that now, but if I click left of the string, the whole line gets selected. No such problem here, or do you mean something else?


Hi,

thats what I meant, correct, this is strange, I tested on windows 10 latest version, selection after space doesnt work, the fourth version ends with an exception.

EXCEPTION_DEBUG_INFO:
           dwFirstChance: 1
           ExceptionCode: C0000005 (EXCEPTION_ACCESS_VIOLATION)
          ExceptionFlags: 00000000
        ExceptionAddress: 004057EF skelguigroup.004057EF
        NumberParameters: 2
ExceptionInformation[00]: 00000000 Read
ExceptionInformation[01]: 00000000 Inaccessible Address
First chance exception on 004057EF (C0000005, EXCEPTION_ACCESS_VIOLATION)!
Title: Re: Event-driven programming
Post by: hutch-- on December 22, 2017, 07:24:26 PM
Nope, version 4 does not run at all. 51712 bytes, if I double click on it, the cursor changes for a moment but it exits without displaying the window.
Title: Re: Event-driven programming
Post by: jj2007 on December 22, 2017, 08:03:57 PM
Thanks, Hutch & LiaoMi. Does it also crash when you drag a file over the exe? It seems that my check for Exist(commandline) has a problem. Should be fixed with attached version 5:

Version 4 (early macro expansion):If_ Exist(CL$()) Then SetWin$ hBigEdit=FileRead$(Exist$)

Version 5 (macro expansion delayed):If_ Exist(CL$()) Then <SetWin$ hBigEdit=FileRead$(Exist$)>

[rant]it won't crash with Win7-64, and only Win7-64, because Micros**t grabs exceptions when they happen inside WndProc[/rant]

This is how it should look like, with the source in the background:(http://www.webalice.it/jj2006/pics/SkelGuiGroup5.png)
Title: Re: Event-driven programming
Post by: hutch-- on December 22, 2017, 08:18:31 PM
Yep, everything on this one worked fine. Looks OK on my Win10 64 pro.
Title: Re: Event-driven programming
Post by: jj2007 on December 22, 2017, 08:28:25 PM
Great, thanks :t

I know this programming style is a bit like the Antichrist for the assembler purist (and I already convinced José to dedicate himself to VB .NOT (http://masm32.com/board/index.php?topic=6771.msg72454#msg72454)); it is a demo how powerful a macro assembler can be. Compare that for example to the desperate attempts of QT to provide a UI system that is compatible between Windows and Linux; my code produces exes around 50k, their code for a hello world UI app starts at 8MB or so.

And the code above is not just a hello world, it's a full-fledged Windows application with 17 controls that loads a RTF file from the commandline and pins a string array into the listbox etc ... the 40k overhead is there, of course, so it won't qualify for the "smallest exe ever" contest. But it works, I use it actually quite a lot for my private stuff :icon_cool:

P.S.: Just learned something when testing in my XP VM: If the manifest includes a reference to GdiPlus 1.1, the OS complains about a bad configuration. The attached XP version has a barebones manifest and loads controls version 6.00. They look nice, actually.
Title: Re: Event-driven programming
Post by: LiaoMi on December 22, 2017, 08:43:50 PM
 ::) Find - Replace still dont mark all text, when I do double-click. All other components work fine  :t
Title: Re: Event-driven programming
Post by: aw27 on December 22, 2017, 08:58:37 PM
Quote from: jj2007 on December 22, 2017, 08:28:25 PM
I know this programming style is a bit like the Antichrist for the assembler purist (and I already convinced José to dedicate himself to VB .NOT (http://masm32.com/board/index.php?topic=6771.msg72454#msg72454));
As much as I have convinced you to produce a compiler for your High Level Language and not be dependent on assemblers.  :icon_rolleyes:
Title: Re: Event-driven programming
Post by: jj2007 on December 22, 2017, 09:07:08 PM
Quote from: LiaoMi on December 22, 2017, 08:43:50 PM
::) Find - Replace still dont mark all text, when I do double-click. All other components work fine  :t

The RichEdit control behaves like that, see screenshot below.
If you place the cursor near the left border, the cursor looks to the right, and a double-click selects the full line
If you place the cursor on top of a single word, the cursor looks to the left, and a double-click selects the word.
Title: Re: Event-driven programming
Post by: LiaoMi on December 22, 2017, 09:57:38 PM
Quote from: jj2007 on December 22, 2017, 09:07:08 PM
Quote from: LiaoMi on December 22, 2017, 08:43:50 PM
::) Find - Replace still dont mark all text, when I do double-click. All other components work fine  :t

The RichEdit control behaves like that, see screenshot below.
If you place the cursor near the left border, the cursor looks to the right, and a double-click selects the full line
If you place the cursor on top of a single word, the cursor looks to the left, and a double-click selects the word.

Here everything is fine, but in the text edit component (Find text edit - Replace text edit), it does not work, just right-click and select all helps.
Title: Re: Event-driven programming
Post by: HSE on December 23, 2017, 12:43:54 AM
Quote from: aw27 on December 22, 2017, 08:58:37 PM
As much as I have convinced you to produce a compiler for your High Level Language and not be dependent on assemblers.  :icon_rolleyes:
:biggrin:

Quote from: jj2007 on December 22, 2017, 08:28:25 PM
I know this programming style is a bit like the Antichrist for the assembler purist
:biggrin:  You can add here that some people like MasmBasic but are incapable to fight with RichMasm   :(  (of course, to use MasmBasic independently require a help file that you never will write).

 

Title: Re: Event-driven programming
Post by: jj2007 on December 23, 2017, 02:05:59 AM
Quote from: HSE on December 23, 2017, 12:43:54 AM:biggrin:  You can add here that some people like MasmBasic but are incapable to fight with RichMasm

Open the *.asc source in WordPad or MS Word, select all, copy, paste in qEditor, and off you go ;-)
Title: Re: Event-driven programming
Post by: LordAdef on December 26, 2017, 01:54:34 PM
What's the problem with Richmasm? It's a neat ide.
Title: Re: Event-driven programming
Post by: jj2007 on December 26, 2017, 07:44:24 PM
That's a nice comment, Alex, is it Christmas? :biggrin:

New version of the controls demo is here (http://masm32.com/board/index.php?topic=94.msg72735#msg72735) and looks like this:
(http://masm32.com/board/index.php?action=dlattach;topic=94.0;attach=7435;image)
Title: Re: Event-driven programming
Post by: jj2007 on January 02, 2018, 09:21:31 PM
We are almost there! Work in progress, the final version will be under 100 lines of code, the exe has 54,784 bytes.
(http://www.webalice.it/jj2006/pics/TableControl.png)
The app features a menu, static, edit, richedit, date+time, progressbar, trackbar, button controls, it can open the links to MasmBasic and MSDN, and the spreadsheet at the bottom can be edited and saved.
Title: Re: Event-driven programming
Post by: LiaoMi on January 02, 2018, 09:59:22 PM
Hi jj2007,

I have a bug, Im running from the desktop  :redface:

---------------------------
Fatal error:
---------------------------
Could not open
FatTable.tab
for Recall, FileRead$ etc.


---------------------------
OK   
---------------------------
Title: Re: Event-driven programming
Post by: jj2007 on January 02, 2018, 10:29:00 PM
Hmmm... sorry, it expects that file. If you have Excel, take a spreadsheet and save it tab-delimited as fattable.tab. Can't post one right now.
Title: Re: Event-driven programming
Post by: LiaoMi on January 02, 2018, 11:05:27 PM
The mathematical table is borrowed here https://www.rapidtables.com/math/symbols/Basic_Math_Symbols.html (https://www.rapidtables.com/math/symbols/Basic_Math_Symbols.html) - Basic math symbols.

If you press if you open a group of colors, there will be a black color by default, if you click cancel, the color changes anyway ...
Title: Re: Event-driven programming
Post by: jj2007 on January 02, 2018, 11:43:57 PM
What do you mean with "press a group of colors"?
Title: Re: Event-driven programming
Post by: LiaoMi on January 03, 2018, 01:08:22 AM
Quote from: jj2007 on January 02, 2018, 11:43:57 PM
What do you mean with "press a group of colors"?

I apologize for mental shift :icon_redface: Edit > Group Colour > Cancel
Title: Re: Event-driven programming
Post by: jj2007 on January 03, 2018, 01:18:12 AM
Ah, ok! I was so concentrated on getting the table control right that I had forgotten that there is functionality behind one of the menus :bgrin:

Next step will be to teach the table control to do some things automagically, like detecting whether the spreadsheet is in tab or csv format; maybe offer a choice between "use first line in spreadsheet as header text" vs "use A B C as in Excel". Row colours could be set by the user, too; and first of all, a simple way to access elements of the table (and that part is easy).

If anybody has clear ideas what are essential features of a spreadsheet control, post them here, please.
Title: Re: Event-driven programming
Post by: hutch-- on January 03, 2018, 10:30:26 AM
JJ,

Its been a long time since I have done on but usually spreadsheet tables are usually done with a modified list view control. I confess I never liked the interface to a listview control and see the common controls as an ugly add on interface but you can get them to work if you are patient. The listview control usually has the selectable bar at the top so you don't have to use the first line as headings.
Title: Re: Event-driven programming
Post by: jj2007 on January 03, 2018, 10:57:36 AM
Quote from: hutch-- on January 03, 2018, 10:30:26 AMusually spreadsheet tables are usually done with a modified list view control.
Yes, that's what I am using.

QuoteThe listview control usually has the selectable bar at the top so you don't have to use the first line as headings.
I plan to leave it to the user/coder if the first line is used for the SysHeader32. Excel, for example, uses just A...Z, AA, AB, etc
But it may look nicer, and has practical advantages, to use line 0 as headers, see screenshot below and attached latest version, btw with an excerpt from a real tricky UN database.
Title: Re: Event-driven programming
Post by: LiaoMi on January 03, 2018, 07:15:13 PM
An example was taken from the site radasm.cherrytree.at, I like the ability to use graphics from the table  :icon14: The example application is SprDemo.exe

Title: Re: Event-driven programming
Post by: jj2007 on January 03, 2018, 08:11:17 PM
Nice demos, LiaoMi. Do you have a link to the documentation of the API? I like SprDemo.exe in particular :t
Title: Re: Event-driven programming
Post by: LiaoMi on January 03, 2018, 11:35:02 PM
This page is no longer available on the Internet. Was there any documentation available? I could not find anything in my archive  :icon_rolleyes:
Title: Spreadsheet editor
Post by: jj2007 on January 26, 2018, 06:21:28 AM
My flu is getting better, and version 2 looks almost OK. Testing requires FatTable.tab in the same folder as the exe, the archive can be downloaded here (http://www.webalice.it/jj2006/FatTable.zip).

The source needs a lot of polishing still, my apologies that I don't dare to include it here. Note that the FatTable.tab can be loaded also with Excel, MS Word or LibreOffice Calc. It just takes a little bit longer - assembly rocks :badgrin:

Note also that:

- LibreOffice complains after ca. 20 seconds that it can't load everything, "excess rows not loaded bla bla", but the last ten rows or so are there. But don't take that as proof of correctness: Further up many rows are missing, about 400 or 10% of the whole database. Interesting for a spreadsheet software, aren't they meant for accounting and other legal & financial stuff?

- MS Excel loads it in "only" 3-4 seconds, with about 50 lines more because Excel can't handle the occasional linefeed in a cell (FatTable.tab contains an official UN database).

Have fun ;)
Title: Spreadsheet editor
Post by: jj2007 on February 17, 2018, 12:39:42 PM
New version, with embedded data. Inter alia, there is now a search function, just hit Ctrl F.
Right-clicking opens a context menu. Note that e.g. "Show selection" won't work if you selected megabytes of data :(
Undo with Ctrl Z and Redo with Ctrl Y work (in view mode, press Escape if you are in edit mode)
This is still work in progress - use at your own risk, and not for valuable data.