pass parameter to function

Hi

function compare(bla bla): int;
I use TList.Sort(compare) to sort something in my component, but I need to somehow pass information to the compare function, and this gives some troubles.

I first used a global variable, but because I have two components on the same from this gives a big error when one of the components are destroyed.

I would include the compare function in the procedure where I use sort, but this don't work

procedure something;
  function compare..
begin
  TList.Sort(compare)

I also would declare the function as
function TObject.compare

But then I can't use the function.

Help me on this one
kogerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

interCommented:
Could you please lay down your code? As you now the compare functions have two untyped pointers. This means that you cannot pass class variables to it. If we see your code fragment may be we could help (by we I mean we and others, I am not a king ;-)

regards,
igor
0
interCommented:
Or I may give you the following example:

The following code sorts the buttons according to their tags (there are 4 buttons on the form named b1,b2,b3 and b4 wich has tags 4, 3, 2 and 1.)

// you should type cast to your types stored in the list
function ListCompare(p1,p2 : Pointer):Integer;
begin
  if TButton(p1).Tag > TButton(p2).Tag then
    Result := 1
  else if TButton(p1).Tag < TButton(p2).Tag then
    Result := -1
  else Result := 0;
end;

procedure TForm1.b1Click(Sender: TObject);
var
  T : TList;
begin
  T := TList.Create;
  try
    T.Add(b1);
    T.Add(b2);
    T.Add(b3);
    T.Add(b4);
    T.Sort(ListCompare);
    Caption := IntToStr(TButton(T.Items[0]).Tag);
  finally
    T.Free;
  end;
end;


regards,
igor
0
kogerAuthor Commented:
This is only part of the code.

unit SortGrid;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Grids;

type
  TSortStyle = (ssAutomatic, ssAlphabetic, ssNumeric, ssDateTime, ssTime,ssCustom);
  {TSortCompare must return < 0 if Str1 is less than Str2,
   0 if they are equal, and > 0 if Str1 is greater than Str2.}
  TSortCompare = function (const Str1, Str2: String): Integer;
  TSortDirection = (sdAscending, sdDescending);

  TSortOptions = record
      SortStyle: TSortStyle;
      SortDirection: TSortDirection;
      SortCaseSensitive: Boolean;
      SortCompare: TSortCompare;
  end;

implementation

{$R SortGrid.Res}

var
   //This is here for Compare.  I can't pass it as a parameter,
   //and I can't make Compare a method.  So I had to use a global. :-(
   GlobalSortOptions: TSortOptions;

//This looks at the global variable GlobalSortOptions.
//I hated to use a global, but I can't pass any additional
//parameters to Compare, and I can't make Compare a
//method of an object.  A global seemed the only choice.
function Compare(Item1, Item2: Pointer): Integer;
var
   Entry1, Entry2: PSortedListEntry;
begin
     Entry1:=Item1;
     Entry2:=Item2;

     //Handle Case-Insensitivity.
     if not GlobalSortOptions.SortCaseSensitive then
     begin
          Entry1^.Str:=Uppercase(Entry1^.Str);
          Entry2^.Str:=Uppercase(Entry2^.Str);
     end;

     //Determine compare type and do the comparison.
     case GlobalSortOptions.SortStyle of
          ssNumeric: Result:=NumericCompare(Entry1^.Str, Entry2^.Str);
          ssDateTime: Result:=DateTimeCompare(Entry1^.Str, Entry2^.Str);
          ssTime: Result:=TimeCompare(Entry1^.Str, Entry2^.Str);
          ssCustom: Result:=GlobalSortOptions.SortCompare(Entry1^.Str, Entry2^.Str);
     else
         Result:=StringCompare(Entry1^.Str, Entry2^.Str);
     end;

     //Now, make sure we don't swap the rows if the Keys are equal.
     //If they're equal then we sort by row number.
     if Result = 0 then
     begin
          if Entry1^.RowNum < Entry2^.RowNum then Result:=-1
          else if Entry1^.RowNum > Entry2^.RowNum then Result:=1
          else Result:=0; //Sometimes an item does get compared to itself.
     end
     else //Reverse polarity if descending sort.
         if GlobalSortOptions.SortDirection = sdDescending then
            Result:=-1*Result;
end;


procedure TSortGrid.ListQuickSort(const ACol: Longint; const SortOptions: TSortOptions);
var
   i: Integer;
   Item: PSortedListEntry;
   BufferGrid: TStringGrid;
begin
        GlobalSortOptions:=SortOptions;

        fSortedList.Sort(Compare);
end;
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

kogerAuthor Commented:
if you want the whole code, give me your email
0
interCommented:
Thanks man,

