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

📄 ngdialog.cpp

📁 ResOrg 图形化管理Vc项目的资源ID的工具的源代码。 ResOrg - Manage and Renumber Resource Symbol IDs Introduction The
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/************************************************************************
 *
 *                   Extended dialog classes
 *
 *    Written by Anna Metcalfe (code@annasplace.me.uk)
 *
 ************************************************************************
 *                                                                       
 *  Filename    : NGDialog.cpp
 *
 *  Compiler    : Microsoft Visual C++ 6.0, Service Pack 3 or later
 *                Microsoft Visual C++.NET
 *                                                                       
 *  Target                                                               
 *  Environment : Win98/Me/NT/2000/XP
 *
 *  NOTE:
 *
 *    Your are free to use this code in your own products, PROVIDED
 *    this notice is not removed or modified.
 *
 ************************************************************************/

#include "StdAfx.h"
#include <AfxPriv.h>			// For HID_BASE_CONTROL definition

#include "NGDebugTrace.h"
#include "NGMacros.h"
#include "NGUtils.h"
#include "NGDialog.h"


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


// ID value for ComboBox edit controls
// Refer to "C/C++ Q & A" in the April 1996 edition of MSJ for more details
#define	IDC_COMBOEDIT	1001


/////////////////////////////////////////////////////////////////////////////
// Helper functions (NOT exported)
//
// These should really be virtuals in CNGDialog and CNGPropertyPage
// The only reason they aren't is that this way we don't end up with
// two sets of identical code.
//
// One day I'll get around to building a C++ class template to overcome this...

typedef enum {	CTRL_NONE = -1,
				CTRL_STATIC,
				CTRL_BUTTON,
				CTRL_EDIT,
				CTRL_LISTBOX,
				CTRL_COMBOBOX,
				CTRL_LISTCTRL,
				CTRL_TREECTRL,
				CTRL_SLIDER,
				CTRL_UNKNOWN } CTRL_TYPE;


//	Use ::GetClassName() in the Win32 SDK to determine the type
//	of a control from its hWnd
static CTRL_TYPE IdentifyCtrl(HWND hWnd)
{	
	// These are the window class names for the most common ones!
	static LPCTSTR szWndClass[] = {
									_T("static"),				// Static text
									_T("button"),				// Button
									_T("edit"),					// Edit box
									_T("listbox"),				// List box
									_T("combobox"),				// Combo box
									_T("SysListView32"),		// List control
									_T("SysTreeView32"),		// Tree control
									_T("msctls_trackbar32")		// Slider control
								};
	int eType = CTRL_NONE;
	static TCHAR szClass[20];

	if (::IsWindow(hWnd))
	{
		// Get the window class of hWnd
		::GetClassName(hWnd, szClass, sizeof(szClass) );

		for (eType = 0; eType < CTRL_UNKNOWN; eType++)
		{
			if (::lstrcmpi( szWndClass[eType], szClass ) == 0)
			{
				break;
			}
		}
	}	
	return (CTRL_TYPE)eType;	
}



// Given the HWND of a control, return it's ID.
// This function is only necessary to handle radio buttons (nasty, horrible things!)
static UINT GetCtrlID(CWnd* pDlg, HWND hWndCtrl)
{
	UINT uCtrlID = 0;
	if (::IsChild(pDlg->GetSafeHwnd(), hWndCtrl))
	{
		while ( (hWndCtrl != NULL) && (::GetParent(hWndCtrl) != pDlg->GetSafeHwnd()) )
		{
			hWndCtrl = ::GetParent(hWndCtrl);
		}
		// Find out whether we're dealing with a radio button...
		if (::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON)
		{
			// ...Radio Buttons are actually multiple controls, with only the first
			// (usually) having an ID. Hence we need to walk up the Z order to
			// the first one, which should have the group property (WS_GROUP)
			// and a valid ID...
 			while ( (::GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP) == 0)
 			{
 				hWndCtrl = ::GetNextWindow(hWndCtrl, GW_HWNDPREV);
 			}
		}
		uCtrlID = ::GetDlgCtrlID(hWndCtrl);	// Found the group control for this radio button
	}
	return uCtrlID;
}


