ndialog.cpp

来自「EVC环境下用SDK开发WINCE的应用程序」· C++ 代码 · 共 634 行

CPP
634
字号
// NDialog.cpp: implementation of the CNDialog class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "NDialog.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CNDialog* CNDialog::sm_pDlg[MAX_DLG] = { NULL, };
UINT CNDialog::sm_nNextDlg = 0;



CNDialog::CNDialog(CNWnd* pParent, UINT IDD)
{
	m_uTemplateID = IDD;
	m_pParentWnd = pParent;

	m_nModalResult = -1;
	m_bContinueModal = TRUE;

	// initialize the index of  next empty entry of child window array.
	m_nNextChildWnd = 0;
	m_hRgnClipChild = NULL;

	m_hRgnCopyScr = NULL;
}

CNDialog::~CNDialog()
{
	SelectObject(g_hdcUI, (HRGN)NULL);
	if( m_hRgnClipChild != NULL )
		DeleteObject(m_hRgnClipChild);
}

BEGIN_MESSAGE_MAP(CNDialog, CNWnd)


END_MESSAGE_MAP()

int CNDialog::DoModal()
{

	HWND	hWndParent;
	CNWnd*	pWndActive;

	// If owner window is not specified, set the active window 
	// as its owner wnd.
	if(m_pParentWnd)
	{
		ASSERT( ::IsWindow(m_pParentWnd->m_hWnd) );
		hWndParent = m_pParentWnd->m_hWnd;
	} else
	{
		pWndActive = NGetActiveWindow();
		if(pWndActive)
		{
			hWndParent = pWndActive->GetSafeHwnd();
			m_pParentWnd = pWndActive;
		}
		else
			hWndParent = NULL;
	}


	// disable parent (before creating dialog)
	BOOL bEnableParent = FALSE;
	if (hWndParent != NULL && ::IsWindowEnabled(hWndParent))
	{
		::EnableWindow(hWndParent, FALSE);
		bEnableParent = TRUE;
	}
	
	// create modeless dialog
	if (Create(m_uTemplateID,	NULL))
	{
		RunModalLoop() ;
		
		// hide the window before enabling the parent, etc.
		if (m_hWnd != NULL)
			SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW|
			SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
	} 
	else
	{
		TRACE(_T("Creating dialog window fail.\n"));
		ASSERT(FALSE);
	}

	if (bEnableParent)
		::EnableWindow(hWndParent, TRUE);


	if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd)
	{
		::SetActiveWindow(hWndParent);
	}

	// destroy modal window
	DestroyWindow();
	return m_nModalResult;
}

int CNDialog::RunModalLoop()
{
	ASSERT(::IsWindow(m_hWnd)); // window must be created

	// for tracking the idle time state
	BOOL bIdle = TRUE;
	LONG lIdleCount = 0;
	BOOL bShowIdle = TRUE;
	HWND hWndParent = ::GetParent(m_hWnd);
	MSG  msg;
	// acquire and dispatch messages until the modal state is done
	for (;;)
	{
		//ASSERT(ContinueModal());

		// phase1: check to see if we can do idle work
		while (bIdle &&
			!::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE))
		{
			//ASSERT(ContinueModal());

			// show the dialog when the message queue goes idle
			if (bShowIdle)
			{
				ShowWindow(SW_SHOWNORMAL);
				UpdateWindow();
				bShowIdle = FALSE;
			}

			OnIdle();
			bIdle = FALSE;
		}

		// phase2: pump messages while available
		do
		{
			//ASSERT(ContinueModal());

			// pump message, but quit on WM_QUIT
			if ( GetMessage(&msg, NULL, 0, 0) )
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			} 
			else
			{
				PostQuitMessage(0);
				return -1;
			}


			//if(WM_MOUSEMOVE != msg.message)
			//	TRACE(_T("msg = %x \n"), msg.message);
			
			// show the window when certain special messages rec'd
			if (bShowIdle )
			{
				ShowWindow(SW_SHOWNORMAL);
				UpdateWindow();
				bShowIdle = FALSE;
			}

			// reset "no idle" state after pumping "normal" message
			if (msg.message<WM_USER 
				&& msg.message != WM_TIMER
				&& msg.message != WM_MOUSEMOVE
				)
			{
				bIdle = TRUE;
				lIdleCount = 0;
			}

			if (!ContinueModal())
				goto ExitModal;
		} while (::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE));
	}

ExitModal:
	RemoveDlg(this);

	return m_nModalResult;
}

BOOL CNDialog::ContinueModal()
{
	return m_bContinueModal;
}


