2017-08-11 14 views
3

私はIP編集を実装しようとしています。この私のコード:コントロールが自分の幅を変更するが、内部の幅は変更しない:変更幅SysIPAddress32

unit Main; 

interface 

uses 
    System.SysUtils, System.Classes, 
    Winapi.Windows, Winapi.Messages, Winapi.CommCtrl, 
    Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.StdCtrls, Vcl.ComCtrls; 

type 

    TIpEdit = class(TWinControl) 
    strict protected 
    procedure CreateParams(var Params: TCreateParams); override; 
    procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE; 
    procedure WMSetFont(var Message: TWMSetFont); message WM_SETFONT;  
    end; 

    TMainForm = class(TForm) 
    Btn1: TButton; 
    procedure FormCreate(Sender: TObject); 
    procedure Btn1Click(Sender: TObject); 
    private 
    FIpEdit: TIpEdit; 
    public 
    { Public declarations } 
    end; 

var 
    MainForm: TMainForm; 

implementation 

{$R *.dfm} 

{ TIPEdit } 

procedure TIPEdit.CreateParams(var Params: TCreateParams); 
begin 
    InitCommonControl(ICC_INTERNET_CLASSES); 
    inherited CreateParams(Params); 
    CreateSubClass(Params, WC_IPADDRESS); 
    Params.Style := Params.Style or WS_TABSTOP or WS_CHILD; 
end; 

procedure TIPEdit.WMGetDlgCode(var Message: TWMGetDlgCode); 
begin 
    inherited; 
    Message.Result := Message.Result or DLGC_WANTARROWS; 
end; 

procedure TIPEdit.WMSetFont(var Message: TWMSetFont); 
var 
    LF: LOGFONT; 
begin 
    if GetObject(Message.Font, SizeOf(LF), @LF) <> 0 then 
    begin 
    Message.Font := CreateFontIndirect(LF); 
    inherited; 
    end; 
end; 

{ TMainForm } 

procedure TMainForm.Btn1Click(Sender: TObject); 
begin 
    FIpEdit.Width := FIpEdit.Width + 100; 
end; 

procedure TMainForm.FormCreate(Sender: TObject); 
begin 
    FIpEdit := TIpEdit.Create(Self); 
    FIpEdit.Parent := Self; 
    FIpEdit.SetBounds(10, 10, 120, 21); 
end; 

end. 

Btn1.Click

enter image description here

結果Btn1.Click

enter image description here

前後編集。

は、私は2つの方法

  • 使用RecreateWnd

    で修正をしてみてください。これは動作しますが、IMHOはその醜い解決策です。
  • 内部編集幅を手動で修正しました。これは動作しますが、たぶん私は何かを逃し、簡単な解決策があるため、制御

の内部作業に、実装 に難しいですか?

は編集:

は私がRecreateWndをテストしたが、DevExpress社のレイアウトコントロールを使用する際には使用できません。レイアウトコントロールは、SetBoundsメソッドをバイパスするAPIの直接呼び出しを使用するようです。この場合RecreateWndは使用できません。

最終的な結論は次のとおりです。

  • RecreateWndは、いくつかのristrictionsでシンプルなソリューション
  • あるRepeatUntil answerより難しいが、常に制御を更新するためのメカニズムを提供していません
+0

VCLの多くは、ウィンドウの変更を適用するために 'RecreateWnd'を使用しています。時には最適なソリューションではないかもしれませんが、醜い解決策ではありません。 –

答えて

0

子供TEditのコントロールを使ってTPanelを使用すると、独自のIP編集を作成することができます。これにより、そのプロパティをより詳細に制御できます。 enter image description here

私は、この時間の前にその完了していない作品を書いたが、私は何を意味するかのアイデアを与えることがあります。実行時にその表情がどのように

これ。

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. 
2

作業作成後のレイアウト。はい、あなたは内部編集コントロールをハックすることができますが、それは危険です。変更が必要な文書化されていない実装の詳細に頼ることになります。

要約すると、私はウィンドウを再作成することが利用可能な最良の解決策であると言います。

関連する問題