|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。
$ h: v' k' E, i欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592
% c5 j5 B u( d$ N r3 O" v# T$ C% F本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:+ T& I+ `7 G, ]; t) q
标题:在Delphi中使用IP控件
8 W" f5 d; X, I' n4 X, K作者:西安交通大学9649# 刘明华$ v7 a2 P; D' H6 u& U$ j2 J( O9 V
在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。% C3 G- M. K& W) w0 U! k! P, I' P
如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com/ [3 |" a& Z0 w) z# `- W) Y
ccrun(老妖)(www.ccrun.com) 2003.10.296 q% i A: M3 Q# C; V
4 R7 s. m- R* f2 ^在网络程序中,我们常常碰到需要用户输入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控件。% k: C' e. }8 `% e; z6 ]
3 g9 a$ R- v8 Z7 QWindows中有两个非常重要的动态联结库:commctrl.dll和comctl32.dll,它们是Windows的自定义控制库(Windows Common Controls)。自定义控制库中包含了许多常用的Windows控件,如Statusbar,Coolbar,HotKey等;在C++ Builder中,这些控件大多数都已被包装成可视化控件了。在Microsoft推出Internet Explorer 3之后,自定义控制库中新增了一些控件,其中就包括Windows的IP控件(IP Address edit control)。
9 c! L9 `% B% z: o. s9 c! q: y) x. u- b& A) b0 n
●初始化Windows自定义控制库●
/ X6 ?! {; w7 P+ k' a, O6 g' oWindows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:7 P/ X: |6 O5 k8 @% }
. _) n: Z& ?. ztypedef struct tagINITCOMMONCONTROLSEX { l$ i, p+ z% J! d( r
DWORD dwSize; // size of this structure8 R" j' C) V7 P. d% b& G) A
DWORD dwICC; // flags indicating which classes to be initialized
, [+ a; ^: q& c3 g* l. N} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
# T. C3 f+ X2 h
# p+ ^+ x5 r1 S- g- BWINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);
) ]" X- o o$ E
8 b2 I4 `. F& c; N; HIP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:: ^! a, D2 Q0 G( U. | S; y
" |; A) w; n9 w3 q
TInitCommonControlsEx ICC;. B/ A! O! |8 t, @8 G; P
ICC.dwSize = sizeof(TInitCommonControlsEx);# |6 O. R1 z! P% L* K1 I0 b
ICC.dwICC = ICC_INTERNET_CLASSES;
' D: ]" h2 b4 M% H. L8 C& E* N4 Lif(!InitCommonControlsEx(&ICC))3 ^ s" j4 ^: x' t6 g9 M
return; //初始化组件失败
: \% G$ ~- J# w/ U8 D% L
' t1 {! D! M( @) ^* V●创建IP控件●$ u5 N2 b) y4 f" v9 ^
Windows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。
* x% y# N X8 a# Z3 [: |/ k {) c: m# M- C
HWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);
! s$ @" \$ E K0 G) Z+ F
8 m8 O' y* c; Z8 F: B●使用IP控件●
4 n8 M( j' h7 e- o) j* T4 R在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:
2 L0 O4 p2 ^* Z/ E
, f2 ~6 m# ^' p3 X, ]2 ~! `4 V消息常量 消息值 作用 参数及返回值
) _/ Z1 P4 [/ l6 a( jIPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无! f" j' l- d) N$ t3 C" e9 R/ M8 a$ b) U) {
IPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值- T; c% L( C( y( W
IPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。 & o# T0 F. q5 k) B4 e. @; E5 d: [) Y
IPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
2 s$ H" F) l8 w% Y6 G' t. I( fIPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点& I* N3 q" [+ K) w/ s0 R
IPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回0
4 {8 l9 J7 ~7 e) R* b. l* R0 Z- ?$ i
★㈠清空IP串(IPM_CLEARADDRESS)★
) K$ u* G4 ]1 \; |/ d: @- _SendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);
# y, m6 o7 N* \& P3 o+ e
: C9 k# |+ c5 y0 w' T) T8 K★㈡设置IP串(IPM_SETADDRESS)★! Q6 A0 f( f5 O: h, L) }
int nIP;
7 O" h: a1 r3 T$ q! e: gnIP=MAKEIPADDRESS(192,168,0,1); 2 D+ O1 n6 g$ @/ E1 m" e
SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);" h: I; P4 d' k
. c" [% y2 [9 v此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:( u: F: f6 {0 \# l+ B
#define MAKEIPADDRESS(b1,b2,b3,b4)# v, v2 V3 }9 k. j! U0 b& d
((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))
/ R# w/ O& _/ q
6 h6 Z. q6 O, Z* t/ \★㈢获取IP值(IPM_GETADDRESS)★
: m; L6 F7 O$ n: V" x4 vint nIP;
* e+ d2 u/ N2 f; OSendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));9 y* B* B; D* k7 S" O7 F
//nIP++;! @) F3 r/ U3 M/ A5 \1 X
//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。
* ~4 Y: T/ b! d
: o, I1 ]: K3 O9 v若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。' H. Y9 y& x- d; J! Z
: k+ e! u' R! E f4 W, ~6 m1 [' i
★㈣设置取值范围(IPM_SETRANGE)★
1 y8 j) O) E. R. k( \* s- {" FSendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);' ?; r& e5 t$ a1 }' N) f, L
此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
; b6 f/ ^) D+ p+ h3 d' v: `- S6 V: [2 J' M+ K M( c
★㈤设置输入焦点(IPM_SETFOCUS)★
- \% T1 ]" C; s3 Z# g% d2 |$ [! ESendMessage(hIpEdit,IPM_SETFOCUS,3,0);; s/ F, q. Q% ~9 z" a: {9 l& @3 a
//将输入焦点设在IP控件的第四部分。
2 ^$ a1 E- B, h: I4 X9 r
/ }/ M: ?7 L( A4 R+ v㈥判断IP串是否为空(IPM_ISBLANK)$ C" W- Y" L0 D. i# u
if(!SendMessage(hIpEdit,IPM_ISBLANK,0,0)) - u6 i1 P2 c" K! C: ]
{
* a) b1 J# Z! Q2 @8 u8 e2 c; ~ //IP控件中的IP串为空- V4 a' q6 D# @ m @% M( a
}
4 h( J' d( y1 A. Y% t3 melse
1 N9 L/ W/ t# C$ E{ Y7 ~1 n3 Q; ?) e; r) `# g
//IP控件中的IP串至少有一部分不是空的1 t7 Y5 A9 a3 D; ]% {
}$ A8 O; }( t1 l& r4 r j" R
9 Q( [" S+ R6 ~8 U: d●IP控件的通知消息●
3 j( z, w; N/ _4 ]当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:
9 N, v7 l J1 p# b! k5 j) x) ~ Q. D8 I3 W" T
void __fastcall TForm1::WndProc(TMessage &Msg). q5 D1 E; N6 O; ?
{ Y" }! S5 P( p
LPNMHDR p=(LPNMHDR)Msg.LParam;
' \! D0 h- g- }4 G if(Msg.Msg==WM_NOTIFY)7 Z4 I" C! o8 H6 s* M" `
{
( Y- a2 M/ F* d8 l* H if(p->code==IPN_FIELDCHANGED)3 [# i& Y; |. U0 P. L T
{1 r+ s s% ?! Q; O1 h
//处理IP控件的IPN_FIELDCHANGED通知消息
V$ x4 x+ H t }
: X' i$ F- r& x }! G9 e+ }8 I% | t7 }! x
TForm::WndProc(Msg);
0 Y, R6 @1 p& {: _} |
|