您的位置:资讯频道 > 技术文档 > 控件开发基础

支持直接粘贴IP字符串的CIPAddressCtrl控件

来源:coldcrane的专栏   作者:coldcrane   时间:2008-04-24  点击:167 次
标准的CIPAddreeeCtrl控件在输入IP地址时很不方便,四个字段要一个一个的输入,平时倒没怎么注意,今天多输了几次,觉得很不爽,所以就想做一个能直接粘贴IP字符串的CIPAddreeeCtrl控件。

思路:

这种问题当然是要拦截WM_PASTE消息了,只不过WM_PASTE并不是直接发给CIPAddreeeCtrl的,因为CIPAddreeeCtrl下面有4个edit子控件,WM_PASTE是发给它们的。

接下来的工作就好办了。给edit控件定义一个消息处理函数:收到WM_PASTE时检查剪贴板的内容是不是一个合法的IP地址,如果是,就把IP地址设置到CIPAddreeeCtrl控件,否则就调用缺省的消息处理函数。

最后,将edit控件的消息处理函数设置成自定义的函数就可以了。


注意一些细节:

1. 设置edit控件的消息处理函数时,使用EnumChildWindows()+SetWindowLong();
2. edit控件设置CIPAddreeeCtrl的IP地址是通过发送一个自定义消息实现的;
3. 设置edit控件的消息处理函数的工作应放在CMyIPAddressCtrl::PreSubclassWindow()里,这样就不需要在使用CIPAddreeeCtrl的窗口里做什么别的操作了。
4. 消息处理函数的功能可以加强一点:如果不是合法的IP地址,就再判断是不是合法的数字,不是的话,就忽略掉WM_PASTE消息。

MyIPAddressCtrl.h

#pragma once


// CMyIPAddressCtrl

class CMyIPAddressCtrl : public CIPAddressCtrl
{
 DECLARE_DYNAMIC(CMyIPAddressCtrl)

 public:
  CMyIPAddressCtrl();
  virtual ~CMyIPAddressCtrl();

 private:
  void SetEditWindowProc();
  LRESULT CMyIPAddressCtrl::OnSetAddress(WPARAM wParam, LPARAM lParam);

 protected:
  DECLARE_MESSAGE_MAP()
  virtual void PreSubclassWindow();
};


MyIPAddressCtrl.cpp

// MyIPAddressCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "MyIPAddressCtrl.h"
#include ".\myipaddressctrl.h"

#define WM_USER_SET_ADDRESS WM_USER+1234
#ifdef STRICT
WNDPROC OldEditWindowProc = NULL;
#else
FARPROC OldEditWindowProc = NULL;
#endif
DWORD ConvertIPAddress( const char *sIP );
BOOL GetTextFromClipboard( HWND hWnd, CString &sText );
BOOL CALLBACK SetEditWindowLong( HWND hWnd, LPARAM param );
LRESULT CALLBACK NewEditWindowProc( HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam );

// CMyIPAddressCtrl

IMPLEMENT_DYNAMIC(CMyIPAddressCtrl, CIPAddressCtrl)

CMyIPAddressCtrl::CMyIPAddressCtrl()
{
}

CMyIPAddressCtrl::~CMyIPAddressCtrl()
{
}

BEGIN_MESSAGE_MAP(CMyIPAddressCtrl, CIPAddressCtrl)
ON_MESSAGE(WM_USER_SET_ADDRESS, OnSetAddress )
END_MESSAGE_MAP()

// CMyIPAddressCtrl message handlers

void CMyIPAddressCtrl::SetEditWindowProc()
{
 EnumChildWindows( m_hWnd, SetEditWindowLong,NULL );
}

LRESULT CMyIPAddressCtrl::OnSetAddress(WPARAM wParam, LPARAM lParam)
{
 SetAddress( (DWORD)wParam );
 return 0;
}

void CMyIPAddressCtrl::PreSubclassWindow()
{
 // TODO: Add your specialized code here and/or call the base class
 SetEditWindowProc();
 CIPAddressCtrl::PreSubclassWindow();
}

BOOL CALLBACK SetEditWindowLong( HWND hWnd, LPARAM param )
{
 OldEditWindowProc = (WNDPROC) SetWindowLong (hWnd, GWL_WNDPROC, (LONG)NewEditWindowProc );
 return TRUE;
}

LRESULT CALLBACK NewEditWindowProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
 if( WM_PASTE == message )
  {
  //::MessageBox(NULL,"click!","",MB_OK);
  CString sText;
   if( GetTextFromClipboard( hwnd, sText ) )
  {
    DWORD dwIPAddress = ConvertIPAddress( sText );
    HWND hParentWnd = ::GetParent( hwnd );
    if( dwIPAddress != -1 && hParentWnd != NULL )
    {
     ::SendMessage( hParentWnd, WM_USER_SET_ADDRESS, dwIPAddress, 0 );
     return 0;
   }
    else
    {
     UINT8 *p = (UINT8*)(LPCSTR)sText;
     BOOL nRet = TRUE;
     while( nRet && *p )
     nRet = isdigit( *p++ );
     if( !nRet )
      return 0;
    }
   }
 }

 //调用控件原来的消息处理函数
 return CallWindowProc(OldEditWindowProc,hwnd,message,wParam,lParam);
}

DWORD ConvertIPAddress( const char *sIP )
{
  DWORD dwIPAddress = -1;
  BOOL bRet = true;
  int ip[4] = { 0 };
  char tmp[2] = { 0 };

  bRet = sIP && *sIP && isdigit( *(UINT8*)sIP )
  && ( 4 == sscanf( sIP, "%d.%d.%d.%d%1s", &ip[0], &ip[1], &ip[2], &ip[3], tmp ) )
  && ( ip[0] >= 0 && ip[0] <= 255 )
  && ( ip[1] >= 0 && ip[1] <= 255 )
  && ( ip[2] >= 0 && ip[2] <= 255 )
  && ( ip[3] >= 0 && ip[3] <= 255 );

  if( bRet )
  {
   dwIPAddress = (ip[0]<<24) | (ip[1]<<16) | (ip[2]<<8) | ip[3];
  }
 return dwIPAddress;
}

BOOL GetTextFromClipboard( HWND hWnd, CString &sText )
{
  BOOL bRet = FALSE;
  if( OpenClipboard( hWnd ) )
 {
   HANDLE hData = GetClipboardData( CF_TEXT );
   if( hData != NULL )
   {
    char *buffer = (char*)GlobalLock( hData );
   sText = buffer;
     GlobalUnlock( hData );
    bRet = TRUE;
   }
   CloseClipboard();
 }
 return bRet;
}