// Identifies control notifications which could result in a change in the
// VALUE of a control (not necessarily the same as its contents!)
// TO DO: Handle slider and other common controls correctly
static BOOL IsCtrlValueChanging(CWnd* pDlg, UINT uID, HWND hWnd, int nCode)
{
	//TRACE1("Control ID: %d\n", uID);
	BOOL bResult = FALSE;
	switch (::IdentifyCtrl(hWnd))
	{
		case CTRL_EDIT:
			//TRACE1("\tEdit Control: nCode = %d\n", nCode);
			if (EN_KILLFOCUS == nCode)
			{
				CEdit* pEdit = (CEdit*)pDlg->GetDlgItem(uID);
				if (pEdit->GetModify())			// Edit control modified since last UpdateData()
				{
					pEdit->SetModify(FALSE);	// Set as unmodified As UpdateData() about to be called
					bResult = TRUE;
				}
			}
			break;

		case CTRL_BUTTON:
			if (BN_CLICKED == nCode)
			{
				// TO DO: Walk to parent radio button if ID is IDC_STATIC
				// If we don't do this pBtn will be NULL and this will fail
				CButton* pBtn = (CButton*)pDlg->GetDlgItem(uID);
				if (pBtn != NULL)
				{
					UINT nStyle = pBtn->GetButtonStyle();
					if ( ( (nStyle & BS_CHECKBOX) == BS_CHECKBOX) ||
						 ( (nStyle & BS_AUTOCHECKBOX) == BS_AUTOCHECKBOX) )
					{
						//TRACE1("\tCheckbox Control: nCode = %d\n", nCode);
						bResult = TRUE;
					}
					else if ( ( (nStyle & BS_RADIOBUTTON) == BS_RADIOBUTTON) ||
						 ( (nStyle & BS_AUTORADIOBUTTON) == BS_AUTORADIOBUTTON) )
					{
						//TRACE1("\tRadio Button Control: nCode = %d\n", nCode);
						bResult = TRUE;
					}
					else
					{
						//TRACE1("\tOther button Control: nCode = %d\n", nCode);
						bResult = TRUE;
					}
				}
			}
			break;

		case CTRL_LISTBOX:
			//TRACE1("\tListBox Control: nCode = %d\n", nCode);
			if (LBN_SELCHANGE == nCode)
			{
				bResult = TRUE;
			}
			break;

		case CTRL_COMBOBOX:
			//TRACE1("\tComboBox Control: nCode = %d\n", nCode);
			if (CBN_SELCHANGE == nCode)
			{
				bResult = TRUE;
			}
			else if (CBN_KILLFOCUS == nCode)
			{
				// When a combo box loses the focus we need to treat the edit control
				// within it in the same way as any other edit control.
				// ComboBox edit controls have an ID of 1001 [refer to "C/C++ Q & A"
				// in the April 1996 edition of MSJ for more details]
				CComboBox* pComboBox = (CComboBox*)pDlg->GetDlgItem(uID);
				ASSERT(pComboBox != NULL);

				CEdit* pEdit = (CEdit*)pComboBox->GetDlgItem(IDC_COMBOEDIT);
				if ( (pEdit != NULL) && (pEdit->GetModify()) )
				{								// If the edit control has been modified since the
					pEdit->SetModify(FALSE);	// last UpdateData(), mark it as unmodified
					bResult = TRUE;				// [UpdateData() is about to be called]
				}
			}
			break;

		case CTRL_SLIDER:	// TO DO: Crack WM_NOTIFY messages
			//TRACE1("\tSlider Control: nCode = %d\n", nCode);
			break;

		default:
			break;
	}
	return bResult;
}


/////////////////////////////////////////////////////////////////////////////
// CNGDialog class

IMPLEMENT_DYNAMIC(CNGDialog, CNGDialog_BASE)

CNGDialog::CNGDialog(UINT uID /*= 0*/, CWnd* pParentWnd /*= NULL*/)
	: CNGDialog_BASE(uID, pParentWnd)
{
	m_pDoc				= NULL;
	m_pServer			= NULL;
	m_bModified			= false;
	m_bLockCtrlUpdates	= false;

	m_rectInitialPosition.SetRectEmpty();
	m_rectPosition.SetRectEmpty();

	//{{AFX_DATA_INIT(CNGDialog)
	//}}AFX_DATA_INIT
}


CNGDialog::~CNGDialog(void)
{
}


void CNGDialog::DoDataExchange(CDataExchange* pDX)
{
	CNGDialog_BASE::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CNGDialog)
	//}}AFX_DATA_MAP

	// These are out of Classwizard's grasp as it can't handle the syntax
}


BEGIN_MESSAGE_MAP(CNGDialog, CNGDialog_BASE)
	//{{AFX_MSG_MAP(CNGDialog)
	ON_WM_MOVE()
	ON_WM_HELPINFO()
	ON_WM_CONTEXTMENU()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()



