{
//
// Components : TwwDBCustomCombo, TwwDBComboDlg
//
// Copyright (c) 1996-2001 by Woll2Woll Software
//
//
// 2/25/98 - Call IsValidChar instead of checking [32..255] in KeyDown method
//
// 9/2/98 -  Call FButton.Update in paint event so Delphi 4 paints icon correctly
//           in DBCtrlGrid
// 11/10/98 - Publish ParentBidiMode
// 1/11/2000- Publish WordWrap
// 3/13/00 - MDI forms should check ActiveControl instead of focused
//          when button is clicked.  This fixes problem where
//          button click not recognized when switching back to mdi child
}
unit vcl.Wwdotdot;

interface
{$i wwIfDef.pas}

uses
  Forms, SysUtils, Windows, Messages, Classes,
  Controls, Buttons, Graphics,
  dbctrls, mask, db, stdctrls, wwdbedit, wwdblook,
  wwframe, wwcombobutton;

type

  TwwHandleDropDownKeys=procedure(Sender: TObject; var Key: Word; Shift: TShiftState) of object;
  TwwDBCustomCombo =class(TwwDBCustomEdit)
   private
    FBtnControl:TWincontrol;
    FButton:TwwComboButton;
    FOnCustomDlg:TNotifyevent;
    FStyle: TwwDBLookupComboStyle;
    FButtonStyle: TwwComboButtonStyle;
    FDroppedDown: boolean;
    FMouseInButtonControl: boolean;
    FLimitEditRect: boolean;
    FButtonEffects: TwwButtonEffects;
    FButtonWidth: integer;
    SkipUpdate: boolean;
    FAutoEnableEdit: boolean;
    FOnHandleDropDownKeys: TwwHandleDropDownKeys;
    procedure CMEnter(var Message: TCMEnter); message CM_ENTER;
    procedure CMExit(var Message: TCMExit); message CM_EXIT;
    procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
    procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
    procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;
    procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
    procedure WMPaint(var Message: TMessage); message WM_PAINT;
    procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
    procedure SetButtonGlyph(Value: TBitmap);
    Function GetButtonGlyph: TBitmap;
    procedure NonEditMouseDown(var Message: TWMLButtonDown);
    procedure SetButtonStyle(val: TwwComboButtonStyle);
    Procedure UpdateButtonPosition;
    Procedure SetButtonWidth(val: integer);
    function GetButtonWidth: integer;

   protected
    function IsVistaComboNonEditable: boolean; override;
    function IsCustom: Boolean; virtual;
    procedure KeyPress(var Key: Char); override;
    procedure CreateParams(var Params: TCreateParams); override;
    Procedure UpdateButtonGlyph;
    Procedure DrawButton(Canvas: TCanvas; R: TRect; State: TButtonState;
       ControlState: TControlState; var DefaultPaint: boolean); virtual;
    procedure SetEditRect; override;
    procedure WMSize(var msg:twmsize); message wm_size;
    procedure BtnClick(sender:tobject);
    procedure BtnMouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
    function GetShowButton: boolean; override;
    procedure SetShowButton(sel: boolean); override;
    Function GetIconIndent: integer; override;
    Function GetIconLeft: integer; override;
    Function Editable: boolean; override;
    Function IsDroppedDown: boolean; override;
    procedure CloseUp(Accept: Boolean); virtual;
    procedure HandleDropDownKeys(var Key: Word; Shift: TShiftState);
    procedure Loaded; override;
    procedure InvalidateTransparentButton;
    Function MouseEditable: boolean; virtual;
    property BtnControl : TWinControl read FBtnControl;

   public
    constructor Create(AOwner:tcomponent); override;
    destructor Destroy; override;
    procedure DropDown; virtual;

    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    property AutoEnableEdit: boolean read FAutoEnableEdit write FAutoEnableEdit default True;
    property Button: TwwComboButton read FButton;
    property OnCustomDlg: TNotifyevent read FOnCustomDlg write FOnCustomDlg;
    property Style: TwwDBLookupComboStyle read FStyle write FStyle;
    property ButtonStyle: TwwComboButtonStyle read FButtonStyle write SetButtonStyle;
    property ButtonEffects: TwwButtonEffects read FButtonEffects write FButtonEffects;
    property LimitEditRect: boolean read FLimitEditRect write FLimitEditRect default False;
    property ButtonGlyph: TBitmap read GetButtonGlyph write SetButtonGlyph stored IsCustom;
    property ButtonWidth: integer read GetButtonWidth write SetButtonWidth default 0;
    property OnHandleDropDownKeys: TwwHandleDropDownKeys read FOnHandleDropDownKeys write FOnHandleDropDownKeys;
     { LimitEditRect allows text to scroll instead of being typed over button area.
       Set this to true to force the caret to always be visible instead of being hidden behind the button.
       The negative consequence of this being set to true is that the combobox will no
       longer close the form on an escape, as the escape goes to the control instead }

  end;

  TwwDBComboDlg =class(TwwDBCustomCombo)
   strict private
      class constructor Create;
   published
    property BevelEdges;
    property BevelInner;
    property BevelKind default bkNone;
    property BevelOuter;

    property Controller;

    property DisableThemes;
    property OnCustomDlg;
    property Anchors;
    property BiDiMode;
    property Constraints;
    property ParentBiDiMode; { 11/10/98 }
    property AutoEnableEdit;
    property ShowButton;
    property Style;
    property ButtonStyle default cbsEllipsis;
    property AutoFillDate;
    property AutoSelect;
    property AutoSize;
    property BorderStyle;
    property CharCase;
    property Color;
    property Ctl3D;
    property DataField;
    property DataSource;
    property DragCursor;
    property DragMode;
    property Enabled;
    property ButtonEffects;
    property Frame;
    property ButtonWidth;
    property ButtonGlyph;
    property Font;
    property EditAlignment;
    {$ifdef wwDelphi3Up}
    property ImeMode;
    property ImeName;
    {$endif}
    property LimitEditRect;
    property MaxLength;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ParentShowHint;
    property PasswordChar;
    property Picture;
    property PopupMenu;
    property ReadOnly;
    property ShowHint;
    property TabOrder;
    property TabStop;
    property WordWrap; { 1/11/0000 }
    property UnboundDataType;
    property UsePictureMask;
    property Visible;
    property UnboundAlignment;
    {$ifdef wwDELPHI2010Up}
    property Touch;
    {$endif}

    property OnChange;
    property OnCheckValue;
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    {$ifdef wwDELPHI2010Up}
    property OnGesture;
    {$endif}
    {$ifdef wwDELPHI2013Up}
    property Align;
    property StyleElements;
    property OEMConvert;
    property NumbersOnly;
    property DoubleBuffered;
    property ParentDoubleBuffered;
    {$endif}

  end;

  TwwComboDlgButton = class(TwwComboButton)
  protected
    procedure Paint; override;
    function IsVistaTransparentButton: boolean; override;    
    function IsVistaComboNonEditable: boolean; override;
    function ParentMouseInControl: boolean; override;
    function ParentDroppedDown: boolean; override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
  end;

  procedure Register;

