zoukankan      html  css  js  c++  java
  • 带复选框可以多选的组合框控件 TCheckCombobox,非常完美

    http://blog.csdn.net/qinmaofan/archive/2007/07/24/1705090.aspx

    转载请勿清除广告。 

    没有合适的局域网管理软件吗?你的网管工具够灵活够高效吗?看看这个network management software【http://www.hainsoft.com/】。

    带复选框可以多选的组合框控件 TCheckCombobox
    For Delphi 7
    作者 覃茂藩

    可以多选的组合框,相对于CheckListbox和ListView在界面上中能够节省很多空间。该控件继承自TCustomComboBox,标准控件,不会有兼容性问题。实现原理简单,没有创建任何TForm、TCheckBox、TCheckListBox,代码极少,非常简洁。相比现在网上能够找到的类似控件,优点非常明显。

    下载地址: http://lczx.sdedu.net/download/TCheckCombobox.rar

    安装方法:把文件CheckCombobox.dcu复制到Delphi安装目录下的LIB,然后点击菜单Component > Install Component,Unit File Name那里点击Browser,打开CheckCombobox.dcu,OK,Compile。然后控件就会在控件工具箱Samples那一页出现了。

    本控件使用免费。
    QQ: 179845876 (需要加验证,否则不通过)
    邮箱: Qinmaofan@21cn.com


    发表于 @2007年07月24日 12:42:00

    其另一个参考源码网址:http://www.delphipraxis.net/127628-tcheckcombobox-komponente-ueberarbeiten.html

    Delphi-Quellcode:

    unit ATCheckedComboBox;
    
    interface
    
    uses
       Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
       StdCtrls;
    type
    
       TATCBQuoteStyle = (qsNone,qsSingle,qsDouble);
    
       TATCheckedComboBox = class(TCustomComboBox)
       private
          { Private declarations }
          FListInstance   : Pointer;
          FDefListProc   : Pointer;
          FListHandle    : HWnd;
          FQuoteStyle      : TATCBQuoteStyle;
          FColorNotFocus: TColor;
          FCheckedCount : integer;
          FTextAsHint    : boolean;
          FOnCheckClick : TNotifyEvent;
          FVersion       : String;
          procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
          procedure CMEnter(var Message: TCMEnter); message CM_ENTER;
          procedure CMExit(var Message: TCMExit); message CM_EXIT;
          procedure ListWndProc(var Message: TMessage);
          procedure SetColorNotFocus(value:TColor);
          procedure SetVersion(value:String);
       protected
          { Protected declarations }
          m_strText          : string;
          m_bTextUpdated   : boolean;
          procedure WndProc(var Message: TMessage);override;
          procedure RecalcText;
          function GetText: string;
          function GetCheckedCount:integer;
       public
          { Public declarations }
          constructor Create(AOwner: TComponent);override;
          destructor    Destroy; override;
          procedure    SetCheck(nIndex:integer;checked:boolean);
          function       AddChecked(value:string;checked:boolean):integer;
          function       IsChecked(nIndex: integer):boolean;
          procedure    CheckAll(checked:boolean);
          property       Text:string read GetText;
          property      CheckedCount :integer read GetCheckedCount;
       published
          { Published declarations }
          property Anchors;
          property BiDiMode;
          property Color;
          property ColorNotFocus : TColor   read FColorNotFocus write SetColorNotFocus;
          property Constraints;
          property Ctl3D;
          property DragCursor;
          property DragKind;
          property DragMode;
          property DropDownCount;
          property Enabled;
          property Font;
          property ImeMode;
          property ImeName;
          property ItemHeight;
          property Items;
          property MaxLength;
          property ParentBiDiMode;
          property ParentColor;
          property ParentCtl3D;
          property ParentFont;
          property ParentShowHint;
          property PopupMenu;
          property QuoteStyle   : TATCBQuoteStyle read FQuoteStyle   write FQuoteStyle default qsNone;
          property ShowHint;
          property ShowTextAsHint : Boolean read FTextAsHint write FTextAsHint default true;
          property Sorted;
          property TabOrder;
          property TabStop;
          property Visible;
          property Version :string read FVersion write SetVersion; // ver 1.1
          property OnChange;
          property OnCheckClick: TNotifyEvent read FOnCheckClick write FOnCheckClick;
          property OnClick;
          property OnDblClick;
          property OnDragDrop;
          property OnDragOver;
          property OnDropDown;
          property OnEndDock;
          property OnEndDrag;
          property OnEnter;
          property OnExit;
          property OnKeyDown;
          property OnKeyPress;
          property OnKeyUp;
          property OnStartDock;
          property OnStartDrag;
       end;
    
    procedure Register;
    
    implementation
    
    { TATCheckedComboBox }
    procedure Register;
    begin
       RegisterComponents('Samples', [TATCheckedComboBox]);
    end;
    
    var
       FCheckWidth, FCheckHeight: Integer;
    
    procedure GetCheckSize;
    begin
       with TBitmap.Create do
          try
             Handle := LoadBitmap(0, PChar(32759));
             FCheckWidth := Width div 4;
             FCheckHeight := Height div 3;
          finally
             Free;
          end;
    end;
    
    procedure TATCheckedComboBox.SetVersion(value: String);
    begin
       // read only
    end;
    
    procedure TATCheckedComboBox.SetCheck(nIndex:integer;checked:boolean);
    begin
       if (nIndex>-1) and (nIndex<Items.count) then
       begin
          Items.Objects[nIndex] := TObject(checked);
          m_bTextUpdated := FALSE;
          Invalidate;
          if Assigned(FOnCheckClick) then
             OnCheckClick(self)
       end;
    end;
    
    function TATCheckedComboBox.AddChecked(value:string;checked:boolean):integer;
    begin
       result := Items.AddObject(value, TObject(checked));
       if result>=0 then
       begin
          m_bTextUpdated := FALSE;
          Invalidate;
       end;
    end;
    
    function TATCheckedComboBox.IsChecked(nIndex: integer):boolean;
    begin
       result := false;
       if (nIndex>-1) and (nIndex<Items.count) then
          result := Items.Objects[nIndex] = TObject(TRUE)
    end;
    
    procedure TATCheckedComboBox.CheckAll(checked:boolean);
    var i:integer;
    begin
       for i:= 0 to Items.count-1 do
          Items.Objects[i] := TObject(checked);
    end;
    
    function GetFormatedText(kind:TATCBQuoteStyle;str:string):string;
    var s : string;
    begin
       result := str;
       if length(str)>0 then
       begin
          s := str;
          case kind of
             qsSingle   : result :=
                   ''''+
                   StringReplace(S, ',', ''',''',[rfReplaceAll])+
                   '''';
             qsDouble    : result :=
                   '"'+
                   StringReplace(S, ',', '","',[rfReplaceAll])+
                   '"';
          end;
       end;
    end;
    
    function TATCheckedComboBox.GetText: string;
    begin
       RecalcText;
       if FQuoteStyle = qsNone then
          result := m_strText
       else
          result := GetFormatedText(FQuoteStyle,m_strText);
    end;
    
    function TATCheckedComboBox.GetCheckedCount:integer;
    begin
       RecalcText;
       result := FCheckedCount;
    end;
    
    
    procedure TATCheckedComboBox.RecalcText;
    var
          nCount,i    : integer;
          strItem,
          strText,
          strSeparator : string;
    begin
       if (not m_bTextUpdated) then
       begin
          FCheckedCount   := 0;
          nCount       := items.count;
          strSeparator    := '; ';
          strText          := '';
          for i := 0 to nCount - 1 do
             if IsChecked(i) then
             begin
                inc(FCheckedCount);
                strItem := items[i];
                if (strText<>'') then
                   strText := strText + strSeparator;
                strText := strText + strItem;
             end;
          // Set the text
          m_strText          := strText;
          if FTextAsHint then
             Hint := m_strText;
          m_bTextUpdated    := TRUE;
       end;
    end;
    
    procedure TATCheckedComboBox.SetColorNotFocus(value:TColor);
    begin
        if FColorNotFocus <> Value then
          FColorNotFocus := Value;
       Invalidate
    end;
    
    procedure TATCheckedComboBox.CMEnter(var Message: TCMEnter);
    begin
       Self.Color      := clWhite;
       if Assigned(OnEnter) then OnEnter(Self);
    end;
    
    procedure TATCheckedComboBox.CMExit(var Message: TCMExit);
    begin
       Self.Color       := FColorNotFocus;
       if Assigned(OnExit) then OnExit(Self);
    end;
    
    
    procedure TATCheckedComboBox.CNDrawItem(var Message: TWMDrawItem);
    var
       State                  : TOwnerDrawState;
       rcBitmap,rcText   : Trect;
       nCheck               : integer; // 0 - No check, 1 - Empty check, 2 - Checked
       nState                : integer;
       strText             : string;
       ItId                  : Integer;
       dc                     : HDC;
    begin
       with Message.DrawItemStruct^ do
       begin
          State       := TOwnerDrawState(LongRec(itemState).Lo);
          dc             := hDC;
          rcBitmap   := rcItem;
          rcText    := rcItem;
          ItId         := itemID;
       end;
       // Check if we are drawing the static portion of the combobox
      if (itID < 0) then
       begin
          RecalcText();
          strText := m_strText;
          nCheck := 0;
       end
       else
       begin
          strtext             := Items[ItId];
          rcBitmap.Left    := 2;
          rcBitmap.Top       := rcText.Top + (rcText.Bottom - rcText.Top - FCheckWidth) div 2;
          rcBitmap.Right    := rcBitmap.Left + FCheckWidth;
          rcBitmap.Bottom := rcBitmap.Top + FCheckHeight;
    
          rcText.left := rcBitmap.right;
          nCheck := 1;
          if IsChecked(ItId) then
             inc(nCheck);
       end;
       if (nCheck > 0) then
       begin
           SetBkColor(dc, GetSysColor(COLOR_WINDOW));
           SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT));
           nState := DFCS_BUTTONCHECK;
          if (nCheck > 1) then
        nState := nState or DFCS_CHECKED;
          DrawFrameControl(dc, rcBitmap, DFC_BUTTON, nState);
       end;
       if (odSelected in State) then
       begin
          SetBkColor(dc, $0091622F);
          SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
       end
       else
       begin
          if (nCheck=0) then
          begin
             SetTextColor(dc, ColorToRGB(Font.Color));
             SetBkColor(dc, ColorToRGB(FColorNotFocus));
          end
          else
          begin
             SetTextColor(dc, ColorToRGB(Font.Color));
          SetBkColor(dc,     ColorToRGB(Brush.Color));
          end;
       end;
       if itID >= 0 then
      strText := ' ' + strtext;
       ExtTextOut(dc, 0, 0, ETO_OPAQUE, @rcText, Nil, 0, Nil);
       DrawText(dc, pchar(strText), Length(strText), rcText, DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS);
       if odFocused in State then DrawFocusRect(dc, rcText);
    end;
    
     //DefWindowProc
    procedure TATCheckedComboBox.ListWndProc(var Message: TMessage);
    var
       nItemHeight, nTopIndex, nIndex: Integer;
       rcItem,rcClient: TRect;
       pt              : TPoint;
    begin
       case Message.Msg of
          LB_GETCURSEL : // this is for to not draw the selected in the text area
             begin
                Message.result := -1;
                exit;
             end;
          WM_CHAR: // pressing space toggles the checked
             begin
                if (TWMKey(Message).CharCode = VK_SPACE) then
                begin
                   // Get the current selection
                   nIndex := CallWindowProcA(FDefListProc, FListHandle, LB_GETCURSEL,Message.wParam, Message.lParam);
                   SendMessage(FListHandle, LB_GETITEMRECT, nIndex, LongInt(@rcItem));
                   InvalidateRect(FListHandle, @rcItem, FALSE);
                   SetCheck(nIndex, not IsChecked(nIndex));
                   SendMessage(WM_COMMAND, handle, CBN_SELCHANGE,handle);
                   Message.result := 0;
                   exit;
                end
             end;
          WM_LBUTTONDOWN:
             begin
                Windows.GetClientRect(FListHandle, rcClient);
                pt.x := TWMMouse(Message).XPos; //LOWORD(Message.lParam);
                pt.y := TWMMouse(Message).YPos; //HIWORD(Message.lParam);
                if (PtInRect(rcClient, pt)) then
                begin
                   nItemHeight := SendMessage(FListHandle, LB_GETITEMHEIGHT, 0, 0);
                   nTopIndex := SendMessage(FListHandle, LB_GETTOPINDEX, 0, 0);
                   // Compute which index to check/uncheck
                   nIndex := trunc(nTopIndex + pt.y / nItemHeight);
                   SendMessage(FListHandle, LB_GETITEMRECT, nIndex, LongInt(@rcItem));
                   if (PtInRect(rcItem, pt)) then
                   begin
                      InvalidateRect(FListHandle, @rcItem, FALSE);
                      SetCheck(nIndex, not IsChecked(nIndex));
                      SendMessage(WM_COMMAND, handle, CBN_SELCHANGE,handle);
                   end
                end
             end;
          WM_LBUTTONUP:
             begin
                Message.result := 0;
                exit;
             end;
       end;
       ComboWndProc(Message, FListHandle, FDefListProc);
    end;
    
    constructor TATCheckedComboBox.Create(AOwner: TComponent);
    begin
       inherited Create(AOwner);
       ShowHint            := true;
       Fversion            := '1.2';
       FTextAsHint       := true;
       ParentShowHint := False;
       FListHandle       := 0;
       FQuoteStyle       := qsNone;
       FColorNotFocus   := clInfoBk;
       Style                := csOwnerDrawVariable;
       m_bTextUpdated := FALSE;
       FListInstance    := MakeObjectInstance(ListWndProc);
    end;
    
    destructor TATCheckedComboBox.Destroy;
    begin
       FreeObjectInstance(FListInstance);
       inherited Destroy;
    end;
    
    procedure TATCheckedComboBox.WndProc(var Message: TMessage);
    var lWnd : HWND;
    begin
       if message.Msg = WM_CTLCOLORLISTBOX then
       begin
          // If the listbox hasn't been subclassed yet, do so...
          if (FListHandle = 0) then
          begin
             lwnd := message.LParam;
             if (lWnd <> 0) and (lWnd <> FDropHandle) then
             begin
                // Save the listbox handle
                FListHandle := lWnd;
                FDefListProc := Pointer(GetWindowLong(FListHandle, GWL_WNDPROC));
                SetWindowLong(FListHandle, GWL_WNDPROC, Longint(FListInstance));
             end;
          end;
       end;
       inherited;
    end;
    
    initialization
       GetCheckSize;
    
    end. 
    

    问题修正后的源码:

    Re: TCheckComboBox: Komponente überarbeiten???

    procedure TATCheckedComboBox.CNDrawItem(var Message: TWMDrawItem);
    var
      State: TOwnerDrawState;
      rcBitmap, rcText: Trect;
      nCheck: integer; // 0 - No check, 1 - Empty check, 2 - Checked
      nState: integer;
      strText: string;
      ItId: Integer;
      dc: HDC;
    begin
      with Message.DrawItemStruct^ do
      begin
        State := TOwnerDrawState(LongRec(itemState).Lo);
        dc := hDC;
        rcBitmap := rcItem;
        rcText := rcItem;
        ItId := itemID;
      end;
       // Check if we are drawing the static portion of the combobox
      if (itID < 0) then
      begin
        RecalcText();
        strText := m_strText;
        nCheck := 0;
      end
      else
      begin
        strtext := Items[ItId];
        rcBitmap.Left := 2;
        rcBitmap.Top := rcText.Top + (rcText.Bottom - rcText.Top - FCheckWidth) div 2;
        rcBitmap.Right := rcBitmap.Left + FCheckWidth;
        rcBitmap.Bottom := rcBitmap.Top + FCheckHeight;
    
        rcText.left := rcBitmap.right;
        nCheck := 1;
        if IsChecked(ItId) then
          inc(nCheck);
      end;
      if (nCheck > 0) then
      begin
        SetBkColor(dc, GetSysColor(COLOR_WINDOW));
        SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT));
        nState := DFCS_BUTTONCHECK;
        if (nCheck > 1) then
          nState := nState or DFCS_CHECKED;
        DrawFrameControl(dc, rcBitmap, DFC_BUTTON, nState);
      end;
    
      if (odSelected in State) then
      begin
        SetBkColor(dc, $0091622F);
        SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
      end
      else
      begin
        if (nCheck = 0) then
        begin
          SetTextColor(dc, ColorToRGB(Font.Color));
          SetBkColor(dc, ColorToRGB(FColorNotFocus));
        end
        else
        begin
          SetTextColor(dc, ColorToRGB(Font.Color));
          if ncheck = 1 then
            SetBkColor(dc, ColorToRGB(Brush.Color))
          else
            SetBkColor(dc, clRed); // <<----- hier
    
        end;
      end;
      if itID >= 0 then
        strText := ' ' + strtext;
      ExtTextOut(dc, 0, 0, ETO_OPAQUE, @rcText, nil, 0, nil);
      DrawText(dc, pchar(strText), Length(strText), rcText, DT_SINGLELINE or DT_VCENTER or DT_END_ELLIPSIS);
      if odFocused in State then DrawFocusRect(dc, rcText);
    end; 
    

    非常感谢老外。

  • 相关阅读:
    Druid 使用 Kafka 将数据载入到 Kafka
    Druid 使用 Kafka 数据加载教程——下载和启动 Kafka
    Druid 集群方式部署 —— 启动服务
    Druid 集群方式部署 —— 端口调整
    Druid 集群方式部署 —— 配置调整
    Druid 集群方式部署 —— 配置 Zookeeper 连接
    Druid 集群方式部署 —— 元数据和深度存储
    Druid 集群方式部署 —— 从独立服务器部署上合并到集群的硬件配置
    Druid 集群方式部署 —— 选择硬件
    Druid 独立服务器方式部署文档
  • 原文地址:https://www.cnblogs.com/chulia20002001/p/1911492.html
Copyright © 2011-2022 走看看