|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。
a" e: J% H+ f9 X欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=5924 W% @. J, ~7 Q* D4 d
本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:
a% _1 l) |0 l: [/ P标题:在Delphi中使用IP控件, S- k3 |# o2 s4 y) w- R
作者:西安交通大学9649# 刘明华
1 l: C: \0 _: F m/ e+ Q在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。
' K S" v1 n, D i7 {5 C9 l! ]如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com r% J- {6 C$ f3 s6 u
ccrun(老妖)(www.ccrun.com) 2003.10.293 Z" P$ T* Z! @( k+ p; e2 S# C# {
. S3 Z, p7 p) h; _9 Q k' ?
在网络程序中,我们常常碰到需要用户输入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控件。
1 k* d- W1 P# j
! r! a0 p: C4 o8 Z% J: V4 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)。
; ^3 }8 X( A' g7 g, L+ I! U0 v5 i$ R. M2 w8 @; m
●初始化Windows自定义控制库●
* ?' w J/ H( W7 {( u5 jWindows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:
5 l4 ^" t5 V. t9 v# q9 o! @% q# P3 K& R
typedef struct tagINITCOMMONCONTROLSEX {: K4 F' ?2 m6 Z+ o* R6 t& l
DWORD dwSize; // size of this structure4 k8 i2 Z. L0 [
DWORD dwICC; // flags indicating which classes to be initialized
% J" J( n% B+ Z( F} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;7 s: W$ u: \4 K& a8 b I
5 V+ |! P* V. \: @( h- J4 IWINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);. }" V. j: ?; J
4 T/ J. g1 {7 MIP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:
7 c, A' s' G F; @9 {/ L2 d% d$ g2 @; A/ s
TInitCommonControlsEx ICC;
* m# C |! k3 e7 u" m2 }, M* TICC.dwSize = sizeof(TInitCommonControlsEx);
7 K0 S9 R+ K/ n' P P+ FICC.dwICC = ICC_INTERNET_CLASSES;+ H/ S* z3 ~' v" S
if(!InitCommonControlsEx(&ICC))
4 l" T, M% G$ r S7 d7 z return; //初始化组件失败
' }4 i+ L; {' h: t$ z* @) ]0 i7 o, ]; T% f2 X) R
●创建IP控件●! p5 E0 D. `. ^4 B+ e
Windows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。
6 x& g% b0 [3 w* C2 @5 h
# y" g0 o$ ~& P$ }8 d3 _) AHWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);
: I# i% x3 I# X8 e/ o K2 \7 Z& k8 H: X* F; u& @6 b7 r9 s
●使用IP控件●6 v# W# E6 w! r1 v
在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:
' I, C' P& g( J; _$ F* ?5 @, H q/ r6 w$ D+ k1 C* y
消息常量 消息值 作用 参数及返回值
4 O2 e/ f# T& D1 i7 D5 {5 m( ^IPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无
% h' J5 S: z; M: H2 @IPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值
0 F0 ? I* m" r5 o) T. x3 ?IPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。
/ P. d% Z8 K5 @, X+ A; t# ]" lIPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。: c) b9 V5 W( m O: x
IPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点- o4 C9 o5 ^( i" r
IPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回0& s# S. c G& O6 a D
9 x+ g( _4 a/ O$ F
★㈠清空IP串(IPM_CLEARADDRESS)★
8 L! z/ d: l$ Q% ^" S3 I: u: V, QSendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);
" x3 w7 k2 t# o( j- l# i* `
; @7 A% W" s* E( M1 i★㈡设置IP串(IPM_SETADDRESS)★
( k S0 l- X6 _int nIP;
$ l$ s5 a) B! H- znIP=MAKEIPADDRESS(192,168,0,1); 3 ?) W/ U: o5 u$ h( F
SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);4 R) {9 c- u, N( b( N7 h
! E% u2 N9 m5 F/ r- r0 x$ @此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:
& Z+ f% g; d0 o, K#define MAKEIPADDRESS(b1,b2,b3,b4)
, r0 B9 x! L7 C5 W((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))
L: |7 ]6 e2 G) ? d) c
8 F4 l. ^. _ z7 {) p/ V★㈢获取IP值(IPM_GETADDRESS)★
$ p/ v' t# n/ [! G% S; |# mint nIP;) C* o8 `6 o, j
SendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));& v' i/ H& a$ ^; U, X
//nIP++;
: T, C3 P# o: t//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。
' j2 S- T9 w; ], W% S( W; z- F
0 L" K( \( f4 I1 u+ a若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。
- {( z9 G" t9 {0 a) w' e) o F; C' k6 w( N. v% V
★㈣设置取值范围(IPM_SETRANGE)★
2 J9 F2 ^ `4 R% d/ h" p6 XSendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);8 n: h( P( O$ |, _6 M9 a
此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。( {6 P5 q5 b+ h9 o$ M. ^
/ I, M8 d: [$ j1 I- E* L( s★㈤设置输入焦点(IPM_SETFOCUS)★* m) v. K5 Y3 o2 \9 Z, N$ H
SendMessage(hIpEdit,IPM_SETFOCUS,3,0);- D2 m" g% K' |) w$ q& K6 i% u9 g
//将输入焦点设在IP控件的第四部分。
7 S2 A4 o4 |8 h) o% V( @2 v
; M. \* ]) A! F# G$ [2 l! w㈥判断IP串是否为空(IPM_ISBLANK)8 n+ u& M# n- I9 \. @+ A
if(!SendMessage(hIpEdit,IPM_ISBLANK,0,0))
" {# e( w {; b- ^0 z6 e, x6 D5 B{
0 p% ]3 j9 Z5 M" k- Y3 P+ \ //IP控件中的IP串为空
* [8 C7 d2 O: E}' K/ b& v' L7 n
else
4 R; |8 q" V, r0 z# h{
* d: K- ^- w' } //IP控件中的IP串至少有一部分不是空的3 S3 }9 k0 T) ^2 {; k- h
}
- f* r, d) E; w2 C8 o4 |% j j
% s6 L" V; \7 y8 c1 M●IP控件的通知消息●
6 o J' j% Y3 K% }1 Y# ^% J9 {当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:4 ], @: h* \; e! U# @ n, M+ p
% P: ^7 ]0 ]- W& g' ]& Hvoid __fastcall TForm1::WndProc(TMessage &Msg)
. ^' c; q3 i6 V) h{% e/ C% H. C* A
LPNMHDR p=(LPNMHDR)Msg.LParam;$ @6 V/ `! W7 X4 b# Z( B
if(Msg.Msg==WM_NOTIFY)
9 p, H8 G. _+ ]6 Y6 B* M5 J {9 Y, `" ?$ J- ^
if(p->code==IPN_FIELDCHANGED)
$ H/ r' d/ }4 K# D {
5 q% z6 k# e6 p! D+ _. p //处理IP控件的IPN_FIELDCHANGED通知消息
. ~ {( G' s- f' t7 l }+ P. w5 F: i0 k4 k6 @9 z8 p; Q
}; [; U q' E4 S! s9 T) o
TForm::WndProc(Msg);) f* J, j: d. m5 s7 i6 W
} |
|