implementation

uses
  {$ifdef wwDelphi7Up}
  Themes, UxTheme,
  {$endif}
  wwcommon;


{.$R *.RES}

type
{  TwwButton = clas(TSpeedButton)
    protected
  end;
}
  TwwComboButtonEffects = class(TwwButtonEffects)
     protected
        procedure Refresh; override;
  end;

  TBtnWinControl = class(TWinControl)
  private
    EditControl: TwwDBCustomCombo;

    procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBkgnd;
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  public
    constructor Create(AOwner: TComponent); override;
  end;

Procedure TwwComboButtonEffects.refresh;
begin
   (Control as TwwDBCustomCombo).Updatebuttonglyph;
//   (Button as TSpeedButton).Glyph.Handle:= TwwDBCustomCombo(Control).LoadComboGlyph;
end;


procedure TBtnWinControl.WMEraseBkgnd(var Message: TWmEraseBkgnd);
var r: TRect;
    cc: TwwDBCustomCombo;
begin
  // Remove parent clipping and don't paint background if styles enabled
  if wwIsCustomStyle(parent) or EditControl.IsVistaComboNonEditable then
  begin
     message.result:=1;
     exit;
  end;
  cc:= TwwDBCustomCombo(parent);
  if cc.skipupdate then exit;
  if (IsInGridPaint(parent) or
     cc.isTransparentEffective)  then
  begin
     { Fixes paint problem when mouse is clicked in button and moved outside
       region, but it is not released }
     if (not IsInGridPaint(parent)) and
        (cc.ButtonEffects.Flat or cc.ButtonEffects.Transparent) and
        (csLButtonDown in cc.FButton.ControlState) then
     begin
        r:= Rect(parent.left + Left , parent.Top+top,
                 parent.left + left + Width, parent.top + Top + Height);
        InvalidateRect(parent.parent.handle, @r, False);
        cc.skipupdate:= true;
        parent.parent.update;
        cc.skipupdate:= False;
     end;
     message.result:= 1;
  end
  else inherited;
