delphi dev 关于cxDropDownEdit 下拉记忆高度宽度的思路

TcxLookupComboBox 或者其他下拉空间,都是继承这个 cxDropDownEdit

cxDropDownEdit.pas

下拉触发流程:

procedure TcxCustomDropDownEdit.DoButtonDown(AButtonVisibleIndex: Integer);
begin
  inherited DoButtonDown(AButtonVisibleIndex);
  if AButtonVisibleIndex = ActiveProperties.DropDownButtonVisibleIndex then
    DroppedDown := True; //这里触发
end;

procedure TcxCustomDropDownEdit.SetDroppedDown(Value: Boolean);
var
  AMsg: TMsg;
begin
  if DroppedDown <> Value then
    if not Value then
      CloseUp(crUnknown)
    else
      if not PeekMessage(AMsg, PopupWindow.Handle, DXM_SHOWPOPUPWINDOW, DXM_SHOWPOPUPWINDOW, PM_NOREMOVE) then
        DropDown;
end;


procedure TcxCustomDropDownEdit.DropDown;
begin
  if not IsWindowVisible(Handle) then
    Exit;
  DoInitPopup;
  if CanDropDown then
  begin   
    SetupPopupWindow;  //这里触发InitializePopupWindow;
    PopupWindow.HandleNeeded;
    PopupWindow.FocusedControl := GetPopupFocusedControl;
    PostMessage(PopupWindow.Handle, DXM_SHOWPOPUPWINDOW, 0, 0);
  end
  else
    DoFinalizePopup;
end;


procedure TcxCustomDropDownEdit.SetupPopupWindow;
var
  P: TPoint;
  AParentForm: TCustomForm;
begin
  PopupWindow.CaptureFocus := ActiveProperties.PopupWindowCapturesFocus;
  InitializeLookupData;
  InitializePopupWindow; //这里读取
  PopupWindow.LockCheckSize;
  try
    PopupWindow.CalculateSize;
    P := PopupWindow.CalculatePosition;
    PopupWindow.CorrectBoundsWithDesktopWorkArea(P);
  finally
    PopupWindow.UnLockCheckSize;
  end;
  PopupWindow.SetBounds(P.X, P.Y, PopupWindow.Width, PopupWindow.Height);
  PopupWindow.RefreshPopupWindow;
  PositionPopupWindowChilds(PopupWindow.ViewInfo.ClientRect);
  SetEditPopupWindowShadowRegion(PopupWindow);

  if IsWinXPOrLater then // W2K bug
  begin
    AParentForm := GetParentForm(Self);
    if AParentForm <> nil then
    begin
      PopupWindow.AlphaBlend := TCustomFormAccess(AParentForm).AlphaBlend;
      PopupWindow.AlphaBlendValue := TCustomFormAccess(AParentForm).AlphaBlendValue;
      PopupWindow.TransparentColor := TCustomFormAccess(AParentForm).TransparentColor;
      PopupWindow.TransparentColorValue := TCustomFormAccess(AParentForm).TransparentColorValue;
    end;
  end;
end;


procedure TcxCustomDropDownEdit.InitializePopupWindow;
begin
  PopupWindow.OwnerParent := Parent;
  with ActiveProperties do
  begin
    PopupWindow.Direction := PopupDirection;
    PopupWindow.AlignHorz := PopupHorzAlignment;
    PopupWindow.AlignVert := PopupVertAlignment;
    PopupWindow.ClientEdge := PopupClientEdge;
    PopupWindow.MinHeight := PopupMinHeight;
    PopupWindow.MinWidth := PopupMinWidth;
    PopupWindow.PopupAutoSize := PopupAutoSize;
    PopupWindow.Sizeable := PopupSizeable;
    PopupWindow.SysPanelStyle := PopupSysPanelStyle;
  end;

  PopupWindow.PopupWidth := GetPopupWidth;
  PopupWindow.PopupHeight := GetPopupHeight;

  PopupWindow.CloseButton := TcxCustomEditStyleAccess(ActiveStyle).PopupCloseButton;

  with ViewInfo do
  begin
    PopupWindow.BorderStyle := PopupBorderStyle;
    PopupWindow.NativeStyle := NativeStyle;
    PopupWindow.Shadow := Shadow;
  end;
