|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。) ~) `& M. Y; e3 z4 {4 `' b1 K
欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592
) a' Y8 @, H( }1 L; E6 ~本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:1 g9 M" }* Y: e) b1 y: w/ F
标题:在Delphi中使用IP控件
' M3 B3 A5 M- A _: ^8 M$ U作者:西安交通大学9649# 刘明华" R+ |" j: l7 M9 i) u; P. \
在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。
. d, `8 K# d; y# d; R. a如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com
' g) N) l! e3 x4 a- Xccrun(老妖)(www.ccrun.com) 2003.10.29) n1 O5 N7 D( l* x# _* Z
- Z) j2 N( X5 _; x9 c; D; k0 S1 g
在网络程序中,我们常常碰到需要用户输入IP地址的情况。然而C++ Builder并没有为我们提供可以用于输入IP串的控件,于是我们只好用TEdit控件(单行文本框)来接受用户输入的IP串。但是,使用TEdit来输入IP串并不是一个好的主意,因为处理起来非常不方便。事实上,在我们的身旁有一个专门用来输入IP串的Windows控件,就象网络链接属性中, Internet 协议 (TCP/IP) 属性中输入IP的控件。IP控件会拒绝非法的IP串(在每个部分只能输入0~255之间的数字);它让你可以轻松地获取控件中的IP串所对应的IP值(32位整数),这省去了IP串和IP值之间相互转换的麻烦;此外,你还能限制IP控件中所能输入的IP的范围。在本文中,我将向大家介绍如何在我们的C++ Builder程序中使用Windows的IP控件。+ u) V$ x2 b9 }) f7 \ `
9 R9 B. |9 U$ P3 B
Windows中有两个非常重要的动态联结库:commctrl.dll和comctl32.dll,它们是Windows的自定义控制库(Windows Common Controls)。自定义控制库中包含了许多常用的Windows控件,如Statusbar,Coolbar,HotKey等;在C++ Builder中,这些控件大多数都已被包装成可视化控件了。在Microsoft推出Internet Explorer 3之后,自定义控制库中新增了一些控件,其中就包括Windows的IP控件(IP Address edit control)。: m; e7 U5 r! p7 n& ~
) l @( m F+ J9 z+ k- K9 O
●初始化Windows自定义控制库●
! A$ }5 Z e, W% m! wWindows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:
2 ~2 l7 K2 k& I8 L8 R7 n
& F# d# P+ t3 A) W6 Atypedef struct tagINITCOMMONCONTROLSEX {+ J4 G, k1 e: n9 ~# y# Q
DWORD dwSize; // size of this structure
6 ]. A/ B2 c* `% Q9 \6 q DWORD dwICC; // flags indicating which classes to be initialized
5 L8 h% ]% L% s) N; h} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;% [8 t9 ^/ b8 Z# c# }
% W6 G' C( q) q4 w, ^
WINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);% z; i9 u8 @4 k7 Q" c1 b5 m, [
3 m+ f7 M7 D0 o& u# O: b
IP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:
; }% I$ R8 J$ D/ A% f& H! ~1 D# o6 ]
TInitCommonControlsEx ICC;
* w x' t. i# b& @) t9 @ICC.dwSize = sizeof(TInitCommonControlsEx);
" U3 R1 R8 z nICC.dwICC = ICC_INTERNET_CLASSES;5 s" G' x& l% i6 @6 K& r
if(!InitCommonControlsEx(&ICC))
% J" K2 d$ ^) v% w+ x8 U' f# h' ] return; //初始化组件失败
" I& t( ?/ Y( Y
( b) Q8 E) _1 x' _' ]●创建IP控件●, l t$ V% p8 K' t) X1 q6 J
Windows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。4 e* B8 ?5 p. Y& \) k5 z# K4 [' T
4 W: i( `. G9 U; D8 r3 P9 ^HWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);
4 ^5 ^+ Q. W2 `" t3 X& m- x% ?- A, w- |" p: P
●使用IP控件●
$ x, | V6 n7 `% c$ }7 L+ o在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:
$ q) C# F& H6 I! N% c5 a% q
/ \* E0 \- y" P* R2 o; U- D消息常量 消息值 作用 参数及返回值* [, c J; g; X; H1 ?
IPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无
3 r. b" X1 V% t6 _# L- l. q# qIPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值! V$ J. F! } U" @# Z9 ?6 v% n
IPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。 - h$ ?+ C* U" h5 o: b1 k9 _9 G7 P
IPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。& k& @6 Q* B4 ^% {
IPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点
; y, y+ C* z* Y6 U/ U9 h* _% UIPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回0) `. h& R( ^% W6 v+ u% g8 n7 Y9 b) N
! k3 d% e4 ]0 M1 n4 E+ s% h
★㈠清空IP串(IPM_CLEARADDRESS)★9 t/ @; ?7 @* {9 k4 X2 M
SendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);
# ]& K0 A% Z; g! r# X8 H0 A' s" K) Y* m* [( J; B6 y- W! f0 b/ B6 G% \
★㈡设置IP串(IPM_SETADDRESS)★: G. n* p) d3 }" |7 } k7 X5 F
int nIP;
! B! G, C: `8 c$ o6 v. o; VnIP=MAKEIPADDRESS(192,168,0,1);
4 g2 h+ Y$ P% U2 X! r" [* J# sSendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);1 b' i# m" N1 q5 \& U; e
9 R6 F% [: y, y, Q9 e! H此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:% F$ B) z0 c/ [: @* t3 k6 L
#define MAKEIPADDRESS(b1,b2,b3,b4); z; p. s: z3 H- X; y
((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))7 ^1 o6 m3 t8 w. V% k
0 E, Y" o Y4 l* [ b+ d" `★㈢获取IP值(IPM_GETADDRESS)★
& p! ~0 s! R M$ `int nIP;! f. e) n0 y5 f# s5 L
SendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));- i. s! v: G! J; @. K( D1 y
//nIP++;% c: e# B8 l. m+ \) P0 j" _
//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。3 p" w- a$ R7 ?& j- v1 w3 a( h
' g" n, l% l+ O' l
若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。
3 s4 o6 M- Z9 q; v9 Z) o4 g8 t7 r# u L6 @
★㈣设置取值范围(IPM_SETRANGE)★
% q0 c5 C$ U" P$ f$ J! _, z5 ESendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);
: \% d3 L% i( s1 c7 h此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
2 D! C `: W/ j. Q( X8 _* m( r) T% v+ C8 w! s
★㈤设置输入焦点(IPM_SETFOCUS)★
7 }& e% P( w cSendMessage(hIpEdit,IPM_SETFOCUS,3,0);* Q( a9 D* G6 L% r! m( v7 W; w- G
//将输入焦点设在IP控件的第四部分。! R. J4 J) i' ~' Y/ I' `, V9 ]
7 c1 B) ^$ N: y: s0 ]1 e) u7 ?6 C5 j㈥判断IP串是否为空(IPM_ISBLANK)
% _; q% G0 P5 A9 e9 b+ gif(!SendMessage(hIpEdit,IPM_ISBLANK,0,0))
: N: X2 O+ U- x6 M{
* i) D: Z+ u0 x0 B6 f0 x" A //IP控件中的IP串为空8 ^4 d/ i8 ~4 ?0 X1 j! {
}) P( }: }7 J7 Q8 A( n8 C+ H' n/ u6 I+ P
else* A/ i5 z; E3 ^ {5 E0 T
{
- f) J& H. H' H+ y3 A5 ~ //IP控件中的IP串至少有一部分不是空的1 x- ?9 q _( {3 ]+ v8 E; d
}6 w l9 T' H2 h/ q6 S2 M' @
5 [' o M' X$ r* r
●IP控件的通知消息●
+ r1 V+ \2 ^6 V' w" Y3 g当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:% E* i7 |% {( r) b; X; ^# L* D
6 S C* {0 U0 e7 |% nvoid __fastcall TForm1::WndProc(TMessage &Msg)5 Z0 Y+ M' |# U8 v) W3 i
{9 E z' U- U4 S' h9 F* L1 k4 K4 Z
LPNMHDR p=(LPNMHDR)Msg.LParam;
2 }7 g) i! l" |; q- ^/ a. k, T if(Msg.Msg==WM_NOTIFY)3 J" n. o# M9 |) ]
{
6 E7 F" J4 a3 d if(p->code==IPN_FIELDCHANGED)
0 M& v' Z9 s% ? {2 c; P. f- j- v; J+ w
//处理IP控件的IPN_FIELDCHANGED通知消息8 b2 n4 Y! Y7 a
}
9 p6 O: s: Z3 S/ H }
6 b2 i: r; a2 T2 m$ M- B" F( c: o/ F. M TForm::WndProc(Msg);* u2 K9 u) K0 ]# i# R
} |
|