HMG_aChoice

HMG Samples and Enhancements

Moderator: Rathinagiri

User avatar
Rathinagiri
Posts: 5264
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 169 times
Been thanked: 172 times
Contact:

HMG_aChoice

Post by Rathinagiri » Mon Jul 19, 2010 9:36 am

Who can forget aChoice() function? :idea:

Here, I have tried to create the basic functionality of aChoice() for a client who is specific on this feature. :)

This is just another version of ComboSearchBox, thanks to Esgici.

Initial version

Code: Select all

#include <hmg.ch>

Function Main
private aCountries := HB_ATOKENS( MEMOREAD( "Countries.lst" ),   CRLF )
public aVar := 1

set navigation extended

define window sample at 0,0 width 800 height 600 main
   define label label1
      row 10
      col 10
      width 100
      value "Name"
   end label
   define textbox textbox1
      row 10
      col 110
      width 100
   end textbox
   define label label2
      row 40
      col 10
      width 100
      value "Country"
   end label
   define textbox textbox2
      row 40
      col 110
      width 100
      on enter doachoice()
   end textbox
   define label label3
      row 70
      col 10
      width 100
      value "City"
   end label
   define textbox textbox3
      row 70
      col 110
      width 100
   end textbox
end window
sample.center
sample.activate
Return

function doachoice
local nTop := 10
local nLeft := 300
local nBottom := 900
local nRight := 800
local nDefault := 1
local nSelected := 0

if len(alltrim(this.value)) > 0
   nDefault := ascan(aCountries,this.value)
endif   
nSelected := HMG_AChoice( nTop, nLeft, , , aCountries, nDefault)
if nSelected > 0
   this.value := aCountries[nSelected]
else
   this.value := ""
endif   
return nil

function HMG_Achoice(nTop,nLeft,nBottom,nRight,aList,nDefault,lAnyWhere)
local nRow := thiswindow.row
local nCol := thiswindow.col
local nWindowWidth := thiswindow.width
local nWindowHeight := thiswindow.height
local nWidth := 0
local nHeight := 0
local i := 0
private _aItems := aclone(aList)
private _nSelected := 0
private lAnyWhereSearch := .f.
default lAnyWhere := .f.
default nDefault := 0
default nBottom := thiswindow.height - 10
default nRight := thiswindow.width - 10
lAnyWhereSearch := lAnyWhere
nWidth := iif(nRight < nWindowWidth,  nRight - nLeft,nWindowWidth - nLeft - 10)
nHeight := iif(nBottom < nWindowHeight, nBottom - nTop,nWindowHeight - nTop - 10)
if iswindowdefined(_HMG_aChoice)
   release window _HMG_aChoice
endif

DEFINE WINDOW _HMG_aChoice AT     nRow+nTop, nCol+nLeft ;
            WIDTH  nWidth  ;
            HEIGHT nHeight ;
            TITLE '' ;
            MODAL ;
            NOCAPTION;
            NOSIZE 
   define textbox _edit
      row 5
      col 5
      width nWidth - 10
      ON CHANGE     _aChoiceTextChanged( lAnyWhere )
      ON ENTER      _aChoiceSelected(  )
   end textbox
   define listbox _list
      row 30
      col 5
      width nWidth - 10
      height nHeight - 50
      items aList
      on change _achoicelistchanged()
      ON DBLCLICK _aChoiceSelected(  )
   end listbox
end window
ON KEY UP     OF _HMG_achoice ACTION _aChoiceDoUpKey()  
ON KEY DOWN   OF _HMG_achoice ACTION _aChoiceDoDownKey()
ON KEY ESCAPE OF _HMG_achoice ACTION _aChoiceDoEscKey()
_hmg_sysdata[296] := {||_aChoiceselected()}
if len(_aItems) > 0
   if nDefault > 0
      _HMG_aChoice._list.value := nDefault
      _HMG_aChoice._edit.value := _aItems[nDefault]
   endif
endif        
_HMG_Achoice.activate
return _nSelected

