|
|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。; }6 A+ W) v' }1 y" A
欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592
, ], ?* O7 b) }本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:" J3 I+ A1 q0 A$ K+ b% _
标题:在Delphi中使用IP控件
2 e0 R; o) z! O9 o4 P& ]! `" Q作者:西安交通大学9649# 刘明华# J9 G6 g$ r! {) i: g$ p
在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。. Y/ w a( [! R3 S/ n3 w( \
如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com1 A. w$ `) a$ l( ]* j! s4 H: i3 W
ccrun(老妖)(www.ccrun.com) 2003.10.29
a3 C, t1 y! ?4 T' `% i8 K" a; H9 _, o0 e
在网络程序中,我们常常碰到需要用户输入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控件。
8 G- e5 K4 |( L4 h4 b" q" C. r
8 l6 `2 R# l9 x/ Y/ V8 ~Windows中有两个非常重要的动态联结库:commctrl.dll和comctl32.dll,它们是Windows的自定义控制库(Windows Common Controls)。自定义控制库中包含了许多常用的Windows控件,如Statusbar,Coolbar,HotKey等;在C++ Builder中,这些控件大多数都已被包装成可视化控件了。在Microsoft推出Internet Explorer 3之后,自定义控制库中新增了一些控件,其中就包括Windows的IP控件(IP Address edit control)。
; L, g8 J1 n3 c& l& x
( F, L+ Z- @ v●初始化Windows自定义控制库●
" d2 w' b5 M" Z6 [8 N& h4 V0 FWindows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:& l/ Q Y' ^ U5 m: F
5 j0 L' I; u% g$ D2 U6 q( P$ d
typedef struct tagINITCOMMONCONTROLSEX {
9 K. y- q. B7 _0 U/ e& L DWORD dwSize; // size of this structure' G! A( U+ |0 O! |
DWORD dwICC; // flags indicating which classes to be initialized
2 _4 f- e: s) w% ~} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;3 G V4 w1 }) b/ |
! q4 Y% N4 P7 G( o; mWINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);
& F* @0 [( ~+ k) O3 y
' a; R3 f( N- s. iIP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:, J& n1 {; i' V( H
7 m \$ t/ z- ?+ i `TInitCommonControlsEx ICC;; H) ^% I- C$ C, L7 m
ICC.dwSize = sizeof(TInitCommonControlsEx);
; C) M5 l& n- @; T- ]' aICC.dwICC = ICC_INTERNET_CLASSES;( W# b1 i' W+ S0 c+ R
if(!InitCommonControlsEx(&ICC))
' j) a; P3 u5 M7 ?8 s) r% X0 m6 f# z return; //初始化组件失败8 \9 r `: k/ {
1 Y% `4 q2 l/ E% g6 q7 k0 r9 s
●创建IP控件●1 Z+ f x) { R; ^& _+ M- S7 x
Windows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。1 k6 n) I' r6 Y" b8 i. R! s
. W0 l3 L, b% Z6 tHWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);
; r2 H- N" F4 M( p. J S7 ~- L6 O% U) D. J% n9 B9 E5 f
●使用IP控件●3 n. G& Q* A& k2 C4 z! Q: I
在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:5 A- |! T2 `3 c* L
- H( e$ P/ \5 z( D消息常量 消息值 作用 参数及返回值
2 g" L1 O5 s' m9 ] Z" W' Y8 b' |( UIPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无. I1 y* U. E" v
IPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值
' Q$ V8 f& ^* T/ ~( ~9 ]1 W9 M( pIPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。
+ @$ Q: ~( u& p. D9 o* h* }" [( F' LIPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
C9 N( j) C$ k9 \' d& }, q. Q8 OIPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点
% D% U) X% Q' b6 hIPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回06 e3 U. T# ~4 X& |: j. V
8 L8 f0 S3 x& @2 _6 r
★㈠清空IP串(IPM_CLEARADDRESS)★1 _8 ~2 x1 b8 ?' h# a2 l, f
SendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);1 a# i' U/ u) v6 K
4 z9 u1 p6 [; S& Y" w- a2 z0 |& `★㈡设置IP串(IPM_SETADDRESS)★* k4 z6 c7 ?# B0 x# a7 \. Z
int nIP;
$ v9 F% [) R; K* SnIP=MAKEIPADDRESS(192,168,0,1); ) h" }9 ~. `/ ]; A: o- v/ K
SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);
- _9 K. ?" z; T" e0 r/ B
' q- ?/ H$ W6 L) R- [& d/ I此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:+ c5 W% J: S& S' M( n5 K/ d/ w
#define MAKEIPADDRESS(b1,b2,b3,b4). ]/ h3 B+ a" ]8 @, h( I
((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))
0 [/ U4 V" ~! n, a, L) C& d& ~
* m8 r7 C# @& S) }: `) g! G★㈢获取IP值(IPM_GETADDRESS)★7 S" f3 ~) |, \% }# q
int nIP;) A1 F& @9 z; a. \2 Q& W& a0 I
SendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));
% [" {8 c1 U+ x0 a0 S* ^- O//nIP++;$ b+ u4 Q( a$ U% F; x1 } `
//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。
9 o0 ~$ Y% {/ r6 U3 n' x, `0 j
9 i0 Q0 K9 {7 K若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。
; F. V: |0 m. }1 |# g5 \
# o' U) e, c; ]/ g) m2 G★㈣设置取值范围(IPM_SETRANGE)★( f# T: L$ a# T E+ M9 Y
SendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);
! o4 X# C. W2 {4 y此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。7 h3 N" n# B& w$ U2 h. z: Q) l
9 h- w1 b% G, w) U, U6 b
★㈤设置输入焦点(IPM_SETFOCUS)★1 c6 F9 C2 m% v" W
SendMessage(hIpEdit,IPM_SETFOCUS,3,0);5 Q! g* Y7 n& K3 H( O$ Z# I
//将输入焦点设在IP控件的第四部分。8 J& b7 m* _$ x+ Y9 B' n: y
$ q7 E/ A8 v$ O
㈥判断IP串是否为空(IPM_ISBLANK)( e3 f/ J" _) U& k7 C0 A
if(!SendMessage(hIpEdit,IPM_ISBLANK,0,0)) : C* d7 O+ }) ?8 e$ }- _
{
! G( O- D# G/ N3 \ C+ D7 ] //IP控件中的IP串为空
1 @( Z) u5 l7 z9 F$ g! W3 D/ l}% l4 X" w/ e- `) N' q
else6 }( f7 \5 @9 ]- |* B' ^
{& E6 P+ d3 ]1 y% {1 r+ T" ?
//IP控件中的IP串至少有一部分不是空的
: b/ F6 B9 q, v! R. [" u$ P7 Q}7 h* G7 S. l: u+ t" Q
. R3 L. K9 `, U●IP控件的通知消息●4 u' V# C, Z, \" F6 J7 p
当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:" S5 Q) k2 q6 v: a
$ E Q, {& G" p9 Y! y# |void __fastcall TForm1::WndProc(TMessage &Msg)5 a% Y% g: e! P5 Z* U, f. N
{; J6 T: b1 B3 O% a2 {! w7 g: [
LPNMHDR p=(LPNMHDR)Msg.LParam;
5 k* x9 A# B5 X1 Q if(Msg.Msg==WM_NOTIFY)- p$ f& }2 z% M: U, S+ T8 Z, R
{
/ Z: c+ S" N+ e h! M# T if(p->code==IPN_FIELDCHANGED)
3 {0 d; d3 g/ ]5 U {9 p& j+ x! J$ ~" A/ F7 p
//处理IP控件的IPN_FIELDCHANGED通知消息' S9 M4 |' X: G. i
}
. \9 {6 W6 a0 r- L }, V' ~) }' v2 G1 [5 {$ G
TForm::WndProc(Msg);
+ Y0 T0 H/ s$ Q( i5 F} |
|