|
|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。+ g. l) _# m& P. M
欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592
0 q9 s, H4 _/ F本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:
0 q( U6 G$ x5 ^4 ]标题:在Delphi中使用IP控件4 g H1 i. H' U: ^: R# i
作者:西安交通大学9649# 刘明华! J. H6 `# P& [6 v7 N
在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。3 q2 H* f* g! v# V) ^
如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com
$ ?' H5 u+ Z. Iccrun(老妖)(www.ccrun.com) 2003.10.291 f, F8 ]0 A# f9 |
" `6 Q, P! u! m! V6 _
在网络程序中,我们常常碰到需要用户输入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控件。* ]& Q4 I p a: ~3 Y; z
2 f# O. j; n/ a* P& E/ \3 \7 i1 VWindows中有两个非常重要的动态联结库:commctrl.dll和comctl32.dll,它们是Windows的自定义控制库(Windows Common Controls)。自定义控制库中包含了许多常用的Windows控件,如Statusbar,Coolbar,HotKey等;在C++ Builder中,这些控件大多数都已被包装成可视化控件了。在Microsoft推出Internet Explorer 3之后,自定义控制库中新增了一些控件,其中就包括Windows的IP控件(IP Address edit control)。, q3 w2 H1 X3 o. r2 n
" g: S6 [1 ]" ?+ K●初始化Windows自定义控制库●
/ L' j w) ~) H5 dWindows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:
$ M" a' N! K* b) f6 I. w6 Y2 @3 C
typedef struct tagINITCOMMONCONTROLSEX {' q, \( S3 G& N5 ^
DWORD dwSize; // size of this structure& J( p' `" y+ b h: ~7 H l ~9 K/ h* z
DWORD dwICC; // flags indicating which classes to be initialized8 D+ t5 i+ g* {# X' y# B( K' c# i
} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;6 X& B" h7 E# R3 _. _! m" P& ?' j8 n4 t
0 \: q! a1 j- H% [6 u- wWINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);
7 u7 V( }5 ]$ p8 x+ Z" [
& W/ e& ]: t3 [) g, [8 }IP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:2 I* B3 Q" w3 B# T2 W8 ~; M0 ?
( t& |: l7 H7 n; }4 [6 a& i& i2 a
TInitCommonControlsEx ICC;
) q" e5 `9 d4 H' ^# N5 V! NICC.dwSize = sizeof(TInitCommonControlsEx);
- S' k$ Q$ C. QICC.dwICC = ICC_INTERNET_CLASSES;# S2 y/ b3 D9 I, V/ T% `3 q
if(!InitCommonControlsEx(&ICC)). E- o; x: [! b, _, [+ |( v6 ?
return; //初始化组件失败8 {& @, g: I& F! I/ k
5 D w- f l7 M/ g/ O7 o●创建IP控件●' f7 M& R% `" Z- c+ Z3 _
Windows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。8 { P* N: d: h0 _0 v3 c
s. D3 Y$ k. ^2 M) X4 c
HWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);
& P0 |) I& x8 K; p8 |: X; f! Y
% l% X7 x: l* R4 }" d●使用IP控件●% Q$ {: T0 z K9 K& V
在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:! Z0 A* ]* |* K( e0 ?- W3 Y
7 w4 V8 V H0 S& u消息常量 消息值 作用 参数及返回值
* v5 j6 @- \3 z; PIPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无+ f6 r# \5 O6 r# H8 |% U
IPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值
8 c) ?! E! ?1 P1 E, _1 J! J& a! U3 ?IPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。 . W1 l7 D6 H3 @2 F# P0 ` S8 Z. x
IPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
- D# T2 k3 B0 w9 KIPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点- j0 k( y& ]( k1 z, S, H
IPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回0
: x% d6 t1 ?. J0 h8 d2 v4 h! d* i8 x
* d# X8 n* R6 s" `$ f. b( ]; ` g. P★㈠清空IP串(IPM_CLEARADDRESS)★
! f9 r, _( ~7 j; V3 G/ {SendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);. V' M( e7 q( O
6 p6 m) G9 F9 _( D
★㈡设置IP串(IPM_SETADDRESS)★
, j; g+ h* Y+ A! A" bint nIP;8 e; V5 q8 [0 l' V% H
nIP=MAKEIPADDRESS(192,168,0,1); 3 g" J: ?# `$ }1 k
SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);
( i! F2 o0 |) d; K. }) g' _
* Y( l( e9 x3 e/ Y' ^9 E3 y此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:
. U9 E( z' e, G5 T- R1 S0 f% B( J" s" R#define MAKEIPADDRESS(b1,b2,b3,b4)
8 f: ` ]0 d; W" u((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))
$ X J3 }6 S4 N* z* y# i i1 f; z! l5 X% P/ q4 }7 [
★㈢获取IP值(IPM_GETADDRESS)★
; N! B n' D; O: x; M8 ?int nIP;
" t( W4 |- z6 }4 ^SendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));
* i) v% ]; ]: \0 b//nIP++;" ?2 t9 j! C1 G6 D8 _
//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。5 Q3 D3 U, ^3 x, X
" G7 O, D1 v9 F: h# h/ P! C若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。9 J& L7 Q0 M( S5 h# K
1 U9 r2 Q7 q' S- T: Y" c4 [
★㈣设置取值范围(IPM_SETRANGE)★
9 F; c* @& l# L, _; Q3 \SendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);
. p0 k+ J& ~+ O& D此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
d! Z2 E2 z' r7 ^3 l2 g7 o0 e b( d8 {- u/ |% i) @
★㈤设置输入焦点(IPM_SETFOCUS)★, l, o) d+ m/ {# C6 t
SendMessage(hIpEdit,IPM_SETFOCUS,3,0);
j3 B, D' O4 X1 ]$ W3 U. s6 b- [//将输入焦点设在IP控件的第四部分。' M, `; q$ V5 A" D
7 t0 r5 q5 ]- k! P/ K$ V7 [4 z4 O
㈥判断IP串是否为空(IPM_ISBLANK)
: H3 ^5 D# Q8 R2 O0 f$ s5 iif(!SendMessage(hIpEdit,IPM_ISBLANK,0,0))
2 l5 F' }8 E# r: Z' E4 d{0 u. \- H4 F# d
//IP控件中的IP串为空4 b; Y+ ?! T o5 L* b# V
}
2 t) s5 C& g! J9 y; zelse
* t% e9 o$ R) @7 o. ]. w0 i{
4 l2 i+ r L0 w //IP控件中的IP串至少有一部分不是空的
- u; |8 ?0 \% _) L, p" y+ L7 s}
B3 ?1 Z1 o. x8 }; ^# Q+ a# |6 @) L; A, ]2 Q6 C6 l* `
●IP控件的通知消息●
% l1 M- u, v( v1 s, T/ Y当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:
8 K- q) B9 s! R* |- B ?# M z3 d
void __fastcall TForm1::WndProc(TMessage &Msg)
. b% T+ @8 }$ u1 x' @& l{4 x) q; c8 T1 q* u, p
LPNMHDR p=(LPNMHDR)Msg.LParam;6 n$ p4 P, g# ]* \/ {
if(Msg.Msg==WM_NOTIFY)5 ?- f& x# v% C3 g' S
{0 k T/ y H2 x6 A$ ?
if(p->code==IPN_FIELDCHANGED)) @, l0 T6 q; l9 y) ]6 Z- o- \
{5 B L3 V( l- D. l) @2 d
//处理IP控件的IPN_FIELDCHANGED通知消息/ m. @1 A+ X5 w/ T3 u
}
0 A. Z- H/ l7 b- P }
2 C7 ^- m2 O8 |+ ~$ K! |2 i TForm::WndProc(Msg);
- j& v$ K' ]3 Q6 n. C, ?) G} |
|