LRESULT CNDialog::WndProc(HWND hDlg,
		UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	LRESULT lResult = 0;

	// Handle windows message.
	// for dialog, the return value must be placed in DWL_MSGRESULT 
	// data field.
	if ( OnWndMsg(uMsg, wParam, lParam, &lResult) )
	{
		// Special case for WM_INITDIALOG
		if ( uMsg == WM_INITDIALOG 
			|| uMsg == WM_CTLCOLORBTN
			|| uMsg == WM_CTLCOLORSTATIC
			// the following control still are not  used in this app.
			/*|| uMsg == WM_CTLCOLORDLG
			|| uMsg == WM_CTLCOLOREDIT
			|| uMsg == WM_CTLCOLORLISTBOX
			|| uMsg == WM_CTLCOLORMSGBOX
			|| uMsg == WM_CTLCOLORSCROLLBAR*/	)
		{
			// when initializeing dialog ends, set the child region.
			if( uMsg == WM_INITDIALOG )
				ResetChildRgn();

			return lResult;
		}

		SetWindowLong(m_hWnd, DWL_MSGRESULT, (LONG) lResult);
		return TRUE;
	}

	// Message not porcessed, return false, dialog manager performs
	// default operations.
	return FALSE;
}


void CNDialog::OnClose()
{
	EndDialog(0);
}


BOOL CNDialog::OnInitDialog()
{
	CNWnd::OnInitDialog();

#ifdef PC_VERSION

	// get window size expanding ratio.
	RECT rc;
	GetClientRect(&rc);
	float ratioX = (float)SCREEN_WIDTH / (float)(rc.right);
	float ratioY = (float)SCREEN_HEIGHT / (float)(rc.bottom);
	// move window to center of the screen.
	::SetWindowPos(GetSafeHwnd(),NULL,
		(GetSystemMetrics(SM_CXSCREEN) - SCREEN_WIDTH)/2,
		(GetSystemMetrics(SM_CYSCREEN) - SCREEN_HEIGHT)/2,
		SCREEN_WIDTH,SCREEN_HEIGHT,SWP_NOACTIVATE);
	SetChildWindowPos(ratioX, ratioY);

#else	// TARGET_VERSION
	::SetWindowPos(GetSafeHwnd(),NULL,
		(GetSystemMetrics(SM_CXSCREEN) - SCREEN_WIDTH)/2,
		(GetSystemMetrics(SM_CYSCREEN) - SCREEN_HEIGHT)/2,
		SCREEN_WIDTH,SCREEN_HEIGHT,SWP_NOACTIVATE);
	
#endif

	// add it to statck.
	AddDlg(this);

	return TRUE;
}

// 
BOOL CNDialog::OnEraseBkgnd(HDC hdc)
{
	RECT	rcClient;
	GetClientRect(&rcClient);

	// fill bkgnd with key color.
	FillSolidRect(hdc, &rcClient, KEY_COLOR);

	return TRUE;
}


void CNDialog::OnActivate(UINT nState, HWND hWndOther, BOOL bMinimized )
{
	if( nState != WA_INACTIVE )
	{
		//ResetChildRgn();
	}
}

int CNDialog::EndDialog(int nResult)
{
	ASSERT(::IsWindow(m_hWnd));

	// this result will be returned from CWnd::RunModalLoop
	m_nModalResult = nResult;
	m_bContinueModal = FALSE;

	// make sure a message goes through to exit the modal loop
	PostMessage(WM_NULL, 0, 0);

	return nResult;
}

void CNDialog::OnIdle()
{
#ifdef PC_VERSION
	HDC hdc = GetWindowDC();
#else // for CE
	HDC hdc = GetDCEx(m_hWnd, NULL, DCX_WINDOW | DCX_CACHE );
#endif
	SelectObject(hdc, m_hRgnCopyScr);
	BitBlt(hdc,0,0,SCREEN_WIDTH, SCREEN_HEIGHT, g_hdcUI,0,0,SRCCOPY);
	ReleaseDC(hdc);
}


void CNDialog::AddDlg(CNDialog* pDlg)
{
	ASSERT( sm_nNextDlg<MAX_DLG );
	sm_pDlg[sm_nNextDlg++] = pDlg;
}

