Delphi 更改SysIPAddress32的宽度

Delphi 更改SysIPAddress32的宽度,delphi,winapi,Delphi,Winapi,我正在尝试实现IP编辑。这是我的代码: unitmain; 接口 使用 System.SysUtils、System.class、, Winapi.Windows、Winapi.Messages、Winapi.CommCtrl、, Vcl.图形、Vcl.控件、Vcl.窗体、Vcl.StdCtrls、Vcl.ComCtrls; 类型 TIpEdit=类(TWinControl) 严格保护 过程CreateParams(变量参数:TCreateParams);推翻 过程WMGetDlgCode(va

我正在尝试实现IP编辑。这是我的代码:

unitmain;
接口
使用
System.SysUtils、System.class、,
Winapi.Windows、Winapi.Messages、Winapi.CommCtrl、,
Vcl.图形、Vcl.控件、Vcl.窗体、Vcl.StdCtrls、Vcl.ComCtrls;
类型
TIpEdit=类(TWinControl)
严格保护
过程CreateParams(变量参数:TCreateParams);推翻
过程WMGetDlgCode(var消息:TWMGetDlgCode);消息WM_GETDLGCODE;
程序WMSetFont(var消息:TWMSetFont);消息WM_SETFONT;
结束;
TMainForm=类(TForm)
Btn1:TButton;
过程表单创建(发送方:ToObject);
程序Btn1Click(发送方:TObject);
私有的
第五部分:第三部分;
公众的
{公开声明}
结束;
变量
主要形式:TMA通知;
实施
{$R*.dfm}
{TIPEdit}
过程TIPEdit.CreateParams(变量参数:TCreateParams);
开始
InitCommonControl(国际商会互联网课程);
继承的CreateParams(Params);
CreateSubClass(参数,WC_IPADDRESS);
Params.Style:=Params.Style或WS_TABSTOP或WS_CHILD;
结束;
过程TIPEdit.WMGetDlgCode(变量消息:TWMGetDlgCode);
开始
继承;
Message.Result:=Message.Result或DLGC_WANTARROWS;
结束;
程序TIPEdit.WMSetFont(变量消息:TWMSetFont);
变量
LF:LOGFONT;
开始
如果GetObject(Message.Font,SizeOf(LF),@LF)为0,则
开始
Message.Font:=CreateFontIndirect(LF);
继承;
结束;
结束;
{tma}
程序TMainForm.Btn1Click(发送方:TObject);
开始
五分之一宽度:=五分之一宽度+100;
结束;
程序TMAInformCreate(发送方:ToObject);
开始
FIpEdit:=TIpEdit.Create(Self);
五、家长:=本人;
五个立根(10,10,120,21);
结束;
结束。
在Btn1之前。单击

在Btn1之后。单击

结果:控件更改自身宽度,但不更改内部编辑的宽度

我试着用两种方法来解决这个问题

  • 使用RecreateWnd。这是可行的,但我认为这是一个丑陋的解决方案
  • 手动固定内部宽度。这是可行的,但很难实现 实施,由于内部工作的控制
也许我错过了什么,有一个更简单的解决办法吗

编辑:

我测试了重新创建的WND,但在使用DevExpress布局控件时无法使用它。布局控件似乎绕过SetBounds方法使用API的直接调用。在这种情况下,不能使用重新创建的WND

最后的结论是:

  • RecreateWnd是一个简单的解决方案,有一些限制
  • 重复,直到更困难,但总是工作

控件在创建后不提供更新其布局的机制。是的,你可以破解内部编辑控件,但那是危险的。您将依赖于可能发生更改的未记录的实现细节


总之,我认为重新创建窗口是最好的解决方案

您可以将
TPanel
与子
TEdit
控件一起使用,创建您自己的IP编辑,这将使您能够更好地控制其属性

这是它对运行时的看法:

我在这段时间前写过,它还没有完成,但可能会让我明白我的意思

unit IPEdit;

interface

uses
  System.SysUtils, System.Classes, Vcl.Controls, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Forms,
  Vcl.Graphics, System.UITypes;

type
  TExitType = (etNone, etNext);

type
  TIPEdit = class(TCustomPanel)
  private
    FPart1      : TEdit;
    FPart2      : TEdit;
    FPart3      : TEdit;
    FPart4      : TEdit;
    FSplitter1  : TPanel;
    FSplitter2  : TPanel;
    FSplitter3  : TPanel;
    FRiseErr    : Boolean;
    FErrMsg     : string;
    FExitType   : TExitType;
    FBevelInner : TPanelBevel;
    FLeadingzero: Boolean;
    procedure SetExitType(Value : TExitType);
    procedure SetBevelInner(Value: TPanelBevel);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  protected
    procedure EditOnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure EditOnChange(Sender: TObject);
    procedure OnPanelResize(Sender: TObject);
    procedure EditOnExit(Sender: TObject);
  published
    property ShowError: Boolean read FRiseErr write FRiseErr default False;
    property Leadingzero: Boolean read FLeadingzero write FLeadingzero default False;
    property ErrorText: string read FErrMsg write FErrMsg;
    property ExitType: TExitType read FExitType write SetExitType default etNext;
    property BevelInner: TPanelBevel read FBevelInner write SetBevelInner default bvNone;
  end;


implementation

const
  Msg_Err_Value_Exceeded  = 'Value cannot be greater than 255';
  SplitterWidth  = 5;

{ TIPEdit }

constructor TIPEdit.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  if AOwner is TWinControl then
    Parent           := TWinControl(AOwner);
  { Main Panle Style }
  ParentBackground := False;
  BevelKind        := bkFlat;
  BevelOuter       := bvNone;
  Color            := clWindow;
  Height           := 25;
  Width            := 165;
  Caption          := '';
  /////////////////////////////

  { Set Handlers}
  OnResize := OnPanelResize;

  { Create child controls }
  FPart1            := TEdit.Create(Self);
  FPart1.Name       := 'IPEditPart1';
  FPart1.Visible    := False;
  FSplitter1        := TPanel.Create(Self);
  FSplitter1.Name   := 'IPSplitter1';
  FSplitter1.Visible:= False;
  FPart2            := TEdit.Create(Self);
  FPart2.Name       := 'IPEditPart2';
  FPart2.Visible    := False;
  FSplitter2        := TPanel.Create(Self);
  FSplitter2.Name   := 'IPSplitter2';
  FSplitter2.Visible:= False;
  FPart3            := TEdit.Create(Self);
  FPart3.Name       := 'IPEditPart3';
  FPart3.Visible    := False;
  FSplitter3        := TPanel.Create(Self);
  FSplitter3.Name   := 'IPSplitter3';
  FSplitter3.Visible:= False;
  FPart4            := TEdit.Create(Self);
  FPart4.Name       := 'IPEditPart4';
  FPart4.Visible    := False;
  FPart1.Align      := alLeft;
  FSplitter1.Align  := alLeft;
  FPart2.Align      := alLeft;
  FSplitter2.Align  := alLeft;
  FPart3.Align      := alLeft;
  FSplitter3.Align  := alLeft;
  FPart4.Align      := alLeft;
  /////////////////////////////

  { Set Child Style }
  // This order is very important //
  FPart1.Parent           := TWinControl(Self);
  FSplitter1.Parent       := TWinControl(Self);
  FPart2.Parent           := TWinControl(Self);
  FSplitter2.Parent       := TWinControl(Self);
  FPart3.Parent           := TWinControl(Self);
  FSplitter3.Parent       := TWinControl(Self);
  FPart4.Parent           := TWinControl(Self);
  FPart1.Visible          := True;
  FSplitter1.Visible      := True;
  FPart2.Visible          := True;
  FSplitter2.Visible      := True;
  FPart3.Visible          := True;
  FSplitter3.Visible      := True;
  FPart4.Visible          := True;
  //////////////////////////////////


  FPart1.Alignment             := taCenter;
  FPart2.Alignment             := taCenter;
  FPart3.Alignment             := taCenter;
  FPart4.Alignment             := taCenter;



  FPart1.Margins.Left          := 0;
  FPart2.Margins.Left          := 0;
  FPart3.Margins.Left          := 0;
  FPart4.Margins.Left          := 0;
  FSplitter1.Margins.Left      := 0;
  FSplitter2.Margins.Left      := 0;
  FSplitter3.Margins.Left      := 0;
  FPart1.Margins.Right         := 0;
  FPart2.Margins.Right         := 0;
  FPart3.Margins.Right         := 0;
  FPart4.Margins.Right         := 0;
  FSplitter1.Margins.Right     := 0;
  FSplitter2.Margins.Right     := 0;
  FSplitter3.Margins.Right     := 0;


  FPart1.AlignWithMargins      := True;
  FSplitter1.AlignWithMargins  := True;
  FPart2.AlignWithMargins      := True;
  FSplitter2.AlignWithMargins  := True;
  FPart3.AlignWithMargins      := True;
  FSplitter3.AlignWithMargins  := True;
  FPart4.AlignWithMargins      := True;
  FPart1.AutoSize              := False;
  FPart2.AutoSize              := False;
  FPart3.AutoSize              := False;
  FPart4.AutoSize              := False;
  FPart1.BorderStyle           := bsNone;
  FPart2.BorderStyle           := bsNone;
  FPart3.BorderStyle           := bsNone;
  FPart4.BorderStyle           := bsNone;
  FPart1.NumbersOnly           := True;
  FPart2.NumbersOnly           := True;
  FPart3.NumbersOnly           := True;
  FPart4.NumbersOnly           := True;
  FPart1.MaxLength             := 3;
  FPart2.MaxLength             := 3;
  FPart3.MaxLength             := 3;
  FPart4.MaxLength             := 3;
  FPart1.Width                 := 36;
  FPart2.Width                 := 36;
  FPart3.Width                 := 36;
  FPart4.Width                 := 36;
  FSplitter1.Alignment         := taCenter;
  FSplitter2.Alignment         := taCenter;
  FSplitter3.Alignment         := taCenter;
  FSplitter1.Caption           := '.';
  FSplitter2.Caption           := '.';
  FSplitter3.Caption           := '.';
  FSplitter1.BevelOuter        := bvNone;
  FSplitter2.BevelOuter        := bvNone;
  FSplitter3.BevelOuter        := bvNone;
  FSplitter1.Color             := clWindow;
  FSplitter2.Color             := clWindow;
  FSplitter3.Color             := clWindow;
  FSplitter1.ParentBackground  := False;
  FSplitter2.ParentBackground  := False;
  FSplitter3.ParentBackground  := False;
  FSplitter1.TabStop           := False;
  FSplitter2.TabStop           := False;
  FSplitter3.TabStop           := False;
  FSplitter1.Width             := SplitterWidth;
  FSplitter2.Width             := SplitterWidth;
  FSplitter3.Width             := SplitterWidth;
  FSplitter1.Font.Style        := FSplitter1.Font.Style + [fsBold];
  FSplitter2.Font.Style        := FSplitter2.Font.Style + [fsBold];
  FSplitter3.Font.Style        := FSplitter3.Font.Style + [fsBold];
  //////////////////////////////

  {Set Child handlers}
  FPart1.OnChange  := EditOnChange;
  FPart2.OnChange  := EditOnChange;
  FPart3.OnChange  := EditOnChange;
  FPart4.OnChange  := EditOnChange;
  FPart1.OnKeyDown := EditOnKeyDown;
  FPart2.OnKeyDown := EditOnKeyDown;
  FPart3.OnKeyDown := EditOnKeyDown;
  FPart4.OnKeyDown := EditOnKeyDown;
  FPart1.OnExit    := EditOnExit;
  FPart2.OnExit    := EditOnExit;
  FPart3.OnExit    := EditOnExit;
  FPart4.OnExit    := EditOnExit;

  {Set Child control tab order for the handlers work}
  FPart1.TabOrder := 0;
  FPart2.TabOrder := 1;
  FPart3.TabOrder := 2;
  FPart4.TabOrder := 3;

  FPart1.Text := '1';
  FPart2.Text := '2';
  FPart3.Text := '3';
  FPart4.Text := '4';

  FExitType := etNext;
  FErrMsg   := Msg_Err_Value_Exceeded;
end;

destructor TIPEdit.Destroy;
begin
  FPart1.Free;
  FPart2.Free;
  FPart3.Free;
  FPart4.Free;

  FSplitter1.Free;
  FSplitter2.Free;
  FSplitter3.Free;
  inherited;
end;

procedure TIPEdit.EditOnChange(Sender: TObject);
var
  iValue     : Integer;
  bValGrater : Boolean;
  I: Integer;
begin
  if NOT (Sender is TEdit) then Exit;
  bValGrater := False;
  if TryStrToInt(TEdit(Sender).Text, iValue) then begin
    if (iValue > 255) then begin
      iValue     := 255;
      bValGrater := True;
      TEdit(Sender).Text := iValue.ToString;
      if (FRiseErr and bValGrater) then
        raise Exception.Create(FErrMsg);
    end;
  end;
  if Length(TEdit(Sender).Text) = 3 then begin
    case FExitType of
      etNone: ;
      etNext: FindNextControl(TEdit(Sender), True, False, False).SetFocus;
    end;
  end;
end;

procedure TIPEdit.EditOnKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
const
    vkReturn  = $0D;
begin
  if not (Sender is TEdit) then Exit;
  if Key = vkReturn then
    FindNextControl(TEdit(Sender), True, False, False).SetFocus;
end;

procedure TIPEdit.OnPanelResize(Sender: TObject);
const
  EditCount      = 4;
  SplitterCount  = 3;
var
  EditWidth      : Integer;
  FSplitterWidth : Integer;
  EditMargin     : Integer;
begin
  EditWidth := Trunc(((Width) / EditCount) - (SplitterCount * (SplitterWidth)));
  FPart1.Width := EditWidth;
  FPart2.Width := EditWidth;
  FPart3.Width := EditWidth;
  FPart4.Width := EditWidth;
  FSplitterWidth := Trunc(( (Width) - ( EditWidth * EditCount) ) / SplitterCount);
  FSplitter1.Width := FSplitterWidth;
  FSplitter2.Width := FSplitterWidth;
  FSplitter3.Width := FSplitterWidth;

  {Center edits text vertically == this is a temporary workaround}
  FPart1.Margins.Top := 0;
  FPart2.Margins.Top := 0;
  FPart3.Margins.Top := 0;
  FPart4.Margins.Top := 0;
  EditMargin := Round( ((Height / 5)));
  FPart1.Margins.Top    := EditMargin;
  FPart2.Margins.Top    := EditMargin;
  FPart3.Margins.Top    := EditMargin;
  FPart4.Margins.Top    := EditMargin;
  FSplitter1.Margins.Top     := EditMargin + SplitterWidth; { the +lblWidth to make it lower than the edits}
  FSplitter2.Margins.Top     := EditMargin + SplitterWidth;
  FSplitter3.Margins.Top     := EditMargin + SplitterWidth;
end;

procedure TIPEdit.SetBevelInner(Value: TPanelBevel);
begin
  TPanel(Self).BevelInner := Value;
end;

procedure TIPEdit.SetExitType(Value: TExitType);
begin
  FExitType := Value;
end;

procedure TIPEdit.EditOnExit(Sender: TObject);
var
  I: Integer;
begin
  if not (Sender IS TEdit) then Exit;
  if FLeadingzero then begin
    if Length(TEdit(Sender).Text) >= 1 then
    for I := Length(TEdit(Sender).Text) to 2 do begin
      TEdit(Sender).Text := '0' + TEdit(Sender).Text;
    end;
  end;
end;

end.

VCL中的很多东西都使用
重新创建wnd
来应用窗口更改。有时这可能不是一个最优的解决方案,但也不是一个丑陋的解决方案。