STATIC PROC _aChoiceTextChanged( lAnyWhere )

   LOCAL cCurValue      := _HMG_aChoice._edit.value 
   LOCAL nItemNo        := 0
   local lFound := .f.
   
   FOR nItemNo := 1 TO LEN(_aitems)
      IF lAnyWhere
         IF AT(UPPER(cCurValue),UPPER(_aItems[nItemNo])) > 0
            _HMG_aChoice._list.value := nItemNo
            lFound := .t.
            exit
         ENDIF            
      ELSE
         IF UPPER( LEFT( _aitems[ nItemNo ], LEN(cCurValue))) == UPPER(cCurValue)
            _HMG_aChoice._list.value := nItemNo
            lFound := .t.
            exit
         ENDIF
      ENDIF   
   NEXT nItemNo
   if .not. lFound
      _HMG_aChoice._list.value := 0
   endif
RETURN  

function _aChoiceselected
if _HMG_aChoice._List.value > 0
   _nSelected := _HMG_aChoice._list.value
else
   _nSelected := 0
endif   
release window _HMG_aChoice
return nil

function _aChoiceDoUpKey()
   IF _HMG_aChoice._List.value > 1 
      _HMG_aChoice._List.value := _HMG_aChoice._List.value - 1
      _HMG_aChoice._edit.value := _HMG_aChoice._List.item(_HMG_aChoice._List.value)
      textboxeditsetsel("_HMG_aChoice","_Edit",0,-1)
       
   ENDIF
return nil
  
function _aChoiceDoDownKey()
   IF _HMG_aChoice._List.value < _HMG_aChoice._List.ItemCount 
      _HMG_aChoice._List.value := _HMG_aChoice._List.value + 1
      _HMG_aChoice._edit.value := _HMG_aChoice._List.item(_HMG_aChoice._List.value) 
      textboxeditsetsel("_HMG_aChoice","_Edit",0,-1)
   ENDIF
return nil

function _aChoiceDoEscKey()
_nSelected := 0
release window _HMG_aChoice
return nil

function _achoicelistchanged
if upper(this.name) == "_EDIT" .and. upper(thiswindow.name) == "_HMG_ACHOICE" .and. .not. lAnyWhereSearch
   _HMG_aChoice._edit.value := _HMG_aChoice._List.item(_HMG_aChoice._List.value) 
   textboxeditsetsel("_HMG_aChoice","_Edit",0,-1)
endif   
return nil


function textboxeditsetsel(cParent,cControl,nStart,nEnd)
local nHandle := GetControlHandle (cControl,cParent)
textboxsetsel(nHandle,nStart,nEnd)
return nil

#pragma BEGINDUMP

#include <windows.h>
#include <commctrl.h>
#include "hbapi.h"
#include <wingdi.h>

HB_FUNC ( TEXTBOXSETSEL )
{
   HWND hWnd1;
   hWnd1 = (HWND) hb_parnl (1);
   SendMessage((HWND) hWnd1,EM_SETSEL, (WPARAM)(int) hb_parni(2),(LPARAM) (int) hb_parni(3));
}

#pragma ENDDUMP
Improved version (on 31/07/2010)

