364 lines
8.8 KiB
C++
364 lines
8.8 KiB
C++
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
|
|
// DlgRefQuery.cpp : implementation file
|
|
//
|
|
|
|
#include "precomp.h"
|
|
#include "singleview.h"
|
|
#include "DlgRefQuery.h"
|
|
#include "resource.h"
|
|
#include "tchar.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
enum {ID_TIMER_MAKE_VISIBLE=1};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDlgRefQuery dialog
|
|
|
|
|
|
CDlgRefQuery::CDlgRefQuery(BSTR bstrPath, int nSecondsDelay, CWnd* pwndParent /*=NULL*/)
|
|
: CDialog(CDlgRefQuery::IDD, pwndParent)
|
|
{
|
|
//{{AFX_DATA_INIT(CDlgRefQuery)
|
|
//}}AFX_DATA_INIT
|
|
|
|
ASSERT(nSecondsDelay < 60);
|
|
m_nSecondsDelay = nSecondsDelay;
|
|
|
|
m_pwndParent = pwndParent;
|
|
if (bstrPath == NULL) {
|
|
m_sMessage.Empty();
|
|
}
|
|
else {
|
|
CString sFormat;
|
|
sFormat.LoadString(IDS_REFQUERY_MSG);
|
|
CString sPath = bstrPath;
|
|
LPTSTR szBuffer = m_sMessage.GetBuffer(2048);
|
|
_stprintf(szBuffer, (LPCTSTR) sFormat, (LPCTSTR) sPath);
|
|
m_sMessage.ReleaseBuffer();
|
|
}
|
|
|
|
m_bCanceled = FALSE;
|
|
m_nRefsRetrieved = 0;
|
|
m_timeConstruct = m_timeConstruct.GetCurrentTime();
|
|
}
|
|
|
|
|
|
void CDlgRefQuery::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CDlgRefQuery)
|
|
DDX_Control(pDX, IDC_EDIT_REFQUERY_MESSAGE, m_edtMessage);
|
|
DDX_Control(pDX, IDC_STAT_REFCOUNT, m_statRefcount);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CDlgRefQuery, CDialog)
|
|
//{{AFX_MSG_MAP(CDlgRefQuery)
|
|
ON_WM_TIMER()
|
|
//}}AFX_MSG_MAP
|
|
ON_MESSAGE(MSG_UPDATE_DIALOG, OnUpdateDialog)
|
|
ON_MESSAGE(MSG_END_THREAD, OnEndThread)
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDlgRefQuery message handlers
|
|
|
|
void CDlgRefQuery::OnCancel()
|
|
{
|
|
// TODO: Add extra cleanup here
|
|
|
|
CDialog::OnCancel();
|
|
m_bCanceled = TRUE;
|
|
::PostMessage(m_hWnd, MSG_END_THREAD, 0, 0);
|
|
}
|
|
|
|
|
|
//**********************************************************
|
|
// CDlgRefQuery::OnInitDialog
|
|
//
|
|
// Initialize the dialog in the hidden state, but set a timer
|
|
// so that it will be made visible when the initial time delay
|
|
// expires.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL
|
|
// TRUE to indicate that we did not set the focus on any
|
|
// child control.
|
|
//
|
|
//***********************************************************
|
|
BOOL CDlgRefQuery::OnInitDialog()
|
|
{
|
|
CDialog::OnInitDialog();
|
|
m_bCanceled = FALSE;
|
|
m_nRefsRetrieved = 0;
|
|
m_edtMessage.SetWindowText(m_sMessage);
|
|
|
|
|
|
// Initially the dialog will be hidden so that the user isn't
|
|
// bothered with a dialog pops up and is taken down immediately
|
|
// when a fast query is executed. For queries that take a long
|
|
// time, the dialog will pop up when the timer expires.
|
|
ShowWindow(SW_HIDE);
|
|
SetTimer(ID_TIMER_MAKE_VISIBLE, m_nSecondsDelay * 1000, NULL);
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
|
// EXCEPTION: OCX Property Pages should return FALSE
|
|
}
|
|
|
|
|
|
|
|
//********************************************************
|
|
// CDlgRefQuery::OnUpdateDialog
|
|
//
|
|
// This event indicates that the reference count value has
|
|
// changed and it is time for the dialog to update the reference
|
|
// count that appears on the dialog.
|
|
//
|
|
// Parameters:
|
|
// Ignored.
|
|
//
|
|
// Returns:
|
|
// 0 to indicate that the event was handled.
|
|
//
|
|
//**********************************************************
|
|
afx_msg LONG CDlgRefQuery::OnUpdateDialog(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (::IsWindow(m_hWnd) && ::IsWindow(m_statRefcount.m_hWnd)) {
|
|
TCHAR szBuffer[64];
|
|
_stprintf(szBuffer, _T("%ld"), m_nRefsRetrieved);
|
|
m_statRefcount.SetWindowText(szBuffer);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
afx_msg LONG CDlgRefQuery::OnEndThread(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if(lParam)
|
|
{
|
|
StopTimer();
|
|
EndDialog(IDOK);
|
|
return 0;
|
|
}
|
|
// EndDialog(IDOK);
|
|
StopTimer();
|
|
PostQuitMessage(0);
|
|
return 0;
|
|
}
|
|
|
|
void CDlgRefQuery::StopTimer()
|
|
{
|
|
if (::IsWindow(m_hWnd)) {
|
|
KillTimer(ID_TIMER_MAKE_VISIBLE);
|
|
}
|
|
}
|
|
|
|
|
|
//**************************************************************
|
|
// CDlgRefQuery::OnTimer
|
|
//
|
|
// The dialog uses a timer as a delay mechanism so that the user
|
|
// sees the dialog only if the query takes longer than some
|
|
// minimum amount of time. This timer event should only occur
|
|
// once.
|
|
//
|
|
// Parameters:
|
|
// See the MFC documentation for the OnTimer events.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//**************************************************************
|
|
void CDlgRefQuery::OnTimer(UINT nIDEvent)
|
|
{
|
|
CDialog::OnTimer(nIDEvent);
|
|
switch(nIDEvent) {
|
|
case ID_TIMER_MAKE_VISIBLE:
|
|
if (::IsWindow(m_hWnd)) {
|
|
ShowWindow(SW_SHOW);
|
|
KillTimer(ID_TIMER_MAKE_VISIBLE);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CQueryThread
|
|
//
|
|
// The CQueryThread class is used to put up a dialog box if a query takes
|
|
// a long time. This is done in a separate thread so that there is no
|
|
// danger of the main thread's message pump being run. This avoids the
|
|
// problem of user interface clicks being processed while in the middle of
|
|
// loading the association graph, etc.
|
|
|
|
|
|
IMPLEMENT_DYNCREATE(CQueryThread, CWinThread)
|
|
|
|
CQueryThread::CQueryThread()
|
|
{
|
|
m_pdlgRefQuery = NULL;
|
|
m_bAutoDelete = FALSE;
|
|
m_hEventStart = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
}
|
|
|
|
CQueryThread::~CQueryThread()
|
|
{
|
|
if(m_hEventStart)
|
|
{
|
|
CloseHandle(m_hEventStart);
|
|
m_hEventStart = NULL;
|
|
}
|
|
delete m_pdlgRefQuery;
|
|
}
|
|
|
|
|
|
//***********************************************************
|
|
// CQueryThread::CQueryThread
|
|
//
|
|
// Construct the CQueryThread. Here we construct the dialog, but
|
|
// we wait until the thread is run to create it so that it is run
|
|
// in the context of the new thread.
|
|
//
|
|
// We will only create one additional thread to run the dialog box.
|
|
//
|
|
//***********************************************************
|
|
CQueryThread::CQueryThread(BSTR bstrPath, int nSecondsDelay, CWnd* pParent)
|
|
{
|
|
m_hEventStart = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
m_pdlgRefQuery = new CDlgRefQuery(bstrPath, nSecondsDelay, pParent);
|
|
m_bAutoDelete = FALSE;
|
|
CreateThread();
|
|
WaitForSingleObject(m_hEventStart, INFINITE);
|
|
}
|
|
|
|
|
|
//***********************************************************
|
|
// CQueryThread::InitInstance
|
|
//
|
|
// When the thread is initialized, the dialog is created, but
|
|
// it will not be visible until the timer that CDlgRefQuery::OnInitDialog
|
|
// set expires.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// TRUE if the thread could be initialized.
|
|
//
|
|
//***********************************************************
|
|
BOOL CQueryThread::InitInstance()
|
|
{
|
|
m_pdlgRefQuery->Create(IDD_REFQUERY);
|
|
SetEvent(m_hEventStart);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
int CQueryThread::ExitInstance()
|
|
{
|
|
return CWinThread::ExitInstance();
|
|
}
|
|
|
|
|
|
|
|
//***********************************************************
|
|
// CQueryThread::WasCanceled
|
|
//
|
|
// Returns TRUE if the query was canceled by the user clicking
|
|
// the CANCEL button on the dialog.
|
|
//
|
|
//***********************************************************
|
|
BOOL CQueryThread::WasCanceled()
|
|
{
|
|
return m_pdlgRefQuery->WasCanceled();
|
|
}
|
|
|
|
|
|
|
|
//************************************************************
|
|
// CQueryThread::AddToRefCount
|
|
//
|
|
// Add a value to the count of the number of references returned
|
|
// by the query.
|
|
//
|
|
// Parameters:
|
|
// [in] long nRefsRetrieved
|
|
// The value to add to the current ref count.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//************************************************************
|
|
void CQueryThread::AddToRefCount(long nRefsRetrieved)
|
|
{
|
|
++m_pdlgRefQuery->m_nRefsRetrieved;
|
|
|
|
HWND hwndDlg = m_pdlgRefQuery->m_hWnd;
|
|
if (!::IsWindow(hwndDlg)) {
|
|
return;
|
|
}
|
|
|
|
|
|
BOOL bDidPostMessage = PostMessage(hwndDlg, MSG_UPDATE_DIALOG, 0, 0);
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
// CQueryThread::TerminateAndDelete
|
|
//
|
|
// Terminate the dialog thread and delete this CQueryThread instance.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//*************************************************************
|
|
void CQueryThread::TerminateAndDelete()
|
|
{
|
|
ASSERT(m_pdlgRefQuery->m_hWnd);
|
|
SendMessage(m_pdlgRefQuery->m_hWnd, MSG_END_THREAD, 0, 1);
|
|
return;
|
|
|
|
#if 0
|
|
// Prevent the timer from going off before or after the MSG_END_THREAD is handled.
|
|
|
|
while (!m_pdlgRefQuery->WasCanceled() && !::IsWindow(m_pdlgRefQuery->m_hWnd)) {
|
|
::Sleep(100);
|
|
}
|
|
BOOL bDidPostMessage = PostMessage(m_pdlgRefQuery->m_hWnd, MSG_END_THREAD, 0, 1);
|
|
::WaitForSingleObject(m_hThread, INFINITE);
|
|
delete this;
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CQueryThread, CWinThread)
|
|
//{{AFX_MSG_MAP(CQueryThread)
|
|
// NOTE - the ClassWizard will add and remove mapping macros here.
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CQueryThread message handlers
|
|
|
|
|
|
|
|
|