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 ...
随机推荐
- Python之路Day17
算法:冒泡排序.插入排序.快速排序.堆排序 冒泡排序 #! /usr/bin/env python # -*- coding: utf-8 -*- # __author__ = "Q1mi& ...
- 入门前端之HTML
本文内容: HTML概念 HTML元素 HTML属性 HTML标题 HTML段落 HTML格式化 HTML样式 HTML 链接 HTML 图像 HTML 表格 HTML 列表 HTML 块 HTML ...
- select_related
作用:减少DB访问次数 from django.db import models class Blog(models.Model): name = models.CharField(max_lengt ...
- Agile methodology
ntroduction Waterfall model follows application development in phases with checkpoint and deliverabl ...
- 移动平台WEB前端开发技巧汇总(转)
最近我很关注移动前端的知识,但做为一个UI设计师和web前端工作人员没有这个工作环境接触,做为门外汉,网上系统的知识也了了,一直有种雾里看花的感觉,见到本文,我自己是奉为经典.所以我分享之后又专门打笔 ...
- 转:JS线程和JS阻塞页面加载的问题
前几日写了一篇文章,介绍了js阻塞页面加载的问题.当时是通过例子来验证的.今天,我介绍一下浏览器内核,从原理上介绍一下js阻塞页面加载的原因. 浏览器的内核是多线程的,它们在内核制控下相互配合以保持同 ...
- 第三节 ISBN 码 / ISSN 码
ISBN与ISSNEAN的用途很广,除了我国的商品条码CAN以及日本商品条码JAN外,目前国际认可的书籍代号与期刊号的条码,也都是由EAN变身而来的.书籍的国际认可代号称为国际标准书号(Interna ...
- Android编程获取网络连接状态(3G/Wifi)及调用网络配置界面
随着3G和Wifi的推广,越来越多的Android应用程序需要调用网络资源,检测网络连接状态也就成为网络应用程序所必备的功能. Android平台提供了ConnectivityManager 类,用 ...
- Python 第一章 基础知识
如果熟其他计算机语言,可能会习惯于每行以分号结束.Python则不同,一行就是一行,不管多少. 如果喜欢的话,可以加上分号,但是不会有任何作用(除非同一行还有更多的代码),而且这也不是同行的做法. & ...
- poj 1442 Black Box(优先队列&Treap)
题目链接:http://poj.org/problem?id=1442 思路分析: <1>维护一个最小堆与最大堆,最大堆中存储最小的K个数,其余存储在最小堆中; <2>使用Tr ...