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 + -
显示快捷键?