Code: Select all

    #include <hmg.ch>

    Function Main
    private aCountries := HB_ATOKENS( MEMOREAD( "Countries.lst" ),   CRLF )
    public aVar := 1

    set navigation extended

    define window sample at 0,0 width 800 height 600 main
       define label label1
          row 10
          col 10
          width 100
          value "Name"
       end label
       define textbox textbox1
          row 10
          col 110
          width 100
       end textbox
       define label label2
          row 40
          col 10
          width 100
          value "Country"
       end label
       define textbox textbox2
          row 40
          col 110
          width 100
          on gotfocus HMG_AChoice( 10, 300, , , aCountries,,.f.)
       end textbox
       define label label3
          row 70
          col 10
          width 100
          value "City"
       end label
       define textbox textbox3
          row 70
          col 110
          width 100
       end textbox
    end window
    sample.center
    sample.activate
    Return


    function HMG_Achoice(nTop,nLeft,nBottom,nRight,aList,nDefault,lAnyWhere)
    local nRow := thiswindow.row
    local nCol := thiswindow.col
    local nWindowWidth := thiswindow.width
    local nWindowHeight := thiswindow.height
    local nWidth := 0
    local nHeight := 0
    local nFound := 0
    local i := 0
    local cInit := this.value
    private _aItems := aclone(aList)
    private _nSelected := 0
    private lAnyWhereSearch := .f.
    private cParentForm := thiswindow.name
    private cThisControl := this.name
    default lAnyWhere := .f.
    default nDefault := 0
    default nBottom := thiswindow.height - 10
    default nRight := thiswindow.width - 10
    lAnyWhereSearch := lAnyWhere
    nWidth := iif(nRight < nWindowWidth,  nRight - nLeft,nWindowWidth - nLeft - 10)
    nHeight := iif(nBottom < nWindowHeight, nBottom - nTop,nWindowHeight - nTop - 10)
    if .not. iswindowdefined(_HMG_AChoice)
       DEFINE WINDOW _HMG_aChoice AT     nRow+nTop, nCol+nLeft ;
                   WIDTH  nWidth  ;
                   HEIGHT nHeight ;
                   TITLE '' ;
                   MODAL ;
                   NOCAPTION;
                   NOSIZE 
          define textbox _edit
             row 5
             col 5
             width nWidth - 10
             ON CHANGE     _aChoiceTextChanged( lAnyWhere )
             ON ENTER      _aChoiceSelected(  )
          end textbox
          define listbox _list
             row 30
             col 5
             width nWidth - 10
             height nHeight - 50
             items aList
             on change _achoicelistchanged()
             ON DBLCLICK _aChoiceSelected(  )
          end listbox
       end window
       ON KEY UP     OF _HMG_achoice ACTION _aChoiceDoUpKey() 
       ON KEY DOWN   OF _HMG_achoice ACTION _aChoiceDoDownKey()
       ON KEY ESCAPE OF _HMG_achoice ACTION _aChoiceDoEscKey()
       _hmg_sysdata[296] := {||_aChoiceselected()}
       if len(_aItems) > 0
          if nDefault > 0
             _HMG_aChoice._list.value := nDefault
             _HMG_aChoice._edit.value := _aItems[nDefault]
          else
             if len(alltrim(cInit)) > 0
                nFound := ascan(_aItems,cInit)
                if nFound > 0
                   _HMG_aChoice._list.value := nFound
                   _HMG_aChoice._edit.value := cInit
                endif                
             endif   
          endif
       endif       
       _HMG_Achoice.activate
       _hmg_sysdata[296] := nil
       inserttab()
    else
       _hmg_sysdata[296] := nil
       inserttab()   
    endif      
    return nil

    STATIC PROC _aChoiceTextChanged( lAnyWhere )

       LOCAL cCurValue      := _HMG_aChoice._edit.value
       LOCAL nItemNo        := 0
       local lFound := .f.
       
       FOR nItemNo := 1 TO LEN(_aitems)
          IF lAnyWhere
             IF AT(UPPER(cCurValue),UPPER(_aItems[nItemNo])) > 0
                _HMG_aChoice._list.value := nItemNo
                lFound := .t.
                exit
             ENDIF           
          ELSE
             IF UPPER( LEFT( _aitems[ nItemNo ], LEN(cCurValue))) == UPPER(cCurValue)
                _HMG_aChoice._list.value := nItemNo
                lFound := .t.
                exit
             ENDIF
          ENDIF   
       NEXT nItemNo
       if .not. lFound
          _HMG_aChoice._list.value := 0
       endif
    RETURN 

    function _aChoiceselected
    if _HMG_aChoice._List.value > 0
       setproperty(cParentForm,cThisControl,"VALUE",_HMG_aChoice._List.item(_HMG_aChoice._List.value))
    else
       setproperty(cParentForm,cThisControl,"VALUE","")
    endif
    release window _HMG_aChoice
    return nil

    function _aChoiceDoUpKey()
       IF _HMG_aChoice._List.value > 1
          _HMG_aChoice._List.value := _HMG_aChoice._List.value - 1
          _HMG_aChoice._edit.value := _HMG_aChoice._List.item(_HMG_aChoice._List.value)
          textboxeditsetsel("_HMG_aChoice","_Edit",0,-1)
           
       ENDIF
    return nil
     
    function _aChoiceDoDownKey()
       IF _HMG_aChoice._List.value < _HMG_aChoice._List.ItemCount
          _HMG_aChoice._List.value := _HMG_aChoice._List.value + 1
          _HMG_aChoice._edit.value := _HMG_aChoice._List.item(_HMG_aChoice._List.value)
          textboxeditsetsel("_HMG_aChoice","_Edit",0,-1)
       ENDIF
    return nil

    function _aChoiceDoEscKey()
    setproperty(cParentForm,cThisControl,"VALUE","")
    release window _HMG_aChoice
    return nil

    function _achoicelistchanged
    if upper(this.name) == "_EDIT" .and. upper(thiswindow.name) == "_HMG_ACHOICE" .and. .not. lAnyWhereSearch
       _HMG_aChoice._edit.value := _HMG_aChoice._List.item(_HMG_aChoice._List.value)
       textboxeditsetsel("_HMG_aChoice","_Edit",0,-1)
    endif   
    return nil


    function textboxeditsetsel(cParent,cControl,nStart,nEnd)
    local nHandle := GetControlHandle (cControl,cParent)
    textboxsetsel(nHandle,nStart,nEnd)
    return nil

    #pragma BEGINDUMP

    #include <windows.h>
    #include <commctrl.h>
    #include "hbapi.h"
    #include <wingdi.h>

    HB_FUNC ( TEXTBOXSETSEL )
    {
       HWND hWnd1;
       hWnd1 = (HWND) hb_parnl (1);
       SendMessage((HWND) hWnd1,EM_SETSEL, (WPARAM)(int) hb_parni(2),(LPARAM) (int) hb_parni(3));
    }

    #pragma ENDDUMP