I have already been using TSortGrid, so I know the whole structure. Then what you want is to make options local and yet use it in compare function. is it?
0
kogerAuthor Commented:
I think so :-)

Acually I have made a lot og improvements to tsortgrid, you might want to see.
0
interCommented:
So, is it the problem(sorry if I am pussing fast):

You may have two sortgrids in a project and options are confused within one an other?
(I propose a solution so I try to understand)
0
interCommented:
sure i want...but lets solve the problem first...I try to propose a modified list does it OK?
0
kogerAuthor Commented:
Yes, I add two sortgrids to the same form. One added at designtime the other at runtime, when I free that I created at runtime, my program freezes up. I think this is because I have the global variable.
0
interCommented:
I don't think so, normal global variables are not destroyed when you destroy the instance. May be there is a creation or destroy fault (e.g. you should not assign AnOwner to Create of sort grid if you want to destroy it yourself)

regards,
igor
0
interCommented:
Coming to the point;
I could see the easiest solution as follows:

1 - put as SortOptionPtr variable to record TSortedListEntry.
2 - Remove GlobalSortOptions and add it to TSortGrid as a variable as (e.g.) InternalSortOptions.
3 - When creating a ListEntry assign
  ListEntry.SortOptionPtr := @InternalSortOptions;
4 - Replace all
GlobalSortOptions. to Entry1.SortOptionPtr^. in Compare function

thats is.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
interCommented:
in expense of 4 bytes for every row in the grid of course...
0
kogerAuthor Commented:
wouldn't this slow the sort down
0
interCommented:
No, because you have just pass a pointer to sort routine. It just slows down only for few cycles for referencing  Entry1.SortOptionPtr^. rather than GlobalSortOptions. Be sure it does not make sense even for 486...
0
interCommented:
There is another solution also. We may override the TList such that compare function has is procedure of object. so every instance of the class could call its compare routine and local options are visible for it.
0
kogerAuthor Commented:
something like ?

function Compare(Item1, Item2: Pointer; sortoptions: TSortOptions): Integer; override
0
interCommented:
It is posibble but if we could give sort to class method (the compares will be methods in the class we don't even need to pass sort options. But if you want what you propose, well we can make it. We just change the TList and rewrite internal quicksort routine.
0
kogerAuthor Commented:
If this works and the other way will take some time, I will stick to this.

Well it seems to work pretty fine, but it didn't solve my problem something else i causing an error, invalid pointer operation. Perhaps you could help with this too?
0
interCommented:
Sure (by the way I was away too long... could you choose any comment as answer?) Let's work on it. Please give me how you create the dynamic sortlist and destroy it...
0
interCommented:
I mean sortgrid not sortlist.
0
kogerAuthor Commented:
I think I have.

constructor TSortGrid.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  fSortedList:=TSortedList.Create;
end;

destructor TSortGrid.Destroy;
begin
  fSortedList.Reset;
  fSortedList.Free;
  inherited Destroy;//when this gets called there is an error
end;
0
kogerAuthor Commented:
Sure you dont want the whole file :-)

0
interCommented:
Could you please send me the sort grid unit (so we can make it quick)?
guclu.ongun@isbank.net.tr
0
interCommented:
oh boy, i have delphi 3, but i try...
0
interCommented:
I need your res file also...
0
interCommented:
I have translated it to delphi but i need your res for testing...
0
interCommented:
ok, i have created two grids dynamically and destroy them with no problem:


procedure TForm1.b2Click(Sender: TObject);
begin
  sg1 := TSortGrid.Create(nil);
  sg1.Parent := Self;
  sg1.Top := 0; sg1.Height := ClientHeight div 2;
  sg2 := TSortGrid.Create(nil);
  sg2.Parent := Self;
  sg2.Top := ClientHeight div 2+4; sg2.Height := ClientHeight div 2;
end;

procedure TForm1.b3Click(Sender: TObject);
begin
  sg1.free;
  sg2.free;
end;


please compare with your creation...


0
kogerAuthor Commented:
I fixed it, I have broken a important role, don't hardcode anything. I have chaged a columnsize in my program but forgot to change it everywhere in the code.

Thanks very much for your help, and I'm very sorry that the fault wasn't in sortgrid.pas, I hope you can use my sortgrid.
Koger
0
interCommented:
Thanks to you also, I have done several additions to the sortgrid also maybe we can combine them...for example for each cell OnGetBitmap method is called, thus you can place a bitmap to each cell...etc.
By the way, since delphi 3 does not have the default values for parameters and some messages, i have translated your code very fast and nasty. when you are done with your additions I may add necessary ifdef staments for your component to work with Delphi 3.

regards, igor
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.