end;

constructor TwwDBCustomCombo.Create;
begin
   inherited create(aowner);

   FButtonStyle:= cbsEllipsis;
   FAutoEnableEdit:= True;

   FBtnControl := TBtnWinControl.Create (Self);
   FBtnControl.ControlStyle := FBtnControl.ControlStyle + [csReplicatable];
   FBtnControl.Width:= wwmax(GetSystemMetrics(SM_CXVSCROLL)+4, 17); {4/10/97}
   FBtnControl.Height := 17;
   FBtnControl.Visible := True;
   FBtnControl.Parent := Self;

   FButton:=TwwComboDlgButton.create(self);
   FButton.ControlStyle := FButton.ControlStyle + [csReplicatable];
   FButton.SetBounds (0, 0, FBtnControl.Width, FBtnControl.Height);
   FButton.Width:= wwmax(GetSystemMetrics(SM_CXVSCROLL), 15); {5/2/97 }
   FButton.Parent:= FBtnControl;
   FButton.OnClick:=BtnClick;
   FButton.OnMouseDown:= BtnMouseDown;
   FButton.OnMouseUp:= BtnMouseDown;
   FLimitEditRect:= False;
   FButtonEffects:= TwwComboButtonEffects.create(self, FButton);

end;

destructor TwwDBCustomCombo.Destroy;
begin
  FButtonEffects.Free;
  FButton.Free;
  FButton:= Nil;
  inherited Destroy;
end;

procedure TwwDBCustomCombo.WMPaint(var Message: TMessage);
begin
  inherited;
  if IsInWWObjectView(self) then
  begin
    FButton.Invalidate;
//    if ShowButton then
//       TwwComboDlgButton(FButton).Paint;
  end
  else begin
    FButton.Invalidate;
    FButton.Update; { 9/2/98 }
  end
end;

Function TwwDBCustomCombo.GetIconIndent: integer;
begin
   result:= FBtnControl.Width;
end;

Function TwwDBCustomCombo.GetIconLeft: integer;
begin
   result:= FBtnControl.Left - 1;
end;

Procedure TwwDBCustomCombo.UpdatebuttonGlyph;
begin
//   FButton.Glyph.Handle:=0;  7/28/01 - Don't clear glyph

   if (FButtonStyle<>cbsCustom) and
      (ButtonEffects.Flat or ButtonEffects.Transparent) then
   begin
      if (FButtonStyle = cbsDownArrow) then
         FButton.Glyph.Handle:= LoadBitmap(HInstance, 'WWDROPDOWN')
   end;
end;

function TwwDBCustomCombo.GetShowButton: boolean;
begin
   result:= FBtnControl.visible;
end;

procedure TwwDBCustomCombo.SetShowButton(sel: boolean);
begin
   if (FBtnControl.visible<> sel) then
   begin
      FBtnControl.visible:= sel;
      {10/5/97 - Don't call SetEditRect when loading as this is called when
                 loading is completed.  SetEditRect should be called after
                 all the properties are read in. }
      if (Owner=nil) or // 5/30/01
         not (csLoading in Owner.ComponentState) then SetEditRect;
      self.invalidate;
   end
end;

procedure TwwDBCustomCombo.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.Style :=(Params.Style and not (ES_AUTOVSCROLL or ES_WANTRETURN) or
                   WS_CLIPCHILDREN);
  {$ifdef wwdelphi4up}
  if UseRightToLeftAlignment or LimitEditRect then
    Params.Style:= Params.Style or ES_MULTILINE;
  {$endif}

  // Remove parent clipping and don't paint background for button if styles enabled
  if wwIsCustomStyle(self) then
     Params.Style := Params.Style and not WS_CLIPCHILDREN;

