US Tray Menu 2: Implementation

From The Uniform Server Wiki
Jump to navigation Jump to search


UniServer 5-Nano
US Tray Menu 2.
UniServer 6-Carbo

US Tray Menu 2 Implementation


This page covers implementing a predefined command.

It assumes no additional commands have been implemented hence first covers how to integrate these into the menu architecture.


Master array

On starting our tray menu data from the configuration file is used to build a master array. Before drawing the menu we want to update this master array using an initialisation function.

This is run from two specific locations:

  • Just after the main window creation
  • Inside main handler function. Called (run) for each redraw request

Lets call this function main_init() integration as shown below:

$mainwin = wb_create_window(NULL, NakedWindow, APPNAME,
  $win_x, $win_y, $win_width, $win_height, WBC_NOTIFY | WBC_TOP  | WBC_TASKBAR ,

//== Update server status
main_init();               // Update main array to match server status

Main handler function

if($lparam1 & WBC_REDRAW) {                 // A redraw required.(e.g. minimize to max)   
 main_init()    ;                          // Update main array to match server status
 mouse_over($window,$frame_1,'main_menu',$win_width, $win_height); // Yes: Call redraw function

When a menu item is clicked tray menu is always minimised. Every time our tray menu is maximised function main_init is executed providing real time monitoring of server status.


Command master array mapping

Main initialisation function (main_init) uses the following master array command mappings.

$main[$i][1]   men1[]      item[] = "Longest text"
$main[$i][2] men2[] action[] = "cmd_xxxx"
$main[$i][3] men3[] file[] = "Text 1"
$main[$i][4] men4[] parameter[] = "Text 2"
$main[$i][5] men5[] icon[] = "Optional Id"

From our point of view only element we know about is men2[]; its one of our predefined commands. If a user has included this menu item in the configuration file it will appear in the master array.

We cannot take for granted a user is using all predefined commands hence the master array is always scanned for existence of predefined commands.

Note: Complete mater array elements see this page


Unavailable Icon

Icons such as start and stop are a complementary pair. Another icon pair is available and unavailable this applies to several menu items.

Currently in the icon image strip there is no icon for Unavailable. I have added a new icon (id 22) this is a circle with a slash indicating Unavailable.

Similarly complementary pairs applies to text, for example "Admin Panel" and "Admin Panel (Unavailable)" text pairs are user definable and translatable into other languages.


Apanel Example

The above ideas are better explained with a simple example for this we will use the Apanel menu item.


Apanel command

This we have already defined (cmd_apanel – Run Apanel)

Configuration file

The configuration file entry needs to be changed from this:

item[]      = "Admin Panel"
action[]    = "runh"
file[]      = "php.exe"
parameter[] = " -n unitray_info.php 1"
icon[]      = "11" 

To this:

men1[] = "Admin Panel (Unavailable)"
men2[] = "cmd_apanel"
men3[] = "Admin Panel"
men4[] = "Admin Panel (Unavailable)"
men5[] = "" 

Note 1: At first it would appear men1[] is not required however it is used to determine maximum width of the menu or sub-menu. Hence set its value to the longest of the two strings.

Note 2: It is possible to run with above changes only. Our menu will not be broken a menu item is displayed with incorrect text (Admin Panel (Unavailable) and no icon.


Initialisation function

Initialisation function determines current server status and configures menu items accordingly.

Master array is scanned for a command (cmd_apanel) configured in the configuration file and perform appropriate task for example:

//=== MAIN INIT ================================================================
// Update main array to match server status

function main_init() {
 global $main; // Master array

 for($i = 0; $i < count($main); $i++) {        // Scan main array
   if($main[$i][2] == "cmd_apanel"){           // Target command
     print "Command found";                    // Do something
//================================================================ MAIN INIT ===

Appropriate task in this example is to print.

What we really require is for the menu item to reflect its availability. It has two states these are dependent on the Apache server’s state which can be determine with function “apache_running()”

If Apache running:

  • Show available icon
  • Display available text


Apache not running

  • Show unavailable icon
  • Display unavailable text

The following code implements the above

//=== MAIN INIT ================================================================
// Update main array to match server status

function main_init() {
 global $main; // Master array

 for($i = 0; $i < count($main); $i++) {        // Scan main array
  //==Command cmd_apanel
  if($main[$i][2] == "cmd_apanel"){            // Target command
      if(apache_running()){                    // Is Apache running
        $main[$i][1]  = $main[$i][3];          // Set available text
        $main[$i][5]  = "7";                   // Set available icon
      else{                                    // No:
        $main[$i][1]  = $main[$i][4];          // Set uavailable text
        $main[$i][5]  = "22";                  // Set unavailable icon
   //== End command cmd_apanel
//================================================================ MAIN INIT ===


Command processor function

When menu item is clicked command processor needs to intercept the command and decide what to do.

There are two states again dependent on Apache serve’s status. If running execute indicated command.

Apache not running and user clicks menu item inform user to start Apache server.

The above states gives this code:

// There are only two types of command to process run and runh (run hidden)

  //==Command cmd_apanel
  if($command_array[0] == "cmd_apanel"){          // Intercept command
      if(apache_running()){                       // Is Apache running
        $cmd = "php.exe  -n unitray_info.php 1" ; // Cmd to run hidden
        $cmd = relative_to_absolute_paths( $cmd); // convert

        $cmd1 = "\"";             // Start quote
        $cmd2 = $cmd;             // Full path and file name to run
        $cmd3 = "\" ";            // Add final quote

        $cmd4 = $cmd1.$cmd2.$cmd3;    // build command string
        wb_exec( "uniserv.exe",   $cmd4);
      else{                                    // No:
       $str =  "To enable and run this menu item\n";
       $str .= "please start Apache server.";
       wb_message_box (NULL, $str, "Unavailable");       
   //== End command cmd_apanel

  //== Convert paths

First line (statement incorrect) and last line are provided to show where the new code is placed. Additional code for new commands are placed sequentially.

Code structure is intentionally unchanged to reflect existing code currently in this function.

Note 1: Each command added requires similar code. To prevent duplication all identical code is encapsulated into a function.

Note 2: Although the above code is functional in final code it introduces an undesirable side effect, command window opens for a short period this is addressed later.



If you have been following this verbatim run the menu with and without Apache running.

Click Apanel menu item expected results as above.



I have show how easy it is to transform our static menu to provide dynamic user feedback. Price paid is additional code, however it is well worth it just to prevent that dead application feel after clicking a menu item.

Applying the above techniques to all other applicable menu items enhances the menu.

An interesting dilemma is one of pop-up message boxes more precisely text displayed. This text is currently embedded within our scripts making life difficult for translators clearly an undesirable situation.

Next page covers Language support