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 ...
随机推荐
- HBase 几点思考
1. http://blog.csdn.net/yueyedeai/article/details/14648067 2. http://blog.csdn.net/pirateleo/article ...
- Qt探秘——谈ui文件的用法
转载自:点击打开链接http://blog.csdn.net/luo_isaiah/article/details/5794973 相信用过Qt Designer的朋友,对Qt Project中的.u ...
- 基于visual Studio2013解决C语言竞赛题之0401阶乘
题目 解决代码及点评 这个是一道经典的教科书题目,基本上每本基础的c/c++语言教科书都会有这个题目 用来演示循环语句 #include <stdio.h> #include ...
- poj 1035 Spell checker(hash)
题目链接:http://poj.org/problem?id=1035 思路分析: 1.使用哈希表存储字典 2.对待查找的word在字典中查找,查找成功输出查找成功信息 3.若查找不成功,对word增 ...
- POJ3264——Balanced Lineup(线段树)
本文出自:http://blog.csdn.net/svitter 题意:在1~200,000个数中.取一段区间.然后在区间中找出最大的数和最小的数字.求这两个数字的差. 分析:按区间取值,非常明显使 ...
- C++ 自定义结构体和类 内存对齐
为什么要提出内存对齐? 比如这么一种处理器,它每次读写内存的时候都从某个8倍数的地址开始,一次读出或写入8个字节的数据,假如软件能保证double类型的数据都从8倍数地址开始,那么读或写一个doubl ...
- 【转】 /etc/fstab功能详解
[转] /etc/fstab功能详解 最近去客户现场时,遇到 了一个关于挂载文件/etc/fstab文件的问题,就写了一下/etc/fstab文件的作用一个文件中各个参数的含义.供大家参考有不正确的地 ...
- <%@ include file=” ”%> ——最简洁易懂的解释
<%@ include file=” ”%> 假如 在B.jsp 中,使用 <%@ include file=”A.jsp”%> ,那么就是把 A.jsp 的内容 原封不动 ...
- PHP学习笔记6-时间/日期
时区/时间/日期 输出unix时间戳(从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数),用time() echo time();//unix时间戳 输出结果:143557475 ...
- PHP学习笔记3-逻辑运算符
逻辑运算符图解: 逻辑且&&: <?php /** * Created by PhpStorm. * User: Administrator * Date: 2015/6/26 ...