windows-nt/Source/XPSP1/NT/enduser/troubleshoot/msinfo/dialogs.cpp
2020-09-26 16:20:57 +08:00

618 lines
16 KiB
C++

// Dialogs.cpp - Create all of our dialogs to get data from the user.
//
// Copyright (c) 1998-1999 Microsoft Corporation
#include <afxdlgs.h>
#include <afxwin.h>
#include <shlobj.h>
#include "StdAfx.h"
#include "Dialogs.h"
#include "DataObj.h"
#include "CompData.h"
#include "Resource.h"
#include "resrc1.h"
// These are the lists of file type for the Save/Open Common Control Dialogs.
CString strMSInfoSaveFileTypes;
CString strMSInfoOpenFileTypes;
CString strMSInfoReportTypes;
// These are the default file types
CString strMSInfoSaveType;
CString strMSInfoReportType;
// This is to implement a change to load the strings for file types, etc.,
// from resources. This is called by the app init.
void LoadDialogResources()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
strMSInfoSaveFileTypes.LoadString(IDS_SAVE_FILE_TYPES);
strMSInfoOpenFileTypes.LoadString(IDS_OPEN_FILE_TYPES);
strMSInfoReportTypes.LoadString(IDS_REPORT_TYPES);
strMSInfoSaveType.LoadString(IDS_SAVE_TYPE);
strMSInfoReportType.LoadString(IDS_REPORT_TYPE);
}
// The custom message number we use to
UINT CFindDialog::WM_MSINFO_FIND = WM_USER + 0x119;
// static data members must be initialized at file scope
TCHAR CMSInfoFileDialog::m_szCurrentDirectory[MAX_PATH] = _T("My Documents");
/*
* GetPathFromIDList - Copy the path from the iilFolder to szPathBuffer.
*
* History: a-jsari 10/31/97 Initial version
*/
inline void GetBasePath(HWND hOwner, LPTSTR szPathBuffer)
{
LPITEMIDLIST iilFolder;
HRESULT hResult;
hResult = SHGetSpecialFolderLocation(hOwner, CSIDL_PERSONAL, &iilFolder);
ASSERT(hResult == NOERROR);
VERIFY(SHGetPathFromIDList(iilFolder, szPathBuffer));
}
/*
* CMSInfoFileDialog - Brings up the CFileDialog window, with a few of our
* own specifications.
*
* History: a-jsari 10/24/97 Initial version
*/
CMSInfoFileDialog::CMSInfoFileDialog(
BOOL bDialogIsOpen,
HWND hOwner,
LPCTSTR lpszDefaultExtension,
LPCTSTR lpszExtensionFilters)
:CFileDialog(bDialogIsOpen, // Open dialog or Save dialog?
lpszDefaultExtension, // Default file extension
NULL, // File name (don't specify)
OFN_EXPLORER, // OPN Flags
lpszExtensionFilters) // Filetype filter string.
{
m_ofn.hwndOwner = hOwner;
m_ofn.nFilterIndex = 0;
// default to "My Documents"
GetBasePath(hOwner, m_szCurrentDirectory);
m_ofn.lpstrInitialDir = m_szCurrentDirectory;
}
/*
* we override DoModal so we can keep track of where the file was last opened from
*
*
*/
INT_PTR CMSInfoFileDialog::DoModal()
{
INT_PTR iRC;
m_ofn.lpstrInitialDir = m_szCurrentDirectory;
iRC = CFileDialog::DoModal();
// remember path user browsed to
TCHAR szDir[MAX_PATH];
TCHAR szDrive[10];
int iLen;
_tsplitpath(GetPathName(), szDrive, szDir, NULL, NULL);
_tmakepath( m_szCurrentDirectory, szDrive, szDir, NULL, NULL);
iLen = _tcslen( CMSInfoFileDialog::m_szCurrentDirectory);
if ( m_szCurrentDirectory[iLen-1] == '\\' )
m_szCurrentDirectory[iLen-1] = 0;
return iRC;
}
/*
* CMSInfoReportDialog - Apply settings specific to the report dialog
*
* History: a-jsari 10/24/97 Initial version
*/
CMSInfoReportDialog::CMSInfoReportDialog(HWND hOwner)
:CMSInfoSaveDialog(hOwner, strMSInfoReportType, strMSInfoReportTypes)
{
m_ofn.Flags |= OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
}
/*
* CMSInfoSaveDialog - Apply settings specific to the save dialog
*
* History: a-jsari 10/24/97 Initial version
*/
CMSInfoSaveDialog::CMSInfoSaveDialog(HWND hOwner, LPCTSTR lpszDefaultExtension,
LPCTSTR lpszExtensionFilters)
:CMSInfoFileDialog(FALSE, hOwner, lpszDefaultExtension, lpszExtensionFilters)
{
m_ofn.Flags |= OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
}
/*
* CMSInfoOpenDialog - Apply settings specific to the open dialog.
*
* History: a-jsari 10/24/97 Initial version
*/
CMSInfoOpenDialog::CMSInfoOpenDialog(HWND hOwner)
:CMSInfoFileDialog(TRUE, hOwner, strMSInfoSaveType, strMSInfoOpenFileTypes)
{
m_ofn.Flags |= OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
}
/*
* CMSInfoPrintDialog - Create the Print dialog
*
* History: a-jsari 12/8/97 Initial version
*/
CMSInfoPrintDialog::CMSInfoPrintDialog(HWND hOwner)
:CPrintDialog(FALSE, PD_SELECTION | PD_USEDEVMODECOPIES | PD_HIDEPRINTTOFILE)
{
m_pd.hwndOwner = hOwner;
}
/////////////////////////////////////////////////////////////////////////////
// CFindDialog dialog
/*
* CFindDialog - Create the modal find dialog (which we will run in its own
* thread, to make it appear modeless.
*
* History: a-jsari 11/28/97 Initial version.
*/
CFindDialog::CFindDialog(CSystemInfoScope *pScope, HWND hPostWindow, HWND hwndMMCWindow)
:CDialog(IDD, NULL),
m_pScope(pScope),
m_hPostWindow(hPostWindow),
m_hMMCWindow(hwndMMCWindow),
m_strSearch(_T("")),
m_fRunning(FALSE)
{
}
/*
* ~CFindDialog - Destroy the find dialog.
*
* History: a-jsari 11/28/97 Initial version.
*/
CFindDialog::~CFindDialog()
{
OnCancel();
if (m_iTimer)
{
KillTimer(m_iTimer);
m_iTimer = 0;
}
}
/*
* Create - Creates the dialog box.
*
* History: a-jsari 1/21/98 Initial version.
*/
BOOL CFindDialog::Create()
{
DoModal();
return FALSE;
}
/*
* SetFocus - Set focus to our Search window.
*
* History: a-jsari 12/17/97 Initial version
*/
CWnd *CFindDialog::SetFocus()
{
CWnd *pwFind;
pwFind = GetDlgItem(IDC_SEARCHTERM);
ASSERT(pwFind != NULL);
return pwFind->SetFocus();
}
/*
* OnInitDialog - ClassWizard generated function
*
* History: a-jsari 12/2/97
*/
BOOL CFindDialog::OnInitDialog()
{
CDialog::OnInitDialog();
::SetWindowPos(GetSafeHwnd(), m_hPostWindow, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
m_iTimer = SetTimer(1, 150, NULL);
return TRUE;// return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
BEGIN_MESSAGE_MAP(CFindDialog, CDialog)
//{{AFX_MSG_MAP(CFindDialog)
ON_EN_CHANGE(IDC_SEARCHTERM, OnSearchTerm)
ON_COMMAND(IDC_FINDNEXT, OnFindNext)
ON_COMMAND(IDC_STOPFIND, OnStopFind)
ON_COMMAND(IDC_NEWSEARCH, OnNewSearch)
ON_WM_ACTIVATE()
ON_WM_HELPINFO()
ON_WM_TIMER()
ON_MESSAGE(WM_HELP, OnHelp)
ON_MESSAGE(WM_CONTEXTMENU, OnContextMenu)
ON_WM_SETCURSOR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFindDialog message handlers
/*
* OnActivate - Set our window position when we activate.
*
* History: a-jsari 3/4/98 Initial version
*/
afx_msg void CFindDialog::OnActivate(UINT, CWnd *, BOOL bMinimized)
{
// If we aren't minimized
if (bMinimized == FALSE)
{
// Don't do this - it makes us stay on top of ALL the windows...
//
// SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
}
}
//-----------------------------------------------------------------------------
// Catch the WM_HELPINFO message, so we can show context sensitive help on
// the controls in the dialog box.
//-----------------------------------------------------------------------------
#include <afxpriv.h>
static DWORD helparray[] =
{
IDC_SEARCHTERM, 1000001,
IDC_FINDIN, 1000002,
IDC_CATEGORYCHECK, 1000003,
IDC_FINDNEXT, 1000004,
IDC_STOPFIND, 1000005,
IDC_NEWSEARCH, 1000006,
IDCANCEL, 1000007,
0, 0
};
afx_msg BOOL CFindDialog::OnHelpInfo(HELPINFO * pHelpInfo)
{
if (pHelpInfo && (pHelpInfo->iContextType == HELPINFO_WINDOW))
::WinHelp((HWND)pHelpInfo->hItemHandle, TEXT("msinfo32.hlp"), HELP_WM_HELP, (DWORD_PTR)helparray);
return TRUE;
}
//-----------------------------------------------------------------------------
// Every time we get a timer message, check to see if the find window is
// behind the MMC window. If it is, bring it forward. What we really want
// is an application always on top effect, but this seems to be the way to
// get this (since we can't change MMC).
//
// I hate this.
//-----------------------------------------------------------------------------
afx_msg void CFindDialog::OnTimer(UINT)
{
if (m_hMMCWindow == NULL)
return;
for (HWND hwndWalk = GetSafeHwnd(); hwndWalk != NULL; hwndWalk = ::GetNextWindow(hwndWalk, GW_HWNDPREV))
if (hwndWalk == m_hMMCWindow)
{
// This is how we bring the find window to the top. Using wndTop with
// SetWindowPos doesn't seem to do anything.
SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
SetWindowPos(&wndNoTopMost, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
break;
}
}
LONG CFindDialog::OnHelp(WPARAM wParam, LPARAM lParam)
{
LONG lResult = 0;
if (lParam)
::WinHelp((HWND)(((LPHELPINFO)lParam)->hItemHandle), TEXT("msinfo32.hlp"), HELP_WM_HELP, (DWORD_PTR)helparray);
return lResult;
}
LONG CFindDialog::OnContextMenu(WPARAM wParam, LPARAM lParam)
{
LONG lResult = 0;
::WinHelp((HWND)wParam, TEXT("msinfo32.hlp"), HELP_CONTEXTMENU,(DWORD_PTR)helparray);
return lResult;
}
/*
* OnSetCursor - Set our cursor depending on whether we are executing the find.
*
* History: a-jsari 3/21/98 Initial version
*/
afx_msg BOOL CFindDialog::OnSetCursor(CWnd *pWndOther, UINT nHitTest, UINT message)
{
static HCURSOR hcPointerHourglass = NULL;
// Set the pointer & hourglass cursor.
if (m_fRunning) {
if (hcPointerHourglass == NULL) {
hcPointerHourglass = ::LoadCursor(NULL, IDC_APPSTARTING);
#ifdef DEBUG
DWORD dwError = ::GetLastError();
#endif
ASSERT(hcPointerHourglass != NULL);
}
::SetCursor(hcPointerHourglass);
return TRUE;
} else return CDialog::OnSetCursor(pWndOther, nHitTest, message);
}
/*
* OnCancel - Destroy the window when the cancel button is selected.
*
* History: a-jsari 12/2/97
*/
afx_msg void CFindDialog::OnCancel()
{
OnStopFind();
::PostQuitMessage(0);
// Exit the containing UI thread.
m_pScope->CloseFindWindow();
}
/*
* OnFindNext - Execute the find next operation, when the "Find Next" button
* is clicked or when a return is hit in the "Find In".
*
* History: a-jsari 12/11/97
*/
afx_msg void CFindDialog::OnFindNext()
{
int wCount;
long lFindState;
// Save our last search.
CString strLast = m_strSearch;
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
// Save our current search
wCount = GetDlgItemText(IDC_SEARCHTERM, m_strSearch);
ASSERT(wCount != 0);
// Enable the Stop button (Disabled in FindComplete).
CButton *pwStop = reinterpret_cast<CButton *>(GetDlgItem(IDC_STOPFIND));
ASSERT(pwStop != NULL);
pwStop->EnableWindow(TRUE);
// Disable our button so we can't activate it while we're running.
// (Enabled in FindComplete)
CButton *pwFindNext = reinterpret_cast<CButton *>(GetDlgItem(IDC_FINDNEXT));
ASSERT(pwFindNext != NULL);
pwFindNext->EnableWindow(FALSE);
// Set the flag indicating whether we search only category names.
CButton *pwCheck = reinterpret_cast<CButton *>(GetDlgItem(IDC_CATEGORYCHECK));
ASSERT(pwCheck != NULL);
lFindState = pwCheck->GetCheck() ? CDataSource::FIND_OPTION_CATEGORY_ONLY : 0;
// Set the flag indicating whether we search the selected category alone.
pwCheck = reinterpret_cast<CButton *>(GetDlgItem(IDC_FINDIN));
ASSERT(pwCheck != NULL);
lFindState |= (pwCheck->GetCheck()) ? CDataSource::FIND_OPTION_ONE_CATEGORY : 0;
// Set the flag indicating whether we are repeating a previous search.
if (::_tcsicmp((LPCTSTR)strLast, (LPCTSTR)m_strSearch) == 0)
lFindState |= CDataSource::FIND_OPTION_REPEAT_SEARCH;
m_fRunning = TRUE;
// In order to perform the find multi-threaded and allow a stop operation,
// we post a custom message to a hidden window attached to the main MMC window
// created in CSystemInfoScope::Initialize
// Our custom WindowProc processes this message, running Find in the main
// window's UI thread.
::PostMessage(m_hPostWindow, WM_MSINFO_FIND, (WPARAM)m_pScope, (LPARAM) lFindState);
}
/*
* OnNewSearch - Clear the controls
*
* History: a-jsari 12/11/97
*/
afx_msg void CFindDialog::OnNewSearch()
{
ResetSearch();
// Clear the text box.
SetDlgItemText(IDC_SEARCHTERM, _T(""));
// Clear the category check box.
CButton *pwCheck = (CButton *) GetDlgItem(IDC_CATEGORYCHECK);
ASSERT(pwCheck != NULL);
pwCheck->SetCheck(0);
// Clear the Restrict Search check box
pwCheck = (CButton *) GetDlgItem(IDC_FINDIN);
ASSERT(pwCheck != NULL);
pwCheck->SetCheck(0);
// Refocus on the text box.
SetFocus();
}
/*
* OnSearchTerm - Callback for when the Search edit box is changed.
*
* History: a-jsari 12/11/97 Initial version.
*/
afx_msg void CFindDialog::OnSearchTerm()
{
CString strSearch;
CWnd *wControl;
int wSearch;
// Get the length of the text box text.
wSearch = GetDlgItemText(IDC_SEARCHTERM, strSearch);
wControl = GetDlgItem(IDC_FINDNEXT);
wControl->EnableWindow(wSearch > 0);
wControl = GetDlgItem(IDC_SEARCHTERM);
wControl->SetFocus();
}
/*
* OnStopFind - MULTI-THREADED Callback for the "Stop Find" button, intended
* to be called while the find is running in the main window thread.
*
* History: a-jsari 1/19/98 Initial version
*/
afx_msg void CFindDialog::OnStopFind()
{
// This will abort the find operation in the main thread which will
// then call FindComplete.
m_pScope->StopFind();
}
/*
* FindComplete - Reset the find dialog upon completion, either by abort or
* by normal completion.
*
* History: a-jsari 2/4/98 Initial version.
*/
void CFindDialog::FindComplete()
{
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
m_fRunning = FALSE;
// Enable our Find Button
CButton *pwFindNext = reinterpret_cast<CButton *>(GetDlgItem(IDC_FINDNEXT));
ASSERT(pwFindNext != NULL);
CString strSearch;
int wSearch = GetDlgItemText(IDC_SEARCHTERM, strSearch);
pwFindNext->EnableWindow(wSearch > 0);
// Disable the Stop Button
CButton *pwStop = reinterpret_cast<CButton *>(GetDlgItem(IDC_STOPFIND));
ASSERT(pwStop != NULL);
pwStop->EnableWindow(FALSE);
OnActivate(0, NULL, FALSE);
}
/*
* ResetSearch - Resets the search so that the next search will register as
* new.
*
* History: a-jsari 2/20/98 Initial version.
*/
void CFindDialog::ResetSearch()
{
m_strSearch = _T("");
}
IMPLEMENT_DYNCREATE(CFindThread, CWinThread)
/*
* CFindThread - Default constructor
*
* History: a-jsari 1/19/98 Initial version.
*/
CFindThread::CFindThread()
:m_pdlgFind(NULL), m_pScope(NULL), m_pDataSource(NULL)
{
}
/*
* ~CFindThread - Our destructor.
*
* History: a-jsari 1/19/98 Initial version.
*/
CFindThread::~CFindThread()
{
}
/*
* SetScope - Sets the scope item for the Find Dialog.
*
* History: a-jsari 1/21/98 Initial version.
*/
void CFindThread::SetScope(CSystemInfoScope *pScope)
{
ASSERT(pScope != NULL);
m_pScope = pScope;
}
/*
* SetParent - Sets the parent window for the Find Dialog.
*
* History: a-jsari 1/21/98 Initial version.
*/
void CFindThread::SetParent(HWND hParent, HWND hMMC)
{
m_hParentWindow = hParent;
m_hMMCWindow = hMMC;
}
/*
* Activate - Reactivate the thread after it's been deselected.
*
* History: a-jsari 1/22/98 Initial version.
*/
void CFindThread::Activate()
{
ASSERT(m_pdlgFind != NULL);
m_pdlgFind->OnActivate(0, NULL, FALSE);
}
/*
* InitInstance - Starts the thread and the dialog object.
*
* History: a-jsari 1/19/98 Initial version
*/
BOOL CFindThread::InitInstance()
{
// else increment some instance pointer?
// Create our new Modal find dialog.
m_pdlgFind = new CFindDialog(m_pScope, m_hParentWindow, m_hMMCWindow);
ASSERT(m_pdlgFind != NULL);
if (m_pdlgFind == NULL) ::AfxThrowMemoryException();
m_pdlgFind->Create();
// We won't get here until our dialog is exiting, since create calls
// DoModal(), which blocks.
return TRUE;
}
/*
* ExitInstance - Ends the thread, destroying the dialog object.
*
* History: a-jsari 1/19/98 Inital version
*/
int CFindThread::ExitInstance()
{
delete m_pdlgFind;
m_pdlgFind = NULL;
return CWinThread::ExitInstance();
}
/*
* RemoteQuit - Ends the thread from an alternate thread, by sending the appropriate
* message to our dialog, waiting for its exit.
*
* History: a-jsari 1/29/98 Initial version
*/
void CFindThread::RemoteQuit()
{
const DWORD dwWaitTimeout = 100000; // 100 ms, Presumably long enough.
DWORD dwResult;
m_pdlgFind->SendMessage(WM_COMMAND, IDCANCEL);
// Wait for the thread to exit, avoiding its using an object destroyed
// by our main thread in CSystemInfoScope.
dwResult = ::WaitForSingleObject(m_hThread, dwWaitTimeout);
ASSERT(dwResult == WAIT_OBJECT_0);
}