end;

procedure TwwDBCustomCombo.SetEditRect;
var
  Loc: TRect;
begin
  Loc.Bottom :=ClientHeight+1; {+1 is workaround for windows paint bug}
  if UseRightToLeftAlignment then // Support bidimode for button - 8/26/08
    Loc.Right:= ClientWidth - 0
  else begin
    if ShowButton then Loc.Right := FBtnControl.Left - 2
    else Loc.Right:= ClientWidth - 2;
  end;

  if (Frame.IsFrameEffective) then
  begin
     Frame.GetEditRectForFrame(Loc);
  end
  else if (BorderStyle = bsNone) and
     (IsInwwObjectView(self)) then begin
     Loc.Top := 1;
     Loc.Left := 1;
  end
  else if (BorderStyle = bsNone) then begin
     Loc.Top := 2;
     Loc.Left := 2;
  end
  else begin
     Loc.Top := 0;
     Loc.Left := 0;
  end;

  SendMessage(Handle, EM_SETRECTNP, 0, LongInt(@Loc));
end;

type
 TCheatButton = class(TwwComboButton);

Procedure TwwDBCustomCombo.UpdateButtonPosition;
var offset :Integer;
begin
  if Frame.IsFrameEffective then
  begin
     offset:= 2;
  end
  else offset:= 0;

  if UseRightToLeftAlignment then // Support bidimode for button - 8/26/08
  begin
    if (not NewStyleControls) or (BorderStyle = bsNone) or (not Ctl3d) then
       FBtnControl.SetBounds (1, offset, FButton.Width, ClientHeight-offset*2)
    else
       FBtnControl.SetBounds (0, offset, FButton.Width, ClientHeight-offset);
  end
  else begin
    if (not NewStyleControls) or (BorderStyle = bsNone) or (not Ctl3d) then
       FBtnControl.SetBounds (Width - FButton.Width - offset, offset, FButton.Width, ClientHeight-offset*2)
    else
       FBtnControl.SetBounds (Width - FButton.Width - 4, offset, FButton.Width, ClientHeight-offset);
  end;
  if BorderStyle = bsNone then begin
     FButton.Top:= -1; {Allows bitmap to be larger }
     FButton.Height := FBtnControl.Height+1;
  end
  else begin
     FButton.Top:= 0; {Allows bitmap to be larger }
     FButton.Height := FBtnControl.Height;
  end;

  SetEditRect;
end;

procedure TwwDBCustomCombo.WMSize;
begin
  inherited;
  UpdateButtonPosition;
end;

procedure TwwDBCustomCombo.BtnMouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
begin
   exit; { Check if following code needed by exiting out and testing }
end;

procedure TwwDBCustomCombo.BtnClick;
var parentForm: TCustomForm;
begin
   if Patch[2]=False then exit;

   if isDroppedDown then CloseUp(True)
   else begin
      if CanFocus then
      begin

         if not IsVistaComboNonEditable then
         begin
            SetFocus;  { 8/30/96 - Set focus to control }
         end;
         // 6/4/02 - Following code causes OnExit to fire twice for exiting control such as TEdit
{
         // 6/16/01 - Fix problem when using WebBrowse and it has text selected
         if Handle<>GetFocus then
            windows.SetFocus(Handle);
}
      end;

      { 3/13/00 - MDI forms should check ActiveControl instead of focused}
      parentForm:= GetParentForm(self);
      if (parentForm<>nil) and
          (TForm(parentForm).formstyle = fsMDIChild) then
      begin
         if (Focused or IsVistaComboNonEditable) or // 4/14/10 - Don't require focus if non-editable combo
            (parentForm.ActiveControl=self) then
            DropDown;
      end
      else if (Focused or IsVistaComboNonEditable) then DropDown;
   end
end;

procedure TwwDBCustomCombo.CloseUp(Accept: boolean);
begin
   if Accept then modified:= True;
end;

procedure TwwDBCustomCombo.DropDown;
begin
   if Assigned(FOnCustomDlg) then begin
      FDroppedDown:= True;

      Invalidate;

      try  { If exception then clean-up }
         if AutoEnableEdit then
         begin
           if (datasource<>nil) and (datasource.dataset<>nil) then
              EnableEdit;
         end;
         FOnCustomDlg(self);
      finally
         if (not editable) then
            HideCaret(Handle); { Support csDropDownList style }
         Invalidate;
         FDroppedDown:= False;
      end;
   end