//	Override the default message processing to try to figure out
//	when the value of a control has changed
//
//	NOTES:
//		1.	UpdateData(TRUE) is automatically called if the control value
//			could have changed, and DDV validation succeeds
//
//		2.	The detection of changed controls is not perfect, and hence the Apply
//			button could be erroneously enabled under certain circumstances.
//
BOOL CNGDialog::OnCommand(WPARAM wParam, LPARAM lParam) 
{
	BOOL bResult = FALSE;

	// Crack message parameters
	// This bit was nicked from CPropertySheet::OnCommand()
	UINT uID		= LOWORD(wParam);
	HWND hWnd		= (HWND)lParam;
	int nCode		= HIWORD(wParam);

	UINT uCtrlID	= uID;						// We'll need this later

	// If the command notification was a control value change
	// which could be linked up via DDX update the DDX member
	// vars and send a WM_COMMAND notification on the affected
	// control (this allows a generic ON_COMMAND handler to be
	// used, irrespective of the type of the control)

	if (hWnd != NULL)
	{
		// Catch ENTER keypresses on a control
		// and convert to a CN_COMMAND call for that control
		// This allows the control focused when ENTER was pressed to receive
		// the change notification...
		if (uID == IDOK)
		{
			// Walk up from the focused window until we find a valid control
			HWND hWndFocusCtrl = ::GetFocus();
			while ( (hWndFocusCtrl != NULL) && (::GetParent(hWndFocusCtrl) != m_hWnd) )
			{
				hWndFocusCtrl=::GetParent(hWndFocusCtrl);
			}
			
			// If the focused control is the one we orignially received the 
			// notification from it must be the OK button itself, so
			// let it through unchanged
			if ( (hWndFocusCtrl == NULL) || (hWndFocusCtrl == hWnd) )
			{
				return CNGDialog_BASE::OnCommand(wParam, lParam);
			}

			// Fire a CN_COMMAND notification on the focused control
			hWnd = hWndFocusCtrl;

			wParam = MAKEWPARAM(uID, CN_COMMAND);
			lParam = (LPARAM)hWnd;
			::SendMessage(hWnd, WM_COMMAND, wParam, lParam);

			// Move the focus to the next control
			::PostMessage(m_hWnd, WM_NEXTDLGCTL, 0, 0L);

			bResult = TRUE;			// Prevent dialog from closing
		}	
		else if (nCode == CN_COMMAND)
		{
			uCtrlID = ::GetCtrlID(this, hWnd);
			hWnd = ::GetDlgItem(GetSafeHwnd(), uCtrlID);
			ASSERT(uCtrlID != 0);
			ASSERT(uCtrlID != 65535);

			// If the ID of the control in the message isn't the same as that
			// of the control we've identified, pass it through
			// (this can happen with radio buttons)
			if (uID != uCtrlID)
			{
				bResult = CNGDialog_BASE::OnCommand(wParam, lParam);
			}
		}
		else
		{
			// All non-button controls end up here...
			bResult = CNGDialog_BASE::OnCommand(wParam, lParam);
		}
		if (::IsCtrlValueChanging(this, uCtrlID, hWnd, nCode) && !m_bLockCtrlUpdates)
		{
			bResult = OnCtrlValueChanging(uCtrlID, hWnd, nCode);

		}
	}
	else
	{
		bResult = CNGDialog_BASE::OnCommand(wParam, lParam);
	}
	return bResult;
}


// Called when the value of a control has been changed
BOOL CNGDialog::OnCtrlValueChanging(UINT uCtrlID, HWND hWnd, int nCode)
{
	UNREFERENCED_PARAMETER(hWnd);
	UNREFERENCED_PARAMETER(nCode);

	BOOL bResult = UpdateData(TRUE);			// Try to retrieve dialog data via DoDataExchange()
	if (bResult)
	{											// Validation succeeded...
		OnCmdMsg(uCtrlID, 0, NULL, NULL);		// ...so generate a WM_COMMAND notification...
		SetModified();							// ...and mark the dialog as changed
	}
	return bResult;
}


// This override is necessary to prevent re-entrant calls to UpdateData() via OnCommand()
void CNGDialog::OnOK(void)
{
	ASSERT_VALID(this);

	m_bLockCtrlUpdates	= true;

	CNGDialog_BASE::OnOK();

	m_bLockCtrlUpdates	= false;
}


/////////////////////////////////////////////////////////////////////////////
// CNGDialog Help Support

⌨️ 快捷键说明

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