BOOL CNDialog::RemoveDlg(CNDialog* pDlg)
{
	// stack must not be empty.
	ASSERT(sm_nNextDlg>0);

	sm_nNextDlg--;
	ASSERT(sm_pDlg[sm_nNextDlg] != NULL); // it's a valid item.
/*
	if ( sm_pDlg[sm_nNextDlg]->GetSafeHwnd() 
		== pDlg->GetSafeHwnd() )
	{
		sm_pDlg[sm_nNextDlg] = NULL;
		return TRUE;
	} else	// may be errors occur in stack.
	{
		ASSERT(FALSE);
	}
*/
	
	for(int nIndex=sm_nNextDlg; nIndex>=0; nIndex--)
	{
		if ( sm_pDlg[nIndex]->GetSafeHwnd() 
			== pDlg->GetSafeHwnd() )	// found in array
		{
			// move the items forward, override this one 
			// that need to be removed.
			while(nIndex<(int)sm_nNextDlg)
			{
				sm_pDlg[nIndex] = sm_pDlg[nIndex+1];
				nIndex++;
			}
			sm_pDlg[sm_nNextDlg] = NULL;
			break;
		}

	}

	if(nIndex >= 0 )	// remove it successfully
		return TRUE;
	else	// may be errors occur in stack.
	{
		ASSERT(FALSE);
		return FALSE;
	}

}

CNDialog* CNDialog::FromHandle(HWND hDlg)
{
	for(UINT i=0; i<sm_nNextDlg; i++)
	{
		if(sm_pDlg[i]->GetSafeHwnd() == hDlg)
			break;
	}

	if( i >= sm_nNextDlg) // not found
		return NULL;

	return sm_pDlg[i];
}

HBRUSH CNDialog::OnCtlColor(HDC hdc,HWND hwnd, UINT nCtlColor)
{
	static HBRUSH s_hbrBtnBkgnd;
	static BOOL bInit = FALSE;
	HBRUSH hbr;
	if(!bInit)
	{
		s_hbrBtnBkgnd = CreateSolidBrush(KEY_COLOR);
		ASSERT( s_hbrBtnBkgnd != NULL );
		bInit = TRUE;
	}
	// use KEY_COLOR for buttons and static controls in default.
	if(nCtlColor == WM_CTLCOLORBTN)
		hbr = (HBRUSH)GetStockObject(HOLLOW_BRUSH);
	else if( nCtlColor == WM_CTLCOLORSTATIC)
	{
		// in default, set output text transparent and in white color.
		::SetBkMode(hdc, TRANSPARENT);
		::SetTextColor(hdc, RGB(255,255,255));
		hbr = s_hbrBtnBkgnd;//(HBRUSH)GetStockObject(WHITE_BRUSH);//s_hbrBtnBkgnd;
	}
	else
		hbr = CNWnd::OnCtlColor(hdc, hwnd, nCtlColor);

	return hbr;
}

#ifdef PC_VERSION
static BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
{
	HWND	hwndParent = ::GetParent(hwnd);
	float	*pRatio = (float*)lParam;
	RECT	rect;
	POINT	ptClient = {0,0};	// original point of window
	POINT	ptParent = {0,0};
	::GetClientRect(hwnd, &rect);
	
	// set size
	//int nLen = GetWindowTextLength(hwnd);
	TCHAR szClassName[128];
	GetClassName(hwnd,szClassName,128-1);
	// not change the size of image static control.
	if( _tcscmp(szClassName,_T("Static")) != 0 )
	{
		rect.right = (long)(rect.right * (pRatio[0]));
		rect.bottom = (long)(rect.bottom * (pRatio[1]));
	}

	// set pos
	::ClientToScreen(hwnd, &ptClient);
	::ClientToScreen(hwndParent, &ptParent);

	ptClient.x = (long)((ptClient.x-ptParent.x) * (pRatio[0]));
	ptClient.y = (long)((ptClient.y-ptParent.y) * (pRatio[1]));

	return ::SetWindowPos(hwnd, NULL,
		ptClient.x ,ptClient.y,
		rect.right, rect.bottom,
		NULL);
	
}
BOOL CNDialog::SetChildWindowPos(float ratioX, float ratioY)
{
	float ratio[2];
	ASSERT( ::IsWindow(m_hWnd) );
	ratio[0] = ratioX;
	ratio[1] = ratioY;
	return EnumChildWindows(m_hWnd, EnumChildProc, (LPARAM)ratio);
}
#endif

// Create modaless dialog

HWND CNDialog::Create( UINT uID , CNWnd* pParentWnd)
{
	HWND	hWndParent;
	CNWnd*	pWndActive;

	// If owner window is not specified,  the dialog object 
	// parent window is set to the main application window. 
	// (retrieve it by NGetMainWnd() )

	if(m_pParentWnd)
	{
		ASSERT( ::IsWindow(m_pParentWnd->m_hWnd) );
		hWndParent = m_pParentWnd->m_hWnd;
	} else
	{
		pWndActive = NGetActiveWindow();
		if(pWndActive)
		{
			hWndParent = pWndActive->GetSafeHwnd();
			m_pParentWnd = pWndActive;
		}
		else
			hWndParent = NULL;

	}

	//hWndOwner = NGetMainWnd()->GetSafeHwnd();
	HWND hwnd = CreateDialogParam(NGetInstanceHandle(),
		MAKEINTRESOURCE(m_uTemplateID),
		hWndParent,		
		(DLGPROC)WindowProc,
		(LPARAM)this);

	
	return hwnd;
}


