|
|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。 M5 }. p, @- F2 g- x/ o& h8 \1 ^
欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592# V# v& w$ j2 k4 v* c: U) _
本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:5 c1 k; A) \2 `" y
标题:在Delphi中使用IP控件
, T6 J7 `4 A6 |2 e作者:西安交通大学9649# 刘明华
4 e: `" f9 l/ L2 f在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。' V5 f% x8 v1 b7 V, O% M1 Q5 T
如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com
# l0 ]4 w& t; T% v- g$ Dccrun(老妖)(www.ccrun.com) 2003.10.29
0 }* ^6 J$ |. A0 }; {; j
d* k1 b0 X2 @6 v; T: A在网络程序中,我们常常碰到需要用户输入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控件。
9 ]9 e/ M% ?( U' z
0 | J: r, Z! m. }) iWindows中有两个非常重要的动态联结库:commctrl.dll和comctl32.dll,它们是Windows的自定义控制库(Windows Common Controls)。自定义控制库中包含了许多常用的Windows控件,如Statusbar,Coolbar,HotKey等;在C++ Builder中,这些控件大多数都已被包装成可视化控件了。在Microsoft推出Internet Explorer 3之后,自定义控制库中新增了一些控件,其中就包括Windows的IP控件(IP Address edit control)。
" u: I3 z: x5 R% X4 ]6 x0 F
8 [' `: J. o1 g, O9 m/ J& Y; A●初始化Windows自定义控制库●
" V% z3 B5 @; o/ P8 [Windows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:
# u! @: |( Q# L3 ^3 C* `( ^6 B0 N4 @1 M3 |
typedef struct tagINITCOMMONCONTROLSEX {
7 U* _$ N! q( D! E DWORD dwSize; // size of this structure( h6 O0 y4 b- Z! c# A
DWORD dwICC; // flags indicating which classes to be initialized9 \0 p8 ]4 E" _1 ^
} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
" k9 O2 U9 Q) ^- {- E8 P
, p& G5 j" t+ \: q; qWINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);: @7 a( f$ K b/ A5 t
" \/ O* y: B% [, nIP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:
) P8 a: e1 f# s3 X9 G
& Z3 R9 C5 N+ I" @* C2 f; ~3 rTInitCommonControlsEx ICC;
( w7 ^! @) l+ W9 R- _2 fICC.dwSize = sizeof(TInitCommonControlsEx);
+ Z" J7 Y$ f) g/ _( e2 j* MICC.dwICC = ICC_INTERNET_CLASSES;
$ g% l) C& P5 W! c! m& p# R/ Jif(!InitCommonControlsEx(&ICC))
1 n' Q! M0 a: G4 i7 C( s4 |% C$ [2 d return; //初始化组件失败
. A, k7 p( t. S" A
. j6 s4 e9 ]9 s% p0 S1 A, y4 L5 o) w4 G●创建IP控件●5 ~2 V5 g( I! b y# T3 m; o2 W T1 i
Windows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。# f' c, S# f+ W$ k6 z" Q; Y
- h8 P& {" n8 n5 Y" d' G5 J0 ]$ o
HWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);% e# A9 n. s) J, x
9 R+ {0 d2 R; ~: z, x6 Q( B" v8 a
●使用IP控件●
) I: [0 x* E9 ~2 T8 _在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:& u+ O- p$ H- V; m7 h3 B- m1 T7 R
+ _+ g/ j' I$ J) A3 V |消息常量 消息值 作用 参数及返回值/ D' f' R8 ?6 j
IPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无" Y$ w: B0 v% f, z5 _: \+ J: Y
IPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值
6 D0 x: x1 k9 p0 w9 M) ZIPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。 6 w0 x4 Z, N8 D y
IPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
8 U: s* Q9 q- J# QIPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点
, Q) G9 X: i5 o1 h5 w g8 LIPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回0
! V% f# h: t/ F* u/ I, B* J8 z" k5 g
★㈠清空IP串(IPM_CLEARADDRESS)★4 |. y( I3 `8 }/ m2 O5 ]
SendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);
; w' o$ B: F" s
( j8 P8 I a) t6 ^★㈡设置IP串(IPM_SETADDRESS)★2 p8 J% O" \* ^' q
int nIP;
! v) r5 T3 B3 ^5 anIP=MAKEIPADDRESS(192,168,0,1); : }9 c6 z( q! J2 D% s( z3 K
SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);
) h" E y5 }. E e( Z$ m' e' {
t1 M9 X. L# }, a7 M此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:4 X' V8 P+ f; B; ?1 @
#define MAKEIPADDRESS(b1,b2,b3,b4)
' r$ L: T. i P& H((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))$ G" e9 l. `0 H" y; q
9 A- { x+ A6 P/ b ?★㈢获取IP值(IPM_GETADDRESS)★8 k, ~1 x4 L5 t" v% D8 Z
int nIP;
! Z# v! |' X2 q1 u- d+ F$ W- LSendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));
2 i3 z: Q. G5 r2 n: t//nIP++;8 |. P. M/ y; c6 E; O: g% n
//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。6 r# o; }& [& }
L# L5 M3 r9 b/ W0 O6 r2 T2 W, h
若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。
+ l9 j9 |4 g8 r$ U0 A9 ~- k# [
; x- J( u o7 h, p; @6 r★㈣设置取值范围(IPM_SETRANGE)★
% K" U1 y! }& B6 J PSendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);
, u4 X4 ?! E5 R* p. ^此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。3 `. ?% R, { p/ ^5 Z/ d9 C! p2 R
9 {6 D( {6 k. A
★㈤设置输入焦点(IPM_SETFOCUS)★9 q2 a j) g1 f6 g
SendMessage(hIpEdit,IPM_SETFOCUS,3,0);* `* m6 g6 Q- V' `
//将输入焦点设在IP控件的第四部分。8 e8 Q6 X# D6 V7 P4 ~) W& [
5 s% U. ^7 v/ ?
㈥判断IP串是否为空(IPM_ISBLANK)* w2 R0 Z; @/ _
if(!SendMessage(hIpEdit,IPM_ISBLANK,0,0)) ( E" B5 Q5 T, V7 b# d/ V
{
- U# z, L* j) n; Z* E0 I //IP控件中的IP串为空9 y! G5 ^: i7 h2 i9 k- I0 q% f& }
}
, e. R7 P2 O4 } Yelse5 g; i# w5 _, s' @9 D) t; ^
{
2 |8 A* y! N& W/ `! J& ^9 p //IP控件中的IP串至少有一部分不是空的* d: R7 f2 b" O! A' m8 L* q! s
}3 a/ u V; y* b: N8 S
# W- p; d8 U& O# h
●IP控件的通知消息●
+ W) f4 J+ n+ M- U当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:& V0 G- w& |6 P9 d# o" m
; U) O1 U9 t5 z7 C7 X( ~
void __fastcall TForm1::WndProc(TMessage &Msg)
% a# D1 h4 A, A: Y$ b{. a8 I6 Z5 b) g0 l/ n
LPNMHDR p=(LPNMHDR)Msg.LParam;3 q5 V9 C7 M- p+ n: d
if(Msg.Msg==WM_NOTIFY)
! a D+ a6 o1 W9 ]- v( k7 w {
) \; {+ t) }% ]+ B* b1 [ if(p->code==IPN_FIELDCHANGED) w2 ]) h8 p6 b# U3 _' G
{: D+ l; K. D# q, @/ v
//处理IP控件的IPN_FIELDCHANGED通知消息. ` S$ H6 P* l9 r8 {1 F5 {8 U
}
6 y4 p3 k+ a& Z( R* r+ K }; B7 c; t0 g6 B# [; R0 Z' k
TForm::WndProc(Msg);
9 v& ~/ a1 T# ]0 b. O/ I} |
|