IP编辑控件(因为封装的是系统自带控件,所以也使用了CreateSubClass,不过为啥要封装CN_COMMAND和CN_NOTIFY不是很明白)
最近需要用一个IP输入控件,网上找了几个,都不符合效果,有些还有一些奇怪的Bug。后来发现原来系统已经提供了IP地址编辑控件,只是系统提供的控件不能设置只读效果。网上找了下资料,封装了一下,自己迂回一下实现了只读效果。
- unit ueIPEdit;
- interface
- uses
- System.SysUtils, System.Classes, Vcl.Controls, Winapi.Windows, Winapi.Messages,
- Vcl.ComCtrls, Winapi.CommCtrl;
- type
- TFieldChangeEvent = procedure(Sender: TObject; OldField, OldValue: Byte) of object;
- TUeIPEdit = class(TWinControl)
- private
- FState: Integer; //Internal use
- FBakIP: Longint; //Internal use
- FMinIP: Longint;
- FMaxIP: Longint;
- FOnChange: TNotifyEvent;
- FOnFieldChange: TFieldChangeEvent;
- procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
- procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;
- protected
- procedure CreateParams(var Params: TCreateParams); override;
- function GetMinIP: String;
- function GetMaxIP: String;
- procedure SetMinIP(const Value: String);
- procedure SetMaxIP(const Value: String);
- procedure UpdateRange;
- function GetIP: String;
- procedure SetIP(const Value: String);
- function GetEmpty: Boolean;
- function GetReadOnly: Boolean;
- procedure SetReadOnly(Value: Boolean);
- function IPToString(const AIp: Longint): String;
- function StringToIP(const Value: String): Longint;
- public
- constructor Create(AOwner: TComponent); override;
- procedure Clear;
- procedure SetActiveField(const Value: Integer);
- property Empty: Boolean read GetEmpty;
- property ReadOnly: Boolean read GetReadOnly write SetReadOnly;
- property IP: String read GetIP write SetIP;
- property MinIP: String read GetMinIP write SetMinIP;
- property MaxIP: String read GetMaxIP write SetMaxIP;
- property OnChange: TNotifyEvent read FOnChange write FOnChange;
- property OnIPFieldChange: TFieldChangeEvent read FOnFieldChange write FOnFieldChange;
- property Font;
- property ParentColor;
- property ParentFont;
- property ParentShowHint;
- property PopupMenu;
- property ShowHint;
- property TabOrder;
- property TabStop;
- property Tag;
- property DragCursor;
- property DragMode;
- property HelpContext;
- end;
- implementation
- uses Vcl.Graphics;
- constructor TUeIPEdit.Create(AOwner: TComponent);
- const
- EditStyle = [csClickEvents, csSetCaption, csDoubleClicks, csFixedHeight, csPannable];
- begin
- inherited Create(AOwner);
- if NewStyleControls then
- ControlStyle := EditStyle else
- ControlStyle := EditStyle + [csFramed];
- ParentColor := False;
- Color := clWindow;
- Width:= 130;
- Height:= 20;
- TabStop:= True;
- FState := 0;
- FBakIP := -1;
- FMinIP:= 0;
- FMaxIP:= $0FFFFFFFF;
- FOnChange:= nil;
- FOnFieldChange:= nil;
- end;
- procedure TUeIPEdit.CreateParams(var Params: TCreateParams);
- begin
- InitCommonControl(ICC_INTERNET_CLASSES);
- inherited CreateParams(Params);
- CreateSubClass(Params, WC_IPADDRESS);
- with Params do
- begin
- Style := WS_VISIBLE or WS_BORDER or WS_CHILD;
- if NewStyleControls and Ctl3D then
- begin
- Style := Style and not WS_BORDER;
- ExStyle := ExStyle or WS_EX_CLIENTEDGE;
- end;
- end;
- end;
- procedure TUeIPEdit.CNNotify(var Message: TWMNotify);
- begin
- if (FState=0) and Assigned(FOnFieldChange) and
- (Message.NMHdr^.code=IPN_FIELDCHANGED) then
- FOnFieldChange(Self, PNMIPAddress(Message.NMHdr)^.iField,
- PNMIPAddress(Message.NMHdr)^.iValue);
- end;
- procedure TUeIPEdit.CNCommand(var Message: TWMCommand);
- begin
- if (Message.NotifyCode = EN_CHANGE) then
- begin
- case FState of
- 0: if Assigned(FOnChange) then FOnChange(Self);
- 1: begin
- FState := 2;
- PostMessage(Handle, IPM_SETADDRESS, 0, FBakIP);
- end;
- 2: FState := 1;
- end;
- end;
- end;
- function TUeIPEdit.IPToString(const AIp: Longint): String;
- begin
- Result:= Format('%d.%d.%d.%d',[FIRST_IPADDRESS(AIp),SECOND_IPADDRESS(AIp),
- THIRD_IPADDRESS(AIp),FOURTH_IPADDRESS(AIp)]);
- end;
- function TUeIPEdit.StringToIp(const Value: String): Longint;
- var
- B: array[0..3] of Byte;
- Strs: TArray<string>;
- i, Cnt : Integer;
- begin
- B[0]:= 0;
- B[1]:= 0;
- B[2]:= 0;
- B[3]:= 0;
- if Value<>'' then
- begin
- Strs := Value.Split(['.'],TStringSplitOptions.ExcludeEmpty);
- try
- Cnt := Length(Strs);
- if Cnt>4 then Cnt := 4;
- for i := 0 to Cnt-1 do
- B[i] := StrToInt(Strs[i]);
- finally
- Strs := nil;
- end;
- end;
- Result:= MakeIPAddress(b[0], b[1], b[2], b[3]);
- end;
- function TUeIPEdit.GetIP: String;
- var
- AIp: Longint;
- begin
- SendMessage(Handle, IPM_GETADDRESS, 0, Longint(@AIp));
- Result:= IPToString(AIp);
- end;
- procedure TUeIPEdit.SetIP(const Value: String);
- begin
- SendMessage(Handle, IPM_SETADDRESS, 0, StringToIp(Value));
- end;
- function TUeIPEdit.GetMinIP: String;
- begin
- Result:= IPToString(FMinIP);
- end;
- procedure TUeIPEdit.SetMinIP(const Value: String);
- var
- AMin: LongInt;
- begin
- AMin := StringToIp(Value);
- if FMinIP<>AMin then
- begin
- FMinIP := AMin;
- UpdateRange;
- end;
- end;
- procedure TUeIPEdit.UpdateRange;
- begin
- SendMessage(Handle, IPM_SETRANGE, 0, MAKEIPRANGE(FIRST_IPADDRESS(FMinIP), FIRST_IPADDRESS(FMaxIP)));
- SendMessage(Handle, IPM_SETRANGE, 1, MAKEIPRANGE(SECOND_IPADDRESS(FMinIP), SECOND_IPADDRESS(FMaxIP)));
- SendMessage(Handle, IPM_SETRANGE, 2, MAKEIPRANGE(THIRD_IPADDRESS(FMinIP), THIRD_IPADDRESS(FMaxIP)));
- SendMessage(Handle, IPM_SETRANGE, 3, MAKEIPRANGE(FOURTH_IPADDRESS(FMinIP), FOURTH_IPADDRESS(FMaxIP)));
- end;
- procedure TUeIPEdit.SetMaxIP(const Value: String);
- var
- AMax: LongInt;
- begin
- AMax := StringToIp(Value);
- if FMaxIP<>AMax then
- begin
- FMaxIP := AMax;
- UpdateRange;
- end;
- end;
- function TUeIPEdit.GetMaxIP: String;
- begin
- Result:= IPToString(FMaxIP);
- end;
- function TUeIPEdit.GetReadOnly: Boolean;
- begin
- Result := FState<>0;
- end;
- procedure TUeIPEdit.SetReadOnly(Value: Boolean);
- begin
- if Value <> GetReadOnly then
- begin
- if Value then
- begin
- SendMessage(Handle, IPM_GETADDRESS, 0, Longint(@FBakIP));
- FState := 1;
- end else begin
- FState := 0;
- end;
- end;
- end;
- function TUeIPEdit.GetEmpty: Boolean;
- begin
- Result:= Boolean(SendMessage(Handle, IPM_ISBLANK, 0, 0));
- end;
- procedure TUeIPEdit.Clear;
- begin
- SendMessage(Handle, IPM_CLEARADDRESS, 0, 0);
- end;
- procedure TUeIPEdit.SetActiveField(const Value: Integer);
- begin
- if (Value < 4) then
- begin
- SendMessage(Handle, IPM_SETFOCUS, wParam(Value), 0);
- end;
- end;
- end.
http://blog.csdn.net/tht2009/article/details/50623816
IP编辑控件(因为封装的是系统自带控件,所以也使用了CreateSubClass,不过为啥要封装CN_COMMAND和CN_NOTIFY不是很明白)的更多相关文章
- 基于wke封装的duilib的webkit浏览器控件,可以c++与js互交,源码及demo下载地址
转载请说明原出处,谢谢~~ 前些日子用wke内核封装了duilib的webkit浏览器控件,好多群里朋友私聊我希望可以我公布源码,今天把这个控件的源码和使用demo公布.其实这个控件封装起来没什么难度 ...
- 示例:WPF中Slider控件封装的缓冲播放进度条控件
原文:示例:WPF中Slider控件封装的缓冲播放进度条控件 一.目的:模仿播放器播放进度条,支持缓冲任务功能 二.进度: 实现类似播放器中带缓存的播放样式(播放区域.缓冲区域.全部区域等样式) 实现 ...
- 使用 WebView2 封装一个生成 PDF 的 WPF 控件
使用 WebView2 封装一个生成 PDF 的 WPF 控件 最近在迁移项目到 .net6,发现项目中用的 PDF 库不支持 .net6,于是想着换一个库.结果找了一大圈,发现不是版本不支持,就是收 ...
- Winform----自定义控件之半透明遮罩(蒙版遮盖指定控件)
先贴运行效果图,源码点击这里下载 1.新建自定义控件 2.实现功能 namespace UserControlLib { [ToolboxBitmap(typeof(ZhLoading)) ...
- 《ASP.NET1200例》解决母版页报错“内容控件必须是内容页中的顶级控件,或是引用母版页的嵌套母版页。”
VS2005下,添加了母版页这个控件,我们可以讲N个页面中共同的部分放在母版页来实现,并让WEB窗体集成自我们的母版页,就可以让我们的站点具有统一的风格了.在VS2005SP1之前的版本中,我们只能创 ...
- <Win32_14>__win32控件(2)__教你自学掌握所有控件的玩法
学习win32 API 编程,我们应该善于利用微软给我们提供的一些辅助工具,例如大家都知道的MSDN.SPY++等等. 今天在讲述之前呢,先给大家介绍一个很有用的工具——Control Spy——它的 ...
- android 给LinearLayout中添加一定数量的控件,并让着一定数量的控件从右到左移动,每隔若干秒停顿一下,最后一个view链接第一个view,然后继续移动循环往复,形成一个死循环简单动画效果
主类:IndexAnimationLinearLayout.java package com.yw.sortlistview; import java.util.ArrayList; import j ...
- FileUpload控件实现单按钮图片自动上传并带预览显示
FileUpload控件实现单按钮图片自动上传并带预览显示 1.实现原理: FileUpload控件默认不支持服务端的ONCHANGE事件,此时用一种变通的方法借用客户端的onchange事件,调 ...
- Android系统UI交互控件Action Bar初探
过年期间,Google正式宣布取消Android系统中MENU键的使用,也就是基于Android 4.0系统的手机都应没有MENU这一固定按键.这无疑是个变革性的改动,在我眼中,这似乎把Android ...
随机推荐
- MFC自绘控件学习总结第二贴---转
首先感谢大家对第一帖的支持,应一些网友烈要求下面我在关于上一贴的一些补充和说明(老鸟可以无视)这一贴是实战+理论不知道第一帖的先看第一帖:http://topic.csdn.net/u/2011071 ...
- java.lang.Math类,方法学习笔记
/**java.lang 包中的Math 类提供有常量 * 并包含有用于执行基本数学运算的 * 方法,如初等指数.对数.平方根 * 用于进行更高级的数学运算.由于 * 在Math 类的方法都是静态的, ...
- 解题报告 HDU1159 Common Subsequence
Common Subsequence Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u ...
- 文件队列 QueueFile
/** * Copyright (C) 2010 Square, Inc. * * Licensed under the Apache License, Version 2.0 (the " ...
- Python用subprocess的Popen来调用系统命令
当我们须要调用系统的命令的时候,最先考虑的os模块.用os.system()和os.popen()来进行操作.可是这两个命令过于简单,不能完毕一些复杂的操作,如给执行的命令提供输入或者读取命令的输出, ...
- svn恢复到之前某个版本号
一直在找svn回滚的方法,这个还是非常有用的,屡试不爽阿 常常因为坑爹的需求,功能要切回到之前的某一个版本号.有两种方法能够实现: 方法1: 用svn merge 1) 先 svn up,保证更新到 ...
- Irrlicht学习之光照的研究
Irrlicht学习之光照的研究 最近研究一下Irrlicht的光照.发现Irrlicht的光照还是比较简单的,相比低于它的OpenGL和Direct3D,设置光源以及设置光照的参数更加人性化(可能是 ...
- hdu 4784 Dinner Coming Soon
spfa+优先队列.刚开始只用的spfa,结果tle到死.然后听队友说要用到优先队列,想了想,对时间分层的话的确每一个结点都只进队列一次即可,因为只有大时间才能更新出小时间,然后就wa成shi了.按队 ...
- 观django-messages包笔记
django_messages是一个提供注册用户之间互相发送消息的django app.最近在研究其实现机制,安装测试非常容易,导入包,配好url以及syncdb生成数据库即可使用. 一.收获一: 我 ...
- mvc导航配置
<?xml version="1.0" encoding="utf-8" ?><Configuration> <Navigatio ...