|
|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。
# F! Z) S) k& w" f2 A欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592% i3 p k% i( w, K4 }" m
本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:
' `3 x, H( }9 g% {2 I9 \) l! k标题:在Delphi中使用IP控件
% A# A& \) N8 |, D' I" X! h3 r作者:西安交通大学9649# 刘明华
C4 U; G* r! Z7 v( _$ {" s, }在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。) ]% j8 F4 |) k, M0 b, W3 i
如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com
, i! g+ T: @' ` A# Bccrun(老妖)(www.ccrun.com) 2003.10.29# R- a1 K: v) S! U- J5 A
8 I3 ]6 x. D; D$ ^& L/ ]
在网络程序中,我们常常碰到需要用户输入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控件。/ t1 O' L" h1 V9 g
" U; n% o% g7 }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)。/ f, P }* S" `( x+ R1 a
$ y6 u0 {6 v: R& a/ y●初始化Windows自定义控制库●
4 E A) A5 H0 k* I+ |: u) VWindows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:
, E/ s% {% {, C, {: g& B$ C6 r, J5 v
typedef struct tagINITCOMMONCONTROLSEX { w, P( P* J' E2 ~0 R) q" g4 f/ }/ w) E! P
DWORD dwSize; // size of this structure
% U3 m( v/ Q0 Y. Y, n DWORD dwICC; // flags indicating which classes to be initialized" I7 m$ l3 ]7 j; _2 A1 z
} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
4 F3 b, t9 I) w" b4 |5 G. z0 c$ u! I$ p" z1 X1 R$ e* `$ F
WINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX); r4 [( j/ K2 ^% L7 Z0 [& F
( D1 k9 @9 G% _IP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:( ?/ ~7 |0 _% E9 a' k( u/ D
; V1 Q7 Q W- x
TInitCommonControlsEx ICC;4 ?2 H9 m9 _9 ^0 [1 {) ~$ m$ i
ICC.dwSize = sizeof(TInitCommonControlsEx);
& x$ z0 Z6 R! I% LICC.dwICC = ICC_INTERNET_CLASSES;5 Y K- M, e+ D1 w$ U
if(!InitCommonControlsEx(&ICC))
`% G% ?# M( z- }, \1 m1 F return; //初始化组件失败
$ G' s1 M8 u( Y) ^, }, I: a1 r2 L z6 _" `" v6 E: @
●创建IP控件●- K3 o8 Z0 A. P- {' D1 H+ v
Windows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。' w' O% `5 h* S: v! J/ S. k/ U' w
0 }' s5 W% W) t4 S& O) v9 }HWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);
- D( n' Y6 f$ z0 x) O' b/ R3 _: F! C+ @
●使用IP控件●
% a. v- j% ]7 G9 b在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:* {! \) g+ u* c0 D
" m/ S+ x1 u9 z `7 |0 f1 E) E7 k% {
消息常量 消息值 作用 参数及返回值* }6 m, g1 y. n' ]6 b
IPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无
T0 W7 D' `7 ?: i4 M# f( P5 q% w' i& |IPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值% N, z$ N' F6 B" K+ L
IPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。
% \* ?! v' G# {8 @' o5 D" m9 wIPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
- ^$ ?& _! G2 ]# XIPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点: p' v. y! ]; T; |: Q% W0 F9 J
IPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回01 u, n+ |) P: P" N. z; l) V+ D+ f5 h
/ z2 ~6 I& i8 `7 e% F; ]$ l& l
★㈠清空IP串(IPM_CLEARADDRESS)★+ j+ l7 r: ]8 w6 a
SendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);
9 c. T- \4 u# K6 g0 A) m9 u3 f% R1 T6 a! T2 `. l$ Y5 ]2 W% ]
★㈡设置IP串(IPM_SETADDRESS)★+ Q8 Z( `6 A5 G- @+ n
int nIP;# T. ]$ ?( [9 s
nIP=MAKEIPADDRESS(192,168,0,1); % a0 e a( ?( H( W+ e8 ~0 E& S6 R
SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);
/ p3 W) x( |0 U4 |3 B; Q3 u# ?4 N4 o5 }6 h( h7 B
此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:4 P; t$ Z- A7 D% F/ j
#define MAKEIPADDRESS(b1,b2,b3,b4) C: W7 V# `3 f/ {4 [# f
((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))
$ z1 z# S1 W/ t) P0 b( P0 V+ i, b; ^- Y) [, q+ m8 ]' C! A3 V( s
★㈢获取IP值(IPM_GETADDRESS)★
5 g x/ p2 x7 l: K, T* C" Lint nIP;
0 v* w6 `$ b' m# rSendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));' n5 W) c# \" x9 E$ Z9 Q% r
//nIP++;
6 i8 T, c0 _$ L: {; h- K+ u) R3 ]//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。% y* M. P- w6 U1 f [# H# L% ?
6 X9 }! H/ K4 v若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。) s# ^( {& n" c2 p
' b9 R* \/ l) I- O: _1 E* L
★㈣设置取值范围(IPM_SETRANGE)★ a5 j9 o" U5 r) k" T4 S/ _
SendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);$ x4 u2 D! K& i$ |. n
此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
* i8 D# i; _( _. D$ N8 |6 b
& H: B9 c+ O; P★㈤设置输入焦点(IPM_SETFOCUS)★
9 P, Z" @+ N8 x2 p X9 W6 RSendMessage(hIpEdit,IPM_SETFOCUS,3,0);/ K4 M' \% ~( F$ \/ e7 y
//将输入焦点设在IP控件的第四部分。2 M( X$ D n0 k$ @
" [7 n n- J- u# G3 N
㈥判断IP串是否为空(IPM_ISBLANK) `* Q) Q) [: `
if(!SendMessage(hIpEdit,IPM_ISBLANK,0,0))
; s6 l/ H+ o- e8 U$ G1 p& i4 W{
$ m- ^' u( U/ g# e //IP控件中的IP串为空
6 M7 B0 p. q2 U1 L, _- }4 S}
( g6 v7 q( y: V$ a( O2 Z( t T/ _else+ |7 C" F# x+ S8 h" j/ c' J
{8 m) r' P; g/ x- x0 ~% r: ^
//IP控件中的IP串至少有一部分不是空的9 D y# n) ` |( R. a
}& n' Y* {" z' A
0 i. z6 g! Q2 c, B1 i- ^/ G
●IP控件的通知消息●
6 s" C9 C* R. H3 l7 [& I) W当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:! U! b& @; f* g' O
# I6 y0 k2 n- f* h- yvoid __fastcall TForm1::WndProc(TMessage &Msg)
, d1 v1 V9 K1 W+ L9 c1 v{
; x9 A8 U) |" n! u7 {6 r LPNMHDR p=(LPNMHDR)Msg.LParam;
0 ^7 f+ H# Y( s. _& z if(Msg.Msg==WM_NOTIFY) u9 h# ]/ b) O0 ]1 E
{9 j7 ]3 S B0 `# s- N- _% U% [
if(p->code==IPN_FIELDCHANGED)6 ]6 g: G8 Q3 U8 A
{
6 P0 `9 V- g# _0 H! H1 ^2 I //处理IP控件的IPN_FIELDCHANGED通知消息8 C3 ?/ v: _- h4 E
}; X! @0 H* D, r! D/ l; G
}4 ]* n' i- z0 B6 D2 e
TForm::WndProc(Msg);# O8 L0 b, G7 f6 Q. F5 _+ n3 h5 @
} |
|