Page 1 of 1
DBCOMBO problem
Posted: Mon Oct 01, 2007 10:11 pm
by alexstrickland
Hi Antonio
With the code below the drop-down is not initialised to "Production".
Code: Select all
#include "fivewin.ch"
#include "dbcombo.ch"
function main()
local oDlg, oDBC2, oBtn
//local cDept:= "400"
local cDept:= 400
local aItems, aList
define dialog oDlg
aList:= {"Accounting","HR","Marketing","Production","Research","Shipping","Sales"}
//aItems:= {"100","200","400","300","600","500","700"}
aItems:= {100,200,400,300,600,500,700}
@ 30,30 DBCOMBO oDBC2 VAR cDept;
items aItems;
size 100,200 pixel;
list aList;
of oDlg;
update
@ 50, 50 button oBtn prompt "Selected";
of oDlg pixel ;
action msgInfo( "DeptNo: "+hb_valtostr(cDept),"Selected" );
default
activate dialog oDlg center;
return nil
The commented (character values) code is OK.
Did you check my last code posted for the XP theme issues with tabs?
Thanks and regards
Alex
Posted: Mon Oct 01, 2007 11:56 pm
by James Bott
Alex,
You cannot use numeric values with DBCombo. This is because DBCombo inherits from TCombobox and TCombobox has methods that assume if a passed parameter is numeric then it is for the location in the array not a value in the array. Since, the array doesn't contain a value in the 400th postion, then DBCombo is empty when it is displayed.
Awhile ago, I did make an attempt to modify DBCombo to handle numeric data for aItems, but I found that it would require rewriting a huge amount of the code and most people use character values for IDs anyway.
I assume from your commented code that you have already tried it using character values for aItems. And I tested it here (using chacter values) and it is working (although in your example "400" corresponds to "Marketing" not "Production").
Regards,
James
Posted: Tue Oct 02, 2007 8:25 am
by alexstrickland
Hi James
Thanks for the reply. I looked into the DBCombo class and made the change below. I created a new command to use my new class - TFixDBCombo. It seems to work ok, perhaps you could see if you can see any problems?
Regards
Alex
Code: Select all
#include "FiveWin.ch"
#include "Constant.ch"
#ifndef __CLIPPER__
#define COMBO_BASE 320
#else
#define COMBO_BASE WM_USER
#endif
#define CB_ADDSTRING ( COMBO_BASE + 3 )
#define CB_DELETESTRING ( COMBO_BASE + 4 )
#define CB_GETCURSEL ( COMBO_BASE + 7 )
#define CB_INSERTSTRING ( COMBO_BASE + 10 )
#define CB_RESETCONTENT ( COMBO_BASE + 11 )
#define CB_FINDSTRING ( COMBO_BASE + 12 )
#define CB_SETCURSEL ( COMBO_BASE + 14 )
#define CB_SHOWDROPDOWN ( COMBO_BASE + 15 )
#define CB_ERR -1
#define COLOR_WINDOW 5
#define COLOR_WINDOWTEXT 8
#define MB_ICONEXCLAMATION 48 // 0x0030
#define GWL_STYLE -16
#ifdef __XPP__
#define Super ::TComboBox
#endif
//----------------------------------------------------------------------------//
CLASS TFixDBCombo FROM TDBCombo
METHOD Default()
ENDCLASS
//----------------------------------------------------------------------------//
METHOD Default() CLASS TFixDBCombo
local cStart := Eval( ::bSetGet )
if ! Empty( ::hWnd ) .and. ::nStyle == CBS_DROPDOWNLIST
::nStyle := GetWindowLong( ::hWnd, GWL_STYLE )
endif
if cStart == nil
Eval( ::bSetGet, If( Len( ::aItems ) > 0, ::aItems[ 1 ], "" ) )
cStart = If( Len( ::aItems ) > 0, ::aItems[ 1 ], "" )
endif
AEval( ::aList, { | cList, nAt | ::SendMsg( CB_ADDSTRING, nAt, cList ) } )
if ValType( cStart ) != "N"
::nAt = AScan( ::aList, { | cList | Upper( AllTrim( cList ) ) == ;
Upper( AllTrim( cStart ) ) } )
else
//::nAt = cStart
::nAt = AScan( ::aItems, { | nList | nList == cStart } )
endif
::nAt = If( ::nAt > 0, ::nAt, 1 )
//if cStart == nil
::Select( ::nAt )
//else
//::Set( cStart )
//endif
return nil
Posted: Tue Oct 02, 2007 1:32 pm
by James Bott
Alex,
As I said it is not that simple. You are going to have to check every method in both TDBCombo and TCombobox. Either methods also have to be modified in TCombobox also or new methods have to be created in DBCombo. But the real problem is that there is existing code that requires values for the location in the array. Changing the behavoir of DBCombo and/or Combobox is going to break this existing code.
It is very easy to convert your numeric data to character when you build the array, and to convert the selection back to numeric. That is a much simpler solution.
Regards,
James
Posted: Fri Oct 10, 2008 7:53 am
by Horizon
Hi James,
What is your suggestion Numeric ID in huge databases about setting default value using DBCombo. Should we use another method?
Thanks,
Posted: Sat Oct 11, 2008 4:50 am
by James Bott
Hakan,
>What is your suggestion Numeric ID in huge databases about setting default value using DBCombo. Should we use another method?
I wouldn't suggest using DBCombo for huge databases. The problem is that the entire database has to be loaded into an array which is going to cause a long delay.
I would suggest using the new ACTION clause of the GET, and calling up a browse in a window or dialog. A browse only loads enough records to fill the screen so it is very fast and the speed is not dependent on the size of the database.
Regards,
James
Posted: Sat Oct 11, 2008 2:24 pm
by Horizon
Thanks James,
I think I have seen that someone has wrote the class you have described. I should do a quick search.
I have also modified the alexstrickland's code. It works perfectly with numeric ID and initialize the value.
Code: Select all
#include "fivewin.ch"
#include "dbcombo.ch"
function main()
local oDlg, oDBC2, oBtn
//local cDept:= "600"
local cDept:= 600
local aItems, aList
define dialog oDlg
aList:= {"Accounting","HR","Marketing","Production","Research","Shipping","Sales"}
//aItems:= {"100","200","400","300","600","500","700"}
aItems:= {100,200,400,300,600,500,700}
@ 30,30 DBCOMBO oDBC2 VAR cDept;
items aItems;
size 100,200 pixel;
list aList;
of oDlg;
update
@ 50, 50 button oBtn prompt "Selected";
of oDlg pixel ;
action msgInfo( "DeptNo: "+hb_valtostr(cDept),"Selected" );
default
activate dialog oDlg center;
ON INIT ( nAt:= ASCAN(oDBC2:aItems,cDept) , oDBC2:Select( nAt ))
return nil