Before compiling keep the file c:\hmg\hfcl\samples\combosearchbox\countries.lst in the prg directory.

Please give your comments and suggestions.
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

User avatar
esgici
Posts: 4517
Joined: Wed Jul 30, 2008 9:17 pm
DBs Used: DBF
Location: iskenderun / Turkiye
Has thanked: 391 times
Been thanked: 111 times
Contact:

Post by esgici » Mon Jul 19, 2010 10:39 am

Thanks Rathi, good work.

The selection window open after enter key in second textbox of main window ( on enter doachoice() ). Is this intended behavior ?

Regards

--

Esgici
Viva INTERNATIONAL HMG :D

User avatar
Rathinagiri
Posts: 5264
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 169 times
Been thanked: 172 times
Contact:

Post by Rathinagiri » Mon Jul 19, 2010 11:07 am

Yes. This is what he wanted.

I am planning to use this in some other places too. (Like in-place edit of grid items)
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

User avatar
esgici
Posts: 4517
Joined: Wed Jul 30, 2008 9:17 pm
DBs Used: DBF
Location: iskenderun / Turkiye
Has thanked: 391 times
Been thanked: 111 times
Contact:

Post by esgici » Mon Jul 19, 2010 11:16 am

Does will be better, adding a "more" ("...")button adjacent to TextBox2 (instead of forcing user to use Enter key) for open AChoice box ?

Regards

--

Esgici
Viva INTERNATIONAL HMG :D

User avatar
Rathinagiri
Posts: 5264
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 169 times
Been thanked: 172 times
Contact:

Post by Rathinagiri » Mon Jul 19, 2010 11:58 am

Nice Suggestion Esgici. Thanks. :)
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