end;

//这里如果是能改变大小的话是读取editdata的 改动后也是保存在editdata
function TcxCustomDropDownEdit.GetPopupWidth: Integer;
begin
  if IsInplace and ActiveProperties.PopupSizeable then
    Result := TcxCustomDropDownEditData(EditData).Width //这里控件创建成功后会读取 Properties.DropDownWidth 但也只限在创建初始化时,后续都是读取在editdata里。也可以用在同单元type一下这个类然后就可以操作editdata了
  else
    Result := ActiveProperties.PopupWidth;
end;

procedure TcxCustomEditPopupWindow.ResizePopupWindow(ALeft, ATop, AWidth, AHeight: Integer);
begin
  Edit.FPopupSizeChanged := True;
  SetBounds(ALeft, ATop, AWidth, AHeight);
  RefreshPopupWindow;
  Edit.StorePopupSize;
end;
//保存
procedure TcxCustomDropDownEdit.StorePopupSize;
begin
  if ActiveProperties.PopupSizeable then
    if IsInplace then
    begin
      if EditData <> nil then
        with TcxCustomDropDownEditData(EditData) do
        begin
          Initialized := True;
          Width := PopupWindow.Width;
          Height := PopupWindow.Height;
        end
    end else
    begin
      with ActiveProperties do
      begin
        PopupWidth := PopupWindow.Width;
        PopupHeight := PopupWindow.Height;
      end;
    end;
end;

整体思路:
1.控件创建后,先设置一下 Properties.DropDownWidth Properties.DropDownHeight
2.然后在closeup时写入,不要在窗口销毁或者关闭时 去循环每个控件记录这样慢。直接在closeup后保存就可以。目前选择的是下面的方案,其实哪个都可以能记忆就行

目前保存宽度信息是hook了,其实也可以hook TcxCustomDropDownEdit.CloseUp
HookProc(@TcxCustomPopupWindow.CloseUp, @cxCustomPopupWindowCloseUpCallBack, @cxCustomPopupWindowCloseUpNext);

TcxCustomDropDownEdit.CloseUp
会触发 PopupWindow.CloseUp;
hook了 TcxCustomPopupWindow.CloseUp

 

要全局处理的思路:
1.hook procedure TcxCustomDropDownEdit.DropDown;
 设置 Properties.DropDownWidth Properties.DropDownHeight 或者修改EditData
 因为EditData是 protected的,所以在目标单元里先type一下为其他的类名(同名也可以但是最好还是不要一样)
2.hook  TcxCustomDropDownEdit.CloseUp 读取EditData 的Width,Height 到ini即可
// 修改EditData 的方法
uses
  cxEdit,cxDropDownEdit;

type
  TcxCustomDropDownEditAccess  = class(cxDropDownEdit.TcxCustomDropDownEdit)
  public
//     function EditDataAccess:TcxCustomEditData;
    procedure SetEditData(aWidth, aHeight: Integer);
  end;
  TcxCustomDropDownEditDataAccess    = class(cxDropDownEdit.TcxCustomDropDownEditData)
//  public
//    Initialized: Boolean;
//    Width, Height: Integer;
  end; 
  
//多开放出一个修改EditData 的过程出来。
procedure TcxCustomDropDownEditAccess.SetEditData(aWidth, aHeight: Integer);
begin
 with TcxCustomDropDownEditDataAccess(EditData) do
 begin
  Initialized := True;
  if aWidth > 0 then
  Width := aWidth;
  if aHeight > 0 then
   aHeight := Height;
 end;
end;  

 不明白为啥本身不提供这种功能,设置个保存的路径,自动保存就可以。甚至可以加个开关要不要自动保存。

补充:
seteditdata还不够还要设置 Properties,不然输入时宽度会不对

cbb.Properties.DropDownWidth := PopupWindowWidth;
cbb.Properties.DropDownHeight := PopupWindowHeight;

posted @ 2026-08-08 13:51  Tag  阅读(3)  评论(0)    收藏  举报