⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipaddr.cpp

📁 在vc++6.0环境下
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#pragma title("IP Address Custom Control Implementation")

// Created by Joseph A. Dziedzic, September 1997
// Revised April 1998
// Thanks to Dan Anderson, Kenny Goers, Kevin Lussier, and Doug Miller for their suggestions
// and code enhancements.
// Mail comments to dziedzic@ma.ultranet.com


#include "stdafx.h"
#include "IPAddr.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// Style bits for the individual edit controls
const int WS_EDIT = WS_CHILD | WS_VISIBLE | ES_CENTER | ES_MULTILINE;
const TCHAR szDialogClass[] = _T("#32770");			// Special window class for dialogs

BOOL CIPAddrCtl::m_bRegistered = Register();		// Register the control during class initialization

/////////////////////////////////////////////////////////////////////////////
// CIPAddrCtl

IMPLEMENT_DYNCREATE(CIPAddrCtl, CWnd)

CIPAddrCtl::CIPAddrCtl()
{
	m_bEnabled = TRUE;								// Window enabled flag (TRUE by default)
	m_bReadOnly = FALSE;							// Read only flag (FALSE by default)
	m_bNoValidate = FALSE;							// Don't do immediate field validation on input
}

CIPAddrCtl::~CIPAddrCtl()
{
}


BEGIN_MESSAGE_MAP(CIPAddrCtl, CWnd)
	//{{AFX_MSG_MAP(CIPAddrCtl)
	ON_WM_CREATE()
	ON_WM_NCDESTROY()
	ON_WM_SIZE()
	ON_WM_SETFOCUS()
	ON_WM_PAINT()
	ON_WM_ENABLE()
	ON_WM_ERASEBKGND()
	ON_MESSAGE(WM_SETFONT, OnSetFont)
	ON_MESSAGE(IPAM_GETADDRESS, OnGetAddress)
	ON_MESSAGE(IPAM_SETADDRESS, OnSetAddress)
	ON_MESSAGE(IPAM_SETREADONLY, OnSetReadOnly)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CIPAddrCtl message handlers

BOOL CIPAddrCtl::Register()
{
	// Register the window class of the control
	WNDCLASS	wc;
	wc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;	// Usual style bits
	wc.lpfnWndProc = IPAddrWndProc;					// Message processing code
	wc.cbClsExtra = 0;								// No extra bytes needed
	wc.cbWndExtra = 0;
	wc.hInstance = NULL;							// No instance handle
	wc.hIcon = NULL;								// No icon
	wc.hCursor = ::LoadCursor(NULL, IDC_IBEAM);		// Use I-beam cursor (like edit control)
	wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);	// Use default window color (overriden in OnEraseBkgnd)
	wc.lpszMenuName = NULL;							// No menus
	wc.lpszClassName = _T("IPAddr");				// Class name
	if (!::RegisterClass(&wc))						// If registration failed, subsequent dialogs will fail
	{
		ASSERT(FALSE);
		return FALSE;
	}
	else
		return TRUE;
}

BOOL CIPAddrCtl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, DWORD dwExStyle/*=0*/)
{
	// Create a window class that has the properties we want
	CString szWndClass = AfxRegisterWndClass(CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW,
		::LoadCursor(NULL, IDC_IBEAM), (HBRUSH) COLOR_WINDOW+1);

	// Create using the extended window style
#if _MSC_VER >= 1100
	// Original VC 5.0 stuff
	return CWnd::CreateEx(dwExStyle, szWndClass, NULL, dwStyle, rect, pParentWnd, nID);
#else
	// Back ported to VC 4.2
	return CWnd::CreateEx(dwExStyle, szWndClass, NULL, dwStyle,
		rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
		pParentWnd->GetSafeHwnd(), (HMENU) nID);
#endif
}

LRESULT CALLBACK IPAddrWndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uiMsg)									// Dispatch on message type
	{
	case WM_NCCREATE:								// On WM_NCCREATE we create a C++ object and attach it to the control
		{
			CIPAddrCtl* pCtl = new CIPAddrCtl;		// Create an instance of the class
			ASSERT(pCtl);							// Better not fail!
			BOOL b = pCtl->SubclassWindow(hWnd);	// Attach the window handle to the new object
			ASSERT(b);								// Better not fail!
			return b;								// Return result to continue/abort window creation
			break;
		}
	default:										// All other messages go through default window processor
		return ::DefWindowProc(hWnd, uiMsg, wParam, lParam);
	}
}

