|
|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。
* R0 g7 {/ i% B/ l n7 t- T欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592
* j6 W. Q. @ R. R/ C本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:
4 j) C# |) Q Z7 ~标题:在Delphi中使用IP控件
2 C Q8 K0 L" k& l; }作者:西安交通大学9649# 刘明华3 } D# x3 |; Q3 X$ ^9 |
在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。
& E7 c Y4 `; s# p/ q W5 @+ s) C如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com3 D# N3 z7 i( z- x" A1 [
ccrun(老妖)(www.ccrun.com) 2003.10.299 p) z1 J; H" A9 h8 z2 U7 o
& n" r- h: V8 ~- f. T- a# 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控件。
0 o" m v% z& V( R$ a# I( o
+ c3 E+ J1 }, T2 q5 uWindows中有两个非常重要的动态联结库:commctrl.dll和comctl32.dll,它们是Windows的自定义控制库(Windows Common Controls)。自定义控制库中包含了许多常用的Windows控件,如Statusbar,Coolbar,HotKey等;在C++ Builder中,这些控件大多数都已被包装成可视化控件了。在Microsoft推出Internet Explorer 3之后,自定义控制库中新增了一些控件,其中就包括Windows的IP控件(IP Address edit control)。
5 X( [5 u( [2 X( N2 l S" n: h* a: j, U
0 P0 @$ b# S1 W0 h●初始化Windows自定义控制库●
1 T; u4 L1 P6 g- tWindows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:
# m; r+ o7 d9 S3 y) C/ j1 D
3 J7 x% ]) P; i5 S4 |5 c" c1 V0 |typedef struct tagINITCOMMONCONTROLSEX {
/ h6 m* h$ J% U# I9 K8 ^% ? DWORD dwSize; // size of this structure6 S: ~, U! C" Y
DWORD dwICC; // flags indicating which classes to be initialized2 ?9 m; T( I, t U: W- s7 u
} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
2 V0 D0 D: V9 @8 q* d+ ^
0 V3 r5 h( S+ p vWINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);
' M& {! p0 r' [4 Y
6 z) [: i* S, h C. hIP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:8 i/ [8 j" u7 e6 x- E1 {5 i
( e9 w0 z7 m) ^+ z/ B
TInitCommonControlsEx ICC;& `# P, S1 W% c
ICC.dwSize = sizeof(TInitCommonControlsEx);
# B1 `( }! k2 N$ fICC.dwICC = ICC_INTERNET_CLASSES;# @+ K) L( P U8 Z# r
if(!InitCommonControlsEx(&ICC))
6 D# b2 c. z. I& ~ return; //初始化组件失败- y* \- S# D2 W" |
) o: N" a8 F8 H5 o& m●创建IP控件●: [! h/ ?2 |* W8 J; |% q. Y" s
Windows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。1 [' C8 g# l2 R
1 b, r2 @. d( S) e* ]7 I
HWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);
* `& j* S/ ~" l* O$ @: n( `' X# p6 k+ P# d
●使用IP控件●3 o+ H r: Q8 s+ w* Y" x
在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:' g5 O0 W# c! |; G
9 T2 p; T7 q( d O% e" b7 n
消息常量 消息值 作用 参数及返回值" {3 }3 j$ ^7 N O) x
IPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无
, j* E$ \- y s n vIPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值
' @: U$ Y# {" h# b; {IPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。 ' }* o8 B# X; d; G
IPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。" ~) W$ _0 P; J/ N
IPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点
8 [. Z0 c2 p3 NIPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回07 e( |* E# A. N/ o; A
/ c1 w8 p( a( D★㈠清空IP串(IPM_CLEARADDRESS)★
' m5 j6 D, A4 `6 ?5 n( KSendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);/ h4 }8 ?; [. K. M2 f7 e3 g
6 M; U2 C8 g8 ?5 C★㈡设置IP串(IPM_SETADDRESS)★1 }2 Q+ A( T p
int nIP;
& m! [7 k" d: y8 O) o0 PnIP=MAKEIPADDRESS(192,168,0,1);
5 N4 x' ^* Q0 X9 E- y- h) b+ G+ ~SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);
x$ X0 w% `$ x" o; | H& M0 y2 ^( n" w$ s' D
此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:& z( h0 x, `2 N T+ x
#define MAKEIPADDRESS(b1,b2,b3,b4)7 Z- O" }/ l: V2 G+ K) `- O' x
((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))
5 a( j3 m4 d, h/ K
3 o& J# w" D2 ~ m★㈢获取IP值(IPM_GETADDRESS)★
! g7 m- ` V7 Y- Hint nIP;
; n O8 o# q! ]SendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));) {) C5 s! K7 @' N- e- \& K7 W
//nIP++;
. u, I# ?6 l% B6 Z, L6 z) H- j//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。
" e1 S6 p, w* C ~( T: V* b
- g# m" x% t' g5 i8 L2 Z若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。
' Z+ s2 F$ v+ n7 d$ X! m
7 q! m; | V, y' a, p3 t8 \4 i★㈣设置取值范围(IPM_SETRANGE)★
( P4 z3 z) {( W% aSendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);
, T( f$ O( x4 w6 w5 r" k& \: C此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。* | I8 n( T" ]
3 J G2 A/ ~. s4 t$ \★㈤设置输入焦点(IPM_SETFOCUS)★% Z; ?2 e! i& `( f
SendMessage(hIpEdit,IPM_SETFOCUS,3,0);9 \# V. G5 ]# l* [& G: n$ F
//将输入焦点设在IP控件的第四部分。! k& K; f/ ^* n; y3 _
2 N9 [2 u) A0 F4 J }5 L$ j; o㈥判断IP串是否为空(IPM_ISBLANK)8 M, E4 o, l, f8 A, Q
if(!SendMessage(hIpEdit,IPM_ISBLANK,0,0)) : I2 |( S! `2 c- P6 m
{, u" @, `" ^" M* y
//IP控件中的IP串为空
+ S* a+ `& i0 y8 j- R5 p}
3 [( h8 ^4 s7 ~6 j2 g) Delse
1 b+ V, F9 t, R! t c5 \% k* w{7 U8 N/ \0 k+ U3 c* a
//IP控件中的IP串至少有一部分不是空的
9 E$ o# H( m2 [* f) r* s; ^}8 p( e; x# c0 f
* C# f% Y) ^. E0 e, n* W; z: z
●IP控件的通知消息●6 l) K! F N5 j" T: C' E5 y
当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:
" q4 Y* r X0 B- j
# b% U2 C7 ~% ^! }4 o0 H, Dvoid __fastcall TForm1::WndProc(TMessage &Msg)4 K) o- x9 u) Y/ W4 }
{# M+ i) G3 G3 Y, a- C
LPNMHDR p=(LPNMHDR)Msg.LParam;
5 Y1 r# U o( P5 P' u4 e if(Msg.Msg==WM_NOTIFY)5 s* P) I) W5 ]" i
{* M& R. p: h( e% Z
if(p->code==IPN_FIELDCHANGED)- E y* F/ w$ S: Y
{8 m7 ~1 f' f0 r2 A
//处理IP控件的IPN_FIELDCHANGED通知消息- n8 E3 _% D+ V( m/ e
}
% p! T8 `$ u+ v( o }
* k- S Y L9 T% _- N TForm::WndProc(Msg);
. i8 {4 [; X4 j5 v4 R} |
|