Devexpress tips:
2004-1-10 17:06:00
View Comments & raquo;
17:08:06 1. Extended cxlookupcombobox to support cxlookupcomboboxex for multi-column queries
// ================================================ ==========================================================
// Unit name: cxlookupcomboboxex
// Author: ysai
// Date: 2003
// Purpose: expands cxlookupcombobox and cxdblookupcombobox to support multi-column filtering.
// History:
// Large data volume Improvement
// Operability Improvement
// Efficiency Improvement
// Added filter latency
// Note:
// Limit 1. You cannot use the properties. onchange event again.
// Limit 2. You cannot use the properties. listsource. dataset. onfilterrecord event.
// Limit 3. You cannot use the properties. listsource. dataset. Filtered attribute.
// Others. It is best to set all attributes during the design period. setting attributes again during the runtime may lead to knowledge errors.
// ================================================ ==========================================================
Unit cxlookupcomboboxex;
Interface
Uses
Sysutils, classes, controls, windows, messages, DB, strutils,
Cxcontrols, cxcontainer, cxedit, cxtextedit,
Cxmaskedit, cxdropdownedit, cxlookupedit, cxdblookupedit,
Cxdblookupcombobox;
Type
Tcxlookupcomboboxex = Class (tcxlookupcombobox)
Private
// Save the list of fields to filter
Ffieldlist: tlist;
Ffindtext: string;
// Filter events
Procedure _ onfilterrecord (Dataset: tdataset; var accept: Boolean );
// Edit the box text change event
Procedure _ onchange (Sender: tobject );
Procedure getfieldlist;
// Delayed message filtering
Procedure wmtimer (VAR message: tmessage); message wm_timer;
Protected
// When the drop-down table is withdrawn
Procedure closeup (aaccept: Boolean); override;
// Filtering process
Procedure _ filterlistsource;
// Initialize the drop-down table event
Procedure doinitpopup; override;
Public
Constructor create (aowner: tcomponent); override;
Destructor destroy; override;
// Update the list of fields to be filtered
Procedure updatefilterfields;
Published
End;
Tcxdblookupcomboboxex = Class (tcxdblookupcombobox)
Private
// Save the list of fields to filter
Ffieldlist: tlist;
Ffindtext: string;
// Filter events
Procedure _ onfilterrecord (Dataset: tdataset; var accept: Boolean );
// Edit the box text change event
Procedure _ onchange (Sender: tobject );
// Obtain the list of fields to be filtered
Procedure getfieldlist;
// Delayed message filtering
Procedure wmtimer (VAR message: tmessage); message wm_timer;
Protected
// When the drop-down table is withdrawn
Procedure closeup (aaccept: Boolean); override;
// Filtering process
Procedure _ filterlistsource;
// Initialize the drop-down table event
Procedure doinitpopup; override;
Public
Constructor create (aowner: tcomponent); override;
Destructor destroy; override;
// Update the list of fields to be filtered
Procedure updatefilterfields;
Published
End;
Procedure register;
Implementation
Const
Um_timer_filter = wm_user + $101; // custom delayed message ID
Filtertimer = 500; // Delay Time
Dropdown_rows = 12;
Procedure register;
Begin
Registercomponents ('dev express ', [tcxlookupcomboboxex, tcxdblookupcomboboxex]);
End;
{Tcxlookupcomboboxex}
Procedure tcxlookupcomboboxex. Closeup (aaccept: Boolean );
Begin
Inherited;
// Hide the drop-down list and cancel Filtering
If assigned (properties. listsource) then
If assigned (properties. listsource. dataset) then
Properties. listsource. dataset. Filtered: = false;
End;
Constructor tcxlookupcomboboxex. Create (aowner: tcomponent );
Begin
Inherited;
// Default Value
Properties. Autoselect: = false;
Properties. dropdownautosize: = true;
Properties. dropdownliststyle: = lseditlist;
Properties. dropdownrows: = dropdown_rows;
Properties. dropdownsizeable: = true;
Properties. incrementalfiltering: = false;
Properties. revertable: = true;
Properties. onchange: = _ onchange;
Properties. useleftalignmentonediting: = false;
End;
Destructor tcxlookupcomboboxex. Destroy;
Begin
// Release the filter Field List
If assigned (ffieldlist) Then ffieldlist. Free;
Inherited;
End;
Procedure tcxlookupcomboboxex. doinitpopup;
Begin
// Obtain the filter Field
If assigned (properties. listsource) then
If assigned (properties. listsource. dataset) then
Begin
Getfieldlist;
Properties. listsource. dataset. Filtered: = false;
End;
Inherited doinitpopup;
End;
Procedure tcxlookupcomboboxex. _ filterlistsource;
// Filter Fields
Begin
If assigned (properties. listsource)
And assigned (properties. listsource. dataset) then
Try
Properties. listsource. dataset. disablecontrols;
Properties. listsource. dataset. Filtered: = false;
Properties. listsource. dataset. onfilterrecord: = _ onfilterrecord;
If text <> ''then
Begin
Ffindtext: = text;
If sellength> 0 then
Ffindtext: = leftstr (text, selstart );
Properties. listsource. dataset. Filtered: = ffindtext <> '';
End;
Changed;
Finally
Properties. listsource. dataset. enablecontrols;
End;
End;
Procedure tcxlookupcomboboxex. getfieldlist;
// Obtain the list of filter Fields
VaR
I: integer;
Sfieldname: string;
Fdtemp: tfield;
Begin
If not assigned (ffieldlist) then
Begin
Ffieldlist: = tlist. Create;
For I: = 0 to properties. listcolumns. Count-1 do
Begin
Sfieldname: = properties. listcolumns. items [I]. fieldname;
If sfieldname = ''then continue;
Fdtemp: = properties. listsource. dataset. findfield (sfieldname );
If assigned (fdtemp) then
Ffieldlist. Add (pointer (fdtemp ));
End;
End;
End;
Procedure tcxlookupcomboboxex. _ onchange (Sender: tobject );
// Set the latency
Begin
If focused and droppeddown then
Begin
Killtimer (handle, um_timer_filter );
Settimer (handle, um_timer_filter, filtertimer, nil );
End;
End;
Procedure tcxlookupcomboboxex. _ onfilterrecord (Dataset: tdataset;
VaR accept: Boolean );
// Filter events
VaR
S: string;
I: integer;
Begin
S: = lowercase (ffindtext );
If (S <> '') and (properties. listcolumns. Count> 0) then
Begin
Accept: = false;
For I: = 0 to ffieldlist. Count-1 do
Begin
Accept: = pos (S, lowercase (tfield (ffieldlist [I]). asstring)> 0;
If accept then exit;
End;
End
Else
Accept: = true;
End;
Procedure tcxlookupcomboboxex. wmtimer (VAR message: tmessage );
// Delayed message update
Begin
Killtimer (handle, um_timer_filter );
If focused and droppeddown then _ filterlistsource;
End;
Procedure tcxlookupcomboboxex. updatefilterfields;
// Update the list of fields to be filtered
Begin
If assigned (ffieldlist) then
Begin
Ffieldlist. Free;
Ffieldlist: = nil;
End;
Getfieldlist;
End;
{Tcxdblookupcomboboxex}
Procedure tcxdblookupcomboboxex. Closeup (aaccept: Boolean );
Begin
Inherited;
// Hide the drop-down list and cancel Filtering
If assigned (properties. listsource) then
If assigned (properties. listsource. dataset) then
Properties. listsource. dataset. Filtered: = false;
End;
Constructor tcxdblookupcomboboxex. Create (aowner: tcomponent );
Begin
Inherited;
// Default Value
Properties. Autoselect: = false;
Properties. dropdownliststyle: = lseditlist;
Properties. dropdownrows: = dropdown_rows;
Properties. dropdownsizeable: = true;
Properties. incrementalfiltering: = false;
Properties. revertable: = true;
Properties. onchange: = _ onchange;
Properties. useleftalignmentonediting: = false;
End;
Destructor tcxdblookupcomboboxex. Destroy;
Begin
// Release the filter Field List
If assigned (ffieldlist) Then ffieldlist. Free;
Inherited;
End;
Procedure tcxdblookupcomboboxex. doinitpopup;
Begin
// Obtain the filter Field
If assigned (properties. listsource) then
If assigned (properties. listsource. dataset) then
Begin
Getfieldlist;
Properties. listsource. dataset. Filtered: = false;
End;
Inherited doinitpopup;
End;
Procedure tcxdblookupcomboboxex. _ filterlistsource;
// Filter Fields
Begin
If assigned (properties. listsource)
And assigned (properties. listsource. dataset) then
Try
Properties. listsource. dataset. disablecontrols;
Properties. listsource. dataset. Filtered: = false;
Properties. listsource. dataset. onfilterrecord: = _ onfilterrecord;
If text <> ''then
Begin
Ffindtext: = text;
If sellength> 0 then
Ffindtext: = leftstr (text, selstart );
Properties. listsource. dataset. Filtered: = ffindtext <> '';
End;
Changed;
Finally
Properties. listsource. dataset. enablecontrols;
End;
End;
Procedure tcxdblookupcomboboxex. getfieldlist;
// Obtain the list of filter Fields
VaR
I: integer;
Sfieldname: string;
Fdtemp: tfield;
Begin
If not assigned (ffieldlist) then
Begin
Ffieldlist: = tlist. Create;
For I: = 0 to properties. listcolumns. Count-1 do
Begin
Sfieldname: = properties. listcolumns. items [I]. fieldname;
If sfieldname = ''then continue;
Fdtemp: = properties. listsource. dataset. findfield (sfieldname );
If assigned (fdtemp) then
Ffieldlist. Add (pointer (fdtemp ));
End;
End;
End;
Procedure tcxdblookupcomboboxex. _ onchange (Sender: tobject );
// Set the latency
Begin
If focused and droppeddown then
Begin
Killtimer (handle, um_timer_filter );
Settimer (handle, um_timer_filter, filtertimer, nil );
End;
End;
Procedure tcxdblookupcomboboxex. _ onfilterrecord (Dataset: tdataset;
VaR accept: Boolean );
// Filter events
VaR
S: string;
I: integer;
Begin
S: = lowercase (ffindtext );
If (S <> '') and (properties. listcolumns. Count> 0) then
Begin
Accept: = false;
For I: = 0 to ffieldlist. Count-1 do
Begin
Accept: = pos (S, lowercase (tfield (ffieldlist [I]). asstring)> 0;
If accept then exit;
End;
End
Else
Accept: = true;
End;
Procedure tcxdblookupcomboboxex. wmtimer (VAR message: tmessage );
// Delayed message update
Begin
Killtimer (handle, um_timer_filter );
If focused and droppeddown then _ filterlistsource;
End;
Procedure tcxdblookupcomboboxex. updatefilterfields;
// Update the list of fields to be filtered
Begin
If assigned (ffieldlist) then
Begin
Ffieldlist. Free;
Ffieldlist: = nil;
End;
Getfieldlist;
End;
End.
17:14:06 2. Dynamic generation of tcxgriddbtableview columns and footer Columns
VaR
I: integer;
CL: tcxgriddbcolumn;
Begin
Screen. cursor: = crhourglass;
Cxtvmaster. beginupdate;
Try
Cxtvmaster. clearitems;
Cxtvmaster. datacontroller. Summary. footersummaryitems. Clear;
For I: = 0 to cxtvmaster. datacontroller. dataset. fieldcount-1 do
Begin
CL: = cxtvmaster. createcolumn;
Cl. databinding. fieldname: =
Cxtvmaster. datacontroller. dataset. Fields [I]. fieldname;
If cxtvmaster. datacontroller. dataset. Fields [I] Is tnumericfield then
Begin
Tnumericfield (cxtvmaster. datacontroller. dataset. Fields [I])
. Displayformat: = '#,# 0.00 ';
Cl. Width: = 80;
With tcxgriddbtablesummaryitem (
Cxtvmaster. datacontroller. Summary. footersummaryitems. Add) Do
Begin
Column: = Cl;
Fieldname: = Cl. databinding. fieldname;
Format: = '#, #0.00 ';
Kind: = sksum;
End;
End
Else if cxtvmaster. datacontroller. dataset. Fields [I] Is tstringfield then
Cl. Width: = 100
Else
Cl. Width: = 80;
Cl. headeralignmenthorz: = tacenter;
End; // If
Finally
Cxtvmaster. endupdate;
Screen. cursor: = crdefault;
End;
End;
17:24:32 3. Dynamic generation of tcxgriddbbandedtableview columns and footer Columns
If the stored procedure or SQL statement returns the following result set
Employees: July 22, $ July 15, $ total $
-------------------------------------------
Tester a 200 1658 300 2487 500 4145
Generate the following grid style (the footer is not drawn, it is troublesome, and the display format is set, the amount will be displayed in the form of #,# 0.00)
_________________________________________________
| Employee | January | February | Total |
| --------------------------------------------- |
| Employee | $ |
| --------------------------------------------- |
| Tester A | 200 | 1658 | 300 | 2487 | 500 | 4145 |
-------------------------------------------------
VaR
I: integer;
CL: tcxgriddbbandedcolumn;
Begin
Screen. cursor: = crhourglass;
Cxbtvmaster. beginupdate;
Try
Cxbtvmaster. clearitems;
Cxbtvmaster. bands. Clear;
Cxbtvmaster. datacontroller. Summary. footersummaryitems. Clear;
For I: = 0 to cxbtvmaster. datacontroller. dataset. fieldcount-1 do
Begin
If I = 0 then
With cxbtvmaster. bands. Add do
Begin
Options. holdowncolumnsonly: = true;
Caption: = cxbtvmaster. datacontroller. dataset. Fields [I]. fieldname;
End;
If rightstr (
Cxbtvmaster. datacontroller. dataset. Fields [I]. fieldname,
1) = '$' then
With cxbtvmaster. bands. Add do
Begin
Options. holdowncolumnsonly: = true;
Caption: = copy (
Cxbtvmaster. datacontroller. dataset. Fields [I]. fieldname, 1,
Length (cxbtvmaster. datacontroller. dataset. Fields [I]. fieldname)
-1 );
Cxbtvmaster. datacontroller. dataset. Fields [I]. displaylabel: = '$ ';
End;
If rightstr (
Cxbtvmaster. datacontroller. dataset. Fields [I]. fieldname,
1) = '¥' then
Cxbtvmaster. datacontroller. dataset. Fields [I]. displaylabel: = '¥ ';
CL: = cxbtvmaster. createcolumn;
Cl. headeralignmenthorz: = tacenter;
Cl. position. bandindex: = cxbtvmaster. bands. Count-1;
Cl. databinding. fieldname: =
Cxbtvmaster. datacontroller. dataset. Fields [I]. fieldname;
If cxbtvmaster. datacontroller. dataset. Fields [I] Is tnumericfield then
Begin
Tnumericfield (cxbtvmaster. datacontroller. dataset. Fields [I])
. Displayformat: = '#,# 0.00 ';
Cl. Width: = 80;
With tcxgriddbbandedtablesummaryitem (
Cxbtvmaster. datacontroller. Summary. footersummaryitems. Add) Do
Begin
Column: = Cl;
Fieldname: = Cl. databinding. fieldname;
Format: = '#, #0.00 ';
Kind: = sksum;
End;
End
Else if cxbtvmaster. datacontroller. dataset. Fields [I] Is tstringfield then
Cl. Width: = 100
Else
Cl. Width: = 80;
End; // If
Finally
Cxbtvmaster. endupdate;
Screen. cursor: = crdefault;
End;
End;
22:36:25 4. Notes for the automatic adjustment of column width
You can use applybestfit to implement automatic column width;
You cannot call this method between beginupdate and endupdate. Otherwise, a subscript out-of-bounds error occurs;
Clearing/creating columns in beginupdate and endupdate will not cause screen blinking. Other operations that require a long time to update cxgrid data are best performed in beginupdate and endupdate and packaged in try.
15:32:30 devexpress bar dynamic menu
There is no description. Be careful when you know the table structure and data content form.
Compared with the code, using dxbar is simpler than using toolbar + popupmenu to generate a dynamic menu. Only one recursive process is used.
Type
// Menu item
Pmenuiteminfo = ^ tmenuiteminfo;
Tmenuiteminfo = record
ID: string;
Parentid: string;
Caption: string;
Hint: string;
Libraryname: string;
Procedurename: string;
Wparam: integer;
Lparam: integer;
End;
Procedure tmgmainform. buildmenu;
// Generate menu
Procedure setmenuiteminfo (
Const adataset: tdataset;
Const aitem: pmenuiteminfo
);
Begin
Aitem. ID: = adataset. fieldbyname ('id'). asstring;
Aitem. parentid: = adataset. fieldbyname ('parentid'). asstring;
Aitem. Caption: = adataset. fieldbyname ('caption '). asstring;
Aitem. Hint: = adataset. fieldbyname ('hint'). asstring;
Aitem. libraryname: = adataset. fieldbyname ('libraryname'). asstring;
Aitem. procedurename: = adataset. fieldbyname ('processurename'). asstring;
Aitem. wparam: = adataset. fieldbyname ('wparam'). asinteger;
Aitem. lparam: = adataset. fieldbyname ('lparam'). asinteger;
End;
Procedure createitemlist (
Const adataset: tdataset;
Const alist: tlist;
Const atext: String
);
// Create a subproject list based on the parent node
VaR
M: pmenuiteminfo;
I: integer;
Begin
Adataset. first;
For I: = 0 to adataset. recordcount-1 do
Begin
If adataset. fieldbyname ('parentid'). asstring = atext then
Begin
New (m );
Setmenuiteminfo (adataset, M );
Alist. Add (m );
Adataset. Delete;
End else
Adataset. Next;
End; //
End;
Procedure createmenuitems (
Const adataset: tdataset;
Const akeyvalue: string;
Const aitemlinks: tdxbaritemlinks;
Const aindex: integer
);
// Create a menu item
VaR
DB: tdxbarbutton;
DBS: tdxbarsubitem;
L: tlist;
I: integer;
J: integer;
BG: Boolean;
Begin
BG: = false;
J: = aindex;
L: = tlist. Create;
Try
Createitemlist (adataset, L, akeyvalue );
For I: = 0 to L. Count-1 do
Begin
If adataset. Locate ('parentid', pmenuiteminfo (L [I]). ID, []) then
Begin
// Subitem
DBS: = tdxbarsubitem. Create (dxbar );
DBS. Caption: = pmenuiteminfo (L [I]). Caption;
DBS. Hint: = pmenuiteminfo (L [I]). Hint;
DBS. Tag: = INTEGER (L [I]);
If aindex> 0 then
DBS. imageindex: = 0;
With aitemlinks. Add do
Begin
Item: = dBs;
Index: = J;
Begingroup: = BG;
End; //
BG: = false;
Createmenuitems (adataset, pmenuiteminfo (L [I]). ID, DBS. itemlinks, 0 );
If DBs. itemlinks. Count = 0 then
DBS. Free
Else
INC (j );
End
Else begin
// No subitem
If not (pmenuiteminfo (L [I]). Caption = '-') then
Begin
DB: = tdxbarbutton. Create (dxbar );
DB. Caption: = pmenuiteminfo (L [I]). Caption;
DB. Hint: = pmenuiteminfo (L [I]). Hint;
DB. Tag: = INTEGER (L [I]);
DB. onclick: = menuitemclick;
If aindex> 0 then
DB. imageindex: = 0;
With aitemlinks. Add do
Begin
Item: = dB;
Index: = J;
Begingroup: = BG;
End;
BG: = false;
INC (j );
End
Else begin
BG: = true;
End; // If BG
End; // If locate
End; //
Finally
L. free;
End;
End;
VaR
Rsmenus: tdataset;
Begin
Rsmenus: = mgdmmain. getmenus; // obtain the dataset
If assigned (rsmenus) then
Try
Createmenuitems (rsmenus, '', dxbar. Bars [0]. itemlinks, 1 );
// Be sure to refresh it. Otherwise, an error will occur if you do not change the style.
Dxbar. Bars [0]. itemlinks [0]. Visible: = false;
Dxbar. Bars [0]. itemlinks [0]. Visible: = true;
Finally
Rsmenus. Free;
End;
End;
16:34:35 get the content of items in the tcxlookupcombobox drop-down list
Properties. datacontroller. Values contains all the content. To obtain the content of the selected row, use the following code:
// CMB: tcxlookupcombobox;
With CMB. properties. datacontroller do
Showmessage (Values [findrecordindexbykey (CMB. editvalue), 0]);
// 0 indicates the first column to be displayed. properties. listcolumns prevails. You can find the corresponding field name from this set.