1{%MainUnit winceint.pp} 2 3{****************************************************************************** 4 wincelistsl.inc 5 TWinCEListStringList, TWinCEComboBoxStringList and TWinCECheckListBoxStrings 6 7 ****************************************************************************** 8 9 ***************************************************************************** 10 This file is part of the Lazarus Component Library (LCL) 11 12 See the file COPYING.modifiedLGPL.txt, included in this distribution, 13 for details about the license. 14 ***************************************************************************** 15} 16 17{$IFOPT H+} 18 {$DEFINE H_PLUS} 19{$ELSE} 20 {$H+} 21 {$UNDEF H_PLUS} 22{$ENDIF} 23 24{*************************************************************} 25{ Default compare function } 26{*************************************************************} 27 28function DefaultCompareFunc(A, B: HWND): Integer; CDecl; 29Var 30 AStr, BStr: PWideChar; 31Begin 32 AStr:=nil; 33 BStr:=nil; 34 GetWindowTextW(A, AStr, GetWindowTextLength(A) + 1); 35 GetWindowTextW(B, BStr, GetWindowTextLength(B) + 1); 36 Result := WideCompareStr(widestring(AStr), widestring(BStr));//roozbeh:does this work?! 37end; 38 39{*************************************************************} 40{ TWinCEListStringList methods } 41{*************************************************************} 42 43{------------------------------------------------------------------------------ 44 Method: TWinCEListStringList.Create 45 Params: 46 Returns: 47 48 ------------------------------------------------------------------------------} 49constructor TWinCEListStringList.Create(List : HWND; TheOwner: TWinControl); 50begin 51 inherited Create; 52 if List = HWND(nil) then 53 Raise Exception.Create('Unspecified list window'); 54 //DebugLn('Trace:Unspecified list window'); 55 FWinCEList := List; 56 FSender := TheOwner; 57 58 //Set proper wince flags for ComboBox/ListBox and get/set Combo Height 59 InitFlags; 60 // Determine if the list is sorted 61 FSorted := (UINT(GetWindowLong(FWinCEList, GWL_STYLE)) and FFlagSort <> 0); 62end; 63 64procedure TWinCEListStringList.InitFlags; 65begin 66 FFlagSort := UINT(LBS_SORT); 67 FFlagGetText := UINT(LB_GETTEXT); 68 FFlagGetTextLen := UINT(LB_GETTEXTLEN); 69 FFlagGetCount := UINT(LB_GETCOUNT); 70 FFlagResetContent := UINT(LB_RESETCONTENT); 71 FFlagDeleteString := UINT(LB_DELETESTRING); 72 FFlagInsertString := UINT(LB_INSERTSTRING); 73 FFlagAddString := UINT(LB_ADDSTRING); 74 FFlagGetItemData := UINT(LB_GETITEMDATA); 75 FFlagSetItemData := UINT(LB_SETITEMDATA); 76 FFlagGetItemIndex := UINT(LB_GETCURSEL); 77 FFlagSetItemIndex := UINT(LB_SETCURSEL); 78 FFlagGetSelected := UINT(LB_GETSEL); 79 FFlagSetSelected := UINT(LB_SETSEL); 80end; 81 82{------------------------------------------------------------------------------ 83 Method: TWinCEListStringList.SetSorted 84 Params: 85 Returns: 86 87 ------------------------------------------------------------------------------} 88procedure TWinCEListStringList.SetSorted(Val: Boolean); 89Begin 90 If Val <> FSorted Then 91 Begin 92 FSorted:= Val; 93 Sort; 94 End; 95End; 96 97{------------------------------------------------------------------------------ 98 Method: TWinCEListStringList.Sort 99 Params: 100 Returns: 101 102 ------------------------------------------------------------------------------} 103procedure TWinCEListStringList.Sort; 104Begin 105 // The win api doesn't allow to change the sort on the fly, 106 // so is needed to recreate the window 107 RecreateWnd(FSender); 108End; 109 110{------------------------------------------------------------------------------ 111 Method: TWinCEListStringList.Assign 112 Params: 113 Returns: 114 115 ------------------------------------------------------------------------------} 116procedure TWinCEListStringList.Assign(Source: TPersistent); 117Var 118 S: TStrings; 119 Counter: Integer; 120 AnIndex: Integer; 121 tmpStr : widestring; 122Begin 123 { Do not call inherited Assign as it does things we do not want to happen } 124 If Source Is TStrings Then 125 Begin 126 S:= TStrings(Source); 127 QuoteChar:=S.QuoteChar; 128 Delimiter:=S.Delimiter; 129 NameValueSeparator:=S.NameValueSeparator; 130 Windows.SendMessage(FWinCEList, FFlagResetContent, 0, 0); 131 For Counter := 0 To (TStrings(Source).Count - 1) Do 132 Begin 133 tmpStr := UTF8Decode(s[Counter]); 134 AnIndex := Windows.SendMessageW(FWinCEList, FFlagAddString, 0, 135 LPARAM(PWideChar(tmpStr))); //Insert 136 PutObject(AnIndex, S.Objects[Counter]); 137 end; 138 End 139 Else 140 inherited Assign(Source); 141End; 142 143 144{------------------------------------------------------------------------------ 145 Method: TWinCEListStringList.Add 146 Params: 147 Returns: 148 149 ------------------------------------------------------------------------------} 150function TWinCEListStringList.Add(const S: string): Integer; 151begin 152 Result := Count; 153 Insert(Count, S); 154 if FSorted then 155 Result := FLastInsertedIndex; 156end; 157 158{------------------------------------------------------------------------------ 159 Method: TWinCEListStringList.Get 160 Params: 161 Returns: 162 163 ------------------------------------------------------------------------------} 164function TWinCEListStringList.Get(Index: Integer): String; 165Var 166 w: widestring; 167Begin 168 If (Index < 0) Or (Index >= Count) Then 169 Raise Exception.Create('Out of bounds.') 170 Else 171 Begin 172 SetLength(w, Windows.SendMessageW(FWinCEList, FFlagGetTextLen, Index, 0)); 173 Windows.SendMessageW(FWinCEList, FFlagGetText, Index, LPARAM(PWideChar(w))); 174 Result := UTF8Encode(w); 175 End; 176End; 177 178{------------------------------------------------------------------------------ 179 Method: TWinCEListStringList.GetCount 180 Params: 181 Returns: 182 183 ------------------------------------------------------------------------------} 184function TWinCEListStringList.GetCount: Integer; 185Begin 186 Result := Windows.SendMessage(FWinCEList, FFlagGetCount, 0, 0); 187End; 188 189{------------------------------------------------------------------------------ 190 Method: TWinCEListStringList.Clear 191 Params: 192 Returns: 193 194 ------------------------------------------------------------------------------} 195procedure TWinCEListStringList.Clear; 196Begin 197 Windows.SendMessage(FWinCEList, FFlagResetContent, 0, 0); 198End; 199 200{------------------------------------------------------------------------------ 201 Method: TWinCEListStringList.Delete 202 Params: 203 Returns: 204 205 ------------------------------------------------------------------------------} 206procedure TWinCEListStringList.Delete(Index: Integer); 207Begin 208 Windows.SendMessage(FWinCEList, FFlagDeleteString, Index, 0); 209End; 210 211{------------------------------------------------------------------------------ 212 Method: TWinCEListStringList.GetObject 213 Params: 214 Returns: 215 216 ------------------------------------------------------------------------------} 217function TWinCEListStringList.GetObject(Index: Integer): TObject; 218Begin 219 HWND(Result) := Windows.SendMessageW(FWinCEList, FFlagGetItemData, Index, 0); 220End; 221 222{------------------------------------------------------------------------------ 223 Method: TWinCEListStringList.Insert 224 Params: 225 Returns: 226 227 ------------------------------------------------------------------------------} 228procedure TWinCEListStringList.Insert(Index: Integer; Const S: String); 229Begin 230 FLastInsertedIndex := Index; 231 if FSorted then 232 FLastInsertedIndex := Windows.SendMessageW(FWinCEList, FFlagAddString, 0, LPARAM(PWideChar(Utf8Decode(S)))) 233 else 234 Windows.SendMessageW(FWinCEList, FFlagInsertString, Index, LPARAM(PWideChar(Utf8Decode(S)))); 235End; 236 237procedure TWinCEListStringList.Put(Index: integer; const S: string); 238var 239 lItemIndex: integer; 240 lSelected: boolean; 241begin 242 // remember selection 243 lItemIndex := -1; 244 if FFlagGetSelected <> 0 then 245 begin 246 lItemIndex := SendMessageW(FWinCEList, FFlagGetSelected, Index, 0); 247 lSelected := lItemIndex > 0; 248 if lItemIndex <> LB_ERR then 249 lItemIndex := Index; 250 end; 251 if lItemIndex = -1 then 252 begin 253 lItemIndex := SendMessageW(FWinCEList, FFlagGetItemIndex, 0, 0); 254 lSelected := true; 255 end; 256 257 inherited; 258 259 if lSelected then 260 begin 261 if (FFlagSetSelected = 0) 262 or (SendMessageW(FWinCEList, FFlagSetSelected, Windows.WParam(true), lItemIndex) = -1) then 263 begin 264 SendMessageW(FWinCEList, FFlagSetItemIndex, lItemIndex, 0); 265 end; 266 end; 267end; 268 269{------------------------------------------------------------------------------ 270 Method: TWinCEListStringList.PutObject 271 Params: 272 Returns: 273 274 ------------------------------------------------------------------------------} 275procedure TWinCEListStringList.PutObject(Index: Integer; AObject: TObject); 276Begin 277 Windows.SendMessage(FWinCEList, FFlagSetItemData, Index, LPARAM(AObject)); 278End; 279 280{ TWinCEComboBoxStringList } 281 282procedure TWinCEComboBoxStringList.InitFlags; 283var 284 R: TRect; 285begin 286 FFlagSort := UINT(CBS_SORT); 287 FFlagGetText := UINT(CB_GETLBTEXT); 288 FFlagGetTextLen := UINT(CB_GETLBTEXTLEN); 289 FFlagGetCount := UINT(CB_GETCOUNT); 290 FFlagResetContent := UINT(CB_RESETCONTENT); 291 FFlagDeleteString := UINT(CB_DELETESTRING); 292 FFlagInsertString := UINT(CB_INSERTSTRING); 293 FFlagAddString := UINT(CB_ADDSTRING); 294 FFlagGetItemData := UINT(CB_GETITEMDATA); 295 FFlagSetItemData := UINT(CB_SETITEMDATA); 296 FFlagGetItemIndex := UINT(CB_GETCURSEL); 297 FFlagSetItemIndex := UINT(CB_SETCURSEL); 298 FFlagGetSelected := UINT(0); 299 FFlagSetSelected := UINT(0); 300 //Get edit and item sizes 301 Windows.GetClientRect(FWinCEList,@R); 302 FEditHeight := R.Bottom; 303 FItemHeight := Windows.SendMessage(FWinCEList, CB_GETITEMHEIGHT, 0, 0); 304 FDropDownCount := TComboBox(FSender).DropDownCount; 305 If FDropDownCount = 0 then 306 FDropDownCount := 8; 307end; 308 309procedure TWinCEComboBoxStringList.UpdateComboHeight; 310var 311 Left, Top, Width, Height: integer; 312begin 313 Left := FSender.Left; 314 Top := FSender.Top; 315 Width := FSender.Width; 316 Height := ComboHeight; 317 LCLBoundsToWin32Bounds(FSender, Left, Top, Width, Height); 318 MoveWindow(FSender.Handle, Left, Top, Width, Height, true); 319 LCLControlSizeNeedsUpdate(FSender, true); 320end; 321 322procedure TWinCEComboBoxStringList.Assign(Source: TPersistent); 323var 324 EditText: string; 325 lItemIndex: integer; 326begin 327 if Source is TStrings then 328 begin 329 // save text in edit box, assigning strings clears the text 330 TWinCEWSCustomComboBox.GetText(FSender, EditText); 331 332 inherited Assign(Source); 333 334 // restore text in edit box 335 UpdateComboHeight; 336 TWinCEWSCustomComboBox.SetText(FSender, EditText); 337 lItemIndex := IndexOf(EditText); 338 if lItemIndex <> -1 then 339 TWinCEWSCustomComboBox.SetItemIndex(TCustomComboBox(FSender), lItemIndex); 340 end else 341 inherited Assign(Source); 342end; 343 344function TWinCEComboBoxStringList.GetComboHeight: integer; 345begin 346 if (FSender is TCustomComboBox) and (TCustomComboBox(FSender).Style = csSimple) then 347 begin 348 // combobox workaround: 349 // if style = csSimple follow the LCL height. 350 Result := FSender.Height; 351 end else 352 begin 353 if Count = 0 then 354 begin 355 Result := FEditHeight + FItemHeight + 2; 356 end else 357 begin 358 Result := FEditHeight + FDropDownCount * FItemHeight + 2; 359 end; 360 end; 361end; 362 363procedure TWinCEComboBoxStringList.Clear; 364var 365 SaveText: String; 366begin 367 if not TCustomComboBox(FSender).ReadOnly then 368 SaveText := TCustomComboBox(FSender).Text; 369 inherited; 370 UpdateComboHeight; 371 if not TCustomComboBox(FSender).ReadOnly then 372 TCustomComboBox(FSender).Text := SaveText; 373end; 374 375procedure TWinCEComboBoxStringList.Delete(Index: integer); 376begin 377 inherited Delete(Index); 378 if Count <= 1 then 379 UpdateComboHeight; 380end; 381 382procedure TWinCEComboBoxStringList.Insert(Index: integer; const S: string); 383begin 384 inherited Insert(Index, S); 385 if GetCount = 1 then 386 UpdateComboHeight; 387end; 388 389 390{ TWinCECheckListBoxStrings } 391 392constructor TWinCECheckListBoxStrings.Create(List : HWND; TheOwner: TWinControl); 393begin 394 inherited Create(List, TheOwner); 395 with FDefaultItem do 396 begin 397 State := cbUnchecked; 398 TheObject := nil; 399 end; 400end; 401 402function TWinCECheckListBoxStrings.GetState(AIndex: Integer): TCheckBoxState; 403var 404 Data: PWinCECheckListBoxItemRecord; 405begin 406 Data := GetItemRecord(AIndex, False); 407 Result := Data^.State 408end; 409 410function TWinCECheckListBoxStrings.GetItemRecord(const Index: Integer; 411 const CreateNew: boolean): PWinCECheckListBoxItemRecord; 412begin 413 Result := PWinCECheckListBoxItemRecord(Windows.SendMessage(FWinCEList, LB_GETITEMDATA, Index, 0)); 414 if (not Assigned(Result)) then begin 415 if CreateNew then begin 416 Result := new(PWinCECheckListBoxItemRecord); 417 Result^ := FDefaultItem; 418 end 419 else Result := @FDefaultItem; 420 end; 421end; 422 423procedure TWinCECheckListBoxStrings.SetItemRecord(const Index: Integer; 424 ItemRecord: PWinCECheckListBoxItemRecord); 425begin 426 Windows.SendMessage(FWinCEList, LB_SETITEMDATA, Index, LPARAM(ItemRecord)); 427end; 428 429procedure TWinCECheckListBoxStrings.SetState(AIndex: Integer; 430 const AValue: TCheckBoxState); 431var 432 ItemRecord: PWinCECheckListBoxItemRecord; 433begin 434 ItemRecord := GetItemRecord(AIndex, True); 435 ItemRecord^.State := AValue; 436 SetItemRecord(AIndex, ItemRecord); 437end; 438 439procedure TWinCECheckListBoxStrings.Clear; 440begin 441 DeleteItemRecords(FWinCEList); 442 inherited Clear; 443end; 444 445procedure TWinCECheckListBoxStrings.Delete(Index: Integer); 446begin 447 DeleteItemRecord(FWinCEList, Index); 448 inherited Delete(Index); 449end; 450 451procedure TWinCECheckListBoxStrings.Move(CurIndex, NewIndex: Integer); 452var 453 AState: TCheckBoxState; 454begin 455 AState := State[CurIndex]; 456 inherited Move(CurIndex, NewIndex); 457 State[NewIndex] := AState; 458end; 459 460function TWinCECheckListBoxStrings.GetObject(Index: Integer): TObject; 461begin 462 Result:= GetItemRecord(Index, false)^.TheObject; 463end; 464 465procedure TWinCECheckListBoxStrings.PutObject(Index: Integer; AObject: TObject); 466var 467 ItemRecord: PWinCECheckListBoxItemRecord; 468begin 469 ItemRecord := GetItemRecord(Index, true); 470 ItemRecord^.TheObject := AObject; 471 SetItemRecord(Index, ItemRecord); 472end; 473 474class procedure TWinCECheckListBoxStrings.DeleteItemRecords(const List: HWND); 475var 476 Index: Integer; 477 ItemCount: Integer; 478begin 479 ItemCount := Windows.SendMessage(List, LB_GETCOUNT, 0, 0); 480 for Index := 0 to ItemCount-1 do 481 DeleteItemRecord(List, Index); 482end; 483 484class procedure TWinCECheckListBoxStrings.DeleteItemRecord(const List: HWND;const Index: integer); 485var 486 ItemRecord: PWinCECheckListBoxItemRecord; 487begin 488 ItemRecord := PWinCECheckListBoxItemRecord(Windows.SendMessage(List, LB_GETITEMDATA, Index, 0)); 489 if Assigned(ItemRecord) 490 then Dispose(ItemRecord); 491end; 492 493{$IFDEF H_PLUS} 494 {$UNDEF H_PLUS} 495{$ELSE} 496 {$H-} 497{$ENDIF} 498 499 500 501 502