|
|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。& T1 |8 g" n f9 H4 f
欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592! i+ Q2 E" y' P4 g
本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:( D5 h) n" w/ `- V
标题:在Delphi中使用IP控件5 K I* l8 t+ O- j
作者:西安交通大学9649# 刘明华4 C) o3 x s6 p3 \# Y5 J4 |
在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。
3 t2 x) B: j- S& \0 ^如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com
. |) `$ e' _, e7 cccrun(老妖)(www.ccrun.com) 2003.10.294 q. X4 r0 V6 \2 p6 U3 L& O! d
4 f; \4 t! I! f2 s
在网络程序中,我们常常碰到需要用户输入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控件。7 I4 x; S0 r- B, I$ E# |
' Y8 E# X( n0 s/ J z4 K
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)。
7 n* Q+ K2 k' t1 M0 M; T
3 l9 o7 {' Z2 W7 z g: `* y●初始化Windows自定义控制库●, d- k3 p& E) \) _1 L9 k
Windows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:
, a5 y4 E p2 {8 @8 m8 q/ C( S1 u/ u: _
typedef struct tagINITCOMMONCONTROLSEX {3 A- k% U" p% G
DWORD dwSize; // size of this structure: l# L7 a, r8 C- b0 _/ `3 R ?
DWORD dwICC; // flags indicating which classes to be initialized
- F) d' |3 `- V, f6 [7 F( D& K} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;% U: ^2 W; r- L" v @
8 \7 d1 n- \6 Z$ \
WINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);" k( n! o! t4 z: E( H
5 D' L% ?1 j" lIP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:1 }8 L9 P2 `* [' d, K0 i' s
4 h% F& o9 P# v. Y' G7 ~5 a3 v; b8 ~TInitCommonControlsEx ICC;4 C& q6 a4 Q$ n% Q
ICC.dwSize = sizeof(TInitCommonControlsEx);6 M; ~: @1 B0 h: Y& f x
ICC.dwICC = ICC_INTERNET_CLASSES;
1 i5 ~2 Z: `* Y$ @if(!InitCommonControlsEx(&ICC))
4 l! H) K: p+ {& d return; //初始化组件失败
6 G0 \ W% x; `: Q
5 F: U6 c7 _) @' S9 a●创建IP控件●) l H7 D; x; m4 s/ b; v
Windows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。
5 d$ N' |6 y; P9 J2 h1 N) I3 T
3 j/ Y& [# @; a8 O4 N$ dHWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);) R5 r" N$ b7 ?
9 e |" }/ i2 f6 _* ~: u●使用IP控件●
- V H2 r/ s$ U O1 y+ z0 {在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:
/ H; w' u* L9 [# p$ o! G7 J) h3 O* j- l2 _6 H
消息常量 消息值 作用 参数及返回值/ E/ a( L4 _" m
IPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无
) a% P6 T. J8 ~+ ~) M7 OIPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值
: I4 V; P) U6 z/ H: SIPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。 8 W2 m0 b: o/ R# t5 A
IPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
% |7 k4 v) u7 G+ o" _% WIPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点
. [ S. x: C. J9 @: x+ |IPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回06 P2 G M+ p9 U
# x) q6 @$ R' p# g5 K5 J; y1 _
★㈠清空IP串(IPM_CLEARADDRESS)★
2 J5 i9 s+ v/ C# w! B: VSendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);% ~& z% M+ O. X7 ^& ^" }; \
" c' L) ?9 v. |3 M* P [
★㈡设置IP串(IPM_SETADDRESS)★1 _( g4 E2 @8 |5 L6 B6 w
int nIP;
7 ^1 g# y) |: y9 F0 mnIP=MAKEIPADDRESS(192,168,0,1); # {9 _. l* F d5 K7 _ K/ J
SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);$ [" r: z n, c, q% _
- ]% h9 }4 u; {2 h3 Q5 ~2 v2 j此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:+ o+ e* v3 V8 J$ @0 l% x! L
#define MAKEIPADDRESS(b1,b2,b3,b4)
1 i' @/ E; _; X- U((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))+ w1 e0 N$ {- l4 H* y" l
8 A8 x5 C) a: Z6 r# h★㈢获取IP值(IPM_GETADDRESS)★$ Q8 r' w* e+ j3 |2 \
int nIP; R& j4 d* b! T0 m8 p8 G4 B
SendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));9 i% g- W8 P9 p
//nIP++;; T6 b x4 B, a1 A8 `3 V
//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。
1 W. u9 X. B @( r! ?8 X0 K5 H
$ @$ X3 S. Y1 d+ y+ s若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。
5 D8 f% B* o+ Z9 i P* v2 b& W, t+ y9 o+ k: R' l" o
★㈣设置取值范围(IPM_SETRANGE)★, c+ ^* U" i8 P& L
SendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);
! K' B! J1 f% b! o此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。/ Z- G: {0 n3 T2 ~: ]
" ]" z9 ^- C- ?$ t★㈤设置输入焦点(IPM_SETFOCUS)★
# d% j. M! d$ q, I0 d; Q" B, ^SendMessage(hIpEdit,IPM_SETFOCUS,3,0);
. z5 `) M T% _& R- E//将输入焦点设在IP控件的第四部分。
) Q* N2 y6 Y# q5 o- g( W5 _1 e* l2 r
7 X" g; }) t+ T㈥判断IP串是否为空(IPM_ISBLANK)
/ }; `1 ^4 o3 K# b% X7 I" ?if(!SendMessage(hIpEdit,IPM_ISBLANK,0,0)) ; n- G5 Q0 k" n4 p/ {
{
- A S6 s, j- f3 v //IP控件中的IP串为空* h% z5 H0 a9 E
}/ u! ^9 v' F4 [) a
else* {* l( j% X" L- {6 u4 N
{; m/ \, p+ O: \; w: r" S3 p
//IP控件中的IP串至少有一部分不是空的% p" C7 Y$ Y$ N9 Z& D( `
}2 r: E& S w! @9 z6 u. J$ \/ D6 }6 R
) {- O& ]: U# A h, l9 V$ r3 b●IP控件的通知消息●
$ g9 k. D2 E4 @/ _6 U当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:
3 @* S/ |+ n4 r. a9 `( y. b4 d, C/ g8 D: U: {1 P
void __fastcall TForm1::WndProc(TMessage &Msg)
$ P& g% P5 q4 X+ o) Z; \{
( W% E, J+ c& E8 ?% u% U LPNMHDR p=(LPNMHDR)Msg.LParam;
; i/ a' @" l1 w if(Msg.Msg==WM_NOTIFY)- h# V0 Q5 C$ C4 [7 ]
{
: D; b8 j1 [/ \0 Z* j, H$ J% v if(p->code==IPN_FIELDCHANGED)$ B; Y0 B7 J8 d& M/ y) }+ J5 f
{
5 ^5 W) B2 S$ d: @% W; {; { //处理IP控件的IPN_FIELDCHANGED通知消息2 D9 n, ^$ e+ S. F; P
}
; J! q) j# b {; A# A5 e5 d }
$ D( [: R3 ]* s- G6 M4 ?) { TForm::WndProc(Msg);1 d2 E+ X6 ~9 p* f2 U( V( }6 ?' l6 {
} |
|