|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。) `8 b2 i. Y! h& W8 h, d3 O
欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592
, u8 P) p$ X( r. y" ?5 ?本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:9 f2 I. I$ r& p% g# i. |/ [, F
标题:在Delphi中使用IP控件( p5 V. T7 E" n" u6 z+ J( z1 d9 g T
作者:西安交通大学9649# 刘明华
- q0 p9 [# x0 M! k在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。
0 x* f; P3 g6 |4 u- f如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com0 `6 E$ |! j( V9 |& c. L
ccrun(老妖)(www.ccrun.com) 2003.10.293 e4 B/ ^& R3 C& J- z$ X
8 B, d* a# k, [" y
在网络程序中,我们常常碰到需要用户输入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控件。
$ h! d/ l" w, R# u0 Z
7 G" {% }3 C" e& C8 J$ V) m FWindows中有两个非常重要的动态联结库:commctrl.dll和comctl32.dll,它们是Windows的自定义控制库(Windows Common Controls)。自定义控制库中包含了许多常用的Windows控件,如Statusbar,Coolbar,HotKey等;在C++ Builder中,这些控件大多数都已被包装成可视化控件了。在Microsoft推出Internet Explorer 3之后,自定义控制库中新增了一些控件,其中就包括Windows的IP控件(IP Address edit control)。
6 z9 f/ }. ?, N; O% T4 h* R n s6 U
8 ~4 @, R- Y0 {●初始化Windows自定义控制库●
/ H& j2 o) L0 A" K* E5 r7 t: ]Windows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:8 d( d1 A1 r& O" T
9 @" U1 K) A2 l* k! T$ Vtypedef struct tagINITCOMMONCONTROLSEX {( u0 N, J: Z/ j9 B0 W
DWORD dwSize; // size of this structure* c* r, p% A$ x0 @: S+ X Y
DWORD dwICC; // flags indicating which classes to be initialized# y* R) J5 ?4 x/ \- k" ^! K) P0 T
} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
9 \7 {# l* A; R2 G$ E W
! {; ^& L9 @0 I# E# VWINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);
% c9 q* q( I7 ]/ q+ i; i. w8 d9 A+ L; u0 J9 q# S1 V S4 W. ]) C
IP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:1 O8 C- E. z8 H/ C2 d
$ c* ^# O: \+ N: PTInitCommonControlsEx ICC;
, \- F2 I& `8 V h4 s- b2 w aICC.dwSize = sizeof(TInitCommonControlsEx); e4 p( E d% Z' A- W2 t1 W
ICC.dwICC = ICC_INTERNET_CLASSES;
8 ]: E z# K! w5 _if(!InitCommonControlsEx(&ICC))
0 C: Q' v7 n3 E# s g return; //初始化组件失败7 U4 ?% f/ O1 ^" C2 c
; F N) G) ~* z2 P0 }
●创建IP控件●
( f/ T5 u$ r$ z1 lWindows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。
; [9 ^: e5 s- C4 Y, Y5 d5 m1 a7 q/ ? j: v6 Q; o# {# h; f+ i1 x7 u
HWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);! {1 w9 J' p6 e# p+ `8 a
: p/ i& K9 ]6 o" K8 J+ }* t4 q
●使用IP控件● B4 L! Q) K! S& Q
在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:3 X: Q( l& m' K1 m
3 t) W" m3 F8 m5 I! Q5 L0 N消息常量 消息值 作用 参数及返回值
5 h0 h+ F! p$ U5 K& ^IPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无
9 G7 n* m3 y( t' T) Z# u( U( DIPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值
7 A, d: b+ E) \0 o4 T( m! d; w7 D4 AIPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。 $ }; F3 g$ L% S& {1 B# k! e
IPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
- ]" _* p4 W$ h2 Y2 t- I. n) `. SIPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点) K4 }0 J9 S: {: n7 N0 |0 G
IPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回0" W& a2 j3 _5 B6 e8 e
U4 ~, W6 X/ D' ^
★㈠清空IP串(IPM_CLEARADDRESS)★: g8 E4 i! M( m2 J' ^3 P! o o$ `- C# n
SendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);' R5 \2 e4 y' s* Q
2 f. w1 u& Q+ {* x8 Y$ z
★㈡设置IP串(IPM_SETADDRESS)★
% W* I, }' X( J% k& w. O$ \int nIP;! V8 k7 {6 S. ]2 U
nIP=MAKEIPADDRESS(192,168,0,1); , e& N+ S) w/ x, O, Q( Q
SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);7 W2 V3 o' s; W: [2 [$ ?
* q$ S: E6 T% l
此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:
* F9 Z9 E+ |# [5 n! @#define MAKEIPADDRESS(b1,b2,b3,b4)3 {& s" `, n3 F3 j- S
((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))
3 {# e! ~8 Y& `+ d$ M9 t5 t* n P/ z$ A! k% A
★㈢获取IP值(IPM_GETADDRESS)★
. p7 [( S( O; J# u$ y7 K( J* Fint nIP;
' i8 x( C7 n5 @; a5 L% y; k% e+ xSendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));
* L2 S9 |0 I$ J9 i( ^6 V, p! t o4 y//nIP++;
4 k& h8 o0 p1 T! r+ ]//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。0 l& i* b% q- P/ w( ?
5 y; u N% Z7 |; `/ O" t0 l; e; d8 I5 R若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。
. ^ A5 \, G/ \5 [
- s! f+ L, M; n1 u★㈣设置取值范围(IPM_SETRANGE)★
% w' N; r8 T: }1 a* z% ~- XSendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);
- Y, N3 u7 F( L* z' F此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
8 v3 Y; b% b6 i/ E4 |
1 M! L4 h. P: m( y5 j& m" r★㈤设置输入焦点(IPM_SETFOCUS)★+ ?8 [) z- }1 ~+ b9 X" T# {, `1 A
SendMessage(hIpEdit,IPM_SETFOCUS,3,0);2 Z. \8 v2 H; Y O& X' ?+ t
//将输入焦点设在IP控件的第四部分。
& s& [' D# o& V* q7 B- j! x1 V8 ^" q* T
㈥判断IP串是否为空(IPM_ISBLANK)
\2 Z, Z2 k: z5 Pif(!SendMessage(hIpEdit,IPM_ISBLANK,0,0))
e: x% J3 k x, ?6 e' k6 U. ~{" W- F1 {7 x2 c- ~: d' @0 P, p
//IP控件中的IP串为空* |) A$ q, E4 m3 c) s
}
b6 ] T1 ?5 `3 z- n3 Melse/ d/ c$ H2 U' O3 H' X
{
$ F! l' T# }$ m, |( x: o4 `& y" Z //IP控件中的IP串至少有一部分不是空的1 C+ j" K9 I: B- t
}" y5 v; Q4 ?; ~
! W# M# a( G% n( e0 g& R+ C
●IP控件的通知消息●
% Y% O3 T8 u( ~4 `2 T# F当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:: W/ e# S% Z# _ E9 x5 {
4 F& L) p `7 m5 V) |
void __fastcall TForm1::WndProc(TMessage &Msg)& T! B. @; n0 T) v9 Y5 r- v. ~, l0 w
{
# T5 Q% `8 X7 R6 q+ T LPNMHDR p=(LPNMHDR)Msg.LParam;
1 X# s& d5 H) X if(Msg.Msg==WM_NOTIFY)' u) Z6 a- X8 t1 s
{# d8 L/ e3 }8 D1 i/ M
if(p->code==IPN_FIELDCHANGED); l/ V2 L5 I9 f3 H' e- _- R7 Z' G
{
8 z" ?; T: k; T( F6 e9 e //处理IP控件的IPN_FIELDCHANGED通知消息
: n( H x! k$ x/ ?9 q; y# x }+ F& w7 s, q3 r1 `5 X5 g
}; X) [: M& s. v5 P9 N& D* T
TForm::WndProc(Msg);
% ~* f8 m& h. t+ ~1 w$ ^0 D} |
|