|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。
. [. P6 u" F1 E4 o/ c1 } U欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592
4 X! m+ S5 Y4 c2 P6 o. y本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:
+ @4 e9 z4 P( H5 }标题:在Delphi中使用IP控件
. a9 } I0 @6 d; H/ k作者:西安交通大学9649# 刘明华
% O! e0 X) \2 S7 H/ P Q" _在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。
R8 }* H# H7 \. ~+ l如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com0 {4 h* ?. R& W% E9 j9 I0 u
ccrun(老妖)(www.ccrun.com) 2003.10.29: Y4 x3 r7 D, k7 b4 u) v, H
" E5 `4 x0 H+ O1 v) B. Z在网络程序中,我们常常碰到需要用户输入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控件。
. r, U$ @1 k: T9 \1 {5 b5 c2 W& |; X% ]% f
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)。
. h' X1 }7 O9 N0 V$ b$ w: g( c1 ~6 M4 H6 A; J1 M& R4 H
●初始化Windows自定义控制库●' b; e) _0 |: r8 I# E
Windows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:& C# ?. _* g- ]6 d5 P: F
3 I0 E* I1 o! h1 d+ [9 Etypedef struct tagINITCOMMONCONTROLSEX {
( h. ~# V+ H- a& Y* f+ r2 N, I DWORD dwSize; // size of this structure7 z! g' Y1 O) a# A7 j" I
DWORD dwICC; // flags indicating which classes to be initialized
& C' V9 s7 x/ V! s9 E' ~} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
; R1 X4 K9 ~: [
& u' F9 y* j3 i2 E$ bWINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);/ |* N+ L7 W' k1 S% b' L9 w
/ x/ r: W1 i0 J3 ?, y' LIP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:
: x! z! t. w+ r {' m# l) b o6 d0 p r& M4 d+ }/ Y
TInitCommonControlsEx ICC;+ b4 b8 @ q4 J# Z
ICC.dwSize = sizeof(TInitCommonControlsEx);' ?: E' G) k: O( i/ |, ~
ICC.dwICC = ICC_INTERNET_CLASSES;( s& Y1 U* q4 l# l
if(!InitCommonControlsEx(&ICC))/ T1 ]. f7 O4 m7 z4 w: ]' y- `+ G9 g( h% V
return; //初始化组件失败8 I+ \9 g+ G I/ h5 F$ b
: P# ~/ H4 b9 f* z9 F●创建IP控件●$ ^. z6 o4 F! T3 ^
Windows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。9 E2 k/ b2 {2 [8 g% e3 q
, {6 D. X x; d: RHWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);$ l# Z5 ]" [$ {, E+ D; k
. T& j& A4 L3 Y: S4 w
●使用IP控件●
3 C0 \( U) k( `$ Q; U( }) B在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:
3 g1 N" D' P4 A9 s- }" ~! l2 Z9 I: e/ i
消息常量 消息值 作用 参数及返回值- ^# n. `2 P& y/ ]
IPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无
# r7 B6 S$ M1 g" UIPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值
. P$ B F$ k" C7 P* _% QIPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。
! H# @* g. S4 ~" D( z3 kIPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。0 }/ k7 n# U9 r7 Y+ h
IPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点+ ]; A/ U( p, j+ e& A6 k. t
IPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回09 L' o6 F0 ~: ]* m* p# I1 K; A( \
) z7 T6 d7 h$ W( ~★㈠清空IP串(IPM_CLEARADDRESS)★
! b" V5 S$ c. |# d4 n2 W5 S% bSendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);
) j' z, X; b7 O7 \4 O. X/ t! W3 S( I0 y, }! F3 c
★㈡设置IP串(IPM_SETADDRESS)★
& A5 X* E& O0 ]* s4 oint nIP;
C% \. ]' g) rnIP=MAKEIPADDRESS(192,168,0,1);
( V% U: `5 t' v8 ~% HSendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);
; C4 p1 w0 C. ]& I
; a" x3 q6 o1 i, }& P此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:: x- ]- k+ U0 s( L
#define MAKEIPADDRESS(b1,b2,b3,b4) S, e' Z, g9 |8 ]$ N5 J$ p5 v
((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))( H* G! f$ Y4 M( |3 l
8 {6 Q& G; p( | I' f' z! p% J) g% g$ Y
★㈢获取IP值(IPM_GETADDRESS)★
; O4 H( ^2 Q2 W% s- Y6 Zint nIP;) M! S& v% ~! i" `( F9 X
SendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));4 B5 U, g9 z; ?* L1 \
//nIP++; ^( k& K& Y2 x/ V# Q5 B
//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。% y8 P1 D' ?9 |! \
4 a1 R) w" C' K5 \若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。
4 T9 b7 Q S7 `" ?6 [5 o; S M; l4 Z, ^
★㈣设置取值范围(IPM_SETRANGE)★: M* h6 s: B8 X; q0 S% f. Z( L
SendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);, [, s0 P, T- q, T/ Q% k6 T0 ]$ q
此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
$ O5 R( W6 M5 ~" Q" r5 Y% B& b6 ^$ Q
★㈤设置输入焦点(IPM_SETFOCUS)★
A) W1 a/ V- \% rSendMessage(hIpEdit,IPM_SETFOCUS,3,0);
1 R8 W1 ]! N1 S) y% F. A7 t3 l//将输入焦点设在IP控件的第四部分。# }- J9 x9 l. _
& p$ q3 v# a; W8 B H㈥判断IP串是否为空(IPM_ISBLANK)
c8 F& S# Y5 w6 S/ N: nif(!SendMessage(hIpEdit,IPM_ISBLANK,0,0))
5 d% X6 i! u5 R{. M. S; H3 ]5 c8 {1 L
//IP控件中的IP串为空
7 L1 C' k4 v$ P/ E1 |}
2 s* C& c7 r" Y+ selse
5 ]6 B6 A) V, M) Z! X/ K{ G& j6 \9 ]& b, a2 E
//IP控件中的IP串至少有一部分不是空的
) H" k5 u# m, b a# h}
- ]) T3 z, R: T# d
2 U% L6 s( ?- I3 T) ^: F●IP控件的通知消息●0 I( F& W4 O$ s' R
当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:1 r0 V% X ?" Z( z2 s; `
# h2 i: Q& C: A W# L1 b, q' Svoid __fastcall TForm1::WndProc(TMessage &Msg)6 L3 ?' ]9 X' f" X
{
: P4 P: G0 D3 @# e6 X LPNMHDR p=(LPNMHDR)Msg.LParam; N7 Y. ?& b- {
if(Msg.Msg==WM_NOTIFY)
' e5 q) c) T: \, y* G {+ o4 B7 m( T& X1 U1 @) I6 \
if(p->code==IPN_FIELDCHANGED)
6 c( {5 r" k4 v: Q: l" y8 J {
7 H& U9 o& W" I* g* _) l4 n. e. {1 r //处理IP控件的IPN_FIELDCHANGED通知消息
' L( b1 w% t/ A }! s% {( H# H) E' {: I6 ^! B3 E
}$ r+ x+ ^0 L' K! F' ?5 n
TForm::WndProc(Msg);: Z- Y7 i3 t, g3 p, s
} |
|