|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。
0 h$ G7 i4 f# b* C+ v欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592
5 p& l& t& \0 q本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:: n5 t+ x3 v) F% B! E! @) J
标题:在Delphi中使用IP控件5 ~3 ?! M }# E. Y) i! E: |
作者:西安交通大学9649# 刘明华
* g/ }- V* m1 p0 ~在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。! @8 r* M7 N& ` Q4 s* ~& @
如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com( C9 W& l+ s3 {& j# D
ccrun(老妖)(www.ccrun.com) 2003.10.29
2 u$ E d8 t' {* M8 T; q9 q6 g7 s" i2 H, t3 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控件。
0 b7 H; b/ d3 Z4 F: @- M3 F- s' t" [" J# `2 |
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)。
2 p* e- L1 A. X( T c# n/ l8 ?8 n# }' f4 t; Y; W0 Z
●初始化Windows自定义控制库●
0 M/ x- H4 k/ JWindows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:
# Y2 ]; X' ~: \1 o3 E( f1 `3 {/ B
, N! F: m {* [' n7 otypedef struct tagINITCOMMONCONTROLSEX {! N7 @/ P) J; [4 \2 L- E
DWORD dwSize; // size of this structure- i* B" P6 [* j
DWORD dwICC; // flags indicating which classes to be initialized6 ~0 w4 q% u& g9 u4 ^
} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
7 Z3 i) h; c) d2 O2 c/ q+ S2 |- {( m% p
, @0 `; a- J/ s. cWINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);8 _9 C/ w- V. y
B6 e5 Q8 r$ l8 B: sIP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:3 F& k2 c- e: n5 ]" J
. F1 C' p) B( T9 aTInitCommonControlsEx ICC;
* V+ I- z) f# U s6 a2 S( M7 RICC.dwSize = sizeof(TInitCommonControlsEx);
3 a+ p" ?. i! {2 l' ZICC.dwICC = ICC_INTERNET_CLASSES;. p; ~, B2 b+ j' G
if(!InitCommonControlsEx(&ICC))
7 z1 x- O. [/ l, c' _0 ~& Q7 y return; //初始化组件失败* r8 s! f$ G! j9 |; V
Q* V4 Y5 _( S6 w6 L. U●创建IP控件●1 w7 w2 ~' D1 v& T8 l
Windows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。9 {* A1 f: B. r A$ O c/ q
3 l. d5 G+ u2 r$ JHWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL); l& c& G9 @9 q# A g
6 H2 S! R+ ~# O* M1 T5 R! M) z●使用IP控件●( `9 @# A6 A1 x
在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:% n1 p2 q! x1 {5 m/ k- d" N" v
# F: N' ]8 _4 M
消息常量 消息值 作用 参数及返回值" g+ e: R4 w) [6 o F- W7 k% V
IPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无
5 v- _0 y. v4 o2 E6 u+ f" MIPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值: q; L8 Y' Z! c1 F, N( M( k
IPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。
' r5 D/ g: n# bIPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
: l3 N& V5 s; Q$ J2 c* W8 KIPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点
& L* k2 P% R+ q( BIPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回0
) m1 y. a* b- q! n6 A: Q8 g. X' ~, `) Y/ f8 }1 H" g: n; Z
★㈠清空IP串(IPM_CLEARADDRESS)★( @- |2 u+ _1 c1 t& O; o
SendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);' f/ N: d) P( }
. b d. p. |: j5 ]' n3 N# ]/ r★㈡设置IP串(IPM_SETADDRESS)★/ G' b; r8 i5 H& } j4 v# `
int nIP;4 V1 @. Z- H8 O. T
nIP=MAKEIPADDRESS(192,168,0,1);
( U8 s. {$ O5 M1 o$ M+ j6 ~2 J# ESendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);
3 A4 n! ?; a9 v. Q
# w6 J, y, N/ {! v' c+ q. g此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:+ s& u5 L: f# d
#define MAKEIPADDRESS(b1,b2,b3,b4)
, P) B U' L* ~" e((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))
$ X* e: S. g1 G9 b |
3 r: r, X, a$ N) A+ l4 D: U. d★㈢获取IP值(IPM_GETADDRESS)★
( R8 `9 N5 T* O9 dint nIP;5 I& e2 [" \7 t$ K5 C
SendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));
0 E! R, K7 n) J1 w2 D& r4 J$ o//nIP++;
! W; C' ^+ }4 ~+ M7 V) R//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。
2 q2 h) w% y# T' y/ }) b3 f Y9 I* U$ W' ]; m: p% U5 C ?
若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。2 _ b% q# a# R: n4 l
9 N' m' P. I7 z6 K4 D
★㈣设置取值范围(IPM_SETRANGE)★
( h0 h I- Q" C) t Y8 k3 y2 RSendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);
' c+ M B8 p, H此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
% T3 s% M* k) Y3 K2 w' A
# H. _. _2 W2 D0 |: ]" W7 N★㈤设置输入焦点(IPM_SETFOCUS)★
( J8 C1 ~/ ]- w9 o& h, lSendMessage(hIpEdit,IPM_SETFOCUS,3,0);1 {- Y& r( \$ p/ A% Y8 e
//将输入焦点设在IP控件的第四部分。( W" ~ q8 k) r/ \
0 \ o2 ?" k' u/ \' t
㈥判断IP串是否为空(IPM_ISBLANK)
5 e- o, x: o9 uif(!SendMessage(hIpEdit,IPM_ISBLANK,0,0)) " z' v+ J8 w; |1 S5 D. q! w
{
* e! I) D h9 c# W- ^( Q* p //IP控件中的IP串为空
4 H6 W1 A( B+ o: v& Z/ |}
1 v6 A$ j0 V: ^0 ~% velse- L# P. p* F! F7 S( \! j$ Q$ u
{: A5 a+ B& S; L: [( m* G
//IP控件中的IP串至少有一部分不是空的
4 W- K$ L1 R! i9 o}
0 g% c7 f Z) W& D- R& Y! S
) E! e" g- d$ m0 g+ D●IP控件的通知消息●8 W! t, b; V( c) [6 c5 F
当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:; v% {7 K$ B8 \
* B6 ]- x; l K) |4 N ^3 X2 Tvoid __fastcall TForm1::WndProc(TMessage &Msg)
2 T" [+ e/ F# S9 k( j{
# _& H% {, ^' s* e# b9 F, P LPNMHDR p=(LPNMHDR)Msg.LParam;3 S: I6 s ^; P7 \0 y, P$ q
if(Msg.Msg==WM_NOTIFY)# n% C! I) e' `. p$ e- \
{
! R h2 }# [; ]3 O+ ^ if(p->code==IPN_FIELDCHANGED)- s1 G7 U+ T) ]. O) J
{1 e/ Z* g; b7 c8 l7 v. `" t
//处理IP控件的IPN_FIELDCHANGED通知消息
4 Z5 a: j6 m S }4 p- F1 M2 _% q2 h1 H
}* M/ Y; b- T/ C: V
TForm::WndProc(Msg);" s3 A: u0 _/ l( v" i2 a
} |
|