end;

Function TwwDBCustomCombo.Editable: boolean;
begin
   Result := (FStyle <> csDropDownList) or isDroppedDown;
end;

Function TwwDBCustomCombo.MouseEditable: boolean;
begin
   Result := (FStyle <> csDropDownList);
end;


procedure TwwDBCustomCombo.HandleDropDownKeys(var Key: Word; Shift: TShiftState);
begin
  if Assigned(FOnHandleDropDownKeys) then
     FOnHandleDropDownKeys(self, Key, Shift);

  case Key of
    VK_F4: // Support F4 for dropping-down
      if not (ssAlt in Shift) then begin
         if isDroppedDown then CloseUp(True)
         else DropDown;
         Key := 0;
      end;
    VK_UP, VK_DOWN:
      if ssAlt in Shift then
      begin
        if isDroppedDown then CloseUp(True)
        else DropDown;
        Key := 0;
      end;
    VK_RETURN, VK_ESCAPE:
      if isDroppedDown and not (ssAlt in Shift) then
      begin
        CloseUp(Key = VK_RETURN);
        Key := 0;
      end;
  end;
end;


procedure TwwDBCustomCombo.KeyDown(var Key: Word; Shift: TShiftState);
begin
  if GetKeyState(VK_MENU) < 0 then
  begin
     Include(Shift, ssAlt);
{     wwClearAltChar;}
  end;

  HandleDropDownKeys(Key, Shift);

  inherited KeyDown (Key, Shift);

  { 2/25/98 }
  if wwIsValidChar(Key) and (not Editable) then key:= 0;
//  if (Key in [32..255]) and (not Editable) then key:=0;

end;

