|
|
作者: ccrun ,如转载请保证本文档的完整性,并注明出处。+ c! h! Z i; P, [* N* C( g
欢迎光临 C++ Builder 研究,http://www.ccrun.com/doc/go.asp?id=592; s& O8 j( ~) ~1 d* K' C
本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料: X0 o: h) M/ P% }4 E- z Q% X# ]- \
标题:在Delphi中使用IP控件! u9 n2 W% o, l7 \. C: F2 m G
作者:西安交通大学9649# 刘明华
7 I& l: Q6 Z- b# P @; a4 ]' v$ n在些对原作者的无私奉献表示感谢!如欲转载请保留完整版权信息。
* P P. {2 b5 z* {$ N6 \如果这篇文章侵犯了您的版权,请来信告诉我们:info@ccrun.com# r# m5 t! p! [; L! _2 Q0 r& V6 Q
ccrun(老妖)(www.ccrun.com) 2003.10.29
2 x' {, L3 A/ g. p i
2 H# H& X% x* ^) W* 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控件。" k7 m* Z9 K, F5 w5 D' t* L( `- N+ G
! E: W5 ?7 t7 q5 X# M' }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)。+ K, n' a2 g: r* I( [* x/ K& n
* p/ g3 @: h; d
●初始化Windows自定义控制库●
2 f# g! M4 k- a$ E+ a6 h9 [; uWindows提供了两个API函数,InitCommonControls和InitCommonControlsEx,用来初始化自定义控制库。从名字我们不难看出这两个API函数的关系:后者是前者的增强。如果你希望在程序中使用IP控件,你必须用InitCommonControlsEx来完成对自定义控制库以及类的初始化。函数InitCommonControlsEx的原型如下:
$ A& |, d% v* F& ^; X8 o& E/ U2 @- R3 D8 l) V( [1 L c; K( Y v
typedef struct tagINITCOMMONCONTROLSEX {
5 f$ }( P% C3 }1 h DWORD dwSize; // size of this structure5 q8 h5 f: U# ^% }, \2 Y) k
DWORD dwICC; // flags indicating which classes to be initialized
8 B4 O$ E% H- o* }) f, p- ^} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
& A% o5 i$ b3 l& k* u! k4 Y/ V5 v+ r7 X1 N
WINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);% l' R0 r4 ~, L# F4 z
7 P+ L+ W, m8 K. ?+ U5 \! C9 ]IP控件属于ICC_INTERNET_CLASSES类别的控件,如果要使用该控件,你应该在程序中包含如下的初始化代码:
6 [6 y, [: f) f( l9 A8 _; V+ s- g& M' A: |6 Z4 h. n% ?
TInitCommonControlsEx ICC; B" V, Q" k& g. ~7 d
ICC.dwSize = sizeof(TInitCommonControlsEx);. W: @* d- {. G/ \ ^1 I. @
ICC.dwICC = ICC_INTERNET_CLASSES;0 j g# R' e J/ T" a/ \
if(!InitCommonControlsEx(&ICC))
( |8 u& l1 _' N1 Q return; //初始化组件失败
- s& a- M0 V( p7 C5 B" k5 P H0 z, O# Q& f/ f. }- }4 U
●创建IP控件● E8 n2 Z, F- A \9 [; }: ~
Windows API函数CreateWindow或者CreateWindowEx都可以用来创建一个IP控件实例。IP控件的窗口类名为"SysIPAddress32",C++ Builder的commctrl.pas单元为其定义了一个符号常量WC_IPADDRESS。下面这条语句将在Form1上创建一个IP控件。
, H) D' S; t" C9 a' u. {) Q5 P$ V8 f$ S2 A$ H
HWND hIpEdit = CreateWindow(WC_IPADDRESS,NULL,WS_CHILD|WS_VISIBLE,10,10,135,47,Handle,0,HInstance,NULL);
0 B3 P0 P7 U5 J" r T. W4 h$ K# }* m5 I5 W
●使用IP控件●
+ a3 {6 W9 ]- h, e在程序中,我们通过向IP控件发送消息来与它通讯。IP控件可以响应的消息有以下6个,这些消息及它们的含义见下表:
, u3 P) S2 S* O
% y- {/ A, ?( h' p# Z5 f1 x3 s( L消息常量 消息值 作用 参数及返回值6 e" v3 V; X) Z# \7 |
IPM_CLEARADDRESS WM_USER+100 清除IP控件中的IP串 参数无" I% p* ~2 p& ?! t
IPM_SETADDRESS WM_USER+101 设置IP控件的IP串 Lparam为32位的IP值
; T; L8 y) F8 S! Q* ZIPM_GETADDRESS WM_USER+102 获取IP控件中的IP串所对应的IP值(32位整数) Lparam为一个指向Integer变量的指针。返回值等于IP控件中非控的字段数目;获取到的IP值存放在lparam 所指向的Integer变量中。 3 ^( }7 |! G; D4 Q7 p
IPM_SETRANGE WM_USER+103 设置IP控件4个部分的其中一个的IP取值范围 Wparam指明要设置取值范围的部分;lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。
" j/ Y5 m, \0 v6 h1 c+ @; SIPM_SETFOCUS WM_USER+104 设输入焦点 Wparam指明哪个部分获取焦点6 D- ^& `6 M; F; P$ p9 i: H
IPM_ISBLANK WM_USER+105 IP串是否为空 参数无。返回值:若为空,返回非0;不为空,返回0
0 g M' _" U- B- ?; @7 D+ z, H6 S: A& p3 W2 }
★㈠清空IP串(IPM_CLEARADDRESS)★2 C+ U% g* p7 e7 O, `
SendMessage(hIpEdit,IPM_CLEARADDRESS,0,0);
$ ?; ?; M! q* C0 }, G' b. c3 j
! z! R" G- d2 w$ u, r★㈡设置IP串(IPM_SETADDRESS)★
2 ]" B1 Y6 V2 a2 S- f Sint nIP;0 q9 E6 r8 ]% u# ^
nIP=MAKEIPADDRESS(192,168,0,1);
/ U3 q5 ~# I$ s5 Q3 T2 K# q! nSendMessage(hIpEdit,IPM_SETADDRESS,0,nIP);+ @9 X8 H1 t/ _6 f* e+ O+ b4 e
( Y3 d |4 H: \此例将IP控件的内容设为"192.168.0.1",其中MAKEIPADDRESS是一个Win32宏,定义在commctrl.h头文件中,它用来合成一个32位的IP值:7 a. E' @, P2 y. {. {2 M% A
#define MAKEIPADDRESS(b1,b2,b3,b4)2 O* L- Q& D/ I: G
((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4)))), ?6 L- [' P( _/ Y0 O8 W! @% s( T
( b- F3 h- \2 ]6 W' q) A; x+ m★㈢获取IP值(IPM_GETADDRESS)★
0 ^( N9 F' m# G- o6 c* g2 iint nIP;% {" k9 }2 C; w8 `
SendMessage(hIpEdit,IPM_GETADDRESS,0,int(&nIP));
# U2 O" u6 {5 g7 i//nIP++;
. x6 ^! s8 b! K/ X//SendMessage(hIpEdit,IPM_SETADDRESS,0,nIP); //将IP加1再赋给IP控件。
" _+ p4 s2 r& w( w1 |( M( ?4 v( w4 I9 \
若想要获取IP控件中IP串所对应的IP值,你应该向IP控件发送IPM_GETADDRESS消息,并且需要把一个32位整数的地址作为SendMessage的最后一个参数。
/ ` z( R& U; y/ |' d, O, b3 t4 C! R7 [
★㈣设置取值范围(IPM_SETRANGE)★
' q) W' u# M" Q! j/ ^SendMessage (hIpEdit, IPM_SETRANGE, 0, 200<<8|100);* e7 H6 ` {+ l, g! q+ P
此语句将IP控件的第一部分的范围限制为100~200。在IPM_SETRANGE消息中,Wparam指明要设置的字段, 而lparam的低16位字为该字段的范围:高字节为上限,低字节为下限。* p6 @3 z3 d+ J, T* w- i4 R
, t3 O( [7 [ U# Q& }★㈤设置输入焦点(IPM_SETFOCUS)★
0 u/ r6 r9 v/ V# PSendMessage(hIpEdit,IPM_SETFOCUS,3,0);
4 _# w& Z5 N( M' b# F% q//将输入焦点设在IP控件的第四部分。
- i( {' H4 S7 O# V0 h3 ]& \0 _/ ^% y P! T e/ I1 o, K) ~
㈥判断IP串是否为空(IPM_ISBLANK)
+ ^6 b6 _4 z8 e9 dif(!SendMessage(hIpEdit,IPM_ISBLANK,0,0)) 2 ~: L9 e# b+ r2 H9 g
{
3 L/ g% h x2 D, O( O% r! d" i //IP控件中的IP串为空, A% w4 ?- n1 K7 f
}
; P/ ]9 u1 p1 q" [else# Q B& K) h0 i1 J- H/ \# [
{4 P' `6 A& I; f# S, O$ b
//IP控件中的IP串至少有一部分不是空的! i8 J* H( e, d) f2 `2 g* }4 d& n
}" Q! K" [- r2 p2 {: I6 n
: G: Q. R4 Y1 {
●IP控件的通知消息●$ a' _$ w' c6 |/ ^; l
当IP串被改动后或者输入焦点发生了转移,IP控件就会向它的父窗口发送通知消息IPN_FIELDCHANGED。在大多数情况下,我们都可以忽略此通知消息。以下是处理通知消息IPN_FIELDCHANGED的一个示例:
" F7 L2 P- V, s7 k
9 n9 r& @/ ?( Q( `8 A6 s( ~/ S$ Nvoid __fastcall TForm1::WndProc(TMessage &Msg)
, ~8 o$ K6 Y7 A4 P5 F{3 G. D( V. \8 @: d: o$ y0 e- B
LPNMHDR p=(LPNMHDR)Msg.LParam;
6 q8 I6 H; @; p* @& E& c ?0 H if(Msg.Msg==WM_NOTIFY)
$ \. K0 U6 [3 d7 j {
& }% [2 i- I0 H1 K# D' ? if(p->code==IPN_FIELDCHANGED)
1 _" ]& U" `7 M& V {
9 P6 N% P& w- X" r //处理IP控件的IPN_FIELDCHANGED通知消息
8 {2 s9 O% \; A6 w4 }* _ }& n1 f/ Y( k0 U" H; H
}) g/ @& {- ^& v& g$ V
TForm::WndProc(Msg);6 {$ Z+ {; k( ?- J2 M
} |
|