fixes for win32 listbox/combobox from Karl Brandt

git-svn-id: trunk@3771 -
This commit is contained in:
mattias 2003-01-01 10:46:59 +00:00
parent d4187e89b6
commit b37432d3e7
8 changed files with 216 additions and 79 deletions

View File

@ -42,6 +42,7 @@ begin
// and use the interface based list
FItems:= NewStrings;
UpdateSorted;
CNSendMessage(LM_SETITEMINDEX, Self, Pointer(FItemIndex));
end;
@ -120,19 +121,10 @@ end;
Set the "sorted" property of the combobox and Sort the current entries.
------------------------------------------------------------------------------}
procedure TCustomComboBox.SetSorted(Val : boolean);
var AMessage : TLMSort;
begin
if (Val <> FSorted) then begin
if HandleAllocated then begin
with AMessage do begin
Msg:= LM_SORT;
List:= Items;
IsSorted:= Val;
end;
CNSendMessage(LM_SORT, Self, @AMessage);
end;
FSorted:= Val;
UpdateSorted;
end;
end;
@ -720,10 +712,29 @@ begin
end;
end;
{------------------------------------------------------------------------------
procedure TCustomComboBox.UpdateSorted;
------------------------------------------------------------------------------}
procedure TCustomComboBox.UpdateSorted;
var
AMessage : TLMSort;
begin
if not HandleAllocated then exit;
with AMessage do begin
Msg:= LM_SORT;
List:= Items;
IsSorted:= FSorted;
end;
CNSendMessage(LM_SORT, Self, @AMessage);
end;
// included by stdctrls.pp
{
$Log$
Revision 1.24 2003/01/01 10:46:59 mattias
fixes for win32 listbox/combobox from Karl Brandt
Revision 1.23 2002/11/17 11:10:04 mattias
TComboBox and TListBox accelerated and now supports objects

View File

@ -253,7 +253,7 @@ begin
raise Exception.Create('TCustomListBox.GetSelected: index '+IntToStr(Index)
+' out of bound. Count='+IntToStr(Items.Count));
if HandleAllocated then
Result:= (CNSendMessage(LM_GETSEL, Self, @Index) >= 0)
Result:= (CNSendMessage(LM_GETSEL, Self, @Index) > 0)
else
Result:=clbiSelected in GetListBoxItemRecord(FItems,Index)^.Flags;
end;

View File

@ -140,8 +140,6 @@ Implementation
Uses
Arrow, Buttons, Calendar, CListBox, Graphics, Menus, Process, Spin, WinExt;
{$I win32listsl.inc}
Type
TEventType = (etNotify, etKey, etKeyPress, etMouseWheeel, etMouseUpDown);
@ -169,6 +167,7 @@ Var
WndList: TList;
{$I win32proc.inc}
{$I win32listsl.inc}
{$I win32callback.inc}
{$I win32object.inc}
{$I win32winapi.inc}
@ -189,6 +188,9 @@ End.
{ =============================================================================
$Log$
Revision 1.27 2003/01/01 10:46:59 mattias
fixes for win32 listbox/combobox from Karl Brandt
Revision 1.26 2002/12/28 09:42:12 mattias
toolbutton patch from Martin Smat

View File

@ -38,6 +38,7 @@ Begin
Result := StrComp(AStr, BStr);
end;
{*************************************************************}
{ TWin32ListStringList methods }
{*************************************************************}
@ -48,14 +49,14 @@ end;
Returns:
------------------------------------------------------------------------------}
Constructor TWin32ListStringList.Create(List: HWND);
Constructor TWin32ListStringList.Create(List : HWND; TheOwner: TControl);
Begin
Inherited Create;
If List = HWND(Nil) Then
Raise Exception.Create('Unspecified list window');
//Assert(False, 'Trace:Unspecified list window');
FWin32List := List;
FSender := TControl(GetProp(FWin32List, 'Lazarus'));
FSender := TheOwner;
FOrigHeight := FSender.Height;
//Set proper win32 flags for ComboBox/ListBox
@ -68,6 +69,7 @@ Begin
FFlagResetContent:=CB_RESETCONTENT;
FFlagDeleteString:=CB_DELETESTRING;
FFlagInsertString:=CB_INSERTSTRING;
FFlagAddString:=CB_ADDSTRING;
end;
csListBox:begin
FFlagSort:=LBS_SORT;
@ -77,9 +79,12 @@ Begin
FFlagResetContent:=LB_RESETCONTENT;
FFlagDeleteString:=LB_DELETESTRING;
FFlagInsertString:=LB_INSERTSTRING;
FFlagAddString:=LB_ADDSTRING;
end;
else Raise Exception.Create('Win32ListStringList: Component type not detected');
end;
// Determine if the list is sorted
FSorted := (GetWindowLong(FWin32List, GWL_STYLE) and FFlagSort <> 0);
End;
{------------------------------------------------------------------------------
@ -105,7 +110,7 @@ End;
------------------------------------------------------------------------------}
Procedure TWin32ListStringList.Sort;
Begin
SetWindowLong(FWin32List, GWL_STYLE, GetWindowLong(FWin32List, GWL_STYLE) Or FFlagSort);
RecreateListControl(FWin32List,FSender,FSorted);
End;
{------------------------------------------------------------------------------
@ -168,8 +173,9 @@ End;
------------------------------------------------------------------------------}
Procedure TWin32ListStringList.Clear;
Begin
FSender.Height := FOrigHeight;
Begin
if FSender.FCompStyle=csComboBox Then
FSender.Height := FOrigHeight;
SendMessage(FWin32List,FFlagResetContent, 0, 0);
End;
@ -181,7 +187,8 @@ End;
------------------------------------------------------------------------------}
Procedure TWin32ListStringList.Delete(Index: Integer);
Begin
If GetCount <> 0 Then
If (FSender.FCompStyle = csComboBox)
and (GetCount <> 0) Then
FSender.Height := (FSender.Height - (FSender.Height Div GetCount));
SendMessage(FWin32List,FFlagDeleteString, Index, 0);
End;
@ -194,12 +201,13 @@ End;
------------------------------------------------------------------------------}
Procedure TWin32ListStringList.Insert(Index: Integer; Const S: String);
Begin
If (GetCount <> 0)
and (FSender.FCompStyle = csComboBox) Then
If (FSender.FCompStyle = csComboBox)
and (GetCount <> 0) Then
FSender.Height := (FSender.Height + (FSender.Height Div GetCount));
SendMessage(FWin32List,FFlagInsertString, Index, LPARAM(PChar(S)));
If FSorted Then
Sort;
SendMessage(FWin32List,FFlagAddString, 0, LPARAM(PChar(S)))
Else
SendMessage(FWin32List,FFlagInsertString, Index, LPARAM(PChar(S)));
End;
{*************************************************************}
@ -212,12 +220,14 @@ End;
Returns:
------------------------------------------------------------------------------}
Constructor TWin32CListStringList.Create(List: HWND);
Constructor TWin32CListStringList.Create(List : HWND; TheOwner: TControl);
Begin
Inherited Create;
If List = HWND(Nil) Then
Raise Exception.Create('Unspecified list widget');
FWin32CList := List;
FSorted := (GetWindowLong(FWin32CList, GWL_STYLE) and LBS_SORT <> 0);
FSender:=TheOwner;
End;
{------------------------------------------------------------------------------
@ -231,10 +241,7 @@ Begin
If Val <> FSorted Then
Begin
FSorted := Val;
If Val Then
Sort
Else
SetWindowLong(FWin32CList, GWL_STYLE, GetWindowLong(FWin32CList, GWL_STYLE) And Not LBS_SORT);
Sort;
End;
End;
@ -246,7 +253,8 @@ End;
------------------------------------------------------------------------------}
Procedure TWin32CListStringList.Sort;
Begin
SetWindowLong(FWin32CList, GWL_STYLE, GetWindowLong(FWin32CList, GWL_STYLE) Or LBS_SORT);
// The win api doesn't allow to change the sort on the fly, so is needed to recreate the window
RecreateListControl(FWin32CList,FSender,FSorted);
End;
{------------------------------------------------------------------------------
@ -343,7 +351,10 @@ End;
------------------------------------------------------------------------------}
Procedure TWin32CListStringList.Insert(Index: Integer; Const S: String);
Begin
SendMessage(FWin32CList, LB_INSERTSTRING, Index, LPARAM(PChar(S)));
If FSorted Then
SendMessage(FWin32CList,LB_ADDSTRING, 0, LPARAM(PChar(S)))
Else
SendMessage(FWin32CList,LB_INSERTSTRING, Index, LPARAM(PChar(S)));
End;
{------------------------------------------------------------------------------
@ -366,6 +377,9 @@ End;
{ =============================================================================
$Log$
Revision 1.8 2003/01/01 10:46:59 mattias
fixes for win32 listbox/combobox from Karl Brandt
Revision 1.7 2002/11/15 23:43:54 mattias
applied patch from Karl Brandt

View File

@ -39,12 +39,13 @@ Type
FFlagResetContent:Cardinal;
FFlagDeleteString:Cardinal;
FFlagInsertString:Cardinal;
FFlagAddString:Cardinal;
Protected
Function Get(Index: Integer): String; Override;
Function GetCount: Integer; Override;
Procedure SetSorted(Val: Boolean); Virtual;
Public
Constructor Create(List: HWND);
Constructor Create(List : HWND; TheOwner: TControl);
Procedure Assign(Source: TPersistent); Override;
Procedure Clear; Override;
Procedure Delete(Index: Integer); Override;
@ -56,6 +57,7 @@ Type
TWin32CListStringList = Class(TStrings)
Private
FWin32CList: HWND;
FSender: TControl; // Needed to recreate the window
FSorted: Boolean;
Protected
Function Get(Index: Integer): String; Override;
@ -64,7 +66,7 @@ Type
Procedure PutObject(Index: Integer; AObject: TObject); Override;
Procedure SetSorted(Val: Boolean); Virtual;
Public
Constructor Create(List: HWND);
Constructor Create(List : HWND; TheOwner: TControl);
Procedure Assign(Source: TPersistent); Override;
Procedure Clear; Override;
Procedure Delete(Index: Integer); Override;
@ -82,6 +84,9 @@ Type
{ =============================================================================
$Log$
Revision 1.5 2003/01/01 10:46:59 mattias
fixes for win32 listbox/combobox from Karl Brandt
Revision 1.4 2002/11/15 23:43:54 mattias
applied patch from Karl Brandt

View File

@ -725,12 +725,12 @@ activate_time : the time at which the activation event occurred.
Begin
If (Sender as TControl).fCompStyle = csCListBox Then
Begin
Data := TWin32CListStringList.Create(Handle);
Data := TWin32CListStringList.Create(Handle,TControl(Sender));
Result := Integer(Data);
End
Else
Begin
Data := TWin32ListStringList.Create(Handle{Control});
Data := TWin32ListStringList.Create(Handle,TControl(Sender));
Result := Integer(Data);
End;
End;
@ -743,19 +743,12 @@ activate_time : the time at which the activation event occurred.
Case (Sender as TControl).FCompStyle Of
csListBox, csCListBox:
Begin
If TListBox(Sender).MultiSelect Then
Begin
Result := SendMessage(Handle, LB_GETSELITEMS, 0, LParam(@Result));
End
Else
Begin
Result := SendMessage(Handle, LB_GETCURSEL, 0, 0);
If Result = LB_ERR Then
Begin
Assert(False, 'Trace:[TWin32Object.IntSendMessage3] Could not retrieve item index via LM_GETITEMINDEX; try selecting an item first');
Result := -1;
End;
End;
End;
csNotebook:
Begin
@ -830,17 +823,13 @@ activate_time : the time at which the activation event occurred.
End;
LM_GETSELCOUNT:
Begin
Case (Sender as TControl).FCompStyle Of
csListBox, csCListBox:
Result := SendMessage(Handle, LB_GETSELCOUNT, 0, 0);
End;
If Sender Is TCustomListBox then
Result := SendMessage(Handle, LB_GETSELCOUNT, 0, 0);
End;
LM_GETSEL:
Begin
If ((Sender As TWinControl).FCompStyle = csListBox) Or ((Sender As TControl).FCompStyle = csCListBox) then
Begin
Result := Windows.SendMessage(Handle, LB_GETSEL, WParam(Data), 0);
End
If Sender Is TCustomListBox then
Result := Windows.SendMessage(Handle, LB_GETSEL, WParam(Data^), 0);
End;
LM_SETLIMITTEXT:
Begin
@ -875,26 +864,23 @@ activate_time : the time at which the activation event occurred.
End;
End;
LM_SETSELMODE:
Begin
If (Sender is TControl) And (TControl(Sender).fCompStyle In [csListBox, csCListBox]) And Assigned(data) Then
If (Sender is TCustomListBox) And Assigned(data) Then
Begin
If TLMSetSelMode(Data^).MultiSelect Then
Begin
If TLMSetSelMode(Data^).ExtendedSelect Then
SelectionMode := LBS_EXTENDEDSEL
Else
SelectionMode := LBS_MULTIPLESEL;
End
Else
SelectionMode:= 0;
SetWindowLong(Handle, GWL_STYLE, GetWindowLong(Handle, GWL_Style) Or SelectionMode);
End;
End;
//The win32 api doesn't change the selection mode on the fly: it needs recreate the window
//RecreateWnd(Sender); -> cause endless loop
//Recreates the window step by step
If TCustomListBox(Sender).FCompStyle = csListBox Then
RecreateListControl(Handle,TControl(Sender),TListBox(Sender).Sorted)
Else
RecreateListControl(Handle,TControl(Sender),TCListBox(Sender).Sorted);
End;
LM_SETBORDER:
Begin
If Sender is TControl Then
Begin
If (TControl(Sender).fCompStyle = csListBox)
If (TControl(Sender).FCompStyle = csListBox)
Or (TControl(Sender).FCompStyle = csCListBox) Then
Begin
If TCustomListBox(Sender).BorderStyle = TBorderStyle(bsSingle) Then
@ -1038,21 +1024,23 @@ End;
Function TWin32Object.RecreateWnd(Sender: TObject): Integer;
Var
AParent : TWinControl;
AParent,AWinControl : TWinControl;
Begin
//could we just call IntSendMessage??
//destroy old widget
If TWinControl(Sender).Handle <> 0 Then
DestroyWindow(TWinControl(Sender).Handle);
// Not Necessary -> See TControl.SetParent
// If TWinControl(Sender).Handle <> 0 Then
// DestroyWindow(TWinControl(Sender).Handle);
AWinControl:= TWinControl(Sender);
AParent := AWinControl.Parent;
//Not necessary
//AParent.RemoveControl(TControl(Sender));
AParent := TWinControl(Sender).Parent;
AParent.RemoveControl(TControl(Sender));
AWinControl.Parent := Nil;
AWinControl.Parent := AParent;
TWinControl(Sender).Parent := Nil;
TWinControl(Sender).Parent := AParent;
ResizeChild(Sender, TWinControl(Sender).Left, TWinControl(Sender).Top, TWinControl(Sender).Width, TWinControl(Sender).Height);
ResizeChild(Sender, AWinControl.Left, AWinControl.Top, AWinControl.Width, AWinControl.Height);
ShowHide(Sender);
Result := 0;
@ -1711,16 +1699,14 @@ Begin
End;
csListBox:
Begin
Window := CreateWindow('LISTBOX', Nil, Flags, Left, Top, Width, Width, Parent, HMENU(Nil), HInstance, Nil);
SendMessage(Window, LB_ADDSTRING, 0, LPARAM(LPCTSTR(StrTemp)));
Window := CreateWindow('LISTBOX', Nil, Flags or WS_VSCROLL, Left, Top, Width, Height, Parent, HMENU(Nil), HInstance, Nil);
SetProp(Window, 'Lazarus', Sender);
SetName(Window, StrTemp);
End;
csCListBox:
Begin
Window := CreateWindow('LISTBOX', Nil, Flags Or LBS_MULTICOLUMN, Left, Top, Width, Width, Parent, HMENU(Nil), HInstance, Nil);
Window := CreateWindow('LISTBOX', Nil, Flags Or LBS_MULTICOLUMN or WS_HSCROLL, Left, Top, Width, Height, Parent, HMENU(Nil), HInstance, Nil);
SendMessage(Window, LB_SETCOLUMNWIDTH, WPARAM((Sender As TCListBox).Width Div ((Sender As TCListBox).ListColumns)), 0);
SendMessage(Window, LB_ADDSTRING, 0, LPARAM(LPCTSTR(StrTemp)));
SetProp(Window, 'Lazarus', Sender);
SetName(Window, StrTemp);
End;
@ -1772,7 +1758,6 @@ Begin
FParentWindow := Window;
Assert(False, 'Trace:CreateComponent - Form Window Handle Value = $' + IntToHex(Window, 8));
Assert(False, 'Trace:Creating a Form - SetProp');
//SetProp(Window, 'Lazarus', Sender);
SetProp(Window, 'Lazarus', Sender);
If Window = 0 then
Begin
@ -2618,6 +2603,9 @@ End;
{
$Log$
Revision 1.40 2003/01/01 10:46:59 mattias
fixes for win32 listbox/combobox from Karl Brandt
Revision 1.39 2002/12/29 18:17:49 mattias
patch from Martin Smat fixing creating handles

View File

@ -623,7 +623,117 @@ Begin
Assert (False, 'Trace:[ObjectToHWND]****** Warning: handle = 0 *******');
End;
{------------------------------------------------------------------------------
Procedure: RecreateListControl
Params: ListHandle - Handle of window
ListControl - TListBox, TCListBox or TComboBox
ToSort - Sort the list?
Returns: nothing
------------------------------------------------------------------------------}
Procedure RecreateListControl(const ListHandle:HWND;const ListControl:TControl; ToSort:Boolean);
var List:TListBox;
CList:TCListBox;
Combo:TComboBox;
TempStrList:TStringList;
ParentHandle,NewHandle,NameProp:HWND;
ListFlags: DWORD;
begin
TempStrList:=TStringList.Create;
ParentHandle:=ListControl.Parent.Handle;
// Get current name property and remove before destroy the window
NameProp:=Integer(GetProp(ListHandle,'Name'));
RemoveProp(ListHandle,'Name');
RemoveProp(ListHandle,'Lazarus');
// Get current flags
ListFlags:=GetWindowLong(ListHandle, GWL_STYLE);
case ListControl.FCompStyle of
csListBox:
with List do
begin
List:=TListBox(ListControl);
TempStrList.Assign(Items);
If MultiSelect Then
begin
if ExtendedSelect then
ListFlags:=ListFlags or LBS_EXTENDEDSEL
else
ListFlags:=(ListFlags or LBS_MULTIPLESEL) and (not LBS_EXTENDEDSEL);
end
else ListFlags:=ListFlags and (not (LBS_MULTIPLESEL or LBS_EXTENDEDSEL));
If ToSort Then
ListFlags:=ListFlags or LBS_SORT
Else
ListFlags:=ListFlags and (not LBS_SORT);
DestroyWindow(ListHandle);
If BorderStyle = TBorderStyle(bsSingle) Then
NewHandle:= CreateWindowEx(WS_EX_CLIENTEDGE,'LISTBOX', Nil, ListFlags or WS_VSCROLL, Left, Top, Width, Height, ParentHandle, HMENU(Nil), HInstance, Nil)
Else
NewHandle:= CreateWindow('LISTBOX', Nil, ListFlags or WS_VSCROLL, Left, Top, Width, Height, ParentHandle, HMENU(Nil), HInstance, Nil);
Handle:=NewHandle;
Items.Free;
Items:= TWin32ListStringList.Create(NewHandle,List);
Items.Assign(TempStrList);
end;
csCListBox:
with CList do
begin
CList:=TCListBox(ListControl);
TempStrList.Assign(Items);
If MultiSelect Then
begin
if ExtendedSelect then
ListFlags:=ListFlags or LBS_EXTENDEDSEL
else
ListFlags:=(ListFlags or LBS_MULTIPLESEL) and (not LBS_EXTENDEDSEL);
end
else ListFlags:=ListFlags and (not (LBS_MULTIPLESEL or LBS_EXTENDEDSEL));
If ToSort Then
ListFlags:=ListFlags or LBS_SORT
Else
ListFlags:=ListFlags and (not LBS_SORT);
DestroyWindow(ListHandle);
If BorderStyle = TBorderStyle(bsSingle) Then
NewHandle := CreateWindowEx(WS_EX_CLIENTEDGE,'LISTBOX', Nil, ListFlags Or LBS_MULTICOLUMN or WS_HSCROLL, Left, Top, Width, Height, ParentHandle, HMENU(Nil), HInstance, Nil)
Else
NewHandle:= CreateWindow('LISTBOX', Nil, ListFlags Or LBS_MULTICOLUMN or WS_HSCROLL, Left, Top, Width, Height, ParentHandle, HMENU(Nil), HInstance, Nil);
Handle:=NewHandle;
Items.Free;
Items:= TWin32CListStringList.Create(NewHandle,CList);
Items.Assign(TempStrList);
end;
csComboBox:with Combo do
begin
Combo:=TComboBox(ListControl);
TempStrList.Assign(Items);
If ToSort Then
ListFlags:=ListFlags or CBS_SORT
Else
ListFlags:=ListFlags and (not CBS_SORT);
DestroyWindow(ListHandle);
NewHandle:= CreateWindow('COMBOBOX', Nil, ListFlags, Left, Top, Width, Height, ParentHandle, HMENU(Nil), HInstance, Nil);
Handle:=NewHandle;
Items.Free;
Items:= TWin32ListStringList.Create(NewHandle,Combo);
Items.Assign(TempStrList);
end;
end;
TempStrList.Free;
// Set the new window properties
SetProp(NewHandle,'Lazarus',ListControl);
SetProp(NewHandle,'Name',Pointer(NameProp));
end;
(***********************************************************************
Widget member Functions
************************************************************************)
@ -676,6 +786,9 @@ End;
{ =============================================================================
$Log$
Revision 1.12 2003/01/01 10:46:59 mattias
fixes for win32 listbox/combobox from Karl Brandt
Revision 1.11 2002/12/16 09:02:27 mattias
applied win32 notebook patch from Vincent

View File

@ -213,6 +213,7 @@ type
procedure SetItems(Value : TStrings);
procedure LMDrawListItem(var TheMessage : TLMDrawListItem); message LM_DrawListItem;
procedure CNCommand(var TheMessage : TLMCommand); message CN_Command;
procedure UpdateSorted;
protected
procedure CreateHandle; override;
procedure DestroyHandle; override;
@ -1392,6 +1393,9 @@ end.
{ =============================================================================
$Log$
Revision 1.74 2003/01/01 10:46:59 mattias
fixes for win32 listbox/combobox from Karl Brandt
Revision 1.73 2002/12/28 21:44:51 mattias
further cleanup