Write a Win32Lib Notepad application (Part 1)

Posted

Photo by Serge Kutuzov on Unsplash

Contents

Getting started

Now that we have Win32Lib installed, let’s use it to write a complete application from start to finish. We’ll be cloning everyone’s favorite text editor, Notepad! You may be surprised how much work goes into such a simple application.

The code I’m showing here will require that you’ve followed Clean up your code by fixing up Win32Lib.

Fire up Notepad++ and open click File > New. Then click File > Save As… and name it notepad.exw.

You can download the complete code from this article here: notepad1.exw (1kB)

Basic layout

The arrangement of a Win32Lib application typically goes like this:

  • include files
  • define controls
  • assign events
  • run main loop

Include files

These are the basic files we’ll need to include:

  • Win32Lib.ew is, of course, the main library with all of the GUI routines
  • std/filesys.e provides routines to easily parse file name parts
  • std/io.e provides routines to easily load and save text files
  • std/win32/msgbox.e provides a standard Windows interface

include Win32Lib.ew
include std/filesys.e
include std/io.e
include std/win32/msgbox.e

Define controls

We’ll need a few controls to get started:

  • Main is a Window – our main window
  • Editor is an MleText – a Multi-Line Edit text control
  • Status is our StatusBar – this sits at the bottom of the window

The create routine accepts eight parameters:

  • integer ctype – the control type to be created
  • sequence text – the text to be assigned to the control
  • integer parent – the parent control ID
  • object left – the left position of the control
  • object top – the top position of the control
  • object width – the width of the control
  • object height – the height of the control
  • object style – additional or default styles for the control

We’re going to need a couple extra window styles:

  • ES_NOWORDWRAP uses WS_HSCROLL and ES_AUTOHSCROLL to disable word wrapping
  • SBARS_SIZEGRIP adds a grip to the StatusBar, but is not included in Win32Lib by default

Win32Lib adds a few styles to controls by default that looked good on previous versions of Windows but they don’t look so great on Windows 10. We’ll turn those off with the removeStyle routine.

constant ES_NOWORDWRAP = WS_HSCROLL+ES_AUTOHSCROLL
constant SBARS_SIZEGRIP = 256

constant
	Main        = create( Window, "Notepad", 0, Center, Center, 960, 600 ),
	Editor      = create( MleText, "", Main, ,,,, ES_NOWORDWRAP ),
	Status      = create( StatusBar, "", Main, ,,,, SBARS_SIZEGRIP ),
$

removeStyle( Editor, {WS_BORDER,WS_EX_CLIENTEDGE} )

Assign events

We didn’t give our Editor control any position or size values, so if you ran this application right now, the control would be nowhere to be found. We can fix that by handling the OnResize event and giving the control some boundaries.

Every Win32Lib event handler is a procedure that requires three parameters:

  • integer self – the control ID of the control generating the event; generated by the create routine
  • integer event – the event ID of the event type being generated; constants declared as w32H-event name
  • sequence params – a list of optional parameters unique to each event

Events are assigned using the setHandler routine, which accepts three parameters:

  • object id – one control ID or a sequence of control IDs to be assigned to this handler; same as above
  • object event – one event ID or a sequence of control IDs to be assigned to this handler; same as above
  • object rtn_id – one routine ID or a sequence of routine IDs to handle the event(s); use routine_id

In most cases you’ll assign one control and one event to a handler routine. You could also assign many controls to the same handler for the same event, and then branch the handler with if or switch blocks, which we’ll see later. I typically name my event handler something obvious like ControlName_EventType but that’s entirely up to you.

Resize event

Now, back to our resize problem. We’ll catch the OnResize event and then use setRect to put the control into place.

The setRect routine accepts six parameters:

  • integer id – the ID of the control to be resized
  • object left – the new left position of the control
  • object top – the new top position of the control
  • object width – the new width of the control
  • object height – the new height of the control
  • integer repaint – a flag indicating to repaint the control after it’s resized

The setRect routine also has a few tricks up its sleeve for each of the size parameters:

  • Specify an interger value as an absolute position
  • Specify an atom value between 0.0 and 1.0 as a percentage
  • Specify the constant w32Edge to align the control’s parent edge
  • Specify the constant w32AltEdge to align the control’s parent opposite edge
  • Specify a sequence { constant, value } where:
    • constant is w32Edge or w32AltEdge
    • value is an integer or atom to offset from that edge

As it turns out, setRect is pretty powerful. I recommend experimenting with these options to get the hang of it.

We’re just going to use setRect to dock the Editor control to the outer bounds of the window with w32Edge.

procedure Main_OnResize( integer self, integer event, sequence params )

	-- dock the Editor to the outer bounds and force it to repaint
	setRect( Editor, w32Edge, w32Edge, w32Edge, w32Edge, w32True )

end procedure
setHandler( Main, w32HResize, routine_id("Main_OnResize") )

The main loop

Now that we have some controls defined and an event handler for OnResize, we can run our application with WinMain.

The WinMain routine accepts two parameters:

  • integer id – the control ID of the Window to be the main window
  • integer style – the initial state of the window: Normal, Minimized, or Maximized

Add this line to the end of our file, save it, and press your Run in Euphoria key (mine is F6).

WinMain( Main, Normal )

Hello, Notepad! In the next part, we’ll add some menus and fill out the basic file loading routines.

Author
Categories Beginner, Win32Lib