## WinBinder scratchpad (miscellaneous notes)

NOTE: These are rough notes. They will be moved from here sooner or later.

# Running WinBinder — some notes (must be reviewed — must give credit where appropriate)

Associating the PHPW extension with WinBinder

To run WinBinder scripts for Windows Explorer, you have to associate .phpw files with php-win.exe. You can accomplish this in several ways.

Option 1. If you use the WinBinder installer, this will be done automatically for you.

Option 2. To manually associate the .phpw extension to php-win.exe:

1. In Explorer, go to Tools - Folder options and select the File Types tab.
2. Press New.
3. From there, you probably have to browse for the php-win.exe file
4. Then you have the option of always using that program for .phpw files. Check it.

In Windows 2000 or Windows XP, you can right-click on the .phpw file and select "Open With...". In some cases, you might need to hold down Shift for the "Open With..." to appear.

To associate the phpw extension with WinBinder: In Windows Explorer, go to Tools / Folder options, then select the File types tab. Click New. This will open a small dialog. Type phpw, then click OK. A new item will show up on the list box. The click the Advanced button. This will open a new dialog box. Click New. Another dialog shows up. In the Action field, type open. In the Application field, type (or navigate to) the path to php-win.exe, followed by "%1" (with quotes). Example:

C:\WinBinder\PHP\PHP5\php-win.exe "%1"

Click OK to close the dialog, then OK, then Close. Now you may execute a PHPW script just by double-clicking it.

Option 3. You can also create a FILENAME.REG file to do this for you:

1. Create a text file with Notepad or whatever
2. Give it a .reg extension
3. Place the following lines in it:

`[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.phpw]
@="phpw_auto_file"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\phpw_auto_file]
@="PHP Winbinder App"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\phpw_auto_file\shell]
@="open"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\phpw_auto_file\shell\open]
@="Run Winbinder App"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\phpw_auto_file\shell\open\command]
@="\"C:\\PHP\\WinBinder\\PHP\\PHP4\\php-win.exe\" \"%1\""`

Be sure to change the line C:\\PHP\\WinBinder\\PHP.... to the path where you have your php-win.exe. Also take note of the extra \'s... just like when you have to escape slashes and quotes (a la addslashes()) in PHP. You only use it on the @="" bits, not in the parts between the []'s.

Another note, You see the words "open" appear in there? If you copy all those lines and change "open" to "edit" or something you can create a new right-click option for your files.