BOOL CNDialog::DestroyWindow()
{
	// delete it from statck.
//	RemoveDlg(this);
	return CNWnd::DestroyWindow();
}


void CNDialog::AddChildWnd(CNWnd* pWnd)
{
	ASSERT( m_nNextChildWnd<MAX_CHILD );

	m_pChildWnd[m_nNextChildWnd++] = pWnd;
}

BOOL CNDialog::RemoveChildWnd(CNWnd* pWnd)
{
	// stack must not be empty.
	ASSERT(m_nNextChildWnd>0);

	m_nNextChildWnd--;
	ASSERT(m_pChildWnd[m_nNextChildWnd] != NULL); // it's a valid item.
	
	for(int nIndex=m_nNextChildWnd; nIndex>=0; nIndex--)
	{
		if ( m_pChildWnd[nIndex]->GetSafeHwnd() 
			== pWnd->GetSafeHwnd() )	// found in array
		{
			// move the items forward, override this one 
			// that need to be removed.
			while(nIndex<(int)m_nNextChildWnd)
			{
				m_pChildWnd[nIndex] = m_pChildWnd[nIndex+1];
				nIndex++;
			}
			m_pChildWnd[m_nNextChildWnd] = NULL;
			break;
		}

	}

	if(nIndex >= 0 )	// remove it successfully
		return TRUE;
	else	// may be errors occur in stack.
	{
		ASSERT(FALSE);
		return FALSE;
	}

}

void CNDialog::ResetChildRgn(CNWnd *pChild, BOOL bVisible)
{
	HRGN hrgn = NULL;
	RECT rect;

	POINT pt = {0,0};
	::ScreenToClient(m_hWnd, &pt);


	GetClientRect(&rect);
	if( m_hRgnClipChild == NULL )	// not create it yet,create now
	{
		m_hRgnClipChild = CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);
		m_hRgnCopyScr = CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);
	}
	else 	// created already, just reset it.
	{
		SetRectRgn(m_hRgnClipChild, rect.left, rect.top, rect.right, rect.bottom);
		SetRectRgn(m_hRgnCopyScr, rect.left, rect.top, rect.right, rect.bottom);
	}

	for(int nIndex=0; nIndex < (int)m_nNextChildWnd; nIndex++)
	{
		// only clip the child windows that are visible.
		if( WS_VISIBLE & 
			GetWindowLong(m_pChildWnd[nIndex]->GetSafeHwnd(), GWL_STYLE) )
		{
			// when assuming it's invisible, ignore WS_VISIBLE style.
			// so don't clip it.
			if(pChild==m_pChildWnd[nIndex] && !bVisible)
				continue;

			// get child window rect in parent's coordinates
			//m_pChildWnd[nIndex]->GetClientRect(&rect);
			m_pChildWnd[nIndex]->GetWindowRect(&rect);
			::OffsetRect(&rect, pt.x, pt.y);

			hrgn = ::CreateRectRgn(rect.left, 
				rect.top, rect.right, rect.bottom);
			// clip the region from parent window's client region
			::CombineRgn(m_hRgnClipChild,m_hRgnClipChild, hrgn, RGN_DIFF);

			// if its not mem window, clip the window when copy to screen.
			if ( ! m_pChildWnd[nIndex]->IsMemWindow() )
			{
				::CombineRgn(m_hRgnCopyScr,m_hRgnCopyScr, hrgn, RGN_DIFF);
			}

			DeleteObject(hrgn);
		}
	}

	// when assuming it's visible, clip it anyway
	if( pChild && bVisible)
	{
		pChild->GetClientRect(&rect);
		hrgn = ::CreateRectRgn(rect.left, 
			rect.top, rect.right, rect.bottom);
		// clip the region from parent window's client region
		::CombineRgn(m_hRgnClipChild,m_hRgnClipChild, hrgn, RGN_DIFF);
		
		if ( ! pChild->IsMemWindow() )
		{
			::CombineRgn(m_hRgnCopyScr,m_hRgnCopyScr, hrgn, RGN_DIFF);
		}
		
		DeleteObject(hrgn);
	}
}

HRGN CNDialog::GetUpdateRgn()
{
	if( this == NGetActiveWindow() )
		return m_hRgnClipChild;

	return g_hRgnNULL;
}

void CNDialog::OnLButtonUp(UINT nFlags, POINT point)
{
//	EndDialog(0);
}

⌨️ 快捷键说明

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