# ...a fancy 'about' BOX

This program is just another example of the custom 'about' box first introduced in lesson 17. It uses a 'modal' window type, without a title bar.
Since there is no title bar, ( WS_CAPTION ),
no minimize, ( WS_MINIMIZE ),
no maximize, ( WS_MAXIMIZEBOX ),
and no [x] to escape the window,
I've used a normal 'OK' button to exit the window.

Since there is no point in letting the user re-size this 'about' box, we will use the ( WS_DLGFRAME ) style. This leaves us with nothing but:
{ WS_POPUP, WS_DLGFRAME} ),
...to define our window style for Win2.

To 'fancy' this ABOUT box up a bit, it will include a bitmap picture, and within this picture I will define an area, which will cause an action to take place whenever the mouse is moved within that area, and another action to take place when the mouse is clicked within that area.

Whenever the mouse is moved within this area of the bitmap, the program will 'un-hide' a simple text window, which will move along with the mouse pointer.
If the mouse is clicked within this area, it will start up your web browser to go to the main Euphoria web-site.

...and what's a 'fancy' ABOUT box without some muzak. ;- )

-- aboutbox2.exw

    without warning
    include win32lib.ew

    atom map, jk
    integer x1, x2, y1, y2
    sequence loc2

    constant
    -- out 'main' program window
    MyWin = create( Window, "..fancy that !", 0, 0, 0, 325, 448, 0 ),

    -- the untitled message-box window
    Win2    = create( Window, "", MyWin, 0, 0, 334, 290, {WS_POPUP, WS_DLGFRAME} ),
    Bitmap1 = create( Bitmap, "", Win2, 2, 51, 322, 120, 0 ),

    -- some text to go in our about box
    about1 = "This custom  ABOUT  box demo has\n" &
              "a web-link 'hot spot' in the bitmap.",
    about2 = "This program was written in the\n" &
              "EUPHORIA programming language, \n" &
              "available at http://www.rapideuphoria.com, \n" &
              "using win32lib by David Cuny.",

    Title1 = create( CText, about1, Win2, 2, 10, 322, 40, 0 ),
    Title2 = create( CText, about2, Win2, 2, 175, 322, 80, 0 ),
    -- a CText( ) *WITH* a border
    myhint = create( CText, "Go to rapideuphoria.com",
          Bitmap1, 0, 0, 170, 18, or_all( {WS_CHILD, ES_CENTER, WS_BORDER} ) ),
    -- our only means of escape
    Button1 = create( PushButton, "OK", Win2, 128, 255, 70, 25, 0 ),
    -- and a simple menu
    MenuHlp = create( Menu, "&Help", MyWin, 0, 0, 0, 0, 0 ),
    HlpAbout= create( MenuItem, "&About", MenuHlp, 0, 0, 0, 0, 0 ),

    --to play MIDI
      mciSendString = registerw32Function( winmm, "mciSendStringA",
                        {C_INT, C_INT, C_INT, C_INT}, C_INT )

    setWindowBackColor( MyWin, rgb( 127, 127, 255 ) )
    setWindowBackColor( Win2, rgb( 0, 127, 127 ) )

    -- MIDI play routines, from midi.ew by Brent Hugh.
    procedure MciSendString( sequence String, integer a, integer b, integer c )
    integer result
    atom outMsg
       outMsg=allocate_string( String )
       result = w32Func( mciSendString, {outMsg, a, b, c} )
    end procedure

    procedure PlayMidiFile( sequence MidiFile )
    sequence outMsg
       --load the file  "A_Song" is the handle of the loaded song
       outMsg="open " & MidiFile & " type sequencer alias A_Song "
       MciSendString ( outMsg, 0, 0, 0 )
       --play the loaded file
       outMsg="play A_Song"
       MciSendString ( outMsg, 0, 0, 0 )
    end procedure

    procedure CloseMidi( )
    --need to close the device to re-use it !.
    sequence outMsg
    outMsg="close A_Song"
       MciSendString ( outMsg, 0, 0, 0 )
    end procedure
    -- end of midi code.

    --slightly modified loadBitmapFromFile2( )
    --reads BMP from file to memory.
    function loadBmpResource(  sequence fileName, atom fSize )
      atom        bmFile, bmInfoHeader, bmBits, bmColors, hdc, hDib
      integer     hFile, byte

      hFile = open(  fileName, "rb"  )
      bmFile = allocate(  fSize  )
      for i = 0 to fSize-1 do
      byte = getc(  hFile  )
        poke(  bmFile+i, byte  )
      end for
      close( hFile )

      bmInfoHeader = bmFile + SIZEOF_BITMAPFILEHEADER
      bmBits = bmFile + fetch(  bmFile, bfOffBits  )
      bmColors = bmInfoHeader + SIZEOF_BITMAPINFOHEADER
      hdc = getDC(  Screen  )

      hDib = w32Func(  xCreateDIBitmap, {
      hdc, address(  bmInfoHeader, bmiHeader  ),
      CBM_INIT,
      bmBits,
      bmInfoHeader,
      DIB_RGB_COLORS}  )
      releaseDC(  Screen  )
      free(  bmFile  )
      return hDib
    end function

    -- this procedure centers our about box
    procedure center_win( atom win_id )
    sequence loc
    atom xsize, ysize, posx, posy
    loc=getRect( win_id )
    xsize=loc[3]-loc[1]
    ysize=loc[4]-loc[2]
    posx=floor( ( w32Func( xGetSystemMetrics, {SM_CXFULLSCREEN} )/2 )-( xsize/2 ) )
    posy=floor( ( w32Func( xGetSystemMetrics, {SM_CYFULLSCREEN} )/2 )-( ysize/2 ) )
    setRect( win_id, posx, posy, xsize, ysize, 1  )
    end procedure

    procedure about(atom self, atom event, sequence params)
    setVisible( myhint, 0 )
    openWindow( Win2, Modal )
    PlayMidiFile( ".\\Bin\\roary2.mid" )
    end procedure

    procedure start_up(atom self, atom event, sequence params)
    map=loadBmpResource(  ".\\Bin\\eu.bmp", 19798  )
    setBitmap(  Bitmap1, map  )
    -- center our about box, even though it's still hidden
    center_win( Win2 )
    -- find our bitmap
    -- and calculate the 'hot zone' at which
    -- our mouse will show the CText( ) window
    loc2=getRect( Bitmap1 )
    x1=loc2[1]+70
    x2=loc2[3]-80
    y1=loc2[2]+17
    y2=loc2[4]-17
    end procedure

    procedure close1(atom self, atom event, sequence params)
    closeWindow( Win2 )
    CloseMidi( )
    end procedure

    procedure on_bitmap(atom self, atom event, sequence params)
      integer mouse_event mouse_event = params[1]	-- fetch values from params (new style)
      atom x   x = params[2]  -- also mouse x and y
      atom y   y = params[3]

    -- if our mouse is within the 'hot zone'
    if x > x1 and x < x2 and y > y1 and y < y2 then
      if mouse_event = MouseMove then
        setRect( myhint, x-85, y-67, 170, 20, 1  )
        setVisible( myhint, 1 )
      end if
    -- if the mouse is clicked within the 'hot zone'
      if mouse_event=LeftDown then
        setVisible( myhint, 0 )
        close1( )
        CloseMidi( )
        shellExecute( "open", "http://www.rapideuphoria.com", Modal )
      end if
    else
    setVisible( myhint, 0 )
    end if
    end procedure

    procedure kill_prog(atom self, atom event, sequence params)
    CloseMidi( )
    jk=w32Func( xDeleteObject, {map} )
    end procedure

    setHandler( MyWin, w32HOpen,  routine_id( "start_up" ) )
    setHandler( HlpAbout, w32HClick,  routine_id("about") )
    setHandler(Button1, w32HClick,  routine_id("close1") )
    setHandler( Win2, w32HMouse,  routine_id("on_bitmap") )
    setHandler( MyWin, w32HDestroy, routine_id("kill_prog") )

    WinMain( MyWin, Normal )
    --end--

In case anyone's wondering about the loadBmpResource( ) function I'm using in this demo, they should check out Extra_06, which benchmarks two different ways of getting bitmap data from a resource file.

While I'm not actually using a resource file with included bitmaps here, in most distributable files, I probably would.

In Lesson 18 I pointed out that you can have more than one bitmap in a single resource file, and also 'bind' the resource file to your executable. All in one !

I have also included another example of this program for this lesson.
aboutbox3.exw
I won't show the whole program here, but just explain it's major differences. You can check out the complete source code, if you want to see all the details.

The first major difference, is that I have defined a custom cursor which is to be used within the 'hot-spot'. This is just a simple 'hand', like the pointer you usually see in web browsers. It's defined like this:

    --a custom cursor for the 'web-link'
    myPointer = createMousePointer(  5, 1, {
    "    xxx          ",
    "   x...x         ",
    "   x...x         ",
    "   x...x         ",
    "   x...x         ",
    "   x...x         ",
    "   x...xxx       ",
    "   x...x..xxx    ",
    "   x...x..x..xxx ",
    " xxx...x..x..x..x",
    "x..x...x..x..x..x",
    "x..x...x..x..x..x",
    "x..x...x..x.....x",
    "x...............x",
    "x...............x",
    "x..............x ",
    " x............x  ",
    "  x...........x  ",
    "   x..........x  ",
    "   x..........x  ",
    "   x..........x  ",
    "   xxxxxxxxxxxx  ",
    "   xxxxxxxxxxxx  "}  )

Using this cursor required some changes to the on_bitmap[] mouse handling routine, as follows:

    procedure on_bitmap(atom self, atom event, sequence params)
      integer mouse_event mouse_event = params[1]	-- fetch values from params (new style)
      atom x   x = params[2]  -- also mouse x and y
      atom y   y = params[3]

      -- change the mouse pointer to the 'hand' defined by myPointer.
      setMousePointer(  Win2, myPointer  )
      if mouse_event = MouseMove then
        setRect( myhint, x-85, y-67, 170, 20, 1  )
        setVisible( myhint, 1 )
      end if
      if mouse_event = LeftDown then
        setVisible( myhint, 0 )
        close1( )
        CloseMidi( )
        shellExecute( "open", "http://www.rapideuphoria.com", Modal )
      end if
    else
    setVisible( myhint, 0 )
    -- change back to standard mouse pointer.
    setMousePointer(  Win2, NULL  )
    end if
    end procedure

...and, of course, I've 'wrapped' the two following functions, in order to both move, and trap the mouse cursor into the about box. ;- )

    --to move the mouse cursor to the about box.
    zSetCursorPos = registerw32Function( user32, "SetCursorPos",
                      {C_INT, C_INT}, C_INT ),
    --to confine the mouse cursor to the about box.
    zClipCursor = registerw32Function( user32, "ClipCursor", {C_POINTER}, C_INT )

...end...

CONTENTS