int CIPAddrCtl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)	
		return -1;

	// Save the "no immediate validation on input" style setting
	m_bNoValidate = (lpCreateStruct->style & IPAS_NOVALIDATE);

	// Set the styles for the parent control
	ModifyStyleEx(0, WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY);

	// Create the four edit controls used to obtain the four parts of the IP address (size
	// of controls gets set during OnSize)
	for (int ii = 0; ii < 4; ii++)
	{
		m_Addr[ii].Create(WS_EDIT, CRect(0,0,0,0), this, IDC_ADDR1 + ii);
		m_Addr[ii].LimitText(3);
		m_Addr[ii].SetParent(this);
	}
	
	return 0;
}

void CIPAddrCtl::OnNcDestroy() 
{
	CWnd::OnNcDestroy();
	
	// Make sure the window was destroyed
	ASSERT(NULL == m_hWnd);

	// Destroy this object since it won't be destroyed otherwise
	delete this;
}

void CIPAddrCtl::OnSize(UINT nType, int cx, int cy) 
{
	CWnd::OnSize(nType, cx, cy);

	// Get the width of a "." drawn in the control
	CDC*	pDC = GetDC();
	CSize	szDot = pDC->GetTextExtent(_T("."), 1);
	int nDotWidth = szDot.cx;
	ReleaseDC(pDC);	

	// Based on the size of the parent window, compute the width & height of the edit
	// controls.  Leave room for the three "." which will be drawn on the parent window
	// to separate the four parts of the IP address.
	CRect	rcClient;
	GetClientRect(&rcClient);
	int nEditWidth = (rcClient.Width() - (3 * nDotWidth)) / 4;
	int nEditHeight = rcClient.Height();
	int cyEdge = ::GetSystemMetrics(SM_CYEDGE);

	// Compute rectangles for the edit controls, then move the controls into place
	CRect rect = CRect(0, cyEdge, nEditWidth, nEditHeight);
	for (int ii = 0; ii < 4; ii++)
	{
		m_rcAddr[ii] = rect;
		m_Addr[ii].MoveWindow(rect);
		rect.OffsetRect(nEditWidth + nDotWidth, 0);
	}

	rect = CRect(nEditWidth, 0, nEditWidth + nDotWidth, nEditHeight);
	for (ii = 0; ii < 3; ii++)
	{
		m_rcDot[ii] = rect;
		rect.OffsetRect(nEditWidth + nDotWidth, 0);
	}
}

void CIPAddrCtl::OnSetFocus(CWnd* pOldWnd) 
{
	CWnd::OnSetFocus(pOldWnd);
	
	m_Addr[0].SetFocus();							// Set focus to first edit control
	m_Addr[0].SetSel(0, -1);						// Select entire contents
}