The @="open" on the ones ending in \shell needs to match the shell\open (that is, if you had @="edit" you'd then need a corresponding shell\edit)

And the @="Run Winbinder App" on the shell\open is the text that appears in the right-click menu for PHPW files.

Example... to add "Edit PHPW With Notepad" you'd add the following lines to what's already above (at the end probably):

`[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\phpw_auto_file\shell\edit]
@="Edit Winbinder App with Notepad"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\phpw_auto_file\shell\edit\command]
@="%SystemRoot%\\system32\\NOTEPAD.EXE\" \"%1\"`

And if you wanted to make this "edit with notepad" the default double-click action, you'd change the one entry above to be the following:

`[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\phpw_auto_file\shell]
@="edit"`

Now you will see "Edit Winbinder App with Notepad" appear in bold on the right-click menu.

Once you get everything in your .REG file, just double click on it and it'll ask you if you want to add these lines to your registry.

These changes will happen immediately when you edit the registry with regedit or will happen as soon as you click "yes" after double-clicking on the .REG file you created with this stuff in it.

DISCLAIMER!!: This alters your registry. If you do it exactly as I've stated, it won't hurt anything. But if you change it (particularly the parts between the []'s) it could overwrite important system data (although it'd take a fluke to hit something critical I think..so the chances are still relatively low). If this worries you or you're not sure what this is all about, don't do it. Stick with the OPEN WITH thing on the right-click or shift-right-click menu. It does effectively the same thing but only lets you set the default double-click action, not alternate edit/open/etc. actions.

Running WinBinder without a console (DOS) window

- Use php-win.exe instead of php.exe
- Optionally associate .phpw files with php-win.exe (see above)
- Suppress all your output: no echo(), print(), printf(), print_r() etc. in your script. If you do not do that, your script may not run at all.
- Suppress errors: use error_reporting = 0 in PHP.INI. If you do not do that, your script may not run at all with php-win.exe.
- Optionally use display_errors = Off in PHP.INI. If you set error_reporting = 0 this is not necessary.

# Minimum structure for distribution:

#

#

#

#

#

#

    	D:
    	+------ phpcode
    	|       +------ include
    	|       |       *.php
    	|       |       +------ db (if you use the database wrapper functions)
    	|       |               *.php
    	|       +------ resources
    	|               *.bmp
    	|               *.ico
    	+------ bin
            	+------ php4
        					*.*
        				     +------ ext
      		    					*.dll

    Calling a script from a batch (.bat) file
    I use a .bat file with the following:

    @echo
    off
    ..\..\..\php\php-win.exe interface.phpw %1 %2 %3 %4 %5 %6 %7 %8 %9
    %10

    And it opens the dos window and the PHP app window, maybe it is
    because of the batch file? How else can i make the call?

    Try it without a batch file, by associating phpw extension to php-win.exe
    (see ***below***)

    And yes.. you're keeping
    the black DOS screen because you're running a .BAT file.  You might be
    able to right-click on the .BAT and under Properties set it so that the window
    doesn't appear, but that's still not a clean way to do what you want to do.
    If you still want to make it work on a BAT file, you'll need to use the start
    batch command before calling the PHP-WIN.
    Some like that:
    @start ..\..\..\php\php-win.exe interface.phpw %1 %2 %3 %4 %5 %6 %7 %8 %9
    %10
    The console window will open and close in less than a second when the batch
    is processed.

    Associating values with combo boxes and list boxes
    It will be possible to use associative arrays with list boxes and combo
    boxes, but this is not currently possible. There are some workarounds, though:
        1) Pass the position of an item to db_get_id() to obtain its identifier.
    In this case you must not change the
    order in which the items appear on your combo / list box.
    $val = db_get_id($table, wb_get_selected($combobox));

        2) Call wb_get_data() to get the id of an element based on its name. This
    works well as long as you don't have repeated names among the elements. In this
        case you can sort the items in the control.
    $sel = wb_get_text($combobox);
    $data = db_get_data($table, null,
    "name");
    $sel_index = (int)array_search($sel, $data);
    $val =
    db_get_data($table, $sel_index, "id");

    3) For each item, append a series of tab characters, then the
    item id. The id's will be hidden from view but they will be there so you can
    access them directly (using a simple filter or regular expression). In this
    case you can sort the items in the control.
    4) Use the OO interface. Check out
    the sample code at OOi_samples/ooi_listboxes.phpw.

    If you want to use
    some of the OOi features, but don't want to convert your entire code, you may
    temporarily convert your non-ooi objects (like your main window), so you'll
    be able to use it. Check out the example below:

                <?
    define("wbpath", "../");
    require wbpath .
    "/include/winbinder.php";
    require wbpath .
    "/include/ooi.inc.php";

    /**
           Create the main
    window
    **/
    $mainwin  = wb_create_window (NULL, AppWindow, "Sample
    WB
    Application", 320, 240);
    wb_set_handler($mainwin,
    "pc_main");

    /**
           To create the WbComboBox widget, you'll need an
    OOi object as
    parent window.
    **/
    $ooi_mainwin = new
    WbAppWindow($mainwin);

    /**
           As you have the OOi Main Window, you
    can add the 'ComboBox' itself.
           Parameters are:

    $parent ($ooi_mainwin)
                   $position_left

    $position_top
                   $width
                   $height (after
    drop-downed)
                   Array($options)

    $id
                   $style
                   $lparam
           You may add the options later
    if you prefer.
    **/
    $combobox = new
    WbComboBox($ooi_mainwin, 10, 10, 100, 100);
    $combobox->id =
    0x100;
    $combobox->addOption("br",
    "Brazil");
    $combobox->addOption("us", "United
    States");
    $combobox->addOption("value1", "Text number
    1");
    $combobox->addOption("who", "Who let the dogs
    out");

    /**
           By using the OOi, you may also sort your combobox,
    and maintain the values
    **/
    $combobox->sort();

    /**
           So,
    you want to continue using your non-OOi
    codes...
    **/
    wb_create_control($mainwin, Label, "I'm just a label...", 5,
    30, 150, 20);

    wb_main_loop();

    function pc_main($window,
    $id){
           global $combobox;
           if($id ==
    $combobox->id){
                   echo "Combobox hit!\n";

    echo "Selected value: " . $combobox->selectedValue . "\n";

    echo "Selected text:  " . $combobox->selectedDesc  . "\n";

    echo "===================\n";
           }
           if($id ==
    IDCLOSE)
                   wb_destroy_window($window);
    }
    ?>

        When the functionality is implemented in the future you may use an associative array instead:

    wb_set_text($combobox, array(
      "value1" =>
    "Text 1",
      "value2" => "Text 2",
      "value3"
    => "Text 3"
     ));
    or
    wb_set_value($combobox, array(
      "value1" =>
    "Text 1",
      "value2" => "Text 2",
      "value3"
    => "Text 3"
     ));

    In this case, wb_get_value() will return the item value instead of its index as it does today:
    $val = wb_get_value($combobox);

    Adding new styles to existing controls (for C developers)
    WinBinder does not currently allow a
    horizontal scroll bar in edit controls. However, it is easy to add a custom flag to a
    controls. In
    this specific case, create the new flag in wb.h:
    #define WBC_HSCROLL 0x00008000    // This value is not
    usedNote that the value above is an unused value.
    You may reutilize a value, however, which is the recommended practice. First
    you have to make sure it will not conflict with existing flags. In this example
    you could safely use 0x00010000 (WBC_CHECKBOXES) instead of 0x00008000
    because edit controls with check boxes do not make sense. So the line becomes:#define WBC_HSCROLL 0x00010000
       // This value is being reutilized (preferred practice)
    Then add some extra code to
    verify the flag in file wb_control.c,
    function wbCreateControl:

                case EditBox:                                    // Inside the first 'switch' statement
        pszClass = "EDIT";                           // Existing code
        dwStyle = WS_CHILD | WS_TABSTOP | nVisible;  // Existing code
    if(BITTEST(dwWBStyle, WBC_HSCROLL))              // <-- insert this line
        dwStyle |= WS_HSCROLL;                       // <-- and this one
        // ....
        break;                                       // Existing code

    ... and export it as a new PHP constant in phpwb_export.c:
    WB_ZEND_CONST(LONG, "WBC_SCROLL", WBC_HSCROLL)
    Now you may use the new
    constant together with WBC_MULTILINE
    inside your PHP code:

    wb_create_control($win, EditBox, "This edit box has a
    horizontal scroll bar", 20, 20, 160, 70, ID_EDIT, WBC_MULTILINE | WBC_HSCROLL);

    A more proper
    implementation should check if WBC_MULTILINE is also set:

                case EditBox:                                           // Inside the first 'switch' statement
        // ....
        if(BITTEST(dwWBStyle, WBC_MULTILINE)) {
            if(BITTEST(dwWBStyle, WBC_READONLY))
                dwStyle |= WS_VSCROLL | ES_MULTILINE;
            else
                dwStyle |= WS_VSCROLL | ES_MULTILINE | ES_WANTRETURN;
            if(BITTEST(dwWBStyle, WBC_HSCROLL))             // <-- insert this line
                dwStyle |= WS_HSCROLL;                      // <-- and this one
        // ....
        break;

    Compiling the WinBinder manual
    Here's the toolset you'll need:

        Namo Web Editor (or any decent
    WYSIWYG HTML editor will do) to edit the pages;
        TextPad (any text editor except
    Notepad will suffice) for some rare HTML fine tuning and general editing;
        The make_release tool (already
    included in the distribution). You can comment out almost everything and keep only the HTML/CHM code;
        The HTML Help project files in
    tools/html_help (already included in the distribution?);
        The original HTML files (included
    here). Note that they must be processed by make_release before they are built into the CHM;
        HTML Help Workshop from Microsoft.

    About sounds

    Not yet implemented!
    I think wb_play_sound() is fine. I agree that wb_play() is too generic, but
    wb_play_wav() is too specific (more than Windows itself, in fact). The idea
    is to use the Windows API PlaySound() and MCI functions as the basis for
    the sound functions. These are fairly high-level functions. We must not forget
    MIDI files, which are completely different in nature but can be controlled with the same functions.

        wb_load_sound() - load a sound into memory
        wb_destroy_sound() - destroy a sound already in memory
        wb_play_sound() - play a sound asynchronously, optionally looping it
        wb_stop_sound() - stop playing all sounds
        wb_get_sound_info() - return information about a sound (length, current
        position, etc.)
        wb_control_sound() - pause, resume, rewind, seek, etc. (i.e. less common
        commands)

    I'll also create some mechanism to notify the application window when a sound stops.
    A "wild" idea: To reduce the number of functions I'd like to use
    names like wb_load_mm(), wm_play_mm() etc. where "mm" stands for "multimedia",
    or something like that. Thus we could use the same set of functions to control
    video, CDs, DVDs, etc. in the future. I don't like the idea of having wb_play_sound(), wb_play_midi(), wb_play_video(), wb_play_cd(),
    wb_play_dvd() etc. You have probably noticed that I'm obsessively economical
    with creating new functions. This is a kind of mental disorder caused by being exposed to very high doses of Windows API functions and messages for
    many years. :)
    > One other comment. Why a "destroy sound" function? Why not
    just a "wb_destroy()" that does a general collection of the object
    being destroyed, also destroying any child/dependant processes or objects?
    A basic unset() type thing. Anytime you want to destroy something, you just assign *nothing* to
    it. I can't think of a reason why sound/media files need their own destroy function. But maybe someone else has a reason (which is cool with me..
    if someone has a good reason that I don't see, I'm always willing to listen
    and learn).
    The idea here is to be able to load a sound (or video, or MIDI, or other
    multimedia type/stream etc.) into memory with wb_load_mm(), play it or do
    whatever is needed with it (still in memory), then free the memory allocated
    to it. Because WinBinder is not object-oriented (without the OOi layer),
    simply setting it to NULL won't do the job. Here:
    $snd = wb_load_mm("test.wav"); // Load a copy of the media file into memory
    $length = wb_get_sound_info($snd, "length");
    // etc...
    wm_play_mm($snd);
    wb_destroy_mm($snd); // This will deallocate the memory
    The function wb_destroy_mm() would simply call a wbDestroyMM(). This one,
    in turn, would simply check if the pointer passed to it is valid. If yes, just
    call eFree() to liberate the memory allocated with wb_load_mm().

    Accepting multiple values

    Not yet implemented!
    Functions that accept multiple values can accept an array of values or a
    newline-separated string. For example:

                //The following examples are equivalent:

    wb_set_text($tabctrl, array("First", "Second",
    "Third"));
    wb_set_text($tabctrl, "First\r\nSecond\r\nThird");
    wb_set_text($tabctrl, "First\nSecond\nThird");
    wb_set_text($tabctrl, "First\rSecond\rThird");

    are equivalent and produce the same results. Note that CR/LF, LF, and CR may
    be used interchangeably to designate a newline.