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 ...
随机推荐
- [LeetCode]题解(python):027-Remove Element
题目来源: https://leetcode.com/problems/remove-element/ 题意分析: 给定一个数组和一个数值val,将数组中数值等于val的数去除.不能申请额外空间,超过 ...
- JQuery 实现返回顶部效果
首先要里了解一下几个知识 $(window).scrollTop() ---滚动条距顶部距离 fadeIn() 方法使用淡入效果来显示被选元素,假如该元素是隐藏的. fadeOut() 方法使用淡出效 ...
- 查找最小的k个元素
题目:输入n个整数,输出其中最小的k个. 例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4. 两种思路,无非就是时间与空间的妥协. 限制空间的时候要对原数组进行排序, ...
- HDFS写入和读取流程
HDFS写入和读取流程 一.HDFS HDFS全称是Hadoop Distributed System.HDFS是为以流的方式存取大文件而设计的.适用于几百MB,GB以及TB,并写一次读多次的场合.而 ...
- VC++中的DDX和DDV
DDX/DDV 通过使用ClassWizard向对话类添加成员变量,你可以利用ClassWizard所提供的高效特征,为对话数据交换和对话数据验证自动生成源代码,也就是人们所熟知的DDX/DDV ...
- Maven--几个需要补充的问题(三)
<Maven--搭建开发环境(一)> <Maven--构建企业级仓库(二)> <Maven—几个需要补充的问题(三)> 前两篇由于篇幅太长,为了给读者理解方便,这篇 ...
- X Window System介绍
1.概述 X Window System是1984年由麻省理工学院(MIT)和DEC公司共同开发研究的,是执行在UNIX系统上的视窗系统.严格地说,X Window System并非一个软件, ...
- 案例分析:java中substring引发的Full gc
问题定位 由于应用频繁地Full gc,就dump了内存下来用MAT分析,发现有个map占用了98%的内存,于是找到这个map private ConcurrentMap<String, Str ...
- Word中使用代码高亮插件
Word中使用代码高亮插件 1.下载并安装:SyntaxHighlighter4Word.zip 解压,然后双击bin\word2010\Kong.SyntaxHighlighter.Word2010 ...
- ubuntu安装greenplum依赖包
ubuntu安装greenplum的过程中有两个比较难找的包,特地写出来给大家分享一下: 错误提示1:configure: error: header file <ldap.h> is r ...