User avatar
esgici
Posts: 4517
Joined: Wed Jul 30, 2008 9:17 pm
DBs Used: DBF
Location: iskenderun / Turkiye
Has thanked: 391 times
Been thanked: 111 times
Contact:

Post by esgici » Mon Jul 19, 2010 12:17 pm

rathinagiri wrote:
I am planning to use this in some other places too. (Like in-place edit of grid items)
I'll wait eagerly.

Regards

--

Esgici
Viva INTERNATIONAL HMG :D

User avatar
Rathinagiri
Posts: 5264
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 169 times
Been thanked: 172 times
Contact:

Post by Rathinagiri » Mon Jul 19, 2010 1:29 pm

Recently I am experimenting some features of combobox control.

Consider this sample. This is more simple than aChoice above. My client likes this, since it reduces keystrokes.

Code: Select all

#include <hmg.ch>

    Function Main

    local aCountries := HB_ATOKENS( MEMOREAD( "Countries.lst" ),   CRLF )
    set navigation extended
    define window x at 0,0 width 300 height 200 main
       define textbox b
          row 10
          col 10
       end textbox
       define combobox a
          row 60
          col 10
          width 100
          items aCountries
          sort .t.
          ongotfocus comboboxdropdown()
          onchange ensuretopindex()
       end combobox
    end window
    x.center
    x.activate
    Return


    function comboboxdropdown
    local nHandle := GetControlHandle (this.name,thiswindow.name)
    ComboBoxShowDropDown(nHandle)
    return nil
    
    function ensuretopindex
    local nHandle := GetControlHandle (this.name,thiswindow.name)
    if this.value > 0
       ComboBoxSetTopIndex(nHandle,this.value)
    endif   
    return nil


    #pragma BEGINDUMP

    #include <windows.h>
    #include <commctrl.h>
    #include "hbapi.h"
    #include <wingdi.h>

    HB_FUNC ( COMBOBOXSHOWDROPDOWN )

    {
       HWND hWnd1;
       hWnd1 = (HWND) hb_parnl (1);
       SendMessage((HWND) hWnd1,CB_SHOWDROPDOWN,    (WPARAM)(int) 1,(LPARAM)(int) 0);
    }

    HB_FUNC ( COMBOBOXSETTOPINDEX )
    {
       HWND hWnd1;
       hWnd1 = (HWND) hb_parnl (1);
       hb_retni(SendMessage((HWND) hWnd1,CB_SETTOPINDEX, (WPARAM)(int) hb_parni(2) - 1,(LPARAM) 0 ));
    }


    #pragma ENDDUMP
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

User avatar
esgici
Posts: 4517
Joined: Wed Jul 30, 2008 9:17 pm
DBs Used: DBF
Location: iskenderun / Turkiye
Has thanked: 391 times
Been thanked: 111 times
Contact:

Post by esgici » Mon Jul 19, 2010 2:00 pm

rathinagiri wrote:
My client likes this, since it reduces keystrokes.
He is right :)

More efficient because more low-level ;)

Regards

--

Esgici
Viva INTERNATIONAL HMG :D

User avatar
mol
Posts: 3247
Joined: Thu Sep 11, 2008 5:31 am
Location: Myszków, Poland
Has thanked: 229 times
Been thanked: 132 times
Contact:

Post by mol » Mon Jul 19, 2010 8:15 pm

I've posted some time ago my achoice version. It was based on listbox and especially, I've turned off scrollbar.

Of course, your sample is very interesting, Rathi.
Thanks for sharing!


(I'm backing to work after holidays... :()

User avatar
Rathinagiri
Posts: 5264
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 169 times
Been thanked: 172 times
Contact:

Post by Rathinagiri » Tue Jul 20, 2010 3:28 am

mol wrote:I've posted some time ago my achoice version. It was based on listbox and especially, I've turned off scrollbar.

Of course, your sample is very interesting, Rathi.
Thanks for sharing!


(I'm backing to work after holidays... :()
Yes Marek. Thanks for reminding. :)

Welcome back. Any interesting events?
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

Post Reply