|
|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。* ~/ L. \% r0 f, ?" F1 h' q) u$ w
欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592
7 H/ ]- X% W% w; e; q4 u本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料:
' R% K/ `( y6 R% f _标题:在Delphi中使用IP控件
" ~& V2 r/ e: r$ A# I" w作者:西安交通大学9649# 刘明华
. P2 m% e9 ^( ]5 [# {在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。$ d: G+ P0 k0 ? K$ r1 l
如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com
; ]6 H/ g2 K+ ^8 W2 l/ Y+ D" zccrun(老妖)(www.ccrun.com) 2003.10.29# M \0 @/ {# _' w3 w/ V
$ N* {9 n5 z Z5 _; |& X
在网络程序中,我们常常碰到需要用户输入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控件。; n2 n$ c& g5 `0 c) Z$ ^
( M4 d d& J5 Z& B. F( Y# PWindows中有两个非常重要的动态联结库: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$ d9 Z5 Q; w5 I3 B& ~
1 b i2 Z3 z6 B# ~
●初始化Windows自定义控制库●5 G5 S3 C! O M
Windows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:% e& l% X3 H% _9 [! _8 ^
1 g6 T: [/ x9 J& E
typedef struct tagINITCOMMONCONTROLSEX {
v# \ T6 g- u* ~$ L, o DWORD dwSize; // size of this structure8 C" @+ a/ \) J5 |8 D2 F
DWORD dwICC; // flags indicating which classes to be initialized
5 w/ T& e5 r& W$ c4 B} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;. I5 P: A7 c ?0 P8 d
: Y9 G. p1 G% P" F9 B+ G
WINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);, |$ e& w3 e& |# k5 u, t6 w
% z/ S2 |6 T: ~! D& s# y
IP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:
* A, |4 e6 z8 e2 i1 K, C' y% J B7 N9 w9 U, M
TInitCommonControlsEx ICC;+ e5 R( {2 B! E3 |0 M+ @0 M
ICC.dwSize = sizeof(TInitCommonControlsEx);- ^. M! d7 M, L' `; `
ICC.dwICC = ICC_INTERNET_CLASSES;
! o0 y0 Z& a2 ?) U3 lif(!InitCommonControlsEx(&ICC))) C ^1 Y6 ^, [5 Z
return; //初始化组件失败6 m) }2 t' F$ Q, }# Y0 c
, \7 i$ G7 h; J; i( v●创建IP控件●
3 h7 K7 ~8 X% ~3 E3 hWindows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。
3 m/ M; G( X; f' Q0 D. a
+ M- c# n- d- t; o- u$ I+ }$ IHWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);+ @, F4 }4 Q- [# x8 j$ ?
. |* y6 N9 D" g0 r& r6 g
●使用IP控件●/ K' r+ r- E8 C9 `) R, [/ {
在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:
' J+ a0 a. H5 e* Y0 z* F! |
' p1 h( J; W# K$ Q消息常量 消息值 作用 参数及返回值6 a! \7 U. q. }0 n( {% A E
IPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无
- [# }0 o( x& v& [2 }IPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值
0 L7 V" o& J% x xIPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。
: G) M6 E) X7 x/ k" \" Z7 xIPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。. B# K# l( U; O9 e0 Q; K+ p
IPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点
1 ]+ u; k- S2 q4 i; z' AIPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回0# w7 c) w8 E' ^, b' P |5 X
- l, P$ k9 m, ~/ \( Y5 c# e
★㈠清空IP串(IPM_CLEARADDRESS)★
" l' ?6 ?2 ^ p& rSendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);
! u U, _. z3 G: ]; J7 o
0 S; L# {) H$ d) b6 F$ g( J★㈡设置IP串(IPM_SETADDRESS)★
9 W/ M' m7 a9 {- nint nIP;
" @& q: ]$ L& F- Y# qnIP=MAKEIPADDRESS(192,168,0,1); ! ~0 k U' v/ |. y* U5 \; V$ t
SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);
: j" ?' D, y2 T! k+ r4 {6 [! X" ?0 ~4 q3 y& |+ p+ h7 c& J
此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:
% E( L* T: O X#define MAKEIPADDRESS(b1,b2,b3,b4)4 x$ H* t% m; u9 ~: }3 ]! x9 S
((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))
8 t- y8 D1 g/ V O! F2 N2 C
! i) E" P$ R2 z: Y5 Q★㈢获取IP值(IPM_GETADDRESS)★
2 J% k+ v' b# w; Xint nIP;
: N: u( e( L" hSendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));
; I& _5 Z, q/ `6 n: S3 t//nIP++;: f6 t. d' L# k1 ^. x2 w1 R
//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。4 _0 m0 A4 r( B, z% U
' G) m: |" }+ q% c若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。! |5 o& K5 E2 l" P+ @: Q# N
2 c5 ~3 i4 u# e+ z7 @
★㈣设置取值范围(IPM_SETRANGE)★3 T' V4 H1 x2 q2 G7 u- r
SendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);
7 R* s( ~. @" I& s此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
( f- f) l* k1 _3 D- V/ R
7 C: p' _- @4 D5 r2 k" I★㈤设置输入焦点(IPM_SETFOCUS)★) ^" v. m8 ]% m. r
SendMessage(hIpEdit,IPM_SETFOCUS,3,0);2 N. {3 R* [7 x" m3 t
//将输入焦点设在IP控件的第四部分。
$ k9 g* C4 X1 Q a, |; i4 t
4 i1 x4 Z' o) z㈥判断IP串是否为空(IPM_ISBLANK)" n. z8 M; P$ z3 Z% B+ f* ]- w
if(!SendMessage(hIpEdit,IPM_ISBLANK,0,0)) - H! a" P# }5 X* {, T; X
{% j8 M8 u' E/ I1 W# y! j
//IP控件中的IP串为空
+ P) W, G/ ]4 m& U0 B& g* l}
+ F( A1 n( y! d5 }5 N+ N2 [else9 z4 \( E; V7 R7 b! v
{
1 _/ `9 X9 Y5 K% S ^ } //IP控件中的IP串至少有一部分不是空的
2 U4 q. k, e+ {4 I}
/ l+ K) Q/ |9 _$ z' g, B- g/ ~- O1 c% w8 K9 j" f
●IP控件的通知消息●
. j$ }' \) j1 N. [1 H0 n5 c当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:& @: ?; |! k& P# F! `- D/ |0 j
- Y* z0 D# _+ }* y
void __fastcall TForm1::WndProc(TMessage &Msg)$ Q3 K. \# I# d2 x/ r
{6 Y! `; s9 g3 I& W% H# l
LPNMHDR p=(LPNMHDR)Msg.LParam;$ o1 u/ ], g3 f1 |
if(Msg.Msg==WM_NOTIFY)5 g2 `8 j2 }7 E6 Y6 u- k
{9 K; N- |4 g3 {% H i. {
if(p->code==IPN_FIELDCHANGED)
- L' P/ B2 c0 m9 g+ r( I+ h' V4 } {
9 O1 i# _8 d: S //处理IP控件的IPN_FIELDCHANGED通知消息
! ]0 L! Z+ u+ o% L! G }. v9 D3 j) d) c. u( F0 T! Q
}
- l; L5 g2 J% b- @ TForm::WndProc(Msg);. }% I+ C) U! A7 O" t3 b
} |
|