// Protected function called by the edit control (friend class) when it receives a
// character which should be processed by the parent
void CIPAddrCtl::OnChildChar(UINT nChar, UINT nRepCnt, UINT nFlags, CIPAddrEdit& child)
{
	switch (nChar)
	{
	case '.':										// Dot means advance to next edit control (if in first 3)
	case VK_RIGHT:									// Ditto for right arrow at end of text
	case ' ':										// Ditto for space
		{
		UINT nIDC = child.GetDlgCtrlID();			// Get control ID of the edit control
		if (nIDC < IDC_ADDR4)						// Move focus to appropriate edit control and select entire contents
		{
			m_Addr[nIDC - IDC_ADDR1 + 1].SetFocus();
			if (VK_RIGHT != nChar)					// Re-select text unless arrow key entered
				m_Addr[nIDC - IDC_ADDR1 + 1].SetSel(0, -1);
		}		
		break;
		}

	case VK_LEFT:									// Left arrow means move to previous edit control (if in last 3)
		{
		UINT nIDC = child.GetDlgCtrlID();			// Get control ID of the edit control
		if (nIDC > IDC_ADDR1)						// Move focus to appropriate edit control
			m_Addr[nIDC - IDC_ADDR1 - 1].SetFocus();
		break;
		}

	case VK_TAB:									// Tab moves between controls in the dialog
		{
		CWnd*	pWnd;
		SHORT nShift = ::GetKeyState(VK_SHIFT);		// Get state of shift key
		if (nShift < 0)
			pWnd = GetParent()->GetNextDlgTabItem(this, TRUE);
		else
			pWnd = GetParent()->GetNextDlgTabItem(this, FALSE);
		if (NULL != pWnd)							// If there's a control, set focus to it
			pWnd->SetFocus();
		break;
		}

	case VK_RETURN:									// Return implies default pushbutton press
		{
		DWORD dw = ((CDialog*) GetParent())->GetDefID();	// Get ID of default pushbutton
		if (DC_HASDEFID == HIWORD(dw))				// If there is a default pushbutton, simulate pressing it
		{
			CWnd* pWnd = GetParent()->GetDlgItem(LOWORD(dw));	// Get the control
			WPARAM wp = MAKEWPARAM(LOWORD(dw), BN_CLICKED);		// Build wParam for WM_COMMAND
			GetParent()->SendMessage(WM_COMMAND, wp, (LPARAM) pWnd->m_hWnd);	// Fake like button was pressed
		}
		}
		break;

	case '-':										// "Field full" indication
		// Validate the contents for proper values (unless suppressed)
		if (!m_bNoValidate)							// If not suppressing immediate validation
		{
			CString		szText;

			child.GetWindowText(szText);			// Get text from edit control
			int n = _ttoi(szText);					// Get numeric value from edit control
			if (n < 0 || n > 255)					// If out of range, notify parent
			{
				szText.Format(_T("%d is not a valid entry.  Please specify a value between 0 and 255 for this field."), n);
				MessageBox(szText, _T("Error"), MB_OK | MB_ICONEXCLAMATION);
				child.SetFocus();					// Set focus to offending field
				child.SetSel(0, -1);				// Select all text
				return;
			}
		}

		// Advance to next field
		OnChildChar('.', 0, nFlags, child);
		break;

	default:
		TRACE(_T("Unexpected call to CIPAddrCtl::OnChildChar!\n"));
	}
}

void CIPAddrCtl::OnPaint() 
{
	CPaintDC dc(this); // device context for painting

	// Save mode and set to transparent (so background remains)
	int nOldMode = dc.SetBkMode(TRANSPARENT);

	// If disabled, set text color to COLOR_GRAYTEXT, else use COLOR_WINDOWTEXT
	COLORREF crText;
	if (m_bEnabled)
		crText = ::GetSysColor(COLOR_WINDOWTEXT);
	else
		crText = ::GetSysColor(COLOR_GRAYTEXT);
	COLORREF crOldText = dc.SetTextColor(crText);

	// Draw the three "." which separate the four edit controls
	for (int ii = 0; ii < 3; ii++)
		dc.DrawText(_T("."), 1, m_rcDot[ii], DT_CENTER | DT_SINGLELINE | DT_BOTTOM);

	// Restore old mode and color
	dc.SetBkMode(nOldMode);
	dc.SetTextColor(crOldText);

	// Do not call CWnd::OnPaint() for painting messages
}

BOOL CIPAddrCtl::OnEraseBkgnd(CDC* pDC) 
{
	CRect	rcClient;
	GetClientRect(&rcClient);

	if (m_bEnabled && !m_bReadOnly)
		::FillRect(pDC->m_hDC, rcClient, (HBRUSH) (COLOR_WINDOW+1));
	else
		::FillRect(pDC->m_hDC, rcClient, (HBRUSH) (COLOR_BTNFACE+1));

	return TRUE;
}

void CIPAddrCtl::OnEnable(BOOL bEnable) 
{
	CWnd::OnEnable(bEnable);
	
	// Nothing to do unless the window state has changed
	if (bEnable != m_bEnabled)
	{
		// Save new state
		m_bEnabled = bEnable;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -