PHP WinBinder 4: Rollover

From The Uniform Server Wiki
Jump to navigation Jump to search

 

UniServer 5-Nano
PHP WinBinder 4 - Tray Menu.

WinBinder Part 4 - Rollover effect

Introduction

Depending on the application creating a rollover effect with WinBinder is straightforward. We require this effect for our tray pop-up menu hence is explained in detail.

Type of window to use

First decision to make is the type of window to use. For a tray menu the NakedWindow is most suitable. This is a fixed-size application window with no border and no title bar. You can add standard windows components as required; our rollover example uses two buttons Minimize and Exit these are included for testing.

Menu items - draw text directly

Menu items can be displayed using labels however changing a label’s background and foreground colours is difficult. An alternative is to draw text directly to the window this gives us finer control and the ability to dynamically change both background and foreground colours.

Note: Drawing over a complete window would obscure our two test buttons. Examples avoid this by drawing in a space directly above them. Our final menu does not use any buttons hence the whole window is drawn over.

Top

Starting point

Example 1

This tutorial includes working examples; rollover_1.phpw is a basic window that displays some text. Note the line that creates a window, it includes WBC_NOTIFY and parameter WBC_REDRAW. When a redraw is required this parameter is passed to the handler function.

The following lines check parameter passed if a redraw is requested runs the function draw_on_window

if($lparam1 & WBC_REDRAW) {  // A redraw required.(e.g. minimize to max)   
 draw_on_window($window);   // Yes: Call redraw function
}

When a window is minimised and restored it generates a redraw request. To see this in action comment out the line

  • draw_on_window($window);

Run the script, minimize and restore the application. The redraw function is not executed hence a naked window is displayed.

The draw_on_window function is called during initial windows creation process (just after the buttons are created) and then as required by the system.

Note 1: the font to use is defined at the top of the script, of importance are colour setting and font height. Font height is defined in points and NOT pixels this becomes an issue when building a list of menu items this will be resolved later.

Note 2: "Tahoma" is the system default font if you wish choose a different one.

  • $font_text = wb_create_font("Tahoma", 8, BLACK, 0);

 



Naked window:

Top

Script - rollover_1.phpw

<?php
include "winbinder.php";

//=== Constants

define("APPNAME", "WinBinder Borderless Window"); // Title displayed in taskbar

$win_width   = 300;
$win_height  = 200;
$win_height2 = 140; // This would be full window height
$win_x       = 200;
$win_y       = 200;

//== Font to use for drawing
$font_text = wb_create_font("Tahoma", 8, BLACK, 0);

// Create main window
$mainwin = wb_create_window(NULL, NakedWindow, APPNAME, WBC_CENTER, WBC_CENTER, $win_width, $win_height,
 WBC_NOTIFY , WBC_REDRAW);

// Add controls
 wb_create_control($mainwin, PushButton, "Exit",  	  10,160, 90, 25, IDCLOSE);
 wb_create_control($mainwin, PushButton, "Minimize",  	 200,160, 90, 25, WBC_MINIMIZED);

 draw_on_window($mainwin); // Draw additional features 

// Assign handler 
wb_set_handler($mainwin, "process_main");

// Start main loop
wb_main_loop();

//=== Handler function ========================================================

/* Process main window commands */

function process_main($window, $id, $ctrl, $lparam1=0, $lparam2=0){
  switch($id) {

    case IDDEFAULT:

      if($lparam1 & WBC_REDRAW) {  // A redraw required.(e.g. minimize to max)   
        draw_on_window($window);   // Yes: Call redraw function
      }
    break;

    case WBC_MINIMIZED:                    // Minimise button clicked
      wb_set_size($window, WBC_MINIMIZED); // Minimize window
    break;

    case IDCLOSE:                          // Exit button clicked
      wb_destroy_window($window);          // Destry window 
      wb_destroy_font();                   // Destroy all fonts
    break;
  }
}
//=== END Handler function ====================================================

//=== Draw on window ==========================================================

function draw_on_window($win){
 global  $win_width;
 global  $win_height2;
 global  $font_text;

 // Draw rectangles
 wb_draw_rect($win, 0, 0, $win_width, $win_height2, WHITE);          // White canvas
 wb_draw_rect($win, 0, 0, $win_width, $win_height2, BLACK,FALSE,5 ); // Border around window

 // Draw some text
 wb_draw_text($win, "Basic building block  基本构建块 and Unicode.", 25, 20, 0, 0, $font_text);
 wb_draw_text($win, "Basic building block  基本构建块 and Unicode.", 25, 50, 0, 0, $font_text);
}
//=== END Draw on window ======================================================
?>

Top

Add text background and foreground colour

Example 2

We have a basic building block now let’s add text background and foreground colour.

At beginning of the script we defined the following text and background colours:

//== Font to use for drawing
$font_text_black = wb_create_font("Tahoma", 8, BLACK, 0);
$font_text_white = wb_create_font("Tahoma", 8, WHITE, 0);

//== Background colour
$back_black = BLACK;
$back_white = WHITE;

 

The redraw section has been modified to the following:

function draw_on_window($win){
 global  $win_width;
 global  $win_height2;
 global  $font_text_black;
 global  $font_text_white;
 global  $back_black;
 global  $back_white;

  // Draw rectangles
 wb_draw_rect($win, 0, 0, $win_width, $win_height2, GREEN);          // Green canvas
 wb_draw_rect($win, 0, 0, $win_width, $win_height2, BLACK,FALSE,5 ); // Border around window

// Draw backgrounds
 wb_draw_rect($win, 10, 15, 280, 30, $back_white);          // Text Background
 wb_draw_rect($win, 10, 50, 280, 30, $back_black);          // Text Background

 // Draw some text
 wb_draw_text($win, "Basic building block  基本构建块 and Unicode.", 25, 20, 0, 0, $font_text_black);
 wb_draw_text($win, "Basic building block  基本构建块 and Unicode.", 25, 55, 0, 0, $font_text_white);

Note: background rectangles are drawn before text otherwise the text will be obscured.

Run test script (double click on rolloever_2.bat) it almost looks like a menu!

Top

Adding mouse support

Example 3

With the basic structure in place we need to add mouse support.

This is achieved by specifying notification of mouse events in the window creation function. We require mouse down and move. The create function parameters are shown below:

$mainwin = wb_create_window(NULL, NakedWindow, APPNAME,
  $win_x, $win_y, $win_width, $win_height, WBC_NOTIFY | WBC_TOP
  | WBC_TASKBAR , WBC_DBLCLICK | WBC_MOUSEDOWN | WBC_MOUSEUP
  | WBC_MOUSEMOVE | WBC_REDRAW);

The handler will now receives mouse events. Mouse x and y coordinates are obtained using the following lines:

    $x = $lparam2 & 0xFFFF;              // Get mouse co-ords
    $y = ($lparam2 & 0xFFFF0000) >> 16;  // Get mouse co-ords
    print "\nMouse $x $y\n"; // For test only

Add above to the handler function jest below redrawn section.

Run example 3. Mouse over window note mouse coordinates displayed in the command window.

 

Top

Add rollover effect

Example 4

Now we are ready to add the rollover effect. First we need to pass the x and y coordinates to the redraw function (see last line).

    $x = $lparam2 & 0xFFFF;              // Get mouse co-ords
    $y = ($lparam2 & 0xFFFF0000) >> 16;  // Get mouse co-ords
    draw_on_window($window,$x,$y);       // Run mouse over      

We are parsing extra parameters to the “draw_on_window” function hence the function definition requires modification as follows:

function draw_on_window($win,$x=0,$y=0){

Note: The “=0” is added to both x and y, required because the function accepts one or three parameters.

Now we can target each rollover area and change background and foreground accordingly. Fore example:

// Create rollover for text 1
 if( ($x >= 5) && ($x <= 280)  && ($y >= 15) && ($y <= 40) ){
  wb_draw_rect($win, 10, 15, 280, 30, $back_black);          // Text Background
  wb_draw_text($win, "Basic building block  基本构建块 and Unicode.", 25, 20, 0, 0, $font_text_white);
 }
 else{
  wb_draw_rect($win, 10, 15, 280, 30, $back_white);          // Text Background
  wb_draw_text($win, "Basic building block  基本构建块 and Unicode.", 25, 20, 0, 0, $font_text_black);
 }

If mouse is within the defined area draw that colour else draw the inverse.

Redraw flicker problem

Run example 4 (double click on rollover_4.bat) and mouse over the text areas.

The mouse over effect works perfectly shame about the flickering artefacts.

Top

Flickering explained

As the mouse moves each pixel movement forces a new window redrawn. Redraws occur in rapid succession and is processor intensive. For each active process a system allocates time slots and cycles through these giving each process a slice of processor time. This prevents the system stalling however switching can occur partway through a window redraw. Other application time slots are processed; on retuning to complete a redraw a significant amount of time has elapsed it’s this gap that produces flickering.

Top

How to avoid redraw flicker

Example 5

Although flickering cannot be prevented there is a trick and that is to hide it from a user! Solution is to perform all redrawing in the background, on completion make that result visible. Switching is extremely fast hence no flicker.

  • Create a label and position it where a redrew is required.
  • In the redraw section first create an image. Same size as above label
  • Perform all drawing on this image (any flickering occurs in background)
  • On completion assign image to label (switching)
  • Delete the image

The above is a general technique it can be applied in other situations where a noticeable flicker is present.

 

Example 5 includes the following modification:

Under controls add a frame to place the image:

//== Add image frame
$frame = wb_create_control($mainwin, Frame, "", 0, 0, $win_width, $win_height2, 101, WBC_IMAGE);

Modify “draw_on_window” function as follows:

Under “global” add the following lines:

global  $frame;

print "\nmmm$x $y\n"; // For test only

//== Create an image
$bmp = wb_create_image($win_width, $win_height2);

Change functions “wb_draw_rect” and “wb_draw_text” replace $win with $bmp each function now draws to the image.

Finally add the following to end of function:

wb_set_image($frame, $bmp); // Swith image to label
 wb_destroy_image($bmp);     // Delete image 

Run example 5 I think you will agree the result is dramatic.

Note: Additional information What is an image resource?

Top

Complete rollover test script (Template)

rollover_5.phpw

<?php
/*
###############################################################################
# Name: rollover_5.phpw
# Developed By: The Uniform Server Development Team
# Modified Last By: Mike Gleaves (Ric)
# Web: http://www.uniformserver.com
# V1.0 2-5-2009
# Comment: WinBinder tutorial (Part 4)
###############################################################################
*/

include "winbinder.php";

//=== Constants

define("APPNAME", "WinBinder Borderless Window"); // Title displayed in taskbar

$win_width   = 300;
$win_height  = 200;
$win_height2 = 140; // This would be full window height
$win_x       = 200;
$win_y       = 200;

//== Font to use for drawing
$font_text_black = wb_create_font("Tahoma", 8, BLACK, 0);
$font_text_white = wb_create_font("Tahoma", 8, WHITE, 0);

//== Background colour
$back_black = BLACK;
$back_white = WHITE;


// Create main window
$mainwin = wb_create_window(NULL, NakedWindow, APPNAME,
  $win_x, $win_y, $win_width, $win_height, WBC_NOTIFY | WBC_TOP  | WBC_TASKBAR ,
  WBC_DBLCLICK | WBC_MOUSEDOWN | WBC_MOUSEUP | WBC_MOUSEMOVE | WBC_REDRAW);

// Add controls
 wb_create_control($mainwin, PushButton, "Exit",  	  10,160, 90, 25, IDCLOSE);
 wb_create_control($mainwin, PushButton, "Minimize",  	 200,160, 90, 25, WBC_MINIMIZED);

//== Add image frame
$frame = wb_create_control($mainwin, Frame, "", 0, 0, $win_width, $win_height2, 101, WBC_IMAGE);

 draw_on_window($mainwin); // Draw additional features 

// Assign handler 
wb_set_handler($mainwin, "process_main");

// Start main loop
wb_main_loop();

//=== Handler function ========================================================

/* Process main window commands */

function process_main($window, $id, $ctrl, $lparam1=0, $lparam2=0){
  switch($id) {

    case IDDEFAULT:

      if($lparam1 & WBC_REDRAW) {  // A redraw required.(e.g. minimize to max)   
        draw_on_window($window);   // Yes: Call redraw function
      }

    $x = $lparam2 & 0xFFFF;              // Get mouse co-ords
    $y = ($lparam2 & 0xFFFF0000) >> 16;  // Get mouse co-ords
    draw_on_window($window,$x,$y);       // Run mouse over

    break;

    case WBC_MINIMIZED:                    // Minimise button clicked
      wb_set_size($window, WBC_MINIMIZED); // Minimize window
    break;

    case IDCLOSE:                          // Exit button clicked
      wb_destroy_window($window);          // Destry window 
      wb_destroy_font();                   // Destroy all fonts
    break;
  }
}
//=== END Handler function ====================================================

//=== Draw on window ==========================================================

function draw_on_window($win,$x=0,$y=0){

 global  $win_width;
 global  $win_height2;
 global  $font_text_black;
 global  $font_text_white;
 global  $back_black;
 global  $back_white;
 global  $frame;

print "\nmmm$x $y\n"; // For test only

//== Create an image
$bmp = wb_create_image($win_width, $win_height2);

 // Draw rectangles
 wb_draw_rect($bmp, 0, 0, $win_width, $win_height2, GREEN);          // Green canvas
 wb_draw_rect($bmp, 0, 0, $win_width, $win_height2, BLACK,FALSE,5 ); // Border around window

// Create rollover for text 1
 if( ($x >= 5) && ($x <= 280)  && ($y >= 15) && ($y <= 40) ){
  wb_draw_rect($bmp, 10, 15, 280, 30, $back_black);          // Text Background
  wb_draw_text($bmp, "Basic building block  基本构建块 and Unicode.", 25, 20, 0, 0, $font_text_white);
 }
 else{
  wb_draw_rect($bmp, 10, 15, 280, 30, $back_white);          // Text Background
  wb_draw_text($bmp, "Basic building block  基本构建块 and Unicode.", 25, 20, 0, 0, $font_text_black);
 }

// Create rollover for text2
 if( ($x >= 5) && ($x <= 280)  && ($y >= 50) && ($y <= 80) ){
  wb_draw_rect($bmp, 10, 50, 280, 30, $back_black);          // Text Background
  wb_draw_text($bmp, "Basic building block  基本构建块 and Unicode.", 25, 55, 0, 0, $font_text_white);
 }
 else{
  wb_draw_rect($bmp, 10, 50, 280, 30, $back_white);          // Text Background
  wb_draw_text($bmp, "Basic building block  基本构建块 and Unicode.", 25, 55, 0, 0, $font_text_black);
 }

 wb_set_image($frame, $bmp); // Swith image to label
 wb_destroy_image($bmp);     // Delete image 

}
//=== END Draw on window ======================================================
?>

Top

Summary

The above rollover effect is general purpose and can be applied to text and images.

What may not be obvious is the significance of function draw_on_window.

The rollover effect is purely cosmetic and secondary to the prime function of selecting a menu item. Knowing which menu item is selected allows us to extract its corresponding data from a master array and return it. The function is a major component in our final tray menu.

More cosmetics (Icons) are covered on the next page extracting a single image from an image strip.

Top