SkinBoxCtrls.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:383k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. begin
  2.   Result := GetSelText = Text;
  3. end;
  4. var
  5.   Item: TMenuItem;
  6. begin
  7.   if FSysPopupMenu <> nil then FSysPopupMenu.Free;
  8.   FSysPopupMenu := TspSkinPopupMenu.Create(Self);
  9.   FSysPopupMenu.ComponentForm := TForm(GetParentForm(Self));
  10.   Item := TMenuItem.Create(FSysPopupMenu);
  11.   with Item do
  12.   begin
  13.     Caption := SP_Edit_Undo;
  14.     OnClick := DoUndo;
  15.     Enabled := Self.CanUndo;
  16.   end;
  17.   FSysPopupMenu.Items.Add(Item);
  18.   Item := TMenuItem.Create(FSysPopupMenu);
  19.   Item.Caption := '-';
  20.   FSysPopupMenu.Items.Add(Item);
  21.   Item := TMenuItem.Create(FSysPopupMenu);
  22.   with Item do
  23.   begin
  24.     Caption := SP_Edit_Cut;
  25.     Enabled := IsSelected and not Self.ReadOnly;
  26.     OnClick := DoCut;
  27.   end;
  28.   FSysPopupMenu.Items.Add(Item);
  29.   Item := TMenuItem.Create(FSysPopupMenu);
  30.   with Item do
  31.   begin
  32.     Caption := SP_Edit_Copy;
  33.     Enabled := IsSelected;
  34.     OnClick := DoCopy;
  35.   end;
  36.   FSysPopupMenu.Items.Add(Item);
  37.   Item := TMenuItem.Create(FSysPopupMenu);
  38.   with Item do
  39.   begin
  40.     Caption := SP_Edit_Paste;
  41.     Enabled := (ClipBoard.AsText <> '') and not ReadOnly;
  42.     OnClick := DoPaste;
  43.   end;
  44.   FSysPopupMenu.Items.Add(Item);
  45.   Item := TMenuItem.Create(FSysPopupMenu);
  46.   with Item do
  47.   begin
  48.     Caption := SP_Edit_Delete;
  49.     Enabled := IsSelected and not Self.ReadOnly;
  50.     OnClick := DoDelete;
  51.   end;
  52.   FSysPopupMenu.Items.Add(Item);
  53.   Item := TMenuItem.Create(FSysPopupMenu);
  54.   Item.Caption := '-';
  55.   FSysPopupMenu.Items.Add(Item);
  56.   Item := TMenuItem.Create(FSysPopupMenu);
  57.   with Item do
  58.   begin
  59.     Caption := SP_Edit_SelectAll;
  60.     Enabled := not IsFullSelected;
  61.     OnClick := DoSelectAll;
  62.   end;
  63.   FSysPopupMenu.Items.Add(Item);
  64. end;
  65. procedure TspSkinMemo.SetDefaultFont;
  66. begin
  67.   FDefaultFont.Assign(Value);
  68.   if FIndex = -1 then Font.Assign(Value);
  69. end;
  70. procedure TspSkinMemo.CMEnabledChanged;
  71. begin
  72.   inherited;
  73.   UpDateScrollRange;
  74.   if Enabled
  75.   then
  76.     begin
  77.       if FIndex = -1
  78.       then Font.Color := FDefaultFont.Color
  79.       else Font.Color := FontColor;
  80.     end
  81.   else
  82.     begin
  83.       if FIndex = -1
  84.       then Font.Color := clGrayText
  85.       else Font.Color := clGrayText;
  86.     end;
  87. end;
  88. procedure TspSkinMemo.OnDefaultFontChange(Sender: TObject);
  89. begin
  90.   if FIndex = -1 then Font.Assign(FDefaultFont);
  91. end;
  92. procedure TspSkinMemo.SetBitMapBG;
  93. begin
  94.   FBitMapBG := Value;
  95.   ReCreateWnd;
  96. end;
  97. procedure TspSkinMemo.WMSize;
  98. begin
  99.   inherited;
  100.   UpDateScrollRange;
  101.   if not FBitMapBG
  102.   then
  103.     SendMessage(Handle, WM_NCPAINT, 0, 0);
  104. end;
  105. procedure TspSkinMemo.Invalidate;
  106. begin
  107.   if FBitMapBG 
  108.   then
  109.     begin
  110.       if Parent = nil then Exit;
  111.       RedrawWindow(Handle, nil, 0, RDW_FRAME + RDW_INVALIDATE);
  112.     end
  113.   else
  114.     begin
  115.       inherited;
  116.     end;
  117. end;
  118. procedure TspSkinMemo.Change;
  119. begin
  120.   inherited;
  121.   UpDateScrollRange;
  122. end;
  123. procedure TspSkinMemo.WMVSCROLL;
  124. begin
  125.   inherited;
  126.   UpDateScrollRange;
  127. end;
  128. procedure TspSkinMemo.WMHSCROLL;
  129. begin
  130.   inherited;
  131.   UpDateScrollRange;
  132. end;
  133. procedure TspSkinMemo.WMLBUTTONDOWN;
  134. begin
  135.   inherited;
  136.   FDown := True;
  137. end;
  138. procedure TspSkinMemo.WMLBUTTONUP;
  139. begin
  140.   inherited;
  141.   if FDown
  142.   then
  143.     begin
  144.       UpDateScrollRange;
  145.       FDown := False;
  146.     end;  
  147. end;
  148. procedure TspSkinMemo.WMMOUSEMOVE;
  149. begin
  150.   inherited;
  151.   if FDown then UpDateScrollRange;
  152. end;
  153. procedure TspSkinMemo.SetVScrollBar;
  154. begin
  155.   FVScrollBar := Value;
  156.   FVScrollBar.Min := 0;
  157.   FVScrollBar.Max := 0;
  158.   FVScrollBar.Position := 0;
  159.   if FVScrollBar <> nil then FVScrollBar.OnChange := OnVScrollBarChange;
  160. end;
  161. procedure TspSkinMemo.OnVScrollBarChange(Sender: TObject);
  162. begin
  163.   SendMessage(Handle, WM_VSCROLL,
  164.     MakeWParam(SB_THUMBPOSITION, FVScrollBar.Position), 0);
  165.   Invalidate;
  166. end;
  167. procedure TspSkinMemo.UpDateScrollRange;
  168. function GetVisibleLines: Integer;
  169. var
  170.   R: TRect;
  171.   C: TCanvas;
  172.   DC: HDC;
  173.   LineHeight: Integer;
  174. begin
  175.   C := TCanvas.Create;
  176.   C.Font.Assign(Font);
  177.   DC := GetDC(0);
  178.   C.Handle := DC;
  179.   R := GetClientRect;
  180.   LineHeight := C.TextHeight('Wq');
  181.   if LineHeight <> 0
  182.   then
  183.     Result := RectHeight(R) div LineHeight
  184.   else
  185.     Result := 1;
  186.   ReleaseDC(0, DC);
  187.   C.Free;
  188. end;
  189. var
  190.   LinesCount: Integer;
  191.   VisibleLines: Integer;
  192.   Pos: Integer;
  193.   P: PPoint;
  194.   X: Integer;
  195. begin
  196.   if FVScrollBar <> nil
  197.   then
  198.   with FVScrollBar do
  199.   begin
  200.     VisibleLines := GetVisibleLines;
  201.     LinesCount := SendMessage(Self.Handle, EM_GETLINECOUNT, 0, 0);
  202.     Pos := SendMessage(Self.Handle, EM_GETFIRSTVISIBLELINE, 0, 0);
  203.     if LinesCount > VisibleLines
  204.     then
  205.       begin
  206.         SetRange(0, LinesCount, Pos, VisibleLines + 1);
  207.         if not Enabled then Enabled := True;
  208.       end
  209.     else
  210.       begin
  211.         SetRange(0, 0, 0, 0);
  212.         if Enabled then Enabled := False;
  213.       end;
  214.   end;
  215. end;
  216. procedure TspSkinMEmo.WMMove;
  217. begin
  218.   inherited;
  219.   if FAlphaBlend and (FIndex <> -1) then Invalidate;
  220. end;
  221. procedure TspSkinMemo.WMCut(var Message: TMessage);
  222. begin
  223.   if FReadOnly then Exit;
  224.   inherited;
  225.   if FBitMapBG then Invalidate;
  226.   UpDateScrollRange;
  227. end;
  228. procedure TspSkinMemo.WMPaste(var Message: TMessage);
  229. begin
  230.   if FReadOnly then Exit;
  231.   inherited;
  232.   if FBitMapBG then Invalidate;
  233.   UpDateScrollRange;
  234. end;
  235. procedure TspSkinMemo.WMClear(var Message: TMessage);
  236. begin
  237.   if FReadOnly then Exit;
  238.   inherited;
  239.   if FBitMapBG then Invalidate;
  240.   UpDateScrollRange;
  241. end;
  242. procedure TspSkinMemo.WMUndo(var Message: TMessage);
  243. begin
  244.   if FReadOnly then Exit;
  245.   inherited;
  246.   if FBitMapBG then Invalidate;
  247.   UpDateScrollRange;
  248. end;
  249. procedure TspSkinMemo.WMSetText(var Message:TWMSetText);
  250. begin
  251.   inherited;
  252.   if FBitMapBG then Invalidate;
  253.   UpDateScrollRange;
  254. end;
  255. procedure TspSkinMemo.WMMOUSEWHEEL;
  256. var
  257.   LParam, WParam: Integer;
  258. begin
  259.   LParam := 0;
  260.   if Message.WParam > 0
  261.   then
  262.     WParam := MakeWParam(SB_LINEUP, 0)
  263.   else
  264.     WParam := MakeWParam(SB_LINEDOWN, 0);
  265.   SendMessage(Handle, WM_VSCROLL, WParam, LParam);
  266.   if FBitMapBG then Invalidate;
  267. end;
  268. procedure TspSkinMemo.WMCHAR(var Message:TMessage);
  269. begin
  270.   if not FReadOnly then inherited;
  271.   UpDateScrollRange;
  272. end;
  273. procedure TspSkinMemo.WMKeyDown(var Message: TWMKeyDown);
  274. begin
  275.   if FReadOnly and (Message.CharCode = VK_DELETE) then Exit;
  276.   inherited;
  277.   if FBitMapBG then Invalidate;
  278.   UpDateScrollRange;
  279. end;
  280. procedure TspSkinMemo.WMEraseBkgnd(var Message: TWMEraseBkgnd);
  281. begin
  282.   if FBitMapBG then Invalidate else inherited;
  283. end;
  284. procedure TspSkinMemo.CNCtlColorStatic;
  285. begin
  286.  if FBitMapBG
  287.  then
  288.     with Message do
  289.     begin
  290.       SetBkMode(ChildDC, Windows.Transparent);
  291.       SetTextColor(ChildDC, Font.Color);
  292.       Result := GetStockObject(NULL_BRUSH);
  293.     end
  294.   else
  295.     inherited;
  296. end;
  297. procedure TspSkinMemo.CNCTLCOLOREDIT(var Message:TWMCTLCOLOREDIT);
  298. begin
  299.   if FBitMapBG
  300.   then
  301.     with Message do
  302.     begin
  303.       SetBkMode(ChildDC, Windows.Transparent);
  304.       SetTextColor(ChildDC, Font.Color);
  305.       Result := GetStockObject(NULL_BRUSH);
  306.     end
  307.   else
  308.     inherited;
  309. end;
  310. procedure TspSkinMemo.SetParentImage;
  311. begin
  312.   if ParentImage <> nil
  313.   then
  314.     begin
  315.       ParentImage.Width := Width;
  316.       ParentImage.Height := Height;
  317.       GetParentImage(Self, ParentImage.Canvas);
  318.     end;
  319. end;
  320. procedure TspSkinMemo.WMNCCALCSIZE;
  321. begin
  322.   GetSkinData;
  323.   if FIndex = -1
  324.   then
  325.     with Message.CalcSize_Params^.rgrc[0] do
  326.     begin
  327.       Inc(Left, 2);
  328.       Inc(Top, 2);
  329.       Dec(Right, 2);
  330.       Dec(Bottom, 2);
  331.     end
  332.   else
  333.     with Message.CalcSize_Params^.rgrc[0] do
  334.     begin
  335.       Inc(Left, ClRect.Left);
  336.       Inc(Top, ClRect.Top);
  337.       Dec(Right, RectWidth(SkinRect) - ClRect.Right);
  338.       Dec(Bottom, RectHeight(SkinRect) - ClRect.Bottom);
  339.     end;
  340. end;
  341. procedure TspSkinMemo.CreateParams(var Params: TCreateParams);
  342. begin
  343.   inherited CreateParams(Params);
  344.   with Params do
  345.   begin
  346.     ExStyle := ExStyle and not WS_EX_CLIENTEDGE;
  347.     ExStyle := Exstyle and not WS_EX_Transparent;
  348.     Style := Style and not WS_BORDER or ES_MULTILINE;
  349.     WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
  350.   end;
  351. end;
  352. procedure TspSkinMemo.SkinNCPaint(C: TCanvas);
  353. var
  354.   B: TBitMap;
  355.   R: TRect;
  356.   EB1, EB2: TspEffectBMP;
  357.   kf: Double;
  358.   NewLTPoint, NewRTPoint, NewLBPoint, NewRBPoint: TPoint;
  359.   NewClRect: TRect;
  360.   OffX, OffY: Integer;
  361. begin
  362.   GetSkinData;
  363.   B := TBitMap.Create;
  364.   B.Width := Width;
  365.   B.Height := Height;
  366.   //
  367.   if FIndex = -1
  368.   then
  369.     with B.Canvas do
  370.     begin
  371.       Brush.Color := clWindow;
  372.       R := Rect(0, 0, Width, Height);
  373.       Frame3D(B.Canvas, R, clBtnShadow, clBtnShadow, 1);
  374.       Frame3D(B.Canvas, R, clBtnFace, clBtnFace, 1);
  375.     end
  376.     else
  377.       begin
  378.         OffX := Width - RectWidth(SkinRect);
  379.         OffY := Height - RectHeight(SkinRect);
  380.         NewLTPoint := LTPoint;
  381.         NewRTPoint := Point(RTPoint.X + OffX, RTPoint.Y);
  382.         NewLBPoint := Point(LBPoint.X, LBPoint.Y + OffY);
  383.         NewRBPoint := Point(RBPoint.X + OffX, RBPoint.Y + OffY);
  384.         NewClRect := Rect(ClRect.Left, ClRect.Top,
  385.                           ClRect.Right + OffX, ClRect.Bottom + OffY);
  386.         if FMouseIn or Focused
  387.         then
  388.           CreateSkinImage(LTPoint, RTPoint, LBPoint, RBPoint, CLRect,
  389.             NewLtPoint, NewRTPoint, NewLBPoint, NewRBPoint, NewCLRect,
  390.             B, Picture, ActiveSkinRect, Width, Height, True)
  391.         else
  392.           CreateSkinImage(LTPoint, RTPoint, LBPoint, RBPoint, CLRect,
  393.             NewLtPoint, NewRTPoint, NewLBPoint, NewRBPoint, NewCLRect,
  394.             B, Picture, SkinRect, Width, Height, True);
  395.       end;
  396.   if FAlphaBlend
  397.   then
  398.     begin
  399.       ParentImage.Width := B.Width;
  400.       EB1 := TspEffectBmp.CreateFromhWnd(B.Handle);
  401.       EB2 := TspEffectBmp.CreateFromhWnd(ParentImage.Handle);
  402.       kf := 1 - FAlphaBlendValue / 255;
  403.       EB1.Morph(EB2, Kf);
  404.       EB1.Draw(C.Handle, 0, 0);
  405.       EB1.Free;
  406.       EB2.Free;
  407.     end
  408.   else
  409.    C.Draw(0, 0, B);
  410.   B.Free;
  411. end;
  412. procedure TspSkinMemo.SkinFramePaint(C: TCanvas);
  413. var
  414.   NewLTPoint, NewRTPoint, NewLBPoint, NewRBPoint: TPoint;
  415.   R, NewClRect: TRect;
  416.   LeftB, TopB, RightB, BottomB: TBitMap;
  417.   OffX, OffY: Integer;
  418. begin
  419.   GetSkinData;
  420.   if FIndex = -1
  421.   then
  422.     with C do
  423.     begin
  424.       Brush.Style := bsClear;
  425.       R := Rect(0, 0, Width, Height);
  426.       Frame3D(C, R, clBtnShadow, clBtnShadow, 1);
  427.       Frame3D(C, R, clBtnFace, clBtnFace, 1);
  428.       Exit;
  429.     end;
  430.   LeftB := TBitMap.Create;
  431.   TopB := TBitMap.Create;
  432.   RightB := TBitMap.Create;
  433.   BottomB := TBitMap.Create;
  434.   OffX := Width - RectWidth(SkinRect);
  435.   OffY := Height - RectHeight(SkinRect);
  436.   NewLTPoint := LTPoint;
  437.   NewRTPoint := Point(RTPoint.X + OffX, RTPoint.Y);
  438.   NewLBPoint := Point(LBPoint.X, LBPoint.Y + OffY);
  439.   NewRBPoint := Point(RBPoint.X + OffX, RBPoint.Y + OffY);
  440.   NewClRect := Rect(ClRect.Left, ClRect.Top,
  441.                     ClRect.Right + OffX, ClRect.Bottom + OffY);
  442.   if FMouseIn or Focused
  443.   then
  444.     CreateSkinBorderImages(LTPoint, RTPoint, LBPoint, RBPoint, CLRect,
  445.       NewLtPoint, NewRTPoint, NewLBPoint, NewRBPoint, NewCLRect,
  446.       LeftB, TopB, RightB, BottomB, Picture, ActiveSkinRect, Width, Height,
  447.       False, False, False, False)
  448.   else
  449.     CreateSkinBorderImages(LTPoint, RTPoint, LBPoint, RBPoint, CLRect,
  450.       NewLtPoint, NewRTPoint, NewLBPoint, NewRBPoint, NewCLRect,
  451.       LeftB, TopB, RightB, BottomB, Picture, SkinRect, Width, Height,
  452.       False, False, False, False);
  453.   C.Draw(0, 0, TopB);
  454.   C.Draw(0, TopB.Height, LeftB);
  455.   C.Draw(Width - RightB.Width, TopB.Height, RightB);
  456.   C.Draw(0, Height - BottomB.Height, BottomB);
  457.   TopB.Free;
  458.   LeftB.Free;
  459.   RightB.Free;
  460.   BottomB.Free;
  461. end;
  462. procedure TspSkinMemo.WMNCPAINT;
  463. var
  464.   DC: HDC;
  465.   C: TCanvas;
  466.   R: TRect;
  467.   EB1, EB2: TspEffectBMP;
  468.   kf: Double;
  469. begin
  470.   if FAlphaBlend and FBitMapBG
  471.   then
  472.     begin
  473.       ParentImage := TBitMap.Create;
  474.       SetParentImage;
  475.     end;
  476.   DC := GetWindowDC(Handle);
  477.   C := TControlCanvas.Create;
  478.   C.Handle := DC;
  479.   try
  480.     if FBitMapBG
  481.     then
  482.       SkinNCPaint(C)
  483.     else
  484.       SkinFramePaint(C);
  485.   finally
  486.     C.Free;
  487.     ReleaseDC(Handle, DC);
  488.   end;
  489.   if FAlphaBlend and FBitMapBG
  490.   then
  491.     begin
  492.       ParentImage.Free;
  493.       ParentImage := nil;
  494.     end;
  495. end;
  496. destructor TspSkinMemo.Destroy;
  497. begin
  498.   FDefaultFont.Free;
  499.   if FSysPopupMenu <> nil then FSysPopupMenu.Free;
  500.   inherited;
  501. end;
  502. procedure TspSkinMemo.WMSETFOCUS;
  503. begin
  504.   inherited;
  505.   if not FMouseIn and (FIndex <> -1)
  506.   then
  507.     begin
  508.       Font.Color := ActiveFontColor;
  509.       if not FBitMapBG then Color := ActiveBGColor;
  510.     end;
  511.   if not FMouseIn then Invalidate;
  512.   if not FBitMapBG
  513.   then
  514.     SendMessage(Handle, WM_NCPAINT, 0, 0);
  515. end;
  516. procedure TspSkinMemo.WMKILLFOCUS;
  517. begin
  518.   inherited;
  519.   if not FMouseIn and (FIndex <> -1)
  520.   then
  521.     begin
  522.       Font.Color := FontColor;
  523.       if not FBitMapBG then Color := BGColor;
  524.     end;
  525.   if not FMouseIn then Invalidate;
  526.   if not FBitMapBG
  527.   then
  528.     SendMessage(Handle, WM_NCPAINT, 0, 0);
  529. end;
  530. procedure TspSkinMemo.CMMouseEnter;
  531. begin
  532.   inherited;
  533.   FMouseIn := True;
  534.   if not Focused and (FIndex <> -1)
  535.   then
  536.     begin
  537.       Font.Color := ActiveFontColor;
  538.       if not FBitMapBG then Color := ActiveBGColor;
  539.     end;  
  540.   if not Focused then Invalidate;
  541.   if not FBitMapBG
  542.   then
  543.     SendMessage(Handle, WM_NCPAINT, 0, 0);
  544. end;
  545. procedure TspSkinMemo.CMMouseLeave;
  546. begin
  547.   inherited;
  548.   FMouseIn := False;
  549.   if not Focused and (FIndex <> -1)
  550.   then
  551.     begin
  552.       Font.Color := FontColor;
  553.       if not FBitMapBG then Color := BGColor;
  554.     end;
  555.   if not Focused then Invalidate;
  556.   if not FBitMapBG
  557.   then
  558.     SendMessage(Handle, WM_NCPAINT, 0, 0);
  559. end;
  560. procedure TspSkinMemo.SetAlphaBlend;
  561. begin
  562.   if FAlphaBlend <> AValue
  563.   then
  564.     begin
  565.       FAlphaBlend := AValue;
  566.       Invalidate;
  567.     end;
  568. end;
  569. procedure TspSkinMemo.SetAlphaBlendValue;
  570. begin
  571.   if FAlphaBlendValue <> AValue
  572.   then
  573.     begin
  574.       FAlphaBlendValue := AValue;
  575.       if FAlphaBlend then Invalidate;
  576.     end;
  577. end;
  578. procedure TspSkinMemo.GetSkinData;
  579. begin
  580.   if FSD = nil
  581.   then
  582.     begin
  583.       FIndex := -1;
  584.       Exit;
  585.     end;
  586.   if FSD.Empty
  587.   then
  588.     FIndex := -1
  589.   else
  590.     FIndex := FSD.GetControlIndex(FSkinDataName);
  591.   if FIndex <> -1
  592.   then
  593.     if TspDataSkinControl(FSD.CtrlList.Items[FIndex]) is TspDataSkinMemoControl
  594.     then
  595.       with TspDataSkinMemoControl(FSD.CtrlList.Items[FIndex]) do
  596.       begin
  597.         if (PictureIndex <> -1) and (PictureIndex < FSD.FActivePictures.Count)
  598.         then
  599.           Picture := TBitMap(FSD.FActivePictures.Items[PictureIndex])
  600.         else
  601.           Picture := nil;
  602.         Self.SkinRect := SkinRect;
  603.         Self.ActiveSkinRect := ActiveSkinRect;
  604.         if isNullRect(ActiveSkinRect)
  605.         then
  606.           Self.ActiveSkinRect := SkinRect;
  607.         Self.LTPoint := LTPoint;
  608.         Self.RTPoint := RTPoint;
  609.         Self.LBPoint := LBPoint;
  610.         Self.RBPoint := RBPoint;
  611.         Self.ClRect := ClRect;
  612.         Self.FontName := FontName;
  613.         Self.FontStyle := FontStyle;
  614.         Self.FontHeight := FontHeight;
  615.         Self.FontColor := FontColor;
  616.         Self.ActiveFontColor := ActiveFontColor;
  617.         Self.BGColor := BGColor;
  618.         Self.ActiveBGColor := ActiveBGColor;
  619.       end;
  620. end;
  621. procedure TspSkinMemo.SetSkinData;
  622. begin
  623.   FSD := Value;
  624.   if (FSD <> nil) then
  625.   if not FSD.Empty and not (csDesigning in ComponentState)
  626.   then
  627.     ChangeSkinData;
  628. end;
  629. procedure TspSkinMemo.Notification;
  630. begin
  631.   inherited Notification(AComponent, Operation);
  632.   if (Operation = opRemove) and (AComponent = FSD) then FSD := nil;
  633.   if (Operation = opRemove) and (AComponent = FVScrollBar)
  634.   then FVScrollBar := nil;
  635. end;
  636. procedure TspSkinMemo.ChangeSkinData;
  637. begin
  638.   GetSkinData;
  639.   //
  640.   if FIndex <> -1
  641.   then
  642.     begin
  643.       if FUseSkinFont
  644.       then
  645.         begin
  646.           Font.Name := FontName;
  647.           Font.Style := FontStyle;
  648.           Font.Height := FontHeight;
  649.           if Focused
  650.           then
  651.             Font.Color := ActiveFontColor
  652.           else
  653.             Font.Color := FontColor;
  654.           Font.CharSet := FDefaultFont.CharSet;    
  655.         end
  656.       else
  657.         begin
  658.           Font.Assign(FDefaultFont);
  659.           if Focused
  660.           then
  661.             Font.Color := ActiveFontColor
  662.           else
  663.             Font.Color := FontColor;
  664.         end;
  665.       Color := BGColor;
  666.     end
  667.   else
  668.     Font.Assign(FDefaultFont);
  669.   //
  670.   UpDateScrollRange;
  671.   ReCreateWnd;
  672.   if FVScrollBar <> nil then FVScrollBar.Align := FVScrollBar.Align;
  673.   if Enabled
  674.   then
  675.     begin
  676.       if FIndex = -1
  677.       then Font.Color := FDefaultFont.Color
  678.       else Font.Color := FontColor;
  679.     end
  680.   else
  681.     begin
  682.       if FIndex = -1
  683.       then Font.Color := clGrayText
  684.       else Font.Color := clGrayText;
  685.     end;
  686. end;
  687. constructor TspListBox.Create;
  688. begin
  689.   inherited;
  690.   SkinListBox := nil;
  691.   Ctl3D := False;
  692.   BorderStyle := bsNone;
  693.   ControlStyle := [csCaptureMouse, csOpaque, csDoubleClicks];
  694.   FHorizontalExtentValue := 0;
  695.   {$IFDEF VER130}
  696.   FAutoComplete := False;
  697.   {$ENDIF}
  698. end;
  699. destructor TspListBox.Destroy;
  700. begin
  701.   inherited;
  702. end;
  703. procedure TspListBox.SetBounds;
  704. var
  705.   OldWidth: Integer;
  706. begin
  707.   OldWidth := Width;
  708.   inherited;
  709.   if (OldWidth <> Width) and (FHorizontalExtentValue > 0)
  710.   then
  711.     begin
  712.       FHorizontalExtentValue := FHorizontalExtentValue + (OldWidth - Width);
  713.       if FHorizontalExtentValue < 0 then FHorizontalExtentValue := 0;
  714.       RePaint;
  715.     end;
  716. end;
  717. procedure TspListBox.CreateWnd;
  718. begin
  719.   inherited;
  720.   if SkinListBox <> nil then SkinListBox.ListBoxCreateWnd;
  721. end;
  722. procedure TspListBox.WMNCCALCSIZE;
  723. begin
  724. end;
  725. procedure TspListBox.CMEnter;
  726. begin
  727.   if SkinListBox <> nil then SkinListBox.ListBoxEnter;
  728.   inherited;
  729. end;
  730. procedure TspListBox.CMExit;
  731. begin
  732.   if SkinListBox <> nil then SkinListBox.ListBoxExit;
  733.   inherited;
  734. end;
  735. procedure TspListBox.MouseDown(Button: TMouseButton; Shift: TShiftState;
  736.       X, Y: Integer);
  737. begin
  738.   if SkinListBox <> nil then SkinListBox.ListBoxMouseDown(Button, Shift, X, Y);
  739.   inherited;
  740. end;
  741. procedure TspListBox.MouseUp(Button: TMouseButton; Shift: TShiftState;
  742.       X, Y: Integer);
  743. begin
  744.   if SkinListBox <> nil then SkinListBox.ListBoxMouseUp(Button, Shift, X, Y);
  745.   inherited;
  746. end;
  747. procedure TspListBox.MouseMove(Shift: TShiftState; X, Y: Integer);
  748. begin
  749.   if SkinListBox <> nil then SkinListBox.ListBoxMouseMove(Shift, X, Y);
  750.   inherited;
  751. end;
  752. procedure TspListBox.KeyDown(var Key: Word; Shift: TShiftState);
  753. begin
  754.   if SkinListBox <> nil then SkinListBox.ListBoxKeyDown(Key, Shift);
  755.   if (Key = VK_LEFT) and (SkinListBox.HScrollBar <> nil)
  756.   then
  757.     with SkinListBox.HScrollBar do
  758.     begin
  759.       Position := Position - SmallChange;
  760.       Key := 0;
  761.     end
  762.   else
  763.   if (Key = VK_RIGHT) and (SkinListBox.HScrollBar <> nil)
  764.   then
  765.     with SkinListBox.HScrollBar do
  766.     begin
  767.       Position := Position + SmallChange;
  768.       Key := 0;
  769.     end;
  770.   inherited;
  771. end;
  772. procedure TspListBox.KeyPress(var Key: Char);
  773.  {$IFDEF VER130}
  774.   procedure FindString;
  775.   var
  776.     Idx: Integer;
  777.   begin
  778.     Idx := SendMessage(Handle, LB_FINDSTRING, -1, LongInt(PChar(FFilter)));
  779.     if Idx <> LB_ERR then
  780.     begin
  781.       if MultiSelect then
  782.       begin
  783. //      ClearSelection;
  784.         SendMessage(Handle, LB_SELITEMRANGE, 1, MakeLParam(Idx, Idx))
  785.       end;
  786.       ItemIndex := Idx;
  787.       Click;
  788.     end;
  789.     if not Ord(Key) in [VK_RETURN, VK_BACK, VK_ESCAPE] then
  790.       Key := #0;  
  791.   end;
  792.   {$ENDIF}
  793. begin
  794.   if SkinListBox <> nil then SkinListBox.ListBoxKeyPress(Key);
  795.   inherited;
  796.   {$IFDEF VER130}
  797.   if not FAutoComplete then Exit;
  798.   if GetTickCount - FLastTime >= 500 then
  799.     FFilter := '';
  800.   FLastTime := GetTickCount;
  801.   if Ord(Key) <> VK_BACK then
  802.     FFilter := FFilter + Key
  803.   else
  804.     Delete(FFilter, Length(FFilter), 1);
  805.   if Length(FFilter) > 0 then
  806.     FindString
  807.   else
  808.   begin
  809.     ItemIndex := 0;
  810.     Click;
  811.   end;
  812.   {$ENDIF}
  813. end;
  814. procedure TspListBox.Click;
  815. begin
  816.   if SkinListBox <> nil then SkinListBox.ListBoxClick;
  817.   inherited;
  818. end;
  819. procedure TspListBox.PaintBGWH;
  820. var
  821.   X, Y, XCnt, YCnt, XO, YO, w, h, w1, h1: Integer;
  822.   Buffer: TBitMap;
  823. begin
  824.   w1 := AW;
  825.   h1 := AH;
  826.   Buffer := TBitMap.Create;
  827.   Buffer.Width := w1;
  828.   Buffer.Height := h1;
  829.   with Buffer.Canvas, SkinListBox do
  830.   begin
  831.     w := RectWidth(ClRect);
  832.     h := RectHeight(ClRect);
  833.     XCnt := w1 div w;
  834.     YCnt := h1 div h;
  835.     for X := 0 to XCnt do
  836.     for Y := 0 to YCnt do
  837.     begin
  838.       if X * w + w > w1 then XO := X * w + w - w1 else XO := 0;
  839.       if Y * h + h > h1 then YO := Y * h + h - h1 else YO := 0;
  840.        CopyRect(Rect(X * w, Y * h, X * w + w - XO, Y * h + h - YO),
  841.                 Picture.Canvas,
  842.                 Rect(SkinRect.Left + ClRect.Left, SkinRect.Top + ClRect.Top,
  843.                 SkinRect.Left + ClRect.Right - XO,
  844.                 SkinRect.Top + ClRect.Bottom - YO));
  845.     end;
  846.   end;
  847.   Cnvs.Draw(AX, AY, Buffer);
  848.   Buffer.Free;
  849. end;
  850. function TspListBox.GetState;
  851. begin
  852.   Result := [];
  853.   if AItemID = ItemIndex
  854.   then
  855.     begin
  856.       Result := Result + [odSelected];
  857.       if Focused then Result := Result + [odFocused];
  858.     end
  859.   else
  860.     if SelCount > 0
  861.     then
  862.       if Selected[AItemID] then Result := Result + [odSelected];
  863. end;
  864. procedure TspListBox.PaintBG(DC: HDC);
  865. var
  866.   C: TControlCanvas;
  867. begin
  868.   C := TControlCanvas.Create;
  869.   C.Handle := DC;
  870.   SkinListBox.GetSkinData;
  871.   if SkinListBox.FIndex <> -1
  872.   then
  873.     PaintBGWH(C, Width, Height, 0, 0)
  874.   else
  875.     with C do
  876.     begin
  877.       Brush.Color := clWindow;
  878.       FillRect(Rect(0, 0, Width, Height));
  879.     end;
  880.   C.Handle := 0;
  881.   C.Free;
  882. end;
  883. procedure TspListBox.PaintColumnsList(DC: HDC);
  884. var
  885.   C: TCanvas;
  886.   i, j, DrawCount: Integer;
  887.   IR: TRect;
  888. begin
  889.   C := TCanvas.Create;
  890.   C.Handle := DC;
  891.   DrawCount := (Height div ItemHeight) * Columns;
  892.   i := TopIndex;
  893.   j := i + DrawCount;
  894.   if j > Items.Count - 1 then j := Items.Count - 1;
  895.   if Items.Count > 0
  896.   then
  897.     for i := TopIndex to j do
  898.     begin
  899.       IR := ItemRect(i);
  900.       if SkinListBox.FIndex <> -1
  901.       then
  902.         begin
  903.           if SkinListBox.UseSkinItemHeight
  904.           then
  905.             DrawSkinItem(C, i, IR, GetState(i))
  906.           else
  907.             DrawStretchSkinItem(C, i, IR, GetState(i));
  908.          end
  909.       else
  910.         DrawDefaultItem(C, i, IR, GetState(i));
  911.     end;
  912.   C.Free;
  913. end;
  914. procedure TspListBox.PaintList(DC: HDC);
  915. var
  916.   C: TCanvas;
  917.   i, j, k, DrawCount: Integer;
  918.   IR: TRect;
  919. begin
  920.   C := TCanvas.Create;
  921.   C.Handle := DC;
  922.   DrawCount := Height div ItemHeight;
  923.   i := TopIndex;
  924.   j := i + DrawCount;
  925.   if j > Items.Count - 1 then j := Items.Count - 1;
  926.   k := 0;
  927.   if Items.Count > 0
  928.   then
  929.     for i := TopIndex to j do
  930.     begin
  931.       IR := ItemRect(i);
  932.       if SkinListBox.FIndex <> -1
  933.       then
  934.         begin
  935.           if SkinListBox.UseSkinItemHeight
  936.           then
  937.             DrawSkinItem(C, i, IR, GetState(i))
  938.           else
  939.             DrawStretchSkinItem(C, i, IR, GetState(i));
  940.         end
  941.       else
  942.         DrawDefaultItem(C, i, IR, GetState(i));
  943.       k := IR.Bottom;
  944.     end;
  945.   if k < Height
  946.   then
  947.     begin
  948.       SkinListBox.GetSkinData;
  949.       if SkinListBox.FIndex <> -1
  950.       then
  951.         PaintBGWH(C, Width, Height - k, 0, k)
  952.       else
  953.         with C do
  954.         begin
  955.           C.Brush.Color := clWindow;
  956.           FillRect(Rect(0, k, Width, Height));
  957.         end;
  958.     end;  
  959.   C.Free;
  960. end;
  961. procedure TspListBox.PaintWindow;
  962. var
  963.   SaveIndex: Integer;
  964. begin
  965.   if (Width <= 0) or (Height <=0) then Exit;
  966.   SaveIndex := SaveDC(DC);
  967.   try
  968.     if Columns > 0
  969.     then
  970.       PaintColumnsList(DC)
  971.     else
  972.       PaintList(DC);
  973.   finally
  974.     RestoreDC(DC, SaveIndex);
  975.   end;
  976. end;
  977. procedure TspListBox.WMPaint;
  978. begin
  979.   PaintHandler(Msg);
  980. end;
  981. procedure TspListBox.WMEraseBkgnd;
  982. begin
  983.   if (Width > 0) and (Height > 0) then PaintBG(Message.DC);
  984.   Message.Result := 1;
  985. end;
  986. procedure TspListBox.DrawDefaultItem(Cnvs: TCanvas; itemID: Integer; rcItem: TRect;
  987.                                      State: TOwnerDrawState);
  988. var
  989.   Buffer: TBitMap;
  990.   R, R1: TRect;
  991.   IIndex, IX, IY, Off: Integer;
  992. begin
  993.   if (ItemID < 0) or (ItemID > Items.Count - 1) then Exit;
  994.   Buffer := TBitMap.Create;
  995.   Buffer.Width := RectWidth(rcItem);
  996.   Buffer.Height := RectHeight(rcItem);
  997.   R := Rect(0, 0, Buffer.Width, Buffer.Height);
  998.   with Buffer.Canvas do
  999.   begin
  1000.     Font.Name := SkinListBox.Font.Name;
  1001.     Font.Style := SkinListBox.Font.Style;
  1002.     Font.Height := SkinListBox.Font.Height;
  1003.     if odSelected in State
  1004.     then
  1005.       begin
  1006.         Brush.Color := clHighLight;
  1007.         Font.Color := clHighLightText;
  1008.       end
  1009.     else
  1010.       begin
  1011.         Brush.Color := clWindow;
  1012.         Font.Color := SkinListBox.Font.Color;
  1013.       end;
  1014.     FillRect(R);
  1015.   end;
  1016.   R1 := Rect(R.Left + 2, R.Top, R.Right - 2, R.Bottom);
  1017.   if Assigned(SkinListBox.FOnDrawItem)
  1018.   then
  1019.     SkinListBox.FOnDrawItem(Buffer.Canvas, ItemID, Buffer.Width, Buffer.Height,
  1020.     R1, State)
  1021.   else
  1022.     begin
  1023.       if (SkinListBox.Images <> nil)
  1024.       then
  1025.         begin
  1026.           if SkinListBox.ImageIndex > -1
  1027.           then IIndex := SkinListBox.FImageIndex
  1028.           else IIndex := itemID;
  1029.           if IIndex < SkinListBox.Images.Count
  1030.           then
  1031.             begin
  1032.               IX := R1.Left;
  1033.               IY := R1.Top + RectHeight(R1) div 2 - SkinListBox.Images.Height div 2;
  1034.               SkinListBox.Images.Draw(Buffer.Canvas, IX - FHorizontalExtentValue, IY, IIndex);
  1035.             end;
  1036.           Off := SkinListBox.Images.Width + 2
  1037.         end
  1038.       else
  1039.         Off := 0;
  1040.       Buffer.Canvas.Brush.Style := bsClear;
  1041.       SPDrawText3(Buffer.Canvas, Items[ItemID], R1, - FHorizontalExtentValue + Off);
  1042.     end;
  1043.   if odFocused in State then DrawFocusRect(Buffer.Canvas.Handle, R);
  1044.   Cnvs.Draw(rcItem.Left, rcItem.Top, Buffer);
  1045.   Buffer.Free;
  1046. end;
  1047. procedure TspListBox.DrawStretchSkinItem(Cnvs: TCanvas; itemID: Integer; rcItem: TRect;
  1048.                                   State: TOwnerDrawState);
  1049. var
  1050.   Buffer, Buffer2: TBitMap;
  1051.   R: TRect;
  1052.   W, H: Integer;
  1053.   IX, IY, IIndex, Off: Integer;
  1054. begin
  1055.   if (SkinListBox.Picture = nil) or (ItemID < 0) or (ItemID > Items.Count - 1) then Exit;
  1056.   Buffer := TBitMap.Create;
  1057.   with SkinListBox do
  1058.   begin
  1059.     W := RectWidth(rcItem);
  1060.     H := RectHeight(SItemRect);
  1061.     Buffer.Width := W;
  1062.     if UseSkinItemHeight
  1063.     then
  1064.       Buffer.Height := H
  1065.     else
  1066.       Buffer.Height := RectHeight(SItemRect);  
  1067.     if odFocused in State
  1068.     then
  1069.       CreateHSkinImage(ItemLeftOffset, ItemRightOffset, Buffer, Picture,
  1070.       FocusItemRect, W, H)
  1071.     else
  1072.     if odSelected in State
  1073.     then
  1074.       CreateHSkinImage(ItemLeftOffset, ItemRightOffset, Buffer, Picture,
  1075.       ActiveItemRect, W, H)
  1076.     else
  1077.       CreateHSkinImage(ItemLeftOffset, ItemRightOffset, Buffer, Picture,
  1078.       SItemRect, W, H);
  1079.     R := ItemTextRect;
  1080.     Inc(R.Right, W - RectWidth(SItemRect));
  1081.     Inc(R.Bottom, RectHeight(rcItem) - RectHeight(SItemRect));
  1082.   end;
  1083.   W := RectWidth(rcItem);
  1084.   H := RectHeight(rcItem);
  1085.   Buffer2 := TBitMap.Create;
  1086.   Buffer2.Width := W;
  1087.   Buffer2.Height := H;
  1088.   Buffer2.Canvas.StretchDraw(Rect(0, 0, Buffer2.Width, Buffer2.Height), Buffer);
  1089.   Buffer.Free;
  1090.   with Buffer2.Canvas do
  1091.   begin
  1092.     if SkinListBox.UseSkinFont
  1093.     then
  1094.       begin
  1095.         Font.Name := SkinListBox.FontName;
  1096.         Font.Style := SkinListBox.FontStyle;
  1097.         Font.Height := SkinListBox.FontHeight;
  1098.         Font.CharSet := SkinListBox.DefaultFont.CharSet;
  1099.       end
  1100.     else
  1101.       Font.Assign(SkinListBox.DefaultFont);
  1102.     if odFocused in State
  1103.     then
  1104.       Font.Color := SkinListBox.FocusFontColor
  1105.     else
  1106.     if odSelected in State
  1107.     then
  1108.       Font.Color := SkinListBox.ActiveFontColor
  1109.     else
  1110.       Font.Color := SkinListBox.FontColor;
  1111.     Brush.Style := bsClear;
  1112.   end;
  1113.   if Assigned(SkinListBox.FOnDrawItem)
  1114.   then
  1115.     SkinListBox.FOnDrawItem(Buffer2.Canvas, ItemID, W, H, R, State)
  1116.   else
  1117.     begin
  1118.       if (SkinListBox.Images <> nil)
  1119.       then
  1120.         begin
  1121.           if SkinListBox.ImageIndex > -1
  1122.           then IIndex := SkinListBox.FImageIndex
  1123.           else IIndex := itemID;
  1124.           if IIndex < SkinListBox.Images.Count
  1125.           then
  1126.             begin
  1127.               IX := R.Left;
  1128.               IY := R.Top + RectHeight(R) div 2 - SkinListBox.Images.Height div 2;
  1129.               SkinListBox.Images.Draw(Buffer2.Canvas,
  1130.                 IX - FHorizontalExtentValue, IY, IIndex);
  1131.             end;
  1132.           Off := SkinListBox.Images.Width + 2;
  1133.         end
  1134.       else
  1135.         Off := 0;  
  1136.       SPDrawText3(Buffer2.Canvas, Items[ItemID], R, -FHorizontalExtentValue + Off);
  1137.     end;
  1138.   Cnvs.Draw(rcItem.Left, rcItem.Top, Buffer2);
  1139.   Buffer2.Free;
  1140. end;
  1141. procedure TspListBox.DrawSkinItem(Cnvs: TCanvas; itemID: Integer; rcItem: TRect;
  1142.                                   State: TOwnerDrawState);
  1143. var
  1144.   Buffer: TBitMap;
  1145.   R: TRect;
  1146.   W, H: Integer;
  1147.   IX, IY, IIndex, Off: Integer;
  1148. begin
  1149.   if (SkinListBox.Picture = nil) or (ItemID < 0) or (ItemID > Items.Count - 1) then Exit;
  1150.   Buffer := TBitMap.Create;
  1151.   with SkinListBox do
  1152.   begin
  1153.     W := RectWidth(rcItem);
  1154.     H := RectHeight(SItemRect);
  1155.     Buffer.Width := W;
  1156.     Buffer.Height := H; 
  1157.     if odFocused in State
  1158.     then
  1159.       begin
  1160.         if not (odSelected in State)
  1161.         then
  1162.           begin
  1163.             CreateHSkinImage(ItemLeftOffset, ItemRightOffset, Buffer, Picture,
  1164.               SItemRect, W, H);
  1165.             R := Rect(0, 0, Buffer.Width, Buffer.Height);
  1166.             DrawFocusRect(Buffer.Canvas.Handle, R);
  1167.           end
  1168.         else
  1169.           CreateHSkinImage(ItemLeftOffset, ItemRightOffset, Buffer, Picture,
  1170.             FocusItemRect, W, H)
  1171.       end
  1172.     else
  1173.     if odSelected in State
  1174.     then
  1175.       CreateHSkinImage(ItemLeftOffset, ItemRightOffset, Buffer, Picture,
  1176.       ActiveItemRect, W, H)
  1177.     else
  1178.       CreateHSkinImage(ItemLeftOffset, ItemRightOffset, Buffer, Picture,
  1179.       SItemRect, W, H);
  1180.     R := ItemTextRect;
  1181.     Inc(R.Right, W - RectWidth(SItemRect));
  1182.   end;
  1183.   with Buffer.Canvas do
  1184.   begin
  1185.     if SkinListBox.UseSkinFont
  1186.     then
  1187.       begin
  1188.         Font.Name := SkinListBox.FontName;
  1189.         Font.Style := SkinListBox.FontStyle;
  1190.         Font.Height := SkinListBox.FontHeight;
  1191.         Font.CharSet := SkinListBox.DefaultFont.CharSet;
  1192.       end
  1193.     else
  1194.       Font.Assign(SkinListBox.DefaultFont);
  1195.     if odFocused in State
  1196.     then
  1197.       begin
  1198.         if not (odSelected in State)
  1199.         then
  1200.           Font.Color := SkinListBox.FontColor
  1201.         else
  1202.           Font.Color := SkinListBox.FocusFontColor;
  1203.       end
  1204.     else
  1205.     if odSelected in State
  1206.     then
  1207.       Font.Color := SkinListBox.ActiveFontColor
  1208.     else
  1209.       Font.Color := SkinListBox.FontColor;
  1210.     Brush.Style := bsClear;
  1211.   end;
  1212.   if Assigned(SkinListBox.FOnDrawItem)
  1213.   then
  1214.     SkinListBox.FOnDrawItem(Buffer.Canvas, ItemID, Buffer.Width, Buffer.Height,
  1215.     R, State)
  1216.   else
  1217.     begin
  1218.       if (SkinListBox.Images <> nil)
  1219.       then
  1220.         begin
  1221.           if SkinListBox.ImageIndex > -1
  1222.           then IIndex := SkinListBox.FImageIndex
  1223.           else IIndex := itemID;
  1224.           if IIndex < SkinListBox.Images.Count
  1225.           then
  1226.             begin
  1227.               IX := R.Left;
  1228.               IY := R.Top + RectHeight(R) div 2 - SkinListBox.Images.Height div 2;
  1229.               SkinListBox.Images.Draw(Buffer.Canvas,
  1230.                 IX - FHorizontalExtentValue, IY, IIndex);
  1231.             end;
  1232.           Off := SkinListBox.Images.Width + 2;
  1233.         end
  1234.       else
  1235.         Off := 0;  
  1236.       SPDrawText3(Buffer.Canvas, Items[ItemID], R, -FHorizontalExtentValue + Off);
  1237.     end;
  1238.   Cnvs.Draw(rcItem.Left, rcItem.Top, Buffer);
  1239.   Buffer.Free;
  1240. end;
  1241. procedure TspListBox.CreateParams;
  1242. begin
  1243.   inherited CreateParams(Params);
  1244.   with Params do
  1245.   begin
  1246.     Style := Style and not WS_BORDER;
  1247.     ExStyle := ExStyle and not WS_EX_CLIENTEDGE;
  1248.     WindowClass.style := CS_DBLCLKS;
  1249.     Style := Style or WS_TABSTOP;
  1250.   end;
  1251. end;
  1252. procedure TspListBox.CNDrawItem;
  1253. var
  1254.   State: TOwnerDrawState;
  1255. begin
  1256.   with Message.DrawItemStruct^ do
  1257.   begin
  1258.     {$IFDEF VER120}
  1259.       State := TOwnerDrawState(WordRec(LongRec(itemState).Lo).Lo);
  1260.     {$ELSE}
  1261.       {$IFDEF VER125}
  1262.         State := TOwnerDrawState(WordRec(LongRec(itemState).Lo).Lo);
  1263.       {$ELSE}
  1264.         State := TOwnerDrawState(LongRec(itemState).Lo);
  1265.       {$ENDIF}
  1266.     {$ENDIF}
  1267.     Canvas.Handle := hDC;
  1268.     Canvas.Font := Font;
  1269.     Canvas.Brush := Brush;
  1270.     if SkinListBox.FIndex <> -1
  1271.     then
  1272.       begin
  1273.         if SkinListBox.UseSkinItemHeight
  1274.         then
  1275.           DrawSkinItem(Canvas, itemID, rcItem, State)
  1276.         else
  1277.           DrawStretchSkinItem(Canvas, itemID, rcItem, State);
  1278.       end
  1279.     else
  1280.       DrawDefaultItem(Canvas, itemID, rcItem, State);
  1281.     Canvas.Handle := 0;
  1282.   end;
  1283. end;
  1284. procedure TspListBox.WndProc;
  1285. var
  1286.   LParam, WParam: Integer;
  1287.   Handled: Boolean;
  1288. begin
  1289.   if SkinListBox <> nil then SkinListBox.ListBoxWProc(Message, Handled);
  1290.   if not Handled then Exit;
  1291.   inherited;
  1292.   case Message.Msg of
  1293.     WM_LBUTTONDBLCLK:
  1294.       begin
  1295.         if SkinListBox <> nil then SkinListBox.ListBoxDblClick;
  1296.       end;
  1297.     WM_MOUSEWHEEL:
  1298.       if (SkinListBox <> nil) and (SkinListBox.ScrollBar <> nil)
  1299.       then
  1300.         begin
  1301.           LParam := 0;
  1302.           if Message.WParam > 0
  1303.           then
  1304.             WParam := MakeWParam(SB_LINEUP, 0)
  1305.           else
  1306.             WParam := MakeWParam(SB_LINEDOWN, 0);
  1307.           SendMessage(Handle, WM_VSCROLL, WParam, LParam);
  1308.           SkinListBox.UpDateScrollBar;
  1309.         end
  1310.       else
  1311.         if (SkinListBox <> nil) and (SkinListBox.HScrollBar <> nil)
  1312.         then
  1313.           begin
  1314.             with SkinListBox.HScrollBar do
  1315.             if Message.WParam > 0
  1316.             then
  1317.               Position := Position - SmallChange
  1318.             else
  1319.               Position := Position + SmallChange;
  1320.           end;
  1321.     WM_ERASEBKGND:
  1322.       SkinListBox.UpDateScrollBar;
  1323.     LB_ADDSTRING, LB_INSERTSTRING,
  1324.     LB_DELETESTRING:
  1325.       begin
  1326.         if SkinListBox <> nil
  1327.         then
  1328.           SkinListBox.UpDateScrollBar;
  1329.       end;
  1330.   end;
  1331. end;
  1332. constructor TspSkinCustomListBox.Create;
  1333. begin
  1334.   inherited;
  1335.   ControlStyle := [csCaptureMouse, csClickEvents,
  1336.     csReplicatable, csOpaque, csDoubleClicks, csAcceptsControls];
  1337.   FUseSkinItemHeight := True;
  1338.   FRowCount := 0;
  1339.   FImageIndex := -1;
  1340.   FGlyph := TBitMap.Create;
  1341.   FNumGlyphs := 1;
  1342.   FSpacing := 2;
  1343.   FDefaultCaptionFont := TFont.Create;
  1344.   FDefaultCaptionFont.OnChange := OnDefaultCaptionFontChange;
  1345.   FDefaultCaptionFont.Name := 'Arial';
  1346.   FDefaultCaptionFont.Height := 14;
  1347.   FDefaultCaptionHeight := 20;
  1348.   ActiveButton := -1;
  1349.   OldActiveButton := -1;
  1350.   CaptureButton := -1;
  1351.   FCaptionMode := False;
  1352.   FDefaultItemHeight := 20;
  1353.   TimerMode := 0;
  1354.   WaitMode := False;
  1355.   Font.Name := 'Arial';
  1356.   Font.Height := 14;
  1357.   Font.Color := clWindowText;
  1358.   Font.Style := [];
  1359.   ScrollBar := nil;
  1360.   HScrollBar := nil;
  1361.   ListBox := TspListBox.Create(Self);
  1362.   ListBox.SkinListBox := Self;
  1363.   ListBox.Style := lbOwnerDrawFixed;
  1364.   ListBox.ItemHeight := FDefaultItemHeight;
  1365.   ListBox.Parent := Self;
  1366.   ListBox.Visible := True;
  1367.   Height := 120;
  1368.   Width := 120;
  1369.   FSkinDataName := 'listbox';
  1370.   FHorizontalExtent := False;
  1371.   FStopUpDateHScrollBar := False;
  1372. end;
  1373. function TspSkinCustomListBox.GetAutoComplete: Boolean;
  1374. begin
  1375.   Result := ListBox.AutoComplete;
  1376. end;
  1377. procedure TspSkinCustomListBox.SetAutoComplete(Value: Boolean);
  1378. begin
  1379.   ListBox.AutoComplete := Value;
  1380. end;
  1381. procedure TspSkinCustomListBox.SetHorizontalExtent(Value: Boolean);
  1382. begin
  1383.   FHorizontalExtent := Value;
  1384.   UpdateScrollBar;
  1385. end;
  1386. function TspSkinCustomListBox.GetListBoxDragMode: TDragMode;
  1387. begin
  1388.   Result := ListBox.DragMode;
  1389. end;
  1390. procedure TspSkinCustomListBox.SetListBoxDragMode(Value: TDragMode);
  1391. begin
  1392.   ListBox.DragMode := Value;
  1393. end;
  1394. function TspSkinCustomListBox.GetListBoxDragKind: TDragKind;
  1395. begin
  1396.   Result := ListBox.DragKind;
  1397. end;
  1398. procedure TspSkinCustomListBox.SetListBoxDragKind(Value: TDragKind);
  1399. begin
  1400.   ListBox.DragKind := Value;
  1401. end;
  1402. function TspSkinCustomListBox.GetListBoxDragCursor: TCursor;
  1403. begin
  1404.   Result := ListBox.DragCursor;
  1405. end;
  1406. procedure TspSkinCustomListBox.SetListBoxDragCursor(Value: TCursor);
  1407. begin
  1408.   ListBox.DragCursor := Value;
  1409. end;
  1410. function TspSkinCustomListBox.GetOnListBoxEndDrag: TEndDragEvent;
  1411. begin
  1412.   Result := ListBox.OnEndDrag;
  1413. end;
  1414. procedure TspSkinCustomListBox.SetOnListBoxEndDrag(Value: TEndDragEvent);
  1415. begin
  1416.   ListBox.OnEndDrag := Value;
  1417. end;
  1418. function TspSkinCustomListBox.GetOnListBoxStartDrag: TStartDragEvent;
  1419. begin
  1420.   Result := ListBox.OnStartDrag;
  1421. end;
  1422. procedure TspSkinCustomListBox.SetOnListBoxStartDrag(Value: TStartDragEvent);
  1423. begin
  1424.   ListBox.OnStartDrag := Value;
  1425. end;
  1426. function TspSkinCustomListBox.GetOnListBoxDragOver: TDragOverEvent;
  1427. begin
  1428.   Result := ListBox.OnDragOver;
  1429. end;
  1430. procedure TspSkinCustomListBox.SetOnListBoxDragOver(Value: TDragOverEvent);
  1431. begin
  1432.   ListBox.OnDragOver := Value;
  1433. end;
  1434. function TspSkinCustomListBox.GetOnListBoxDragDrop: TDragDropEvent;
  1435. begin
  1436.   Result := ListBox.OnDragDrop;
  1437. end;
  1438. procedure TspSkinCustomListBox.SetOnListBoxDragDrop(Value: TDragDropEvent);
  1439. begin
  1440.   ListBox.OnDragDrop := Value;
  1441. end;
  1442. procedure TspSkinCustomListBox.ListBoxCreateWnd;
  1443. begin
  1444. end;
  1445. function  TspSkinCustomListBox.GetColumns;
  1446. begin
  1447.   Result := ListBox.Columns;
  1448. end;
  1449. procedure TspSkinCustomListBox.SetColumns;
  1450. begin
  1451.   ListBox.Columns := Value;
  1452.   UpDateScrollBar;
  1453. end;
  1454. procedure TspSkinCustomListBox.SetRowCount;
  1455. begin
  1456.   FRowCount := Value;
  1457.   if FRowCount <> 0
  1458.   then
  1459.     Height := Self.CalcHeight(FRowCount);
  1460. end;
  1461. procedure TspSkinCustomListBox.SetNumGlyphs;
  1462. begin
  1463.   FNumGlyphs := Value;
  1464.   RePaint;
  1465. end;
  1466. procedure TspSkinCustomListBox.SetGlyph;
  1467. begin
  1468.   FGlyph.Assign(Value);
  1469.   RePaint;
  1470. end;
  1471. procedure TspSkinCustomListBox.SetSpacing;
  1472. begin
  1473.   FSpacing := Value;
  1474.   RePaint;
  1475. end;
  1476. procedure TspSkinCustomListBox.SetImages(Value: TCustomImageList);
  1477. begin
  1478.   FImages := Value;
  1479.   ListBox.RePaint;
  1480. end;
  1481. procedure TspSkinCustomListBox.SetImageIndex(Value: Integer);
  1482. begin
  1483.   FImageIndex := Value;
  1484.   ListBox.RePaint;
  1485. end;
  1486. procedure TspSkinCustomListBox.Notification(AComponent: TComponent;
  1487.   Operation: TOperation);
  1488. begin
  1489.   inherited Notification(AComponent, Operation);
  1490.   if (Operation = opRemove) and (AComponent = Images) then
  1491.     Images := nil;
  1492. end;
  1493. procedure TspSkinCustomListBox.ListBoxWProc(var Message: TMessage; var Handled: Boolean);
  1494. begin
  1495.   Handled := True;
  1496. end;
  1497. procedure TspSkinCustomListBox.DefaultFontChange;
  1498. begin
  1499.   if FIndex = -1 then Font.Assign(FDefaultFont);
  1500. end;
  1501. procedure TspSkinCustomListBox.OnDefaultCaptionFontChange;
  1502. begin
  1503.   if (FIndex = -1) and FCaptionMode then RePaint;
  1504. end;
  1505. procedure TspSkinCustomListBox.SetDefaultCaptionHeight;
  1506. begin
  1507.   FDefaultCaptionHeight := Value;
  1508.   if (FIndex = -1) and FCaptionMode
  1509.   then
  1510.     begin
  1511.       CalcRects;
  1512.       RePaint;
  1513.     end;  
  1514. end;
  1515. procedure TspSkinCustomListBox.SetDefaultCaptionFont;
  1516. begin
  1517.   FDefaultCaptionFont.Assign(Value);
  1518. end;
  1519. procedure TspSkinCustomListBox.SetDefaultItemHeight;
  1520. begin
  1521.   FDefaultItemHeight := Value;
  1522.   if FIndex = -1
  1523.   then
  1524.     ListBox.ItemHeight := FDefaultItemHeight;
  1525. end;
  1526. procedure TspSkinCustomListBox.StartTimer;
  1527. begin
  1528.   KillTimer(Handle, 1);
  1529.   SetTimer(Handle, 1, 100, nil);
  1530. end;
  1531. procedure TspSkinCustomListBox.StopTimer;
  1532. begin
  1533.   KillTimer(Handle, 1);
  1534.   TimerMode := 0;
  1535. end;
  1536. procedure TspSkinCustomListBox.WMTimer;
  1537. begin
  1538.   inherited;
  1539.   if WaitMode
  1540.   then
  1541.     begin
  1542.       WaitMode := False;
  1543.       StartTimer;
  1544.       Exit;
  1545.     end;
  1546.   case TimerMode of
  1547.     1: if ItemIndex > 0 then ItemIndex := ItemIndex - 1;
  1548.     2: ItemIndex := ItemIndex + 1;
  1549.   end;
  1550. end;
  1551. procedure TspSkinCustomListBox.CMMouseEnter;
  1552. begin
  1553.   inherited;
  1554.   if FCaptionMode
  1555.   then
  1556.     TestActive(-1, -1);
  1557. end;
  1558. procedure TspSkinCustomListBox.CMMouseLeave;
  1559. var
  1560.   i: Integer;
  1561. begin
  1562.   inherited;
  1563.   if FCaptionMode
  1564.   then
  1565.   for i := 0 to 1 do
  1566.     if Buttons[i].MouseIn
  1567.     then
  1568.        begin
  1569.          Buttons[i].MouseIn := False;
  1570.          RePaint;
  1571.        end;
  1572. end;
  1573. procedure TspSkinCustomListBox.MouseDown;
  1574. begin
  1575.   if FCaptionMode
  1576.   then
  1577.     begin
  1578.       TestActive(X, Y);
  1579.       if ActiveButton <> -1
  1580.       then
  1581.         begin
  1582.           CaptureButton := ActiveButton;
  1583.           ButtonDown(ActiveButton, X, Y);
  1584.       end;
  1585.     end;
  1586.   inherited;
  1587. end;
  1588. procedure TspSkinCustomListBox.MouseUp;
  1589. begin
  1590.   if FCaptionMode
  1591.   then
  1592.     begin
  1593.       if CaptureButton <> -1
  1594.       then ButtonUp(CaptureButton, X, Y);
  1595.       CaptureButton := -1;
  1596.     end;  
  1597.   inherited;
  1598. end;
  1599. procedure TspSkinCustomListBox.MouseMove;
  1600. begin
  1601.   inherited;
  1602.   if FCaptionMode then TestActive(X, Y);
  1603. end;
  1604. procedure TspSkinCustomListBox.TestActive(X, Y: Integer);
  1605. var
  1606.   i, j: Integer;
  1607. begin
  1608.   if (FIndex <> -1) and IsNullRect(UpButtonRect) and IsNullRect(DownButtonRect)
  1609.   then Exit;
  1610.   j := -1;
  1611.   OldActiveButton := ActiveButton;
  1612.   for i := 0 to 2 do
  1613.   begin
  1614.     if PtInRect(Buttons[i].R, Point(X, Y))
  1615.     then
  1616.       begin
  1617.         j := i;
  1618.         Break;
  1619.       end;
  1620.   end;
  1621.   ActiveButton := j;
  1622.   if (CaptureButton <> -1) and
  1623.      (ActiveButton <> CaptureButton) and (ActiveButton <> -1)
  1624.   then
  1625.     ActiveButton := -1;
  1626.   if (OldActiveButton <> ActiveButton)
  1627.   then
  1628.     begin
  1629.       if OldActiveButton <> - 1
  1630.       then
  1631.         ButtonLeave(OldActiveButton);
  1632.       if ActiveButton <> -1
  1633.       then
  1634.         ButtonEnter(ActiveButton);
  1635.     end;
  1636. end;
  1637. procedure TspSkinCustomListBox.ButtonDown;
  1638. begin
  1639.   Buttons[i].MouseIn := True;
  1640.   Buttons[i].Down := True;
  1641.   DrawButton(Canvas, i);
  1642.   case i of
  1643.     0: if Assigned(FOnUpButtonClick) then Exit;
  1644.     1: if Assigned(FOnDownButtonClick) then Exit;
  1645.     2: if Assigned(FOnCheckButtonClick) then Exit;
  1646.   end;
  1647.   TimerMode := 0;
  1648.   case i of
  1649.     0: TimerMode := 1;
  1650.     1: TimerMode := 2;
  1651.   end;
  1652.   if TimerMode <> 0
  1653.   then
  1654.     begin
  1655.       WaitMode := True;
  1656.       SetTimer(Handle, 1, 500, nil);
  1657.     end;
  1658. end;
  1659. procedure TspSkinCustomListBox.ButtonUp;
  1660. begin
  1661.   Buttons[i].Down := False;
  1662.   if ActiveButton <> i then Buttons[i].MouseIn := False;
  1663.   DrawButton(Canvas, i);
  1664.   if Buttons[i].MouseIn
  1665.   then
  1666.   case i of
  1667.     0:
  1668.       if Assigned(FOnUpButtonClick)
  1669.       then
  1670.         begin
  1671.           FOnUpButtonClick(Self);
  1672.           Exit;
  1673.         end;
  1674.     1:
  1675.       if Assigned(FOnDownButtonClick)
  1676.       then
  1677.         begin
  1678.           FOnDownButtonClick(Self);
  1679.           Exit;
  1680.         end;
  1681.     2:
  1682.       if Assigned(FOnCheckButtonClick)
  1683.       then
  1684.         begin
  1685.           FOnCheckButtonClick(Self);
  1686.           Exit;
  1687.         end;
  1688.   end;
  1689.   case i of
  1690.     1: ItemIndex := ItemIndex + 1;
  1691.     0: if ItemIndex > 0 then ItemIndex := ItemIndex - 1;
  1692.     2: ListBox.Click;
  1693.   end;
  1694.   if TimerMode <> 0 then StopTimer;
  1695. end;
  1696. procedure TspSkinCustomListBox.ButtonEnter(I: Integer);
  1697. begin
  1698.   Buttons[i].MouseIn := True;
  1699.   DrawButton(Canvas, i);
  1700.   if (TimerMode <> 0) and Buttons[i].Down
  1701.   then SetTimer(Handle, 1, 50, nil);
  1702. end;
  1703. procedure TspSkinCustomListBox.ButtonLeave(I: Integer);
  1704. begin
  1705.   Buttons[i].MouseIn := False;
  1706.   DrawButton(Canvas, i);
  1707.   if (TimerMode <> 0) and Buttons[i].Down
  1708.   then KillTimer(Handle, 1);
  1709. end;
  1710. procedure TspSkinCustomListBox.CMTextChanged;
  1711. begin
  1712.   inherited;
  1713.   if FCaptionMode then RePaint;
  1714. end;
  1715. procedure TspSkinCustomListBox.SetAlignment(Value: TAlignment);
  1716. begin
  1717.   if FAlignment <> Value
  1718.   then
  1719.     begin
  1720.       FAlignment := Value;
  1721.       if FCaptionMode then RePaint;
  1722.     end;
  1723. end;
  1724. procedure TspSkinCustomListBox.DrawButton;
  1725. var
  1726.   C: TColor;
  1727.   kf: Double;
  1728.   R1: TRect;
  1729. begin
  1730.   if FIndex = -1
  1731.   then
  1732.     with Buttons[i] do
  1733.     begin
  1734.       R1 := R;
  1735.       if Down and MouseIn
  1736.       then
  1737.         begin
  1738.           Frame3D(Cnvs, R1, SP_XP_BTNFRAMECOLOR, SP_XP_BTNFRAMECOLOR, 1);
  1739.           Cnvs.Brush.Color := SP_XP_BTNDOWNCOLOR;
  1740.           Cnvs.FillRect(R1);
  1741.         end
  1742.       else
  1743.         if MouseIn
  1744.         then
  1745.           begin
  1746.             Frame3D(Cnvs, R1, SP_XP_BTNFRAMECOLOR, SP_XP_BTNFRAMECOLOR, 1);
  1747.             Cnvs.Brush.Color := SP_XP_BTNACTIVECOLOR;
  1748.             Cnvs.FillRect(R1);
  1749.           end
  1750.         else
  1751.           begin
  1752.             Cnvs.Brush.Color := clBtnFace;
  1753.             Cnvs.FillRect(R1);
  1754.           end;
  1755.       C := clBlack;
  1756.       case i of
  1757.         0: DrawArrowImage(Cnvs, R, C, 3);
  1758.         1: DrawArrowImage(Cnvs, R, C, 4);
  1759.         2: DrawCheckImage(Cnvs, R.Left + 4, R.Top + 4, C);
  1760.       end;
  1761.     end
  1762.   else
  1763.     with Buttons[i] do
  1764.     if not IsNullRect(R) then
  1765.     begin
  1766.       R1 := NullRect;
  1767.       case I of
  1768.         0:
  1769.           begin
  1770.             if Down and MouseIn
  1771.             then R1 := DownUpButtonRect
  1772.             else if MouseIn then R1 := ActiveUpButtonRect;
  1773.           end;
  1774.         1:
  1775.           begin
  1776.             if Down and MouseIn
  1777.             then R1 := DownDownButtonRect
  1778.             else if MouseIn then R1 := ActiveDownButtonRect;
  1779.           end;
  1780.         2: begin
  1781.             if Down and MouseIn
  1782.             then R1 := DownCheckButtonRect
  1783.             else if MouseIn then R1 := ActiveCheckButtonRect;
  1784.            end;
  1785.       end;
  1786.       if not IsNullRect(R1)
  1787.       then
  1788.         Cnvs.CopyRect(R, Picture.Canvas, R1)
  1789.       else
  1790.         begin
  1791.           case I of
  1792.             0: R1 := UpButtonRect;
  1793.             1: R1 := DownButtonRect;
  1794.             2: R1 := CheckButtonRect;
  1795.           end;
  1796.           OffsetRect(R1, SkinRect.Left, SkinRect.Top);
  1797.           Cnvs.CopyRect(R, Picture.Canvas, R1);
  1798.         end;
  1799.     end;
  1800. end;
  1801. procedure TspSkinCustomListBox.CreateControlSkinImage;
  1802. var
  1803.   GX, GY, GlyphNum, TX, TY, i, OffX, OffY: Integer;
  1804. function GetGlyphTextWidth: Integer;
  1805. begin
  1806.   Result := B.Canvas.TextWidth(Caption);
  1807.   if not FGlyph.Empty then Result := Result + FGlyph.Width div FNumGlyphs + FSpacing;
  1808. end;
  1809. function CalcBRect(BR: TRect): TRect;
  1810. var
  1811.   R: TRect;
  1812. begin
  1813.   R := BR;
  1814.   if BR.Top <= LTPt.Y
  1815.   then
  1816.     begin
  1817.       if BR.Left > RTPt.X then OffsetRect(R, OffX, 0);
  1818.     end
  1819.   else
  1820.     begin
  1821.       OffsetRect(R, 0, OffY);
  1822.       if BR.Left > RBPt.X then OffsetRect(R, OffX, 0);
  1823.     end;
  1824.   Result := R;
  1825. end;
  1826. begin
  1827.   inherited;
  1828.   // calc rects
  1829.   OffX := Width - RectWidth(SkinRect);
  1830.   OffY := Height - RectHeight(SkinRect);
  1831.   NewClRect := ClRect;
  1832.   Inc(NewClRect.Right, OffX);
  1833.   Inc(NewClRect.Bottom, OffY);
  1834.   if FCaptionMode
  1835.   then
  1836.     begin
  1837.       NewCaptionRect := CaptionRect;
  1838.       if CaptionRect.Right >= RTPt.X
  1839.       then
  1840.         Inc(NewCaptionRect.Right, OffX);
  1841.       Buttons[0].R := CalcBRect(UpButtonRect);
  1842.       Buttons[1].R := CalcBRect(DownButtonRect);
  1843.       Buttons[2].R := CalcBRect(CheckButtonRect);
  1844.     end;  
  1845.   // paint caption
  1846.   if not IsNullRect(CaptionRect)
  1847.   then
  1848.     with B.Canvas do
  1849.     begin
  1850.       Font.Name := CaptionFontName;
  1851.       Font.Height := CaptionFontHeight;
  1852.       Font.Color := CaptionFontColor;
  1853.       Font.Style := CaptionFontStyle;
  1854.       Font.CharSet := DefaultCaptionFont.CharSet;
  1855.       TY := NewCaptionRect.Top + RectHeight(NewCaptionRect) div 2 -
  1856.             TextHeight(Caption) div 2;
  1857.       TX := NewCaptionRect.Left + 2;
  1858.       case Alignment of
  1859.         taCenter: TX := TX + RectWidth(NewCaptionRect) div 2 - GetGlyphTextWidth div 2;
  1860.         taRightJustify: TX := NewCaptionRect.Right - GetGlyphTextWidth - 2;
  1861.       end;
  1862.       Brush.Style := bsClear;
  1863.       if not FGlyph.Empty
  1864.       then
  1865.       begin
  1866.         GY := NewCaptionRect.Top + RectHeight(NewCaptionRect) div 2 - FGlyph.Height div 2;
  1867.         GX := TX;
  1868.         TX := GX + FGlyph.Width div FNumGlyphs + FSpacing;
  1869.         GlyphNum := 1;
  1870.         if not Enabled and (NumGlyphs = 2) then GlyphNum := 2;
  1871.        end;
  1872.       TextRect(NewCaptionRect, TX, TY, Caption);
  1873.       if not FGlyph.Empty
  1874.       then DrawGlyph(B.Canvas, GX, GY, FGlyph, NumGlyphs, GlyphNum);
  1875.     end;
  1876.   // paint buttons
  1877.   for i := 0 to 2 do DrawButton(B.Canvas, i);
  1878. end;
  1879. procedure TspSkinCustomListBox.CreateControlDefaultImage;
  1880. function GetGlyphTextWidth: Integer;
  1881. begin
  1882.   Result := B.Canvas.TextWidth(Caption);
  1883.   if not FGlyph.Empty then Result := Result + FGlyph.Width div FNumGlyphs + FSpacing;
  1884. end;
  1885. var
  1886.   BW, i, TX, TY: Integer;
  1887.   R: TRect;
  1888.   GX, GY: Integer;
  1889.   GlyphNum: Integer;
  1890. begin
  1891.   inherited;
  1892.   if FCaptionMode
  1893.   then
  1894.     begin
  1895.       BW := 17;
  1896.       if BW > FDefaultCaptionHeight - 3 then BW := FDefaultCaptionHeight - 3;
  1897.       Buttons[0].R := Rect(Width - BW - 2, 2, Width - 2, 1 + BW);
  1898.       Buttons[1].R := Rect(Buttons[0].R.Left - BW, 2, Buttons[0].R.Left, 1 + BW);
  1899.       Buttons[2].R := Rect(Buttons[1].R.Left - BW, 2, Buttons[1].R.Left, 1 + BW);
  1900.     end;  
  1901.   R := ClientRect;
  1902.   Frame3D(B.Canvas, R, clBtnShadow, clBtnShadow, 1);
  1903.   if FCaptionMode
  1904.   then
  1905.     with B.Canvas do
  1906.     begin
  1907.       R := Rect(3, 2, Width - BW * 3 - 3, FDefaultCaptionHeight - 2);
  1908.       Font.Assign(FDefaultCaptionFont);
  1909.       case Alignment of
  1910.         taLeftJustify: TX := R.Left;
  1911.         taCenter: TX := R.Left + RectWidth(R) div 2 - GetGlyphTextWidth div 2;
  1912.         taRightJustify: TX := R.Right - GetGlyphTextWidth;
  1913.       end;
  1914.       TY := (FDefaultCaptionHeight - 2) div 2 - TextHeight(Caption) div 2;
  1915.       if not FGlyph.Empty
  1916.       then
  1917.         begin
  1918.           GY := R.Top + RectHeight(R) div 2 - FGlyph.Height div 2 - 1;
  1919.           GX := TX;
  1920.           if FNumGlyphs = 0 then FNumGlyphs := 1;
  1921.           TX := GX + FGlyph.Width div FNumGlyphs + FSpacing;
  1922.           GlyphNum := 1;
  1923.           if not Enabled and (NumGlyphs = 2) then GlyphNum := 2;
  1924.         end;
  1925.       TextRect(R, TX, TY, Caption);
  1926.       if not FGlyph.Empty
  1927.       then DrawGlyph(B.Canvas, GX, GY, FGlyph, NumGlyphs, GlyphNum);
  1928.       Pen.Color := clBtnShadow;
  1929.       MoveTo(1, FDefaultCaptionHeight - 1); LineTo(Width - 1, FDefaultCaptionHeight - 1);
  1930.       for i := 0 to 2 do DrawButton(B.Canvas, i);
  1931.     end;
  1932. end;
  1933. procedure TspSkinCustomListBox.SetCaptionMode;
  1934. begin
  1935.   FCaptionMode := Value;
  1936.   if FIndex = -1
  1937.   then
  1938.     begin
  1939.       CalcRects;
  1940.       RePaint;
  1941.     end;
  1942. end;
  1943. function TspSkinCustomListBox.CalcHeight;
  1944. begin
  1945.   if FIndex = -1
  1946.   then
  1947.     begin
  1948.       Result := AitemsCount * ListBox.ItemHeight + 4;
  1949.       if CaptionMode then Result := Result + FDefaultCaptionHeight;
  1950.     end  
  1951.   else
  1952.     Result := ClRect.Top + AitemsCount * ListBox.ItemHeight +
  1953.               RectHeight(SkinRect) - ClRect.Bottom;
  1954.   if HScrollBar <> nil
  1955.   then
  1956.     Inc(Result, HScrollBar.Height);
  1957. end;
  1958. procedure TspSkinCustomListBox.Clear;
  1959. begin
  1960.   ListBox.Clear;
  1961.   UpDateScrollBar;
  1962. end;
  1963. function TspSkinCustomListBox.ItemAtPos(Pos: TPoint; Existing: Boolean): Integer;
  1964. begin
  1965.   Result := ListBox.ItemAtPos(Pos, Existing);
  1966. end;
  1967. function TspSkinCustomListBox.ItemRect(Item: Integer): TRect;
  1968. begin
  1969.   Result := ListBox.ItemRect(Item);
  1970. end;
  1971. function TspSkinCustomListBox.GetListBoxPopupMenu;
  1972. begin
  1973.   Result := ListBox.PopupMenu;
  1974. end;
  1975. procedure TspSkinCustomListBox.SetListBoxPopupMenu;
  1976. begin
  1977.   ListBox.PopupMenu := Value;
  1978. end;
  1979. function TspSkinCustomListBox.GetCanvas: TCanvas;
  1980. begin
  1981.   Result := ListBox.Canvas;
  1982. end;
  1983. function TspSkinCustomListBox.GetExtandedSelect: Boolean;
  1984. begin
  1985.   Result := ListBox.ExtendedSelect;
  1986. end;
  1987. procedure TspSkinCustomListBox.SetExtandedSelect(Value: Boolean);
  1988. begin
  1989.   ListBox.ExtendedSelect := Value;
  1990. end;
  1991. function TspSkinCustomListBox.GetSelCount: Integer;
  1992. begin
  1993.   Result := ListBox.SelCount;
  1994. end;
  1995. function TspSkinCustomListBox.GetSelected(Index: Integer): Boolean;
  1996. begin
  1997.   Result := ListBox.Selected[Index];
  1998. end;
  1999. procedure TspSkinCustomListBox.SetSelected(Index: Integer; Value: Boolean);
  2000. begin
  2001.   ListBox.Selected[Index] := Value;
  2002. end;
  2003. function TspSkinCustomListBox.GetSorted: Boolean;
  2004. begin
  2005.   Result := ListBox.Sorted;
  2006. end;
  2007. procedure TspSkinCustomListBox.SetSorted(Value: Boolean);
  2008. begin
  2009.   if ScrollBar <> nil then HideScrollBar;
  2010.   ListBox.Sorted := Value;
  2011. end;
  2012. function TspSkinCustomListBox.GetTopIndex: Integer;
  2013. begin
  2014.   Result := ListBox.TopIndex;
  2015. end;
  2016. procedure TspSkinCustomListBox.SetTopIndex(Value: Integer);
  2017. begin
  2018.   ListBox.TopIndex := Value;
  2019. end;
  2020. function TspSkinCustomListBox.GetMultiSelect: Boolean;
  2021. begin
  2022.   Result := ListBox.MultiSelect;
  2023. end;
  2024. procedure TspSkinCustomListBox.SetMultiSelect(Value: Boolean);
  2025. begin
  2026.   ListBox.MultiSelect := Value;
  2027. end;
  2028. function TspSkinCustomListBox.GetListBoxFont: TFont;
  2029. begin
  2030.   Result := ListBox.Font;
  2031. end;
  2032. procedure TspSkinCustomListBox.SetListBoxFont(Value: TFont);
  2033. begin
  2034.   ListBox.Font.Assign(Value);
  2035. end;
  2036. function TspSkinCustomListBox.GetListBoxTabOrder: TTabOrder;
  2037. begin
  2038.   Result := ListBox.TabOrder;
  2039. end;
  2040. procedure TspSkinCustomListBox.SetListBoxTabOrder(Value: TTabOrder);
  2041. begin
  2042.   ListBox.TabOrder := Value;
  2043. end;
  2044. function TspSkinCustomListBox.GetListBoxTabStop: Boolean;
  2045. begin
  2046.   Result := ListBox.TabStop;
  2047. end;
  2048. procedure TspSkinCustomListBox.SetListBoxTabStop(Value: Boolean);
  2049. begin
  2050.   ListBox.TabStop := Value;
  2051. end;
  2052. procedure TspSkinCustomListBox.ShowScrollBar;
  2053. begin
  2054.   ScrollBar := TspSkinScrollBar.Create(Self);
  2055.   with ScrollBar do
  2056.   begin
  2057.     if Columns > 0
  2058.     then
  2059.       Kind := sbHorizontal
  2060.     else
  2061.       Kind := sbVertical;
  2062.     Height := 100;
  2063.     Width := 20;
  2064.     PageSize := 0;
  2065.     Min := 0;
  2066.     Position := 0;
  2067.     OnChange := SBChange;
  2068.     if Self.FIndex = -1
  2069.     then
  2070.       SkinDataName := ''
  2071.     else
  2072.       if Columns > 0
  2073.       then
  2074.         SkinDataName := HScrollBarName
  2075.       else
  2076.         SkinDataName := VScrollBarName;
  2077.     SkinData := Self.SkinData;
  2078.     Parent := Self;
  2079.     //
  2080.     if HScrollBar <> nil
  2081.     then
  2082.     with HScrollBar do
  2083.     begin
  2084.       if Self.FIndex = -1
  2085.       then
  2086.         begin
  2087.           SkinDataName := '';
  2088.           FBoth := True;
  2089.           BothMarkerWidth := 19;
  2090.         end
  2091.       else
  2092.         begin
  2093.           BothSkinDataName := BothScrollBarName;
  2094.           SkinDataName := BothScrollBarName;
  2095.           FBoth := True;
  2096.         end;
  2097.       SkinData := Self.SkinData;
  2098.     end;
  2099.     //
  2100.     CalcRects;
  2101.     Visible := True;
  2102.   end;
  2103.   RePaint;
  2104. end;
  2105. procedure TspSkinCustomListBox.ShowHScrollBar;
  2106. begin
  2107.   HScrollBar := TspSkinScrollBar.Create(Self);
  2108.   with HScrollBar do
  2109.   begin
  2110.     Kind := sbHorizontal;
  2111.     Height := 100;
  2112.     Width := 20;
  2113.     PageSize := 0;
  2114.     Min := 0;
  2115.     Position := 0;
  2116.     OnChange := HSBChange;
  2117.     if Self.FIndex = -1
  2118.     then
  2119.       begin
  2120.         SkinDataName := '';
  2121.         if ScrollBar <> nil
  2122.         then
  2123.           begin
  2124.             FBoth := True;
  2125.             BothMarkerWidth := 19;
  2126.           end;
  2127.       end
  2128.     else
  2129.       if ScrollBar <> nil
  2130.       then
  2131.         begin
  2132.           BothSkinDataName := BothScrollBarName;
  2133.           SkinDataName := BothScrollBarName;
  2134.           FBoth := True;
  2135.         end
  2136.       else
  2137.         begin
  2138.           BothSkinDataName := HScrollBarName;
  2139.           SkinDataName := HScrollBarName;
  2140.           FBoth := False;
  2141.         end;
  2142.     SkinData := Self.SkinData;
  2143.     Parent := Self;
  2144.     Visible := True;
  2145.     CalcRects;
  2146.   end;
  2147.   RePaint;
  2148. end;
  2149. procedure TspSkinCustomListBox.ListBoxEnter;
  2150. begin
  2151. end;
  2152. procedure TspSkinCustomListBox.ListBoxExit;
  2153. begin
  2154. end;
  2155. procedure TspSkinCustomListBox.ListBoxKeyDown;
  2156. begin
  2157.   if Assigned(FOnListBoxKeyDown) then FOnListBoxKeyDown(Self, Key, Shift);
  2158. end;
  2159. procedure TspSkinCustomListBox.ListBoxKeyUp;
  2160. begin
  2161.   if Assigned(FOnListBoxKeyUp) then FOnListBoxKeyUp(Self, Key, Shift);
  2162. end;
  2163. procedure TspSkinCustomListBox.ListBoxKeyPress;
  2164. begin
  2165.   if Assigned(FOnListBoxKeyPress) then FOnListBoxKeyPress(Self, Key);
  2166. end;
  2167. procedure TspSkinCustomListBox.ListBoxDblClick;
  2168. begin
  2169.   if Assigned(FOnListBoxDblClick) then FOnListBoxDblClick(Self);
  2170. end;
  2171. procedure TspSkinCustomListBox.ListBoxClick;
  2172. begin
  2173.   if Assigned(FOnListBoxClick) then FOnListBoxClick(Self);
  2174. end;
  2175. procedure TspSkinCustomListBox.ListBoxMouseDown;
  2176. begin
  2177.   if Assigned(FOnListBoxMouseDown) then FOnListBoxMouseDown(Self, Button, Shift, X, Y);
  2178. end;
  2179. procedure TspSkinCustomListBox.ListBoxMouseMove;
  2180. begin
  2181.   if Assigned(FOnListBoxMouseMove) then FOnListBoxMouseMove(Self, Shift, X, Y);
  2182. end;
  2183. procedure TspSkinCustomListBox.ListBoxMouseUp;
  2184. begin
  2185.   if Assigned(FOnListBoxMouseUp) then FOnListBoxMouseUp(Self, Button, Shift, X, Y);
  2186. end;
  2187. procedure TspSkinCustomListBox.HideScrollBar;
  2188. begin
  2189.   ScrollBar.Visible := False;
  2190.   ScrollBar.Free;
  2191.   ScrollBar := nil;
  2192.   CalcRects;
  2193. end;
  2194. procedure TspSkinCustomListBox.HideHScrollBar;
  2195. begin
  2196.   ListBox.HorizontalExtentValue := 0;
  2197.   HScrollBar.Visible := False;
  2198.   HScrollBar.Free;
  2199.   HScrollBar := nil;
  2200.   CalcRects;
  2201.   ListBox.Repaint;
  2202. end;
  2203. procedure TspSkinCustomListBox.CreateParams(var Params: TCreateParams);
  2204. begin
  2205.   inherited CreateParams(Params);
  2206.   with Params do
  2207.   begin
  2208.     WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
  2209.   end;
  2210. end;
  2211. procedure TspSkinCustomListBox.HSBChange(Sender: TObject);
  2212. begin
  2213.   ListBox.HorizontalExtentValue := HScrollBar.Position;
  2214.   ListBox.Repaint;
  2215. end;
  2216. procedure TspSkinCustomListBox.SBChange;
  2217. var
  2218.   LParam, WParam: Integer;
  2219. begin
  2220.   LParam := 0;
  2221.   WParam := MakeWParam(SB_THUMBPOSITION, ScrollBar.Position);
  2222.   if Columns > 0
  2223.   then
  2224.     SendMessage(ListBox.Handle, WM_HSCROLL, WParam, LParam)
  2225.   else
  2226.     begin
  2227.       SendMessage(ListBox.Handle, WM_VSCROLL, WParam, LParam);
  2228.     end;
  2229. end;
  2230. function TspSkinCustomListBox.GetItemIndex;
  2231. begin
  2232.   Result := ListBox.ItemIndex;
  2233. end;
  2234. procedure TspSkinCustomListBox.SetItemIndex;
  2235. begin
  2236.   ListBox.ItemIndex := Value;
  2237. end;
  2238. procedure TspSkinCustomListBox.SetItems;
  2239. begin
  2240.   ListBox.Items.Assign(Value);
  2241.   UpDateScrollBar;
  2242. end;
  2243. function TspSkinCustomListBox.GetItems;
  2244. begin
  2245.   Result := ListBox.Items;
  2246. end;
  2247. destructor TspSkinCustomListBox.Destroy;
  2248. begin
  2249.   if ScrollBar <> nil then ScrollBar.Free;
  2250.   if ListBox <> nil then ListBox.Free;
  2251.   FDefaultCaptionFont.Free;
  2252.   FGlyph.Free;
  2253.   inherited;
  2254. end;
  2255. procedure TspSkinCustomListBox.CalcRects;
  2256. var
  2257.   LTop: Integer;
  2258.   OffX, OffY: Integer;
  2259.   HSY: Integer;
  2260. begin
  2261.   if FIndex <> -1
  2262.   then
  2263.     begin
  2264.       OffX := Width - RectWidth(SkinRect);
  2265.       OffY := Height - RectHeight(SkinRect);
  2266.       NewClRect := ClRect;
  2267.       Inc(NewClRect.Right, OffX);
  2268.       Inc(NewClRect.Bottom, OffY);
  2269.     end
  2270.   else
  2271.     if FCaptionMode
  2272.     then
  2273.       LTop := FDefaultCaptionHeight
  2274.     else
  2275.       LTop := 1;
  2276.   if (Columns = 0) and (HScrollBar <> nil) and (HScrollBar.Visible)
  2277.   then
  2278.     begin
  2279.       if FIndex = -1
  2280.       then
  2281.         begin
  2282.           HScrollBar.SetBounds(1, Height - 20, Width - 2, 19);
  2283.           HSY := HScrollBar.Height - 1;
  2284.         end
  2285.       else
  2286.         begin
  2287.           HScrollBar.SetBounds(NewClRect.Left,
  2288.             NewClRect.Bottom - HScrollBar.Height,
  2289.             RectWidth(NewClRect), HScrollBar.Height);
  2290.           HSY := HScrollBar.Height;
  2291.         end;
  2292.     end
  2293.   else
  2294.     HSY := 0;
  2295.   if (ScrollBar <> nil) and ScrollBar.Visible
  2296.   then
  2297.     begin
  2298.       if FIndex = -1
  2299.       then
  2300.         begin
  2301.           if Columns > 0
  2302.           then
  2303.             begin
  2304.               ScrollBar.SetBounds(1, Height - 20, Width - 2, 19);
  2305.               ListRect := Rect(2, LTop + 1, Width - 2, ScrollBar.Top);
  2306.             end
  2307.           else
  2308.             begin
  2309.               ScrollBar.SetBounds(Width - 20, LTop, 19, Height - 1 - LTop - HSY);
  2310.               ListRect := Rect(2, LTop + 1, ScrollBar.Left, Height - 2 - HSY);
  2311.             end;
  2312.         end
  2313.       else
  2314.         begin
  2315.           if Columns > 0
  2316.           then
  2317.             begin
  2318.               ScrollBar.SetBounds(NewClRect.Left,
  2319.                 NewClRect.Bottom - ScrollBar.Height,
  2320.                 RectWidth(NewClRect), ScrollBar.Height);
  2321.               ListRect := NewClRect;
  2322.               Dec(ListRect.Bottom, ScrollBar.Height);
  2323.             end
  2324.           else
  2325.             begin
  2326.               ScrollBar.SetBounds(NewClRect.Right - ScrollBar.Width,
  2327.                 NewClRect.Top, ScrollBar.Width, RectHeight(NewClRect) - HSY);
  2328.               ListRect := NewClRect;
  2329.               Dec(ListRect.Right, ScrollBar.Width);
  2330.               Dec(ListRect.Bottom, HSY);
  2331.             end;
  2332.         end;
  2333.     end
  2334.   else
  2335.     begin
  2336.       if FIndex = -1
  2337.       then
  2338.         ListRect := Rect(2, LTop + 1, Width - 2, Height - 2)
  2339.       else
  2340.         ListRect := NewClRect;
  2341.     end;
  2342.   if ListBox <> nil
  2343.   then
  2344.     ListBox.SetBounds(ListRect.Left, ListRect.Top,
  2345.       RectWidth(ListRect), RectHeight(ListRect));
  2346. end;
  2347. procedure TspSkinCustomListBox.GetSkinData;
  2348. begin
  2349.   inherited;
  2350.   if FIndex <> -1
  2351.   then
  2352.     if TspDataSkinControl(FSD.CtrlList.Items[FIndex]) is TspDataSkinListBox
  2353.     then
  2354.       with TspDataSkinListBox(FSD.CtrlList.Items[FIndex]) do
  2355.       begin
  2356.         Self.FontName := FontName;
  2357.         Self.FontStyle := FontStyle;
  2358.         Self.FontHeight := FontHeight;
  2359.         Self.SItemRect := SItemRect;
  2360.         Self.ActiveItemRect := ActiveItemRect;
  2361.         if isNullRect(ActiveItemRect)
  2362.         then
  2363.           Self.ActiveItemRect := SItemRect;
  2364.         Self.FocusItemRect := FocusItemRect;
  2365.         if isNullRect(FocusItemRect)
  2366.         then
  2367.           Self.FocusItemRect := SItemRect;
  2368.         Self.ItemLeftOffset := ItemLeftOffset;
  2369.         Self.ItemRightOffset := ItemRightOffset;
  2370.         Self.ItemTextRect := ItemTextRect;
  2371.         Self.FontColor := FontColor;
  2372.         Self.ActiveFontColor := ActiveFontColor;
  2373.         Self.FocusFontColor := FocusFontColor;
  2374.         //
  2375.         Self.CaptionRect := CaptionRect;
  2376.         Self.CaptionFontName := CaptionFontName;
  2377.         Self.CaptionFontStyle := CaptionFontStyle;
  2378.         Self.CaptionFontHeight := CaptionFontHeight;
  2379.         Self.CaptionFontColor := CaptionFontColor;
  2380.         Self.UpButtonRect := UpButtonRect;
  2381.         Self.ActiveUpButtonRect := ActiveUpButtonRect;
  2382.         Self.DownUpButtonRect := DownUpButtonRect;
  2383.         if IsNullRect(Self.DownUpButtonRect)
  2384.         then Self.DownUpButtonRect := Self.ActiveUpButtonRect;
  2385.         Self.DownButtonRect := DownButtonRect;
  2386.         Self.ActiveDownButtonRect := ActiveDownButtonRect;
  2387.         Self.DownDownButtonRect := DownDownButtonRect;
  2388.         if IsNullRect(Self.DownDownButtonRect)
  2389.         then Self.DownDownButtonRect := Self.ActiveDownButtonRect;
  2390.         Self.CheckButtonRect := CheckButtonRect;
  2391.         Self.ActiveCheckButtonRect := ActiveCheckButtonRect;
  2392.         Self.DownCheckButtonRect := DownCheckButtonRect;
  2393.         if IsNullRect(Self.DownCheckButtonRect)
  2394.         then Self.DownCheckButtonRect := Self.ActiveCheckButtonRect;
  2395.         //
  2396.         Self.VScrollBarName := VScrollBarName;
  2397.         Self.HScrollBarName := HScrollBarName;
  2398.         Self.BothScrollBarName := BothScrollBarName;
  2399.       end;
  2400. end;
  2401. procedure TspSkinCustomListBox.ChangeSkinData;
  2402. begin
  2403.   inherited;
  2404.   //
  2405.   FStopUpDateHScrollBar := True;
  2406.   if (FIndex <> -1)
  2407.   then
  2408.     begin
  2409.       if FUseSkinItemHeight
  2410.       then
  2411.         ListBox.ItemHeight := RectHeight(sItemRect);
  2412.     end
  2413.   else
  2414.     begin
  2415.       ListBox.ItemHeight := FDefaultItemHeight;
  2416.       Font.Assign(FDefaultFont);
  2417.     end;
  2418.     
  2419.   if ScrollBar <> nil
  2420.   then
  2421.     with ScrollBar do
  2422.     begin
  2423.       if Self.FIndex = -1
  2424.       then
  2425.         SkinDataName := ''
  2426.       else
  2427.         if Columns > 0
  2428.         then
  2429.           SkinDataName := HScrollBarName
  2430.         else
  2431.           SkinDataName := VScrollBarName;
  2432.       SkinData := Self.SkinData;
  2433.     end;
  2434.   if HScrollBar <> nil
  2435.   then
  2436.     with HScrollBar do
  2437.     begin
  2438.       if Self.FIndex = -1
  2439.       then
  2440.         begin
  2441.           SkinDataName := '';
  2442.           if ScrollBar <> nil then BothMarkerWidth := 19;
  2443.         end
  2444.       else
  2445.         if ScrollBar <> nil
  2446.         then
  2447.           SkinDataName := BothScrollBarName
  2448.         else
  2449.           SkinDataName := HScrollBarName;
  2450.       SkinData := Self.SkinData;
  2451.     end;
  2452.   if FRowCount <> 0
  2453.   then
  2454.     Height := Self.CalcHeight(FRowCount);
  2455.   CalcRects;
  2456.   FStopUpDateHScrollBar := False;
  2457.   UpDateScrollBar;
  2458.   ListBox.RePaint;
  2459. end;
  2460. procedure TspSkinCustomListBox.WMSIZE;
  2461. begin
  2462.   inherited;
  2463.   CalcRects;
  2464.   UpDateScrollBar;
  2465.   if ScrollBar <> nil then ScrollBar.RePaint;
  2466. end;
  2467. procedure TspSkinCustomListBox.SetBounds;
  2468. begin
  2469.   inherited;
  2470.   if FIndex = -1 then RePaint;
  2471. end;
  2472. function TspSkinCustomListBox.GetFullItemWidth(Index: Integer; ACnvs: TCanvas): Integer;
  2473. begin
  2474.   Result := ACnvs.TextWidth(Items[Index]);
  2475. end;
  2476. procedure TspSkinCustomListBox.UpDateScrollBar;
  2477. var
  2478.   I, FMaxWidth, Min, Max, Pos, Page: Integer;
  2479. function GetPageSize: Integer;
  2480. begin
  2481.   if FIndex = -1
  2482.   then Result := ListBox.Width - 4
  2483.   else
  2484.     begin
  2485.       Result := RectWidth(SItemRect) - RectWidth(ItemTextRect);
  2486.       Result := ListBox.Width - Result;
  2487.     end;
  2488.   if Images <> nil then Result := Result - Images.Width - 4;
  2489. end;
  2490. begin
  2491.   if (ListBox = nil) then Exit;
  2492.   if Columns > 0
  2493.   then
  2494.     begin
  2495.       GetScrollRange(ListBox.Handle, SB_HORZ, Min, Max);
  2496.       Pos := GetScrollPos(ListBox.Handle, SB_HORZ);
  2497.       Page := ListBox.Columns;
  2498.       if (Max > Min) and (Pos <= Max) and (Page <= Max) and
  2499.          ((ListBox.Height div ListBox.ItemHeight) * Columns < ListBox.Items.Count)
  2500.       then
  2501.         begin
  2502.           if ScrollBar = nil
  2503.           then ShowScrollBar;
  2504.           ScrollBar.SetRange(Min, Max, Pos, Page);
  2505.         end
  2506.      else
  2507.        if (ScrollBar <> nil) and ScrollBar.Visible
  2508.        then HideScrollBar;
  2509.     end
  2510.   else
  2511.     begin
  2512.       if FHorizontalExtent and not FStopUpDateHScrollBar
  2513.       then
  2514.         begin
  2515.           FMaxWidth := 0;
  2516.           with ListBox.Canvas do
  2517.           begin
  2518.             if FIndex = -1
  2519.             then
  2520.               Font.Assign(ListBox.Font)
  2521.             else
  2522.               begin
  2523.                 Font.Name := FontName;
  2524.                 Font.Style := FontStyle;
  2525.                 Font.Height := FontHeight;
  2526.               end;
  2527.           end;
  2528.           for I := 0 to Items.Count - 1 do
  2529.             FMaxWidth := spUtils.Max(FMaxWidth, GetFullItemWidth(I, ListBox.Canvas));
  2530.           Page := GetPageSize;
  2531.           if FMaxWidth > Page
  2532.           then
  2533.             begin
  2534.              if HScrollBar = nil then ShowHScrollBar;
  2535.              HScrollBar.SetRange(0, FMaxWidth, HScrollBar.Position, Page);
  2536.              HScrollBar.SmallChange := ListBox.Canvas.TextWidth('0');
  2537.              HScrollBar.LargeChange := ListBox.Canvas.TextWidth('0');
  2538.            end
  2539.          else
  2540.           if (HScrollBar <> nil) and HScrollBar.Visible then HideHScrollBar;
  2541.        end
  2542.       else
  2543.         if (HScrollBar <> nil) and HScrollBar.Visible then HideHScrollBar;
  2544.       if not ((FRowCount > 0) and (RowCount = Items.Count))
  2545.       then
  2546.         begin
  2547.           GetScrollRange(ListBox.Handle, SB_VERT, Min, Max);
  2548.           Pos := GetScrollPos(ListBox.Handle, SB_VERT);
  2549.           Page := ListBox.Height div ListBox.ItemHeight;
  2550.           if (Max > Min) and (Pos <= Max) and (Page < Items.Count)
  2551.           then
  2552.             begin
  2553.               if ScrollBar = nil then ShowScrollBar;
  2554.               ScrollBar.SetRange(Min, Max, Pos, Page);
  2555.               ScrollBar.LargeChange := Page; 
  2556.             end
  2557.           else
  2558.             if (ScrollBar <> nil) and ScrollBar.Visible then HideScrollBar;
  2559.         end
  2560.       else
  2561.         if (ScrollBar <> nil) and ScrollBar.Visible then HideScrollBar;
  2562.     end;
  2563. end;
  2564. // combobox
  2565. constructor TspSkinCustomComboBox.Create;
  2566. begin
  2567.   inherited Create(AOwner);
  2568.   ControlStyle := [csCaptureMouse, csOpaque, csDoubleClicks, csAcceptsControls];
  2569.   FAutoComplete := False;
  2570.   FListBoxAlphaBlendAnimation := False;
  2571.   FListBoxAlphaBlend := False;
  2572.   FListBoxAlphaBlendValue := 200;
  2573.   TabStop := True;
  2574.   Font.Name := 'Arial';
  2575.   Font.Color := clWindowText;
  2576.   Font.Style := [];
  2577.   Font.Height := 14;
  2578.   Width := 120;
  2579.   Height := 20;
  2580.   FromEdit := False;
  2581.   FEdit := nil;
  2582.   //
  2583.   FStyle := spcbFixedStyle;
  2584.   FOnListBoxDrawItem := nil;
  2585.   FListBox := TspPopupListBox.Create(Self);
  2586.   FListBox.Visible := False;
  2587.   FlistBox.Parent := Self;
  2588.   FListBox.ListBox.TabStop := False;
  2589.   FlistBox.ListBox.OnMouseDown := ListBoxMouseDown;
  2590.   FlistBox.ListBox.OnMouseMove := ListBoxMouseMove;
  2591.   FlistBox.ListBox.OnMouseUp  := ListBoxMouseUp;
  2592.   FListBoxWindowProc := FlistBox.ListBox.WindowProc;
  2593.   FlistBox.ListBox.WindowProc := ListBoxWindowProcHook;
  2594.   FListBox.OnCheckButtonClick := CheckButtonClick;
  2595.   FLBDown := False;
  2596.   FDropDownCount := 8;
  2597.   //
  2598.   CalcRects;
  2599.   FSkinDataName := 'combobox';
  2600. end;
  2601. destructor TspSkinCustomComboBox.Destroy;
  2602. begin
  2603.   if FEdit <> nil then FEdit.Free;
  2604.   FlistBox.Free;
  2605.   FlistBox := nil;
  2606.   inherited;
  2607. end;
  2608. procedure TspSkinCustomComboBox.FindLBItem(S: String);
  2609. var
  2610.   I: Integer;
  2611.   S1: String;
  2612. begin
  2613.   if (FListBox = nil) or (FListBox.ListBox = nil) then Exit;
  2614.   if FAutoComplete
  2615.   then
  2616.     begin
  2617.       if GetTickCount - FLastTime >= 500 then FFilter := '';
  2618.       FLastTime := GetTickCount;
  2619.       FFilter := FFilter + S;
  2620.       S := FFilter;
  2621.     end;
  2622.   if Length(S) > 0
  2623.   then
  2624.     I := SendMessage(FListBox.ListBox.Handle, LB_FINDSTRING, ItemIndex, LongInt(PChar(S)))
  2625.   else
  2626.     I := -1;
  2627.   if I >= 0 then ItemIndex := I;
  2628. end;
  2629. procedure TspSkinCustomComboBox.KeyPress;
  2630. begin
  2631.   inherited;
  2632.   FindLBItem(Key);
  2633. end;
  2634. function TspSkinCustomComboBox.GetSelStart: Integer;
  2635. begin
  2636.   if (FEdit <> nil) then Result := FEdit.SelStart else Result := 0;
  2637. end;
  2638. procedure TspSkinCustomComboBox.SetSelStart(Value: Integer);
  2639. begin
  2640.   if (FEdit <> nil) then FEdit.SelStart := Value;
  2641. end;
  2642. function TspSkinCustomComboBox.GetSelLength: Integer;
  2643. begin
  2644.   if (FEdit <> nil) then Result := FEdit.SelLength else Result := 0;
  2645. end;
  2646. procedure TspSkinCustomComboBox.SetSelLength(Value: Integer);
  2647. begin
  2648.   if (FEdit <> nil) then FEdit.SelLength := Value;
  2649. end;
  2650. function TspSkinCustomComboBox.GetListBoxUseSkinItemHeight: Boolean;
  2651. begin
  2652.   Result := FListBox.UseSkinItemHeight;
  2653. end;
  2654. procedure TspSkinCustomComboBox.SetListBoxUseSkinItemHeight(Value: Boolean);
  2655. begin
  2656.   FListBox.UseSkinItemHeight := Value;
  2657. end;
  2658. procedure TspSkinCustomComboBox.EditKeyDown;
  2659. begin
  2660.   if Assigned(OnKeyDown) then OnKeyDown(Self, Key, Shift);
  2661. end;
  2662. procedure TspSkinCustomComboBox.EditKeyUp;
  2663. begin
  2664.   if Assigned(OnKeyUp) then OnKeyUp(Self, Key, Shift);
  2665. end;
  2666. procedure TspSkinCustomComboBox.EditKeyPress(Sender: TObject; var Key: Char);
  2667. begin
  2668.   if Assigned(OnKeyPress) then OnKeyPress(Self, Key);
  2669. end;
  2670. procedure TspSkinCustomComboBox.CMEnabledChanged;
  2671. begin
  2672.   inherited;
  2673.   RePaint;
  2674. end;
  2675. function TspSkinCustomComboBox.GetHorizontalExtent: Boolean;
  2676. begin
  2677.   Result := FlistBox.HorizontalExtent;
  2678. end;
  2679. procedure TspSkinCustomComboBox.SetHorizontalExtent(Value: Boolean);
  2680. begin
  2681.   FlistBox.HorizontalExtent := Value;
  2682. end;
  2683. procedure TspSkinCustomComboBox.Change;
  2684. begin
  2685. end;
  2686. procedure TspSkinCustomComboBox.Notification(AComponent: TComponent;
  2687.   Operation: TOperation);
  2688. begin
  2689.   inherited Notification(AComponent, Operation);
  2690.   if (Operation = opRemove) and (AComponent = Images) then
  2691.     Images := nil;
  2692. end;
  2693. function TspSkinCustomComboBox.GetImages: TCustomImageList;
  2694. begin
  2695.   if FListBox <> nil
  2696.   then
  2697.     Result := FListBox.Images
  2698.   else
  2699.     Result := nil;
  2700. end;
  2701. function TspSkinCustomComboBox.GetImageIndex: Integer;
  2702. begin
  2703.   Result := FListBox.ImageIndex;
  2704. end;
  2705. procedure TspSkinCustomComboBox.SetImages(Value: TCustomImageList);
  2706. begin
  2707.   FListBox.Images := Value;
  2708.   RePaint;
  2709. end;
  2710. procedure TspSkinCustomComboBox.SetImageIndex(Value: Integer);
  2711. begin
  2712.   FListBox.ImageIndex := Value;
  2713.   RePaint;
  2714. end;
  2715. procedure TspSkinCustomComboBox.EditCancelMode(C: TControl);
  2716. begin
  2717.   if (C <> Self)and
  2718.      (C <> Self.FListBox) and
  2719.      (C <> Self.FListBox.ScrollBar) and
  2720.      (C <> Self.FListBox.HScrollBar) and
  2721.      (C <> Self.FListBox.ListBox)
  2722.   then
  2723.     CloseUp(False);
  2724. end;
  2725. procedure TspSkinCustomComboBox.CMCancelMode;
  2726. begin
  2727.   inherited;
  2728.   if (Message.Sender <> Self)and
  2729.      (Message.Sender <> Self.FListBox) and
  2730.      (Message.Sender <> Self.FListBox.ScrollBar) and
  2731.      (Message.Sender <> Self.FListBox.HScrollBar) and
  2732.      (Message.Sender <> Self.FListBox.ListBox)
  2733.   then
  2734.     CloseUp(False);
  2735. end;
  2736. function TspSkinCustomComboBox.GetListBoxDefaultFont;
  2737. begin
  2738.   Result := FListBox.DefaultFont;
  2739. end;
  2740. procedure TspSkinCustomComboBox.SetListBoxDefaultFont;
  2741. begin
  2742.   FListBox.DefaultFont.Assign(Value);
  2743. end;
  2744. function TspSkinCustomComboBox.GetListBoxDefaultCaptionFont;
  2745. begin
  2746.   Result := FListBox.DefaultCaptionFont;
  2747. end;
  2748. procedure TspSkinCustomComboBox.SetListBoxDefaultCaptionFont;
  2749. begin
  2750.   FListBox.DefaultCaptionFont.Assign(Value);
  2751. end;
  2752. function TspSkinCustomComboBox.GetListBoxDefaultItemHeight;
  2753. begin
  2754.   Result := FListBox.DefaultItemHeight;
  2755. end;
  2756. procedure TspSkinCustomComboBox.SetListBoxDefaultItemHeight;
  2757. begin
  2758.   FListBox.DefaultItemHeight := Value;
  2759. end;
  2760. function TspSkinCustomComboBox.GetListBoxCaptionAlignment;
  2761. begin
  2762.   Result := FListBox.Alignment;
  2763. end;
  2764. procedure TspSkinCustomComboBox.SetListBoxCaptionAlignment;
  2765. begin
  2766.   FListBox.Alignment := Value;
  2767. end;
  2768. procedure TspSkinCustomComboBox.DefaultFontChange;
  2769. begin
  2770.   Font.Assign(FDefaultFont);
  2771. end;
  2772. procedure TspSkinCustomComboBox.CheckButtonClick;
  2773. begin
  2774.   CloseUp(True);
  2775. end;
  2776. procedure TspSkinCustomComboBox.SetListBoxCaption;
  2777. begin
  2778.   FListBox.Caption := Value;
  2779. end;
  2780. function  TspSkinCustomComboBox.GetListBoxCaption;
  2781. begin
  2782.   Result := FListBox.Caption;
  2783. end;
  2784. procedure TspSkinCustomComboBox.SetListBoxCaptionMode;
  2785. begin
  2786.   FListBox.CaptionMode := Value;
  2787. end;
  2788. function  TspSkinCustomComboBox.GetListBoxCaptionMode;
  2789. begin
  2790.   Result := FListBox.CaptionMode;
  2791. end;
  2792. function TspSkinCustomComboBox.GetSorted: Boolean;
  2793. begin
  2794.   Result := FListBox.Sorted;
  2795. end;
  2796. procedure TspSkinCustomComboBox.SetSorted(Value: Boolean);
  2797. begin
  2798.   FListBox.Sorted := Value;
  2799. end;
  2800. procedure TspSkinCustomComboBox.SetListBoxDrawItem;
  2801. begin
  2802.   FOnListboxDrawItem := Value;
  2803.   FListBox.OnDrawItem := FOnListboxDrawItem;
  2804. end;
  2805. procedure TspSkinCustomComboBox.ListBoxDrawItem(Cnvs: TCanvas; Index: Integer;
  2806.             ItemWidth, ItemHeight: Integer; TextRect: TRect; State: TOwnerDrawState);
  2807. begin
  2808.   if Assigned(FOnListBoxDrawItem)
  2809.   then FOnListBoxDrawItem(Cnvs, Index, ItemWidth, ItemHeight, TextRect, State);
  2810. end;
  2811. procedure TspSkinCustomComboBox.SetStyle;
  2812. begin
  2813.   if (FStyle = Value) and (csDesigning in ComponentState) then Exit;
  2814.   FStyle := Value;
  2815.   case FStyle of
  2816.     spcbFixedStyle:
  2817.       begin
  2818.         TabStop := True;
  2819.         if FEdit <> nil then HideEditor;
  2820.       end;
  2821.     spcbEditStyle:
  2822.       begin
  2823.         TabStop := False;
  2824.         ShowEditor;
  2825.         FEdit.Text := Text; 
  2826.         if Focused then FEdit.SetFocus;
  2827.       end;
  2828.   end;
  2829.   CalcRects;
  2830.   ReCreateWnd;
  2831.   RePaint;
  2832. end;
  2833. procedure TspSkinCustomComboBox.CMWantSpecialKey(var Msg: TCMWantSpecialKey);
  2834. begin
  2835.   inherited;
  2836.   case Msg.CharCode of
  2837.     VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT:  Msg.Result := 1;
  2838.   end;
  2839. end;
  2840. procedure TspSkinCustomComboBox.KeyDown;
  2841. begin
  2842.   inherited KeyDown(Key, Shift);
  2843.   case Key of
  2844.     VK_UP, VK_LEFT:
  2845.       if ssAlt in Shift
  2846.       then
  2847.         begin
  2848.           if FListBox.Visible then CloseUp(False);
  2849.         end
  2850.       else
  2851.         EditUp1(True);
  2852.     VK_DOWN, VK_RIGHT:
  2853.       if ssAlt in Shift
  2854.       then
  2855.         begin
  2856.           if not FListBox.Visible then DropDown;
  2857.         end
  2858.       else
  2859.         EditDown1(True);
  2860.     VK_NEXT: EditPageDown1(True);
  2861.     VK_PRIOR: EditPageUp1(True);
  2862.     VK_ESCAPE: if FListBox.Visible then CloseUp(False);
  2863.     VK_RETURN: if FListBox.Visible then CloseUp(True);
  2864.   end;
  2865. end;
  2866. procedure TspSkinCustomComboBox.WMMOUSEWHEEL;
  2867. begin
  2868.   if FEdit <> nil then Exit;
  2869.   if Message.WParam > 0
  2870.   then
  2871.     EditUp1(not FListBox.Visible)
  2872.   else
  2873.     EditDown1(not FListBox.Visible);
  2874. end;
  2875. procedure TspSkinCustomComboBox.WMSETFOCUS;
  2876. begin
  2877.   if FEdit <> nil
  2878.   then
  2879.     FEDit.SetFocus
  2880.   else
  2881.     begin
  2882.       inherited;
  2883.       RePaint;
  2884.     end;  
  2885. end;
  2886. procedure TspSkinCustomComboBox.WMKILLFOCUS;
  2887. begin
  2888.   inherited;
  2889.   if FListBox.Visible and (FEdit = nil)
  2890.   then CloseUp(False);
  2891.   RePaint;
  2892. end;
  2893. procedure TspSkinCustomComboBox.GetSkinData;
  2894. begin
  2895.   inherited;
  2896.   if FIndex <> -1
  2897.   then
  2898.     if TspDataSkinControl(FSD.CtrlList.Items[FIndex]) is TspDataSkinComboBox
  2899.     then
  2900.       with TspDataSkinComboBox(FSD.CtrlList.Items[FIndex]) do
  2901.       begin
  2902.         Self.SItemRect := SItemRect;
  2903.         Self.FocusItemRect := FocusItemRect;
  2904.         if isNullRect(FocusItemRect)
  2905.         then
  2906.           Self.FocusItemRect := SItemRect;
  2907.         Self.ItemLeftOffset := ItemLeftOffset;
  2908.         Self.ItemRightOffset := ItemRightOffset;
  2909.         Self.ItemTextRect := ItemTextRect;
  2910.         Self.FontName := FontName;
  2911.         Self.FontStyle := FontStyle;
  2912.         Self.FontHeight := FontHeight;
  2913.         Self.FontColor := FontColor;
  2914.         Self.FocusFontColor := FocusFontColor;
  2915.         Self.ButtonRect := ButtonRect;
  2916.         Self.ActiveButtonRect := ActiveButtonRect;
  2917.         Self.DownButtonRect := DownButtonRect;
  2918.         Self.UnEnabledButtonRect := UnEnabledButtonRect;
  2919.         Self.ListBoxName := ListBoxName;
  2920.       end;
  2921. end;
  2922. procedure TspSkinCustomComboBox.Invalidate;
  2923. begin
  2924.   inherited;
  2925.   if (FIndex <> -1) and (FEdit <> nil) then FEdit.Invalidate;
  2926. end;
  2927. function TspSkinCustomComboBox.GetItemIndex;
  2928. begin
  2929.   Result := FListBox.ItemIndex;
  2930. end;
  2931. procedure TspSkinCustomComboBox.SetItemIndex;
  2932. begin
  2933.   FListBox.ItemIndex := Value;
  2934.   if (FListBox.Items.Count > 0) and (FListBox.ItemIndex <> -1)
  2935.   then
  2936.     Text := FListBox.Items[FListBox.ItemIndex];
  2937.   FOldItemIndex := FListBox.ItemIndex;
  2938.   if FEdit = nil then RePaint;
  2939.   if not (csDesigning in ComponentState) and
  2940.      not (csLoading in ComponentState)
  2941.   then
  2942.     begin
  2943.       if Assigned(FOnClick) then FOnClick(Self);
  2944.       Change;
  2945.     end;
  2946. end;
  2947. function TspSkinCustomComboBox.IsPopupVisible: Boolean;
  2948. begin
  2949.   Result := FListBox.Visible;
  2950. end;
  2951. function TspSkinCustomComboBox.CanCancelDropDown;
  2952. begin
  2953.   Result := FListBox.Visible and not FMouseIn;
  2954. end;
  2955. procedure TspSkinCustomComboBox.EditWindowProcHook(var Message: TMessage);
  2956. var
  2957.   FOld: Boolean;
  2958.   Index: Integer;
  2959. begin
  2960.   FOld := True;
  2961.   case Message.Msg of
  2962.     WM_LBUTTONDOWN, WM_RBUTTONDOWN:
  2963.       begin
  2964.         if FListBox.Visible then CloseUp(False);
  2965.       end;
  2966.     WM_KILLFOCUS:
  2967.       begin
  2968.         if FListBox.Visible then CloseUp(False);
  2969.       end;
  2970.     WM_MOUSEWHEEL:
  2971.      begin
  2972.        if Message.WParam > 0
  2973.        then
  2974.          EditUp(not FListBox.Visible)
  2975.        else
  2976.          EditDown(not FListBox.Visible);
  2977.      end;
  2978.     WM_KEYDOWN:
  2979.       begin
  2980.         case TWMKEYDOWN(Message).CharCode of
  2981.           VK_PRIOR:
  2982.             if FListBox.Visible
  2983.             then
  2984.               begin
  2985.                 Index := FListBox.ItemIndex - DropDownCount - 1;
  2986.                 if Index < 0
  2987.                 then
  2988.                   Index := 0;
  2989.                 FListBox.ItemIndex := Index;
  2990.               end;
  2991.           VK_NEXT:
  2992.             if FListBox.Visible
  2993.             then
  2994.               begin
  2995.                 Index := FListBox.ItemIndex + DropDownCount - 1;
  2996.                 if Index > FListBox.Items.Count - 1
  2997.                 then
  2998.                   Index := FListBox.Items.Count - 1;
  2999.                 FListBox.ItemIndex := Index;
  3000.               end;
  3001.           VK_RETURN:
  3002.             begin
  3003.               if FListBox.Visible then CloseUp(True);
  3004.             end;
  3005.           VK_ESCAPE:
  3006.             begin
  3007.               if FListBox.Visible then CloseUp(False);
  3008.             end;
  3009.           VK_UP:
  3010.             begin
  3011.               EditUp(True);
  3012.               FOld := False;
  3013.             end;
  3014.           VK_DOWN:
  3015.             begin
  3016.               EditDown(True);
  3017.               FOld := False;
  3018.             end;
  3019.         end;
  3020.       end;
  3021.   end;
  3022.   if FOld then FEditWindowProc(Message);
  3023. end;
  3024. procedure TspSkinCustomComboBox.ListBoxWindowProcHook(var Message: TMessage);
  3025. var
  3026.   FOld: Boolean;
  3027. begin
  3028.   FOld := True;
  3029.   case Message.Msg of
  3030.      WM_LBUTTONUP:
  3031.        begin
  3032.          CloseUp(True);
  3033.          FOLD := False;
  3034.        end;
  3035.      WM_RBUTTONDOWN, WM_RBUTTONUP,
  3036.      WM_MBUTTONDOWN, WM_MBUTTONUP,
  3037.      WM_LBUTTONDOWN:
  3038.       begin
  3039.          FOLd := False;
  3040.        end;
  3041.      WM_MOUSEACTIVATE:
  3042.       begin
  3043.         Message.Result := MA_NOACTIVATE;
  3044.       end;
  3045.   end;
  3046.   if FOld then FListBoxWindowProc(Message);
  3047. end;
  3048. procedure TspSkinCustomComboBox.CMMouseEnter;
  3049. begin
  3050.   inherited;
  3051.   FMouseIn := True;
  3052. end;
  3053. procedure TspSkinCustomComboBox.CMMouseLeave;
  3054. begin
  3055.   inherited;
  3056.   FMouseIn := False;
  3057.   if Button.MouseIn
  3058.   then
  3059.     begin
  3060.       Button.MouseIn := False;
  3061.       RePaint;
  3062.     end;
  3063. end;
  3064. procedure TspSkinCustomComboBox.SetDropDownCount(Value: Integer);
  3065. begin
  3066.   if Value > 0
  3067.   then
  3068.     FDropDownCount := Value;
  3069. end;
  3070. procedure TspSkinCustomComboBox.ListBoxMouseDown(Sender: TObject; Button: TMouseButton;
  3071.                            Shift: TShiftState; X, Y: Integer);
  3072. begin
  3073.   FLBDown := True;
  3074. end;
  3075. procedure TspSkinCustomComboBox.ListBoxMouseMove(Sender: TObject; Shift: TShiftState;
  3076.                            X, Y: Integer);
  3077. var
  3078.   Index: Integer;
  3079. begin
  3080.   if not FLBDown
  3081.   then
  3082.     begin
  3083.       Index := FListBox.ItemAtPos(Point (X, Y), True);
  3084.       if (Index >= 0) and (Index < Items.Count)
  3085.       then
  3086.         FListBox.ItemIndex := Index;
  3087.     end;
  3088. end;
  3089. procedure TspSkinCustomComboBox.ListBoxMouseUp(Sender: TObject; Button: TMouseButton;
  3090.                          Shift: TShiftState; X, Y: Integer);
  3091. begin
  3092.   FLBDown := False;
  3093.   CloseUp(True);
  3094. end;
  3095. procedure TspSkinCustomComboBox.SetItems;
  3096. begin
  3097.   FListBox.Items.Assign(Value);
  3098. end;
  3099. function TspSkinCustomComboBox.GetItems;
  3100. begin
  3101.   Result := FListBox.Items;
  3102. end;
  3103. procedure TspSkinCustomComboBox.MouseDown;
  3104. begin
  3105.   inherited;
  3106.   if not Focused and (FEdit = nil) then SetFocus;
  3107.   if Button <> mbLeft then Exit;
  3108.   if Self.Button.MouseIn or
  3109.      (PtInRect(CBItem.R, Point(X, Y)) and (FEdit = nil))
  3110.   then
  3111.     begin
  3112.       Self.Button.Down := True;
  3113.       RePaint;
  3114.       if FListBox.Visible then CloseUp(False) else DropDown;
  3115.     end
  3116.   else
  3117.     if FListBox.Visible then CloseUp(False);
  3118. end;
  3119. procedure TspSkinCustomComboBox.MouseUp(Button: TMouseButton; Shift: TShiftState;
  3120.       X, Y: Integer);
  3121. begin
  3122.   inherited;
  3123.   if Self.Button.Down
  3124.   then
  3125.     begin
  3126.       Self.Button.Down := False;
  3127.       RePaint;
  3128.     end;
  3129. end;
  3130. procedure TspSkinCustomComboBox.MouseMove(Shift: TShiftState; X, Y: Integer);
  3131. begin
  3132.   inherited;
  3133.   if PtInRect(Button.R, Point(X, Y)) and not Button.MouseIn
  3134.   then
  3135.     begin
  3136.       Button.MouseIn := True;
  3137.       RePaint;
  3138.     end
  3139.   else
  3140.   if not PtInRect(Button.R, Point(X, Y)) and Button.MouseIn
  3141.   then
  3142.     begin
  3143.       Button.MouseIn := False;
  3144.       RePaint;
  3145.     end;
  3146. end;
  3147. procedure TspSkinCustomComboBox.CloseUp;
  3148. begin
  3149.   if not FListBox.Visible then Exit;
  3150.   FListBox.Hide;
  3151.   if (FListBox.ItemIndex >= 0) and
  3152.      (FListBox.ItemIndex < FListBox.Items.Count) and Value
  3153.   then
  3154.     begin
  3155.       if FEdit <> nil
  3156.       then
  3157.         FEdit.Text := FListBox.Items[FListBox.ItemIndex]
  3158.       else
  3159.         begin
  3160.           Text := FListBox.Items[FListBox.ItemIndex];
  3161.           RePaint;
  3162.         end;
  3163.        if Assigned(FOnClick) then FOnClick(Self);
  3164.        Change;
  3165.      end
  3166.   else
  3167.     FListBox.ItemIndex := FOldItemIndex;
  3168.   if Value
  3169.   then
  3170.     if Assigned(FOnCloseUp) then FOnCloseUp(Self);
  3171. end;
  3172. procedure TspSkinCustomComboBox.DropDown;
  3173. var
  3174.   P: TPoint;
  3175.   WorkArea: TRect;
  3176. begin
  3177.   if Items.Count = 0 then Exit;
  3178.   if Assigned(FOnDropDown) then FOnDropDown(Self);
  3179.   FListBox.Width := Width;
  3180.   if Items.Count < DropDownCount
  3181.   then
  3182.     FListBox.Height := FListBox.CalcHeight(Items.Count)
  3183.   else
  3184.     FListBox.Height := FListBox.CalcHeight(DropDownCount);
  3185.   P := Point(Left, Top + Height);
  3186.   P := Parent.ClientToScreen (P);
  3187.   WorkArea := GetMonitorWorkArea(Handle, True);
  3188.   if P.Y + FListBox.Height > WorkArea.Bottom
  3189.   then
  3190.     P.Y  := P.Y - Height - FListBox.Height;
  3191.   if FEdit <> nil then FEdit.SetFocus;
  3192.   FOldItemIndex := FListBox.ItemIndex;
  3193.   if (FListBox.ItemIndex = 0) and (FListBox.Items.Count > 1)
  3194.   then
  3195.     begin
  3196.       FListBox.ItemIndex := 1;
  3197.       FListBox.ItemIndex := 0;
  3198.     end;
  3199.   FListBox.TopIndex := FListBox.ItemIndex;
  3200.   
  3201.   FListBox.Show(P);
  3202. end;
  3203. procedure TspSkinCustomComboBox.EditPageUp1(AChange: Boolean);
  3204. var
  3205.   Index: Integer;
  3206. begin
  3207.   Index := FListBox.ItemIndex - DropDownCount - 1;
  3208.   if Index < 0 then Index := 0;
  3209.   if AChange
  3210.   then
  3211.     ItemIndex := Index
  3212.   else
  3213.     FListBox.ItemIndex := Index;
  3214. end;
  3215. procedure TspSkinCustomComboBox.EditPageDown1(AChange: Boolean);
  3216. var
  3217.   Index: Integer;
  3218. begin
  3219.   Index := FListBox.ItemIndex + DropDownCount - 1;
  3220.   if Index > FListBox.Items.Count - 1
  3221.   then
  3222.     Index := FListBox.Items.Count - 1;
  3223.   if AChange
  3224.   then
  3225.     ItemIndex := Index
  3226.   else
  3227.     FListBox.ItemIndex := Index;
  3228. end;
  3229. procedure TspSkinCustomComboBox.EditUp1;
  3230. begin
  3231.   if FListBox.ItemIndex > 0
  3232.   then
  3233.     begin
  3234.       if AChange
  3235.       then
  3236.         ItemIndex := ItemIndex - 1
  3237.       else
  3238.         FListBox.ItemIndex := FListBox.ItemIndex - 1;
  3239.     end;
  3240. end;
  3241. procedure TspSkinCustomComboBox.EditDown1;
  3242. begin
  3243.   if FListBox.ItemIndex < FListBox.Items.Count - 1
  3244.   then
  3245.     begin
  3246.       if AChange
  3247.       then
  3248.         ItemIndex := ItemIndex + 1
  3249.       else
  3250.         FListBox.ItemIndex := FListBox.ItemIndex + 1;
  3251.     end;    
  3252. end;
  3253. procedure TspSkinCustomComboBox.EditUp;
  3254. begin
  3255.   if FListBox.ItemIndex > 0
  3256.   then
  3257.     begin
  3258.       FListBox.ItemIndex := FListBox.ItemIndex - 1;
  3259.       if AChange
  3260.       then
  3261.         begin
  3262.           Text := FListBox.Items[FListBox.ItemIndex];
  3263.           if Assigned(FOnClick) then FOnClick(Self); 
  3264.         end;
  3265.     end;
  3266. end;
  3267. procedure TspSkinCustomComboBox.EditDown;
  3268. begin
  3269.   if FListBox.ItemIndex < FListBox.Items.Count - 1
  3270.   then
  3271.     begin
  3272.       FListBox.ItemIndex := FListBox.ItemIndex + 1;
  3273.       if AChange
  3274.       then
  3275.         begin
  3276.           Text := FListBox.Items[FListBox.ItemIndex];
  3277.           if Assigned(FOnClick) then FOnClick(Self);
  3278.         end;
  3279.     end;
  3280. end;
  3281. procedure TspSkinCustomComboBox.EditChange(Sender: TObject);
  3282. var
  3283.   I: Integer;
  3284. begin
  3285.   FromEdit := True;
  3286.   if (FListBox <> nil) and (FEdit.Text <> '')
  3287.   then
  3288.     begin
  3289.       I := SendMessage(FListBox.ListBox.Handle, LB_FINDSTRING, -1, LongInt(PChar(FEdit.Text)));
  3290.       if I >= 0
  3291.       then
  3292.         if FAutoComplete
  3293.         then
  3294.           SendMessage(FListBox.ListBox.Handle, LB_SETCURSEL, I, 0)
  3295.         else
  3296.           SendMessage(FListBox.ListBox.Handle, LB_SETTOPINDEX, I, 0);
  3297.     end;
  3298.   Text := FEdit.Text;
  3299.   FromEdit := False;  
  3300. end;
  3301. procedure TspSkinCustomComboBox.ShowEditor;
  3302. begin
  3303.   FEdit := TspCustomEdit.Create(Self);
  3304.   FEdit.Parent := Self;
  3305.   FEdit.AutoSize := False;
  3306.   FEdit.Visible := True;
  3307.   FEdit.EditTransparent := False;
  3308.   FEditWindowProc := FEdit.WindowProc;
  3309.   FEdit.WindowProc := EditWindowProcHook;
  3310.   FEdit.OnEditCancelMode := EditCancelMode;
  3311.   FEdit.OnChange := EditChange;
  3312.   FEdit.OnKeyDown := EditKeyDown;
  3313.   FEdit.OnKeyPress := EditKeyPress;
  3314.   FEdit.OnKeyUp := EditKeyUp;
  3315.   //
  3316.   if FIndex <> -1
  3317.   then
  3318.     with FEdit.Font do
  3319.     begin
  3320.       Style := FontStyle;
  3321.       Color := FontColor;
  3322.       Height := FontHeight;
  3323.       Name := FontName;
  3324.     end
  3325.   else
  3326.     with FEdit.Font do
  3327.     begin
  3328.       Name := Self.Font.Name;
  3329.       Style := Self.Font.Style;
  3330.       Color := Self.Font.Color;
  3331.       Height := Self.Font.Height;
  3332.     end;
  3333.     if FIndex <> -1
  3334.     then FEdit.EditTransparent := True
  3335.     else FEdit.EditTransparent := False;
  3336.   //
  3337.   CalcRects;
  3338. end;
  3339. procedure TspSkinCustomComboBox.HideEditor;
  3340. begin
  3341.   FEdit.Visible := False;
  3342.   FEdit.Free;
  3343.   FEdit := nil;
  3344. end;
  3345. procedure TspSkinCustomComboBox.CMTextChanged;
  3346. begin
  3347.   inherited;
  3348.   if (FEdit <> nil) and not FromEdit then FEdit.Text := Text;
  3349.   if Assigned(FOnChange) then FOnChange(Self);
  3350.   if FromEdit then Change;
  3351. end;
  3352. procedure TspSkinCustomComboBox.WMSIZE;
  3353. begin
  3354.   inherited;
  3355.   CalcRects;
  3356. end;
  3357. procedure TspSkinCustomComboBox.DrawDefaultItem;
  3358. var
  3359.   Buffer: TBitMap;
  3360.   R, R1: TRect;
  3361.   Index, IIndex, IX, IY: Integer;
  3362. begin
  3363.   if RectWidth(CBItem.R) <=0 then Exit;
  3364.   Buffer := TBitMap.Create;
  3365.   Buffer.Width := RectWidth(CBItem.R);
  3366.   Buffer.Height := RectHeight(CBItem.R);
  3367.   R := Rect(0, 0, Buffer.Width, Buffer.Height);
  3368.   with Buffer.Canvas do
  3369.   begin
  3370.     Font.Name := Self.Font.Name;
  3371.     Font.Style := Self.Font.Style;
  3372.     Font.Height := Self.Font.Height;
  3373.     if Focused
  3374.     then
  3375.       begin
  3376.         Brush.Color := clHighLight;
  3377.         Font.Color := clHighLightText;
  3378.       end
  3379.     else
  3380.       begin
  3381.         Brush.Color := clWindow;
  3382.         Font.Color := clWindowText;
  3383.       end;
  3384.     FillRect(R);
  3385.   end;
  3386.   if FListBox.Visible
  3387.   then Index := FOldItemIndex
  3388.   else Index := FListBox.ItemIndex;
  3389.   CBItem.State := [];
  3390.   if Focused then CBItem.State := [odFocused];
  3391.   R1 := Rect(R.Left + 2, R.Top, R.Right - 2, R.Bottom);
  3392.   if (Index > -1) and (Index < FListBox.Items.Count)
  3393.   then
  3394.     if Assigned(FOnComboBoxDrawItem)
  3395.     then
  3396.       FOnComboBoxDrawItem(Buffer.Canvas, Index, Buffer.Width, Buffer.Height,
  3397.                           R1, CBItem.State)
  3398.     else
  3399.       begin
  3400.         if Images <> nil
  3401.         then
  3402.           begin
  3403.             if ImageIndex > -1
  3404.             then IIndex := ImageIndex
  3405.             else IIndex := Index;
  3406.             if IIndex < Images.Count
  3407.             then
  3408.               begin
  3409.                 IX := R1.Left;
  3410.                 IY := R1.Top + RectHeight(R1) div 2 - Images.Height div 2;
  3411.                 Images.Draw(Buffer.Canvas, IX, IY, IIndex);
  3412.               end;
  3413.             Inc(R1.Left, Images.Width + 2);
  3414.           end;
  3415.         SPDrawText(Buffer.Canvas, FListBox.Items[Index], R1);
  3416.       end;
  3417.   if Focused then DrawFocusRect(Buffer.Canvas.Handle, R);
  3418.   Cnvs.Draw(CBItem.R.Left, CBItem.R.Top, Buffer);
  3419.   Buffer.Free;
  3420. end;
  3421. procedure TspSkinCustomComboBox.DrawSkinItem;
  3422. var
  3423.   Buffer: TBitMap;
  3424.   R, R2: TRect;
  3425.   W, H: Integer;
  3426.   Index, IIndex, IX, IY: Integer;
  3427. begin
  3428.   W := RectWidth(CBItem.R);
  3429.   if W <= 0 then Exit;
  3430.   H := RectHeight(SItemRect);
  3431.   if H = 0 then H := RectHeight(FocusItemRect);
  3432.   if H = 0 then H := RectWidth(CBItem.R);
  3433.   Buffer := TBitMap.Create;
  3434.   if Focused
  3435.   then
  3436.     begin
  3437.       if not IsNullRect(FocusItemRect)
  3438.       then
  3439.         CreateHSkinImage(ItemLeftOffset, ItemRightOffset, Buffer, Picture,
  3440.           FocusItemRect, W, H)
  3441.       else
  3442.         begin
  3443.           Buffer.Width := W;
  3444.           BUffer.Height := H;
  3445.           Buffer.Canvas.CopyRect(Rect(0, 0, W, H), Cnvs, CBItem.R);
  3446.         end;
  3447.     end
  3448.   else
  3449.     begin
  3450.       if not IsNullRect(SItemRect)
  3451.       then
  3452.         CreateHSkinImage(ItemLeftOffset, ItemRightOffset, Buffer, Picture,
  3453.           SItemRect, W, H)
  3454.       else
  3455.         begin
  3456.           Buffer.Width := W;
  3457.           BUffer.Height := H;
  3458.           Buffer.Canvas.CopyRect(Rect(0, 0, W, H), Cnvs, CBItem.R);
  3459.         end;
  3460.     end;
  3461.   R := ItemTextRect;
  3462.   if not IsNullRect(SItemRect)
  3463.   then
  3464.     Inc(R.Right, W - RectWidth(SItemRect))
  3465.   else
  3466.     Inc(R.Right, W - RectWidth(ClRect));
  3467.   with Buffer.Canvas do
  3468.   begin
  3469.     if FUseSkinFont
  3470.     then
  3471.       begin
  3472.         Font.Name := FontName;
  3473.         Font.Style := FontStyle;
  3474.         Font.Height := FontHeight;
  3475.         Font.CharSet := FDefaultFont.CharSet;
  3476.       end
  3477.     else
  3478.       Font.Assign(FDefaultFont);
  3479.     if Focused
  3480.     then
  3481.       Font.Color := FocusFontColor
  3482.     else
  3483.       Font.Color := FontColor;
  3484.     Brush.Style := bsClear;
  3485.   end;
  3486.   if FListBox.Visible
  3487.   then Index := FOldItemIndex
  3488.   else Index := FListBox.ItemIndex;
  3489.   if (Index > -1) and (Index < FListBox.Items.Count)
  3490.   then
  3491.     if Assigned(FOnComboBoxDrawItem)
  3492.     then
  3493.       FOnComboBoxDrawItem(Buffer.Canvas, Index, Buffer.Width, Buffer.Height,
  3494.                           R, CBItem.State)
  3495.     else
  3496.       begin
  3497.         if Images <> nil
  3498.         then
  3499.           begin
  3500.             if ImageIndex > -1
  3501.             then IIndex := ImageIndex
  3502.             else IIndex := Index;
  3503.             if IIndex < Images.Count
  3504.             then
  3505.               begin
  3506.                 IX := R.Left;
  3507.                 IY := R.Top + RectHeight(R) div 2 - Images.Height div 2;
  3508.                 Images.Draw(Buffer.Canvas, IX, IY, IIndex);
  3509.               end;
  3510.             Inc(R.Left, Images.Width + 2);
  3511.           end;
  3512.         SPDrawText(Buffer.Canvas, FListBox.Items[Index], R);
  3513.       end;
  3514.   Cnvs.Draw(CBItem.R.Left, CBItem.R.Top, Buffer);
  3515.   Buffer.Free;
  3516. end;
  3517. procedure TspSkinCustomComboBox.DrawButton;
  3518. var
  3519.   ArrowColor: TColor;
  3520.   R1: TRect;
  3521. begin
  3522.   if FIndex = -1
  3523.   then
  3524.     with Button do
  3525.     begin
  3526.       R1 := R;  
  3527.       if Down and MouseIn
  3528.       then
  3529.         begin
  3530.           Frame3D(C, R1, SP_XP_BTNFRAMECOLOR, SP_XP_BTNFRAMECOLOR, 1);
  3531.           C.Brush.Color := SP_XP_BTNDOWNCOLOR;
  3532.           C.FillRect(R1);
  3533.         end
  3534.       else
  3535.         if MouseIn
  3536.         then
  3537.           begin
  3538.             Frame3D(C, R1, SP_XP_BTNFRAMECOLOR, SP_XP_BTNFRAMECOLOR, 1);
  3539.             C.Brush.Color := SP_XP_BTNACTIVECOLOR;
  3540.             C.FillRect(R1);
  3541.           end
  3542.         else
  3543.           begin
  3544.             Frame3D(C, R1, clBtnShadow, clBtnShadow, 1);
  3545.             C.Brush.Color := clBtnFace;
  3546.             C.FillRect(R1);
  3547.           end;
  3548.       if Enabled
  3549.       then
  3550.         ArrowColor := clBlack
  3551.       else
  3552.         ArrowColor := clBtnShadow;
  3553.       DrawArrowImage(C, R, ArrowColor, 4);
  3554.     end
  3555.   else
  3556.     with Button do
  3557.     begin
  3558.       R1 := NullRect;
  3559.       if not Enabled and not IsNullRect(UnEnabledButtonRect)
  3560.       then
  3561.         R1 := UnEnabledButtonRect
  3562.       else
  3563.       if Down and MouseIn
  3564.       then R1 := DownButtonRect
  3565.       else if MouseIn then R1 := ActiveButtonRect;
  3566.       if not IsNullRect(R1)
  3567.       then
  3568.         C.CopyRect(R, Picture.Canvas, R1);
  3569.     end;
  3570. end;
  3571. procedure TspSkinCustomComboBox.CalcRects;
  3572. const
  3573.   BW = 17;
  3574. var
  3575.   OX: Integer;
  3576. begin
  3577.   if FIndex = -1
  3578.   then
  3579.     begin
  3580.       Button.R := Rect(Width - BW - 2, 2, Width - 2, Height - 2);
  3581.       CBItem.R := Rect(2, 2, Button.R.Left - 1 , Height -  2);
  3582.     end
  3583.   else
  3584.     begin
  3585.       OX := Width - RectWidth(SkinRect);
  3586.       Button.R := ButtonRect;
  3587.       if ButtonRect.Left >= RectWidth(SkinRect) - RTPt.X
  3588.       then
  3589.         OffsetRect(Button.R, OX, 0);
  3590.       CBItem.R := ClRect;
  3591.       Inc(CBItem.R.Right, OX);
  3592.     end;
  3593.   if FEdit <> nil
  3594.   then
  3595.     begin
  3596.       FEdit.Left := CBItem.R.Left;
  3597.       FEdit.Top := CBItem.R.Top;
  3598.       FEdit.Width := RectWidth(CBItem.R);
  3599.       FEdit.Height := RectHeight(CBItem.R);
  3600.     end;
  3601. end;
  3602. procedure TspSkinCustomComboBox.ChangeSkinData;
  3603. begin
  3604.   inherited;
  3605.   CalcRects;
  3606.   if FEdit <> nil
  3607.   then
  3608.     begin
  3609.       if FIndex <> -1
  3610.       then
  3611.         with FEdit.Font do
  3612.         begin
  3613.           Style := FontStyle;
  3614.           Color := FontColor;
  3615.           Height := FontHeight;
  3616.           Name := FontName;
  3617.           CharSet := FDefaultFont.CharSet;
  3618.         end
  3619.       else
  3620.         FEdit.Font.Assign(FDefaultFont);
  3621.       if FIndex <> -1
  3622.       then FEdit.EditTransparent := True
  3623.       else FEdit.EditTransparent := False;
  3624.     end;
  3625.   RePaint;
  3626.     
  3627.   if FIndex = -1
  3628.   then
  3629.     begin
  3630.       FListBox.SkinDataName := '';
  3631.     end  
  3632.   else
  3633.     FListBox.SkinDataName := ListBoxName;
  3634.   FListBox.SkinData := SkinData;
  3635.   //
  3636. end;
  3637. procedure TspSkinCustomComboBox.CreateControlDefaultImage;
  3638. var
  3639.   R: TRect;
  3640. begin
  3641.   CalcRects;
  3642.   with B.Canvas do
  3643.   begin
  3644.     Brush.Color := clBtnFace;
  3645.     R := ClientRect;
  3646.     FillRect(R);
  3647.   end;
  3648.   Frame3D(B.Canvas, R, clbtnShadow, clbtnShadow, 1);
  3649.   DrawButton(B.Canvas);
  3650.   if FEdit = nil then  DrawDefaultItem(B.Canvas);
  3651. end;
  3652. procedure TspSkinCustomComboBox.CreateControlSkinImage;
  3653. begin
  3654.   CalcRects;
  3655.   inherited;
  3656.   DrawButton(B.Canvas);
  3657.   if FEdit = nil then DrawSkinItem(B.Canvas);
  3658. end;
  3659. // ==================== TspSkinFontComboBox ======================= //
  3660. const
  3661.   WRITABLE_FONTTYPE = 256;
  3662. function IsValidFont(Box: TspSkinFontComboBox; LogFont: TLogFont;
  3663.   FontType: Integer): Boolean;
  3664. begin
  3665.   Result := True;
  3666.   if (foAnsiOnly in Box.Options) then
  3667.     Result := Result and (LogFont.lfCharSet = ANSI_CHARSET);
  3668.   if (foTrueTypeOnly in Box.Options) then
  3669.     Result := Result and (FontType and TRUETYPE_FONTTYPE = TRUETYPE_FONTTYPE);
  3670.   if (foFixedPitchOnly in Box.Options) then
  3671.     Result := Result and (LogFont.lfPitchAndFamily and FIXED_PITCH = FIXED_PITCH);
  3672.   if (foOEMFontsOnly in Box.Options) then
  3673.     Result := Result and (LogFont.lfCharSet = OEM_CHARSET);
  3674.   if (foNoOEMFonts in Box.Options) then
  3675.     Result := Result and (LogFont.lfCharSet <> OEM_CHARSET);
  3676.   if (foNoSymbolFonts in Box.Options) then
  3677.     Result := Result and (LogFont.lfCharSet <> SYMBOL_CHARSET);
  3678.   if (foScalableOnly in Box.Options) then
  3679.     Result := Result and (FontType and RASTER_FONTTYPE = 0);
  3680. end;
  3681. function EnumFontsProc(var EnumLogFont: TEnumLogFont;
  3682.   var TextMetric: TNewTextMetric; FontType: Integer; Data: LPARAM): Integer;
  3683.   export; stdcall;
  3684. var
  3685.   FaceName: string;
  3686. begin
  3687.   FaceName := StrPas(EnumLogFont.elfLogFont.lfFaceName);
  3688.   with TspSkinFontComboBox(Data) do
  3689.     if (Items.IndexOf(FaceName) < 0) and
  3690.       IsValidFont(TspSkinFontComboBox(Data), EnumLogFont.elfLogFont, FontType) then
  3691.     begin
  3692.       if EnumLogFont.elfLogFont.lfCharSet <> SYMBOL_CHARSET then
  3693.         FontType := FontType or WRITABLE_FONTTYPE;
  3694.       Items.AddObject(FaceName, TObject(FontType));
  3695.     end;
  3696.   Result := 1;
  3697. end;
  3698. constructor TspSkinFontComboBox.Create(AOwner: TComponent);
  3699. begin
  3700.   inherited Create(AOwner);
  3701.   OnListBoxDrawItem := DrawLBFontItem;
  3702.   OnComboBoxDrawItem := DrawCBFontItem;
  3703.   FDevice := fdScreen;
  3704.   Sorted := True;
  3705. end;
  3706. procedure TspSkinFontComboBox.DrawTT;
  3707. begin
  3708.   with Cnvs do
  3709.   begin
  3710.     Pen.Color := C;
  3711.     MoveTo(X, Y);
  3712.     LineTo(X + 7, Y);
  3713.     LineTo(X + 7, Y + 3);
  3714.     MoveTo(X, Y);
  3715.     LineTo(X, Y + 3);
  3716.     MoveTo(X + 1, Y);
  3717.     LineTo(X + 1, Y + 1);
  3718.     MoveTo(X + 6, Y);
  3719.     LineTo(X + 6, Y + 1);
  3720.     MoveTo(X + 3, Y);
  3721.     LineTo(X + 3, Y + 8);
  3722.     MoveTo(X + 4, Y);
  3723.     LineTo(X + 4, Y + 8);
  3724.     MoveTo(X + 2, Y + 8);
  3725.     LineTo(X + 6, Y + 8);
  3726.   end;
  3727. end;
  3728. procedure TspSkinFontComboBox.Reset;
  3729. var
  3730.   SaveName: TFontName;
  3731. begin
  3732.   if HandleAllocated then begin
  3733.     FUpdate := True;
  3734.     try
  3735.       SaveName := FontName;
  3736.       PopulateList;
  3737.       FontName := SaveName;
  3738.     finally
  3739.       FUpdate := False;
  3740.       if FontName <> SaveName
  3741.       then
  3742.         begin
  3743.           if not (csReading in ComponentState) then
  3744.           if not FUpdate and Assigned(FOnChange) then FOnChange(Self);
  3745.         end;
  3746.     end;
  3747.   end;
  3748. end;
  3749. procedure TspSkinFontComboBox.WMFontChange(var Message: TMessage);
  3750. begin
  3751.   inherited;
  3752.   Reset;
  3753. end;
  3754. procedure TspSkinFontComboBox.SetFontName(const NewFontName: TFontName);
  3755. var
  3756.   Item: Integer;
  3757. begin
  3758.   if FontName <> NewFontName then begin
  3759.     if not (csLoading in ComponentState) then begin
  3760.       HandleNeeded;
  3761.       { change selected item }
  3762.       for Item := 0 to Items.Count - 1 do
  3763.         if AnsiCompareText(Items[Item], NewFontName) = 0 then begin
  3764.           ItemIndex := Item;
  3765.           //
  3766.           if not (csReading in ComponentState) then
  3767.             if not FUpdate and Assigned(FOnChange) then FOnChange(Self);
  3768.           //
  3769.           Exit;
  3770.         end;
  3771.       if Style = spcbFixedStyle then ItemIndex := -1
  3772.       else Text := NewFontName;
  3773.     end
  3774.     else inherited Text := NewFontName;
  3775.     //
  3776.     if not (csReading in ComponentState) then
  3777.     if not FUpdate and Assigned(FOnChange) then FOnChange(Self);
  3778.     //
  3779.   end;
  3780. end;
  3781. function TspSkinFontComboBox.GetFontName: TFontName;
  3782. begin
  3783.   Result := inherited Text;
  3784. end;
  3785. function TspSkinFontComboBox.GetTrueTypeOnly: Boolean;
  3786. begin
  3787.   Result := foTrueTypeOnly in FOptions;
  3788. end;
  3789. procedure TspSkinFontComboBox.SetOptions;
  3790. begin
  3791.   if Value <> Options then begin
  3792.     FOptions := Value;
  3793.     Reset;
  3794.   end;
  3795. end;
  3796. procedure TspSkinFontComboBox.SetTrueTypeOnly(Value: Boolean);
  3797. begin
  3798.   if Value <> TrueTypeOnly then begin
  3799.     if Value then FOptions := FOptions + [foTrueTypeOnly]
  3800.     else FOptions := FOptions - [foTrueTypeOnly];
  3801.     Reset;
  3802.   end;
  3803. end;
  3804. procedure TspSkinFontComboBox.SetDevice;
  3805. begin
  3806.   if Value <> FDevice then begin
  3807.     FDevice := Value;
  3808.     Reset;
  3809.   end;
  3810. end;
  3811. procedure TspSkinFontComboBox.SetUseFonts(Value: Boolean);
  3812. begin
  3813.   if Value <> FUseFonts then begin
  3814.     FUseFonts := Value;
  3815.     Invalidate;
  3816.   end;
  3817. end;
  3818. procedure TspSkinFontComboBox.DrawCBFontItem;
  3819. var
  3820.   FName: array[0..255] of Char;
  3821.   R: TRect;
  3822. begin
  3823.   R := TextRect;
  3824.   R.Left := R.Left + 2;
  3825.   with Cnvs do
  3826.   begin
  3827.     StrPCopy(FName, Items[Index]);
  3828.     SPDrawText(Cnvs, FName, R);
  3829.   end;
  3830. end;
  3831. procedure TspSkinFontComboBox.DrawLBFontItem;
  3832. var
  3833.   FName: array[0..255] of Char;
  3834.   R: TRect;
  3835.   X, Y: Integer;
  3836. begin
  3837.   R := TextRect;
  3838.   if (Integer(Items.Objects[Index]) and TRUETYPE_FONTTYPE) <> 0
  3839.   then
  3840.     begin
  3841.       X := TextRect.Left;
  3842.       Y := TextRect.Top + RectHeight(TextRect) div 2 - 7;
  3843.       DrawTT(Cnvs, X, Y, clGray);
  3844.       DrawTT(Cnvs, X + 4, Y + 4, clBlack);
  3845.     end;
  3846.   Inc(R.Left, 15);
  3847.   with Cnvs do
  3848.   begin
  3849.     Font.Name := Items[Index];
  3850.     Font.Style := [];
  3851.     StrPCopy(FName, Items[Index]);
  3852.     SPDrawText(Cnvs, Items[Index], R);
  3853.   end;
  3854. end;
  3855. procedure TspSkinFontComboBox.PopulateList;
  3856. var
  3857.   DC: HDC;
  3858.   Proc: TFarProc;
  3859.   FOldItemIndex: Integer;
  3860. begin
  3861.   if not HandleAllocated then Exit;
  3862.   FOldItemIndex := ItemIndex;
  3863.   Items.BeginUpdate;
  3864.   try
  3865.     Items.Clear;
  3866.     DC := GetDC(0);
  3867.     try
  3868.       if (FDevice = fdScreen) or (FDevice = fdBoth) then
  3869.         EnumFontFamilies(DC, nil, @EnumFontsProc, Longint(Self));
  3870.       if (FDevice = fdPrinter) or (FDevice = fdBoth) then
  3871.       try
  3872.         EnumFontFamilies(Printer.Handle, nil, @EnumFontsProc, Longint(Self));
  3873.       except
  3874.         { skip any errors }
  3875.       end;
  3876.     finally
  3877.       ReleaseDC(0, DC);
  3878.     end;
  3879.   finally
  3880.     Items.EndUpdate;
  3881.   end;
  3882.   ItemIndex := FOldItemIndex;
  3883. end;
  3884. procedure TspSkinFontComboBox.CreateWnd;
  3885. var
  3886.   OldFont: TFontName;
  3887. begin
  3888.   OldFont := FontName;
  3889.   inherited CreateWnd;
  3890.   FUpdate := True;
  3891.   try
  3892.     PopulateList;
  3893.     inherited Text := '';
  3894.     SetFontName(OldFont);
  3895.   finally
  3896.     FUpdate := False;
  3897.   end;
  3898. //  if AnsiCompareText(FontName, OldFont) <> 0 then DoChange;
  3899. end;
  3900. // ==================== TspSkinColorComboBox ======================= //
  3901. const
  3902.   SColorBoxCustomCaption = 'Custom...';
  3903.   NoColorSelected = TColor($FF000000);
  3904.   StandardColorsCount = 16;
  3905.   ExtendedColorsCount = 4;
  3906. constructor TspSkinColorComboBox.Create(AOwner: TComponent);
  3907. begin
  3908.   inherited Create(AOwner);
  3909.   Style := spcbFixedStyle;
  3910.   FExStyle := [spcbStandardColors, spcbExtendedColors, spcbSystemColors];
  3911.   FSelectedColor := clBlack;
  3912.   FDefaultColorColor := clBlack;
  3913.   FNoneColorColor := clBlack;
  3914.   OnListBoxDrawItem := DrawColorItem;
  3915.   OnComboBoxDrawItem := DrawColorItem;
  3916.   OnCloseUp := OnLBCloseUp;
  3917.   FShowNames := True;
  3918. end;
  3919. procedure TspSkinColorComboBox.SetShowNames(Value: Boolean);
  3920. begin
  3921.   FShowNames := Value;
  3922.   RePaint;
  3923. end;
  3924. procedure TspSkinColorComboBox.DrawColorItem;
  3925. var
  3926.   R: TRect;
  3927.   MarkerRect: TRect;
  3928. begin
  3929.   if FShowNames
  3930.   then
  3931.     MarkerRect := Rect(TextRect.Left + 1, TextRect.Top + 1,
  3932.       TextRect.Left + RectHeight(TextRect) - 1, TextRect.Bottom - 1)
  3933.   else
  3934.     MarkerRect := Rect(TextRect.Left + 1, TextRect.Top + 1,
  3935.       TextRect.Right - 1, TextRect.Bottom - 1);
  3936.   with Cnvs do
  3937.   begin
  3938.     Brush.Style := bsSolid;
  3939.     Brush.Color := Colors[Index];
  3940.     FillRect(MarkerRect);
  3941.     Brush.Style := bsClear;
  3942.   end;
  3943.   if FShowNames
  3944.   then
  3945.     begin
  3946.       R := TextRect;
  3947.       R := Rect(R.Left + 5 + RectWidth(MarkerRect), R.Top, R.Right - 2, R.Bottom);
  3948.       SPDrawText(Cnvs, FListBox.Items[Index], R);
  3949.     end;
  3950. end;
  3951. procedure TspSkinColorComboBox.OnLBCloseUp;
  3952. begin
  3953.   if (spcbCustomColor in ExStyle) and (ItemIndex = 0) then
  3954.    PickCustomColor;
  3955. end;
  3956. function TspSkinColorComboBox.PickCustomColor: Boolean;
  3957. var
  3958.   LColor: TColor;
  3959. begin
  3960.   with TspSkinColorDialog.Create(nil) do
  3961.     try
  3962.       SkinData := Self.SkinData;
  3963.       CtrlSkinData := Self.SkinData;
  3964.       LColor := ColorToRGB(TColor(Items.Objects[0]));
  3965.       Color := LColor;
  3966.       Result := Execute;
  3967.       if Result then
  3968.       begin
  3969.         Items.Objects[0] := TObject(Color);
  3970.         Self.Invalidate;
  3971.         if Assigned(FOnClick) then FOnClick(Self);
  3972.         if Assigned(FOnChange) then FOnChange(Self);
  3973.       end;
  3974.     finally
  3975.       Free;
  3976.     end;
  3977. end;
  3978. procedure TspSkinColorComboBox.KeyDown;
  3979. begin
  3980.   if (spcbCustomColor in ExStyle) and (Key = VK_RETURN) and (ItemIndex = 0)
  3981.   then
  3982.   begin
  3983.     PickCustomColor;
  3984.     Key := 0;
  3985.   end;
  3986.   inherited;
  3987. end;
  3988. procedure TspSkinColorComboBox.CreateWnd;
  3989. begin
  3990.   inherited;
  3991.   PopulateList;
  3992. end;
  3993. procedure TspSkinColorComboBox.SetDefaultColorColor(const Value: TColor);
  3994. begin
  3995.   if Value <> FDefaultColorColor then
  3996.   begin
  3997.     FDefaultColorColor := Value;
  3998.     Invalidate;
  3999.   end;
  4000. end;
  4001. procedure TspSkinColorComboBox.SetNoneColorColor(const Value: TColor);
  4002. begin
  4003.   if Value <> FNoneColorColor then
  4004.   begin
  4005.     FNoneColorColor := Value;
  4006.     Invalidate;
  4007.   end;
  4008. end;
  4009. procedure TspSkinColorComboBox.ColorCallBack(const AName: String);
  4010. var
  4011.   I, LStart: Integer;
  4012.   LColor: TColor;
  4013.   LName: string;
  4014. begin
  4015.   LColor := StringToColor(AName);
  4016.   if spcbPrettyNames in ExStyle then
  4017.   begin
  4018.     if Copy(AName, 1, 2) = 'cl' then
  4019.       LStart := 3
  4020.     else
  4021.       LStart := 1;
  4022.     LName := '';
  4023.     for I := LStart to Length(AName) do
  4024.     begin
  4025.       case AName[I] of
  4026.         'A'..'Z':
  4027.           if LName <> '' then
  4028.             LName := LName + ' ';
  4029.       end;
  4030.       LName := LName + AName[I];
  4031.     end;
  4032.   end
  4033.   else
  4034.     LName := AName;
  4035.   Items.AddObject(LName, TObject(LColor));
  4036. end;
  4037. procedure TspSkinColorComboBox.SetSelected(const AColor: TColor);
  4038. var
  4039.   I: Integer;
  4040. begin
  4041.   if HandleAllocated and (FListBox <> nil) then
  4042.   begin
  4043.     I := FListBox.Items.IndexOfObject(TObject(AColor));
  4044.     if (I = -1) and (spcbCustomColor in ExStyle) and (AColor <> NoColorSelected) then
  4045.     begin
  4046.       Items.Objects[0] := TObject(AColor);
  4047.       I := 0;
  4048.     end;
  4049.     ItemIndex := I;
  4050.   end;
  4051.   FSelectedColor := AColor;
  4052. end;
  4053. procedure TspSkinColorComboBox.PopulateList;
  4054.   procedure DeleteRange(const AMin, AMax: Integer);
  4055.   var
  4056.     I: Integer;
  4057.   begin
  4058.     for I := AMax downto AMin do
  4059.       Items.Delete(I);
  4060.   end;
  4061.   procedure DeleteColor(const AColor: TColor);
  4062.   var
  4063.     I: Integer;
  4064.   begin
  4065.     I := Items.IndexOfObject(TObject(AColor));
  4066.     if I <> -1 then
  4067.       Items.Delete(I);
  4068.   end;
  4069. var
  4070.   LSelectedColor, LCustomColor: TColor;
  4071. begin
  4072.   if HandleAllocated then
  4073.   begin
  4074.     Items.BeginUpdate;
  4075.     try
  4076.       LCustomColor := clBlack;
  4077.       if (spcbCustomColor in ExStyle) and (Items.Count > 0) then
  4078.         LCustomColor := TColor(Items.Objects[0]);
  4079.       LSelectedColor := FSelectedColor;
  4080.       Items.Clear;
  4081.       GetColorValues(ColorCallBack);
  4082.       if not (spcbIncludeNone in ExStyle) then
  4083.         DeleteColor(clNone);
  4084.       if not (spcbIncludeDefault in ExStyle) then
  4085.         DeleteColor(clDefault);
  4086.       if not (spcbSystemColors in ExStyle) then
  4087.         DeleteRange(StandardColorsCount + ExtendedColorsCount, Items.Count - 1);
  4088.       if not (spcbExtendedColors in ExStyle) then
  4089.         DeleteRange(StandardColorsCount, StandardColorsCount + ExtendedColorsCount - 1);
  4090.       if not (spcbStandardColors in ExStyle) then
  4091.         DeleteRange(0, StandardColorsCount - 1);
  4092.       if spcbCustomColor in ExStyle then
  4093.         Items.InsertObject(0, SColorBoxCustomCaption, TObject(LCustomColor));
  4094.       Self.Selected := LSelectedColor;
  4095.     finally
  4096.       Items.EndUpdate;
  4097.       FNeedToPopulate := False;
  4098.     end;
  4099.   end
  4100.   else
  4101.     FNeedToPopulate := True;
  4102. end;
  4103. procedure TspSkinColorComboBox.SetExStyle(AStyle: TspColorBoxStyle);
  4104. begin
  4105.   FExStyle := AStyle;
  4106.   Enabled := ([spcbStandardColors, spcbExtendedColors, spcbSystemColors, spcbCustomColor] * FExStyle) <> [];
  4107.   PopulateList;
  4108.   if (Items.Count > 0) and (ItemIndex = -1) then ItemIndex := 0;
  4109. end;
  4110. function TspSkinColorComboBox.GetColor(Index: Integer): TColor;
  4111. begin
  4112.   Result := TColor(Items.Objects[Index]);
  4113. end;
  4114. function TspSkinColorComboBox.GetColorName(Index: Integer): string;
  4115. begin
  4116.   Result := Items[Index];
  4117. end;
  4118. function TspSkinColorComboBox.GetSelected: TColor;
  4119. begin
  4120.   if HandleAllocated then
  4121.     if ItemIndex <> -1 then
  4122.       Result := Colors[ItemIndex]
  4123.     else
  4124.       Result := NoColorSelected
  4125.   else
  4126.     Result := FSelectedColor;
  4127. end;
  4128. ///////////////////check listbox//////////////////////////
  4129. type
  4130. TspCheckListBoxDataWrapper = class
  4131. private
  4132.   FData: LongInt;
  4133.   FState: TCheckBoxState;
  4134.   procedure SetChecked(Check: Boolean);
  4135.   function GetChecked: Boolean;
  4136. public
  4137.   class function GetDefaultState: TCheckBoxState;
  4138.   property Checked: Boolean read GetChecked write SetChecked;
  4139.   property State: TCheckBoxState read FState write FState;
  4140. end;
  4141. procedure TspCheckListBoxDataWrapper.SetChecked(Check: Boolean);
  4142. begin
  4143.   if Check then FState := cbChecked else FState := cbUnchecked;
  4144. end;
  4145. function TspCheckListBoxDataWrapper.GetChecked: Boolean;
  4146. begin
  4147.   Result := FState = cbChecked;
  4148. end;
  4149. class function TspCheckListBoxDataWrapper.GetDefaultState: TCheckBoxState;
  4150. begin
  4151.   Result := cbUnchecked;
  4152. end;
  4153. constructor TspCheckListBox.Create;
  4154. begin
  4155.   inherited;
  4156.   SkinListBox := nil;
  4157.   Ctl3D := False;
  4158.   BorderStyle := bsNone;
  4159.   ControlStyle := [csCaptureMouse, csOpaque, csDoubleClicks];
  4160.   {$IFDEF VER130}
  4161.   FAutoComplete := False;
  4162.   {$ENDIF}
  4163. end;
  4164. destructor TspCheckListBox.Destroy;
  4165. begin
  4166.   inherited;
  4167. end;
  4168. procedure TspCheckListBox.SkinDrawCheckImage(X, Y: Integer; Cnvs: TCanvas; IR: TRect; DestCnvs: TCanvas);
  4169. var
  4170.   B: TBitMap;
  4171. begin
  4172.   B := TBitMap.Create;
  4173.   B.Width := RectWidth(IR);
  4174.   B.Height := RectHeight(IR);
  4175.   B.Canvas.CopyRect(Rect(0, 0, B.Width, B.Height), Cnvs, IR);
  4176.   B.Transparent := True;
  4177.   DestCnvs.Draw(X, Y, B);
  4178.   B.Free;
  4179. end;
  4180. procedure TspCheckListBox.WMNCCALCSIZE;
  4181. begin
  4182. end;
  4183. procedure TspCheckListBox.CMEnter;
  4184. begin
  4185.   if SkinListBox <> nil then SkinListBox.ListBoxEnter;
  4186.   inherited;
  4187. end;
  4188. procedure TspCheckListBox.CMExit;
  4189. begin
  4190.   if SkinListBox <> nil then SkinListBox.ListBoxExit;
  4191.   inherited;
  4192. end;
  4193. procedure TspCheckListBox.MouseUp(Button: TMouseButton; Shift: TShiftState;
  4194.       X, Y: Integer);
  4195. begin
  4196.   if SkinListBox <> nil then SkinListBox.ListBoxMouseUp(Button, Shift, X, Y);
  4197.   inherited;
  4198. end;
  4199. procedure TspCheckListBox.MouseMove(Shift: TShiftState; X, Y: Integer);
  4200. begin
  4201.   if SkinListBox <> nil then SkinListBox.ListBoxMouseMove(Shift, X, Y);
  4202.   inherited;
  4203. end;
  4204. procedure TspCheckListBox.KeyDown(var Key: Word; Shift: TShiftState);
  4205. begin
  4206.   if SkinListBox <> nil then SkinListBox.ListBoxKeyDown(Key, Shift);
  4207.   inherited;
  4208. end;
  4209. procedure TspCheckListBox.Click;
  4210. begin
  4211.   if SkinListBox <> nil then SkinListBox.ListBoxClick;
  4212.   inherited;
  4213. end;
  4214. procedure TspCheckListBox.PaintBGWH;
  4215. var
  4216.   X, Y, XCnt, YCnt, XO, YO, w, h, w1, h1: Integer;
  4217.   Buffer: TBitMap;
  4218. begin
  4219.   w1 := AW;
  4220.   h1 := AH;
  4221.   Buffer := TBitMap.Create;
  4222.   Buffer.Width := w1;
  4223.   Buffer.Height := h1;
  4224.   with Buffer.Canvas, SkinListBox do
  4225.   begin
  4226.     w := RectWidth(ClRect);
  4227.     h := RectHeight(ClRect);
  4228.     XCnt := w1 div w;
  4229.     YCnt := h1 div h;
  4230.     for X := 0 to XCnt do
  4231.     for Y := 0 to YCnt do
  4232.     begin
  4233.       if X * w + w > w1 then XO := X * w + w - w1 else XO := 0;
  4234.       if Y * h + h > h1 then YO := Y * h + h - h1 else YO := 0;
  4235.        CopyRect(Rect(X * w, Y * h, X * w + w - XO, Y * h + h - YO),
  4236.                 Picture.Canvas,
  4237.                 Rect(SkinRect.Left + ClRect.Left, SkinRect.Top + ClRect.Top,
  4238.                 SkinRect.Left + ClRect.Right - XO,
  4239.                 SkinRect.Top + ClRect.Bottom - YO));
  4240.     end;
  4241.   end;
  4242.   Cnvs.Draw(AX, AY, Buffer);
  4243.   Buffer.Free;
  4244. end;
  4245. function TspCheckListBox.GetItemData(Index: Integer): LongInt;
  4246. begin
  4247.   Result := 0;
  4248.   if HaveWrapper(Index) then
  4249.     Result := TspCheckListBoxDataWrapper(GetWrapper(Index)).FData;
  4250. end;
  4251. procedure TspCheckListBox.SetItemData(Index: Integer; AData: LongInt);
  4252. var
  4253.   Wrapper: TspCheckListBoxDataWrapper;
  4254. begin
  4255.   Wrapper := TspCheckListBoxDataWrapper(GetWrapper(Index));
  4256.   Wrapper.FData := AData;
  4257.   if FSaveStates <> nil then
  4258.     if FSaveStates.Count > 0 then
  4259.     begin
  4260.      Wrapper.FState := TCheckBoxState(FSaveStates[0]);
  4261.      FSaveStates.Delete(0);
  4262.     end;
  4263. end;
  4264. procedure TspCheckListBox.ResetContent;
  4265. var
  4266.   I: Integer;
  4267. begin
  4268.   for I := 0 to Items.Count - 1 do
  4269.     if HaveWrapper(I) then
  4270.       GetWrapper(I).Free;
  4271.   inherited;
  4272. end;
  4273. procedure TspCheckListBox.CreateWnd;
  4274. begin
  4275.   inherited CreateWnd;
  4276.   if FSaveStates <> nil then
  4277.   begin
  4278.     FSaveStates.Free;
  4279.     FSaveStates := nil;
  4280.   end;
  4281. end;
  4282. procedure TspCheckListBox.DestroyWnd;
  4283. var
  4284.   I: Integer;
  4285. begin
  4286.   if Items.Count > 0 then
  4287.   begin
  4288.     FSaveStates := TList.Create;
  4289.     for I := 0 to Items.Count -1 do
  4290.       FSaveStates.Add(TObject(State[I]));
  4291.   end;
  4292.   inherited DestroyWnd;
  4293. end;
  4294. procedure TspCheckListBox.WMDestroy(var Msg: TWMDestroy);
  4295. var
  4296.   i: Integer;
  4297. begin
  4298.   for i := 0 to Items.Count -1 do
  4299.     ExtractWrapper(i).Free;
  4300.   inherited;
  4301. end;
  4302. procedure TspCheckListBox.DeleteString(Index: Integer);
  4303. begin
  4304.   if HaveWrapper(Index) then
  4305.     GetWrapper(Index).Free;
  4306.   inherited;
  4307. end;
  4308. procedure TspCheckListBox.KeyPress(var Key: Char);
  4309. {$IFDEF VER130}
  4310.   procedure FindString;
  4311.   var
  4312.     Idx: Integer;
  4313.   begin
  4314.     Idx := SendMessage(Handle, LB_FINDSTRING, -1, LongInt(PChar(FFilter)));
  4315.     if Idx <> LB_ERR then
  4316.     begin
  4317.       if MultiSelect then
  4318.       begin
  4319. //      ClearSelection;
  4320.         SendMessage(Handle, LB_SELITEMRANGE, 1, MakeLParam(Idx, Idx))
  4321.       end;
  4322.       ItemIndex := Idx;
  4323.       Click;
  4324.     end;
  4325.     if not Ord(Key) in [VK_RETURN, VK_BACK, VK_ESCAPE] then
  4326.       Key := #0;
  4327.   end;
  4328.   {$ENDIF}
  4329. begin
  4330.   inherited;
  4331.   if (Key = ' ') then ToggleClickCheck(ItemIndex);
  4332.   if SkinListBox <> nil then SkinListBox.ListBoxKeyPress(Key);
  4333.   {$IFDEF VER130}
  4334.   if not FAutoComplete then Exit;
  4335.   if GetTickCount - FLastTime >= 500 then
  4336.     FFilter := '';
  4337.   FLastTime := GetTickCount;
  4338.   if Ord(Key) <> VK_BACK then
  4339.     FFilter := FFilter + Key
  4340.   else
  4341.     Delete(FFilter, Length(FFilter), 1);
  4342.   if Length(FFilter) > 0 then
  4343.     FindString
  4344.   else
  4345.   begin
  4346.     ItemIndex := 0;
  4347.     Click;
  4348.   end;
  4349.   {$ENDIF}
  4350. end;
  4351. procedure TspCheckListBox.MouseDown(Button: TMouseButton; Shift: TShiftState;
  4352.       X, Y: Integer);
  4353. function InCheckArea(IR: TRect): Boolean;
  4354. var
  4355.   R, R1: TRect;
  4356.   OX: Integer;
  4357. begin
  4358.   R := SkinListBox.ItemTextRect;
  4359.   OX :=  RectWidth(IR) - RectWidth(SkinListBox.SItemRect);
  4360.   Inc(R.Right, OX);
  4361.   R1 := SkinListBox.ItemCheckRect;
  4362.   if R1.Left >= SkinListBox.ItemTextRect.Right
  4363.   then OffsetRect(R1, OX, 0);
  4364.   OffsetRect(R1, IR.Left, IR.Top);
  4365.   Result := PtInRect(R1, Point(X, Y));
  4366. end;
  4367. var
  4368.   Index: Integer;
  4369. begin
  4370.   inherited;
  4371.   Index := ItemAtPos(Point(X,Y),True);
  4372.   if (Index <> -1)
  4373.   then 
  4374.     if (SkinListBox <> nil) and (SkinListBox.FIndex <> -1)
  4375.     then
  4376.       begin
  4377.         if InCheckArea(ItemRect(Index)) then ToggleClickCheck(Index);
  4378.       end
  4379.     else
  4380.       begin
  4381.         if X - ItemRect(Index).Left < 20 then ToggleClickCheck(Index);
  4382.       end;
  4383.   if SkinListBox <> nil then SkinListBox.ListBoxMouseDown(Button, Shift, X, Y);    
  4384. end;
  4385. procedure TspCheckListBox.ToggleClickCheck;
  4386. var
  4387.   State: TCheckBoxState;
  4388. begin
  4389.   if (Index >= 0) and (Index < Items.Count) then
  4390.   begin
  4391.     State := Self.State[Index];
  4392.     case State of
  4393.       cbUnchecked: State := cbChecked;
  4394.       cbChecked: State := cbUnchecked;
  4395.     end;
  4396.     Self.State[Index] := State;
  4397.     if Assigned(FOnClickCheck) then FOnClickCheck(Self);
  4398.   end;
  4399. end;
  4400. procedure TspCheckListBox.InvalidateCheck(Index: Integer);
  4401. var
  4402.   R: TRect;
  4403. begin
  4404.   R := ItemRect(Index);
  4405.   InvalidateRect(Handle, @R, not (csOpaque in ControlStyle));
  4406.   UpdateWindow(Handle);
  4407. end;
  4408. function TspCheckListBox.GetWrapper(Index: Integer): TObject;
  4409. begin
  4410.   Result := ExtractWrapper(Index);
  4411.   if Result = nil then
  4412.     Result := CreateWrapper(Index);
  4413. end;
  4414. function TspCheckListBox.ExtractWrapper(Index: Integer): TObject;
  4415. begin
  4416.   Result := TspCheckListBoxDataWrapper(inherited GetItemData(Index));
  4417.   if LB_ERR = Integer(Result) then
  4418.     raise EListError.CreateFmt('List index out of bounds (%d)', [Index]);
  4419.   if (Result <> nil) and (not (Result is TspCheckListBoxDataWrapper)) then
  4420.     Result := nil;
  4421. end;
  4422. function TspCheckListBox.CreateWrapper(Index: Integer): TObject;
  4423. begin
  4424.   Result := TspCheckListBoxDataWrapper.Create;
  4425.   inherited SetItemData(Index, LongInt(Result));
  4426. end;
  4427. function TspCheckListBox.HaveWrapper(Index: Integer): Boolean;
  4428. begin
  4429.   Result := ExtractWrapper(Index) <> nil;
  4430. end;
  4431. procedure TspCheckListBox.SetChecked(Index: Integer; Checked: Boolean);
  4432. begin
  4433.   if Checked <> GetChecked(Index) then
  4434.   begin
  4435.     TspCheckListBoxDataWrapper(GetWrapper(Index)).SetChecked(Checked);
  4436.     InvalidateCheck(Index);
  4437.   end;
  4438. end;
  4439. procedure TspCheckListBox.SetState(Index: Integer; AState: TCheckBoxState);
  4440. begin
  4441.   if AState <> GetState(Index) then
  4442.   begin
  4443.     TspCheckListBoxDataWrapper(GetWrapper(Index)).State := AState;
  4444.     InvalidateCheck(Index);
  4445.   end;
  4446. end;
  4447. function TspCheckListBox.GetChecked(Index: Integer): Boolean;
  4448. begin
  4449.   if HaveWrapper(Index) then
  4450.     Result := TspCheckListBoxDataWrapper(GetWrapper(Index)).GetChecked
  4451.   else
  4452.     Result := False;
  4453. end;
  4454. function TspCheckListBox.GetState(Index: Integer): TCheckBoxState;
  4455. begin
  4456.   if HaveWrapper(Index) then
  4457.     Result := TspCheckListBoxDataWrapper(GetWrapper(Index)).State
  4458.   else
  4459.     Result := TspCheckListBoxDataWrapper.GetDefaultState;
  4460. end;
  4461. function TspCheckListBox.GetState1;
  4462. begin
  4463.   Result := [];
  4464.   if AItemID = ItemIndex
  4465.   then
  4466.     begin
  4467.       Result := Result + [odSelected];
  4468.       if Focused then Result := Result + [odFocused];
  4469.     end
  4470.   else
  4471.     if SelCount > 0
  4472.     then
  4473.       if Selected[AItemID] then Result := Result + [odSelected];
  4474. end;
  4475. procedure TspCheckListBox.PaintBG(DC: HDC);
  4476. var
  4477.   C: TControlCanvas;
  4478. begin
  4479.   C := TControlCanvas.Create;
  4480.   C.Handle := DC;
  4481.   SkinListBox.GetSkinData;
  4482.   if SkinListBox.FIndex <> -1
  4483.   then
  4484.     PaintBGWH(C, Width, Height, 0, 0)
  4485.   else
  4486.     with C do
  4487.     begin
  4488.       C.Brush.Color := clWindow;
  4489.       FillRect(Rect(0, 0, Width, Height));
  4490.     end;
  4491.   C.Handle := 0;
  4492.   C.Free;
  4493. end;
  4494. procedure TspCheckListBox.PaintColumnsList(DC: HDC);
  4495. var