procedure TwwDBCustomCombo.KeyPress(var Key: Char);
begin
  { Disregard tab key since inherited maskedit event will beep }
  if isMasked and (Key=#9) then exit;
  inherited KeyPress(Key);
end;

procedure TwwDBCustomCombo.WMLButtonDown(var Message: TWMLButtonDown);
begin
  if MouseEditable then
    inherited
  else
    NonEditMouseDown (Message);
end;

procedure TwwDBCustomCombo.WMLButtonDblClk(var Message: TWMLButtonDblClk);
begin
  if MouseEditable then
    inherited
  else
    NonEditMouseDown (Message);
end;

procedure TwwDBCustomCombo.WMLButtonUp(var Message: TWMLButtonUp);
begin
  if not MouseEditable then MouseCapture := False;
  inherited;
end;

procedure TwwDBCustomCombo.NonEditMouseDown(var Message: TWMLButtonDown);
var
  CtrlState: TControlState;
begin
  // 3/15/02 - Remove dependency upon grid
  if (parent=nil) or
     (not wwIsClass(parent.classtype, 'TwwCustomDBGrid')) then
  begin
     if not IsVistaComboNonEditable then
     begin
        SetFocus;
        if (not IsDroppedDown) and (not Focused) then
        begin
           with Message do
              MouseDown(mbLeft, KeysToShiftState(Keys), XPos, YPos);
           exit; // 12/15/03 - If did not receive focus then don't dropdown
        end;
     end;
  end;

  if isDroppedDown then CloseUp(True)
  else DropDown;

  if csClickEvents in ControlStyle then
  begin
    CtrlState := ControlState;
    Include(CtrlState, csClicked);
    ControlState := CtrlState;
  end;
  with Message do
    MouseDown(mbLeft, KeysToShiftState(Keys), XPos, YPos);
end;

Procedure TwwDBCustomCombo.DrawButton(Canvas: TCanvas; R: TRect; State: TButtonState;
       ControlState: TControlState; var DefaultPaint: boolean);
var Transparent: boolean;
begin
   if ButtonStyle=cbsCustom then exit;

   DefaultPaint:= False;
   Transparent:=  FButton.Flat and
      (not FMouseInButtonControl) and not (FFocused);
   if ButtonStyle=cbsDownArrow then
      wwDrawDropDownArrow(Canvas, R, State, Enabled, ControlState)
   else begin
      wwDrawEllipsis(Canvas, R, State, Enabled, Transparent,
         ButtonEffects.Transparent {and ButtonEffects.Flat},
         ControlState)
   end
end;

constructor TBtnWinControl.Create(AOwner: TComponent);
begin
   inherited Create(AOwner);
   EditControl:= AOwner as TwwDBCustomCombo;
end;

procedure TBtnWinControl.CMMouseEnter(var Message: TMessage);
begin
  inherited;
end;

procedure TBtnWinControl.CMMouseLeave(var Message: TMessage);
var r: TRect;
    offset: integer;
begin
  inherited;
  if not EditControl.ButtonEffects.Flat then exit;

  if EditControl.BorderStyle=bsSingle then offset:=2 else offset:= 0;
  if not EditControl.FFocused then begin
     if EditControl.IsTransparentEffective then begin
        r:= Rect(parent.left + Left + offset, parent.Top+top+offset,
                 parent.left + left + offset + Width, parent.top + offset + Top + Height);
        if wwIsTransparentParent(self) then
          wwInvalidateTransparentArea(self, false) // just to be safer, but probably works in both cases
        else
          InvalidateRect(parent.parent.handle, @r, True);
        Invalidate;
     end;
     Invalidate;
  end
end;

function TwwComboDlgButton.IsVistaTransparentButton: boolean;
var combo: TwwDBCustomCombo;
begin
   combo:= TwwDBCustomCombo(parent.parent);
   if wwUseThemes(self) and IsVista and not IsVistaComboNonEditable and
      not (combo.Frame.Enabled and combo.Frame.Transparent) then
      result:= true
   else
      result:=false;
end;

function TwwComboDlgButton.IsVistaComboNonEditable: boolean;
begin
   result:= twwdbCustomCombo(parent.parent).IsVistaComboNonEditable;
end;

function TwwComboDlgButton.ParentMouseInControl: boolean;
begin
   result:= twwdbCustomCombo(parent.parent).MouseInControl;
end;

function TwwComboDlgButton.ParentDroppedDown: boolean;
begin
   result:= twwdbCustomCombo(parent.parent).IsDroppedDown;
end;

procedure TwwComboDlgButton.Paint;
var R : TRect;
    DefaultPaint: boolean;
begin
   if twwdbCustomCombo(parent.parent).SkipUpdate then exit;

   if (csPaintCopy in ControlState) and
      not (csDesigning in ComponentState) and IsInGrid(parent.parent) then exit;

   SetRect(R, 0, 0, ClientWidth, ClientHeight);
   with TwwDBCustomCombo(Parent.Parent) do
   begin
      DefaultPaint:= True;
      FMouseInButtonControl:= self.MouseInControl;

      if (FButton.Glyph.Handle=0) or self.MouseInControl or
         FFocused or wwisClass(Parent.classType, 'TwwDBGrid') then
         if not (ButtonEffects.Transparent and (ButtonStyle=cbsDownArrow)) then
           if not wwUseThemes(self.parent.parent) then
           begin
              DrawButton(Canvas, R, FState, ControlState, DefaultPaint);
           end;

      if DefaultPaint then begin
         Ellipsis:= ButtonStyle = cbsEllipsis;
         inherited Paint;
      end;

      { Draw edges  }
      if self.MouseInControl or (not ButtonEffects.Flat) or
         FFocused or wwisClass(Parent.classType, 'TwwDBGrid') then
      begin
         if not wwUseThemes(self.parent.parent) then
         begin
           if FState=bsDown then
              DrawEdge(Canvas.Handle, R, EDGE_SUNKEN, BF_RECT)
           else
              DrawEdge(Canvas.Handle, R, EDGE_RAISED, BF_RECT)
         end
      end

   end
end;

procedure TwwDBCustomCombo.SetButtonStyle(val: TwwComboButtonStyle);
begin
   if val<>FButtonStyle then begin
      FButtonStyle:= val;
      UpdateButtonGlyph;
      FButton.Invalidate;
   end
end;

Function TwwDBCustomCombo.IsDroppedDown: boolean;
begin
   result:= FDroppedDown;
end;

procedure TwwDBCustomCombo.Loaded;
begin
  if FButtonWidth=0 then
     FButton.Width:= wwmax(GetSystemMetrics(SM_CXVSCROLL), 15);
  if (parent<>Nil) or (owner<>nil) then  { 11/17/97 - parent=nil causes runtime error }
     UpdateButtonPosition;
  inherited Loaded;
end;

procedure TwwDBCustomCombo.CMEnabledChanged(var Message: TMessage);
begin
  inherited;
  FButton.Enabled := Enabled;
end;

procedure TwwDBCustomCombo.WMSetFocus(var Message: TWMSetFocus);
begin
  inherited;
  Invalidate;
end;

procedure Register;
begin
{  RegisterComponents('InfoPower', [TwwDBComboDlg]);}
end;

procedure TwwDBCustomCombo.InvalidateTransparentButton;
var r: TRect;
begin
   if ButtonEffects.Flat or ButtonEffects.Transparent then begin
     with FBtnControl do begin
         r:= Rect(parent.left + Left, parent.Top+top,
               parent.left + left+ Width, parent.top + Top + Height);
        { Calling with True causes flicker for any control that is invalidated.
          Test with False to see if any side effects  }
         InvalidateRect(parent.parent.handle, @r, False);
         if not wwIsTransparentParent(self) then
            parent.parent.Update;
      end
   end;
   FButton.invalidate;
end;

procedure TwwComboDlgButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
  X, Y: Integer);
begin
   inherited MouseUp(Button, Shift, X, Y);
   TwwDBComboDlg(parent.parent).InvalidateTransparentButton;
end;

procedure TwwComboDlgButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
  X, Y: Integer);
var dropDownListVisible: boolean;
begin

  if TwwDBComboDlg(Parent.Parent).Patch[2]=True then
  begin
     inherited MouseDown (Button, Shift, X, Y);
     TwwDBComboDlg(parent.parent).InvalidateTransparentButton;
     exit;
  end;

  with TwwDBComboDlg(Parent.Parent) do
  begin

    dropDownListVisible:= IsDroppedDown;

    if isDroppedDown then
    begin
      if (Handle <> GetFocus) and CanFocus then
      begin
        SetFocus;
        if GetFocus <> Handle then Exit;
      end;
    end;
  end;
  inherited MouseDown (Button, Shift, X, Y);
  if not wwIsTransparentParent(Parent.Parent) then
     Update;  { 4/17/98 - Finish drawing down state }

  with TwwDBComboDlg(Parent.Parent) do
  begin
    if not dropDownListVisible and isDroppedDown then exit; {skip remaining code }

    if IsDroppedDown then begin
//      if InList then GridClick(self);  {Now hiding drop down so select current selection } {5/14/97 - if InList}
      CloseUp(True)
    end
    else
    begin
      DropDown;
    end;
  end;


end;

procedure TwwDBCustomCombo.CMExit(var Message: TCMExit);
begin
   inherited;
   if ButtonEffects.Flat then FButton.invalidate;
end;

procedure TwwDBCustomCombo.CMEnter(var Message: TCMEnter);
begin
   inherited;
   if ButtonEffects.Flat then begin
      UpdateButtonPosition;
      FButton.invalidate;
   end
end;

function TwwDBCustomCombo.IsCustom: Boolean;
begin
  Result := ButtonStyle = cbsCustom;
end;

function TwwDBCustomCombo.GetButtonGlyph: TBitmap;
begin
  result:= FButton.Glyph;
end;

procedure TwwDBCustomCombo.SetButtonGlyph(Value: TBitmap);
begin
  FButton.Glyph.Assign(Value);
  Invalidate;
end;

Procedure TwwDBCustomCombo.SetButtonWidth(val: integer);
begin
   if FButtonWidth<>val then
   begin
      FButtonWidth:= val;
      if val<>0 then Button.Width:= val
      else Button.Width:= wwmax(GetSystemMetrics(SM_CXVSCROLL), 15);
      UpdateButtonPosition;
   end
end;

function TwwDBCustomCombo.GetButtonWidth: integer;
begin
   result:= FButtonWidth;
end;

function TwwDBCustomCombo.IsVistaComboNonEditable: boolean;
begin
   result:= inherited IsVistaComboNonEditable;
   if result and ButtonEffects.Flat then
      result:=false;
end;


class constructor TwwDBComboDlg.Create;
begin
  TCustomStyleEngine.RegisterStyleHook(TwwDBComboDlg, TwwEditStyleHook);
end;


end.
