|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。: _5 O- W& f+ U7 w) j* d
欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592
# B. P. H$ R% B# t# v: d本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:' E4 V- K( p4 d5 Q/ w
标题:在Delphi中使用IP控件( ~) e8 O3 A, G9 T, p8 B) P
作者:西安交通大学9649# 刘明华& z1 p9 K3 N$ I9 |) r1 r# U
在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。
) d% D; M% j2 G2 F8 q如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com1 b- }; E8 ?( k( Y+ U
ccrun(老妖)(www.ccrun.com) 2003.10.291 G0 U6 T: {, O8 ^& I
% L; H W0 W+ J" L在网络程序中,我们常常碰到需要用户输入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控件。
[( l1 J# V: D4 E
5 Q7 r9 Z# Y6 e' 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)。
. p+ L2 t; ~9 h4 |' k: [
6 j0 [9 y; h( U u●初始化Windows自定义控制库●7 |8 R* H" r2 K
Windows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:% p1 X7 s* Z0 |; w& t& ?% Z
& G/ }7 P! M8 P1 `- D! dtypedef struct tagINITCOMMONCONTROLSEX {
6 L5 ?7 G5 ?4 `6 C6 J, V. t DWORD dwSize; // size of this structure; g- v- y7 N7 H* c; W: j+ Y
DWORD dwICC; // flags indicating which classes to be initialized
6 A& } T$ e1 n) @( ]} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
( \4 F6 O: u& v' b" E1 ~* }$ A" |0 f' i2 K, r
WINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);$ u1 p7 @7 B c" t2 m2 S% \4 \
, o0 u( N( k' h# v9 EIP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:
7 L3 _. t3 w) C1 S) v+ m
' z( X! w& ^% l `0 XTInitCommonControlsEx ICC;& m& c- ]# V" K: i; E
ICC.dwSize = sizeof(TInitCommonControlsEx);
5 t( ~( k2 w9 J! J' J2 ZICC.dwICC = ICC_INTERNET_CLASSES;
2 e- _7 |* f/ j) O+ Wif(!InitCommonControlsEx(&ICC))7 @% `4 w# c, K9 G3 j0 |
return; //初始化组件失败+ ^$ S6 M$ u( z/ z4 r8 y5 b
[9 q3 A' a. ~" i) U' t
●创建IP控件●
* T6 b2 h+ a. H# Z0 AWindows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。9 L. r5 S; Z& u) R4 o
' n, ]6 o& K: s, V7 B- q+ M
HWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);# S5 W( W3 O% v. |6 [, a+ I: O. g
: i2 v/ Y! e1 a8 u●使用IP控件●3 K: n3 Q# ~7 v! V: h
在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:! w. d* F# O; i/ ^
2 `. [6 c. z$ r3 D/ ^
消息常量 消息值 作用 参数及返回值
& t% T# f, b+ L, l9 I0 _, FIPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无# S0 w! {3 h e1 X* E+ w' L8 P
IPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值& z5 h6 `, ]+ K9 o/ \+ K/ T) t
IPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。 # S! m7 T- C8 f6 n1 `; }$ O
IPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。3 h: f" }, p2 p4 |/ @
IPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点) i0 o! e8 m" z" Y; l9 ]
IPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回0
0 K K7 t) \( d, ]& r! V
! U, B# J! g, n! E+ ]9 s3 Y★㈠清空IP串(IPM_CLEARADDRESS)★# x) v/ H$ O8 r' k2 v
SendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);
8 K7 {& V& Y, a1 t1 F$ t. M2 }
- A% n$ H5 f y' O/ x: S★㈡设置IP串(IPM_SETADDRESS)★2 E" n0 s: |% F( d
int nIP;
% v! Z) \4 ~. G" O( dnIP=MAKEIPADDRESS(192,168,0,1);
' j/ F0 }, P" \ NSendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);
& R; v1 ?6 Y6 e) [. J: W' `/ \
此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:9 M# v) y% k1 L' N: G! u2 G6 V
#define MAKEIPADDRESS(b1,b2,b3,b4)
. N; l# P6 [9 n9 g+ h((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))7 H! q% b* G9 P) K9 \+ ]" S
+ |* z- _& V/ _( f★㈢获取IP值(IPM_GETADDRESS)★
3 c8 c$ x1 M. Uint nIP;
8 v. _7 b4 z1 w VSendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));
& W; Q+ s3 ~' A' [7 h7 L! v//nIP++;& j$ [, O5 L2 D$ H" O1 ^+ E
//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。
" B: } ^7 q9 P& [ k. Q# Y2 U7 V" d p$ B& S3 A
若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。
+ H+ \" t6 t8 N# K9 b3 k v) J" m0 R, H Z9 S
★㈣设置取值范围(IPM_SETRANGE)★% c: X2 [ f8 g. h3 b; m6 u1 h
SendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);* P: ]. w% k, E: A) i: z4 c
此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
! R6 x* q. g4 E+ G; Y( C }+ T* K: v8 m Q7 q" O
★㈤设置输入焦点(IPM_SETFOCUS)★
9 q8 y8 ?5 m* s5 d, VSendMessage(hIpEdit,IPM_SETFOCUS,3,0);' ~5 S0 t1 z" u+ ^( g2 }; g
//将输入焦点设在IP控件的第四部分。. o7 N; G8 z% T' H* |
, o/ Z2 D7 R, U: |- C
㈥判断IP串是否为空(IPM_ISBLANK)# Q* }6 J9 t4 E) ] B. V) u
if(!SendMessage(hIpEdit,IPM_ISBLANK,0,0)) 8 C6 y' K) \) r2 T* v% N7 [ s
{
" d5 G: W3 Y5 h5 G" U. r //IP控件中的IP串为空 N8 {5 C* R6 ?. D- T7 q% W1 G
}
, u( q( H9 D( u0 }5 helse
0 B _2 u2 V- A3 k& J5 V4 @' I{5 r$ M2 `0 u9 J+ D" b' [5 C2 J% \) _1 M. B; C
//IP控件中的IP串至少有一部分不是空的8 G( L8 }' _6 D) H4 E
}5 A& A- G& X1 R, }% L$ ^
2 w1 e; s* d$ v7 |2 N1 E1 L. h. `6 F7 `●IP控件的通知消息●
" o3 S d/ E- g6 F当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:% Y5 u4 E- e; |
1 i) b* D! q% O: \9 ]void __fastcall TForm1::WndProc(TMessage &Msg)
5 j# C% @1 B7 m' e* ?- K/ `{
, ?% E) J0 s. \+ O LPNMHDR p=(LPNMHDR)Msg.LParam;
/ c, |" f9 v8 F) c3 l if(Msg.Msg==WM_NOTIFY)5 g( B' C. y( y! g. b+ @
{
. Q+ K8 j6 t$ H5 ?; q( f* s7 e if(p->code==IPN_FIELDCHANGED)
0 b& m$ \ n2 ]& j6 G5 W/ z& L$ V {
, S1 k. r0 n- L" m I' T //处理IP控件的IPN_FIELDCHANGED通知消息( r4 H1 e& E" N
}' {8 d K. O6 J- L0 B, G5 V& q! ?
}
4 f# J: k& U3 q* Q TForm::WndProc(Msg);
8 K+ Q% `/ H( u- G& ]9 T- Y3 B} |
|