|
|
/*++
Copyright (C) 1996-1999 Microsoft Corporation
Module Name:
smonprop.cpp
Abstract:
Sysmon property page base class.
--*/
#include "polyline.h"
#include <strsafe.h>
#include "smonprop.h"
#include "genprop.h"
#include "ctrprop.h"
#include "grphprop.h"
#include "srcprop.h"
#include "appearprop.h"
#include "unihelpr.h"
#include "utils.h"
#include "smonhelp.h"
#include "globals.h"
static ULONG aulControlIdToHelpIdMap[] = { IDC_CTRLIST, IDH_CTRLIST, // Data
IDC_ADDCTR, IDH_ADDCTR, IDC_DELCTR, IDH_DELCTR, IDC_LINECOLOR, IDH_LINECOLOR, IDC_LINEWIDTH, IDH_LINEWIDTH, IDC_LINESTYLE, IDH_LINESTYLE, IDC_LINESCALE, IDH_LINESCALE, IDC_GALLERY_REPORT, IDH_GALLERY_REPORT, // General
IDC_GALLERY_GRAPH, IDH_GALLERY_GRAPH, IDC_GALLERY_HISTOGRAM, IDH_GALLERY_HISTOGRAM, IDC_VALUEBAR, IDH_VALUEBAR, IDC_TOOLBAR, IDH_TOOLBAR, IDC_LEGEND, IDH_LEGEND, IDC_RPT_VALUE_DEFAULT, IDH_RPT_VALUE_DEFAULT, IDC_RPT_VALUE_MINIMUM, IDH_RPT_VALUE_MINIMUM, IDC_RPT_VALUE_MAXIMUM, IDH_RPT_VALUE_MAXIMUM, IDC_RPT_VALUE_AVERAGE, IDH_RPT_VALUE_AVERAGE, IDC_RPT_VALUE_CURRENT, IDH_RPT_VALUE_CURRENT, IDC_COMBOAPPEARANCE, IDH_COMBOAPPEARANCE, IDC_COMBOBORDERSTYLE, IDH_COMBOBORDERSTYLE, IDC_PERIODIC_UPDATE, IDH_PERIODIC_UPDATE, IDC_DISPLAY_INTERVAL, IDH_DISPLAY_INTERVAL, IDC_UPDATE_INTERVAL, IDH_UPDATE_INTERVAL, IDC_DUPLICATE_INSTANCE, IDH_DUPLICATE_INSTANCE, IDC_GRAPH_TITLE, IDH_GRAPH_TITLE, // Graph
IDC_YAXIS_TITLE, IDH_YAXIS_TITLE, IDC_VERTICAL_GRID, IDH_VERTICAL_GRID, IDC_HORIZONTAL_GRID, IDH_HORIZONTAL_GRID, IDC_VERTICAL_LABELS, IDH_VERTICAL_LABELS, IDC_VERTICAL_MAX, IDH_VERTICAL_MAX, IDC_VERTICAL_MIN, IDH_VERTICAL_MIN, IDC_SRC_REALTIME, IDH_SRC_REALTIME, // Source
IDC_SRC_LOGFILE, IDH_SRC_LOGFILE, IDC_SRC_SQL, IDH_SRC_SQL, IDC_LIST_LOGFILENAME, IDH_LIST_LOGFILENAME, IDC_ADDFILE, IDH_ADDFILE, IDC_REMOVEFILE, IDH_REMOVEFILE, IDC_LOGSET_COMBO, IDH_LOGSET_COMBO, IDC_DSN_COMBO, IDH_DSN_COMBO, IDC_TIMESELECTBTN, IDH_TIMESELECTBTN, IDC_TIMERANGE, IDH_TIMERANGE, IDC_COLOROBJECTS, IDH_COLOROBJECTS, IDC_FONTBUTTON, IDH_FONTBUTTON, IDC_COLORBUTTON, IDH_COLORBUTTON, IDC_COLORSAMPLE, IDH_COLORSAMPLE, IDC_FONTSAMPLE, IDH_FONTSAMPLE, 0,0 };
/*
* CSysmonPropPageFactory::CSysmonPropPageFactory * CSysmonPropPageFactory::~CSysmonPropPageFactory * CSysmonPropPageFactory::QueryInterface * CSysmonPropPageFactory::AddRef * CSysmonPropPageFactory::Release */
CSysmonPropPageFactory::CSysmonPropPageFactory(INT nPageID) { m_cRef=0L; m_nPageID = nPageID; return; }
CSysmonPropPageFactory::~CSysmonPropPageFactory(void) { return; }
STDMETHODIMP CSysmonPropPageFactory::QueryInterface(REFIID riid, PPVOID ppv) { HRESULT hr = S_OK;
try { *ppv=NULL;
if (IID_IUnknown==riid || IID_IClassFactory==riid) { *ppv=this; AddRef(); } else { hr = E_NOINTERFACE; } } catch (...) { hr = E_POINTER; }
return hr; }
STDMETHODIMP_(ULONG) CSysmonPropPageFactory::AddRef(void) { return ++m_cRef; }
STDMETHODIMP_(ULONG) CSysmonPropPageFactory::Release(void) { if (0!=--m_cRef) return m_cRef;
delete this; return 0; }
/*
* CSysmonPropPageFactory::CreateInstance * CSysmonPropPageFactory::LockServer */
STDMETHODIMP CSysmonPropPageFactory::CreateInstance( IN LPUNKNOWN pUnkOuter, IN REFIID riid, OUT PPVOID ppvObj ) { PCSysmonPropPage pObj; HRESULT hr = NOERROR;
//
// No aggregation supported
//
if (NULL != pUnkOuter) { return (CLASS_E_NOAGGREGATION); }
switch (m_nPageID) { case GENERAL_PROPPAGE: pObj = new CGeneralPropPage(); break; case SOURCE_PROPPAGE: pObj = new CSourcePropPage(); break; case COUNTER_PROPPAGE: pObj = new CCounterPropPage(); break; case GRAPH_PROPPAGE: pObj = new CGraphPropPage(); break; case APPEAR_PROPPAGE: pObj = new CAppearPropPage(); break; default: pObj = NULL; }
if (NULL == pObj) return E_OUTOFMEMORY;
if (pObj->Init()) { try { *ppvObj = NULL; hr = pObj->QueryInterface(riid, ppvObj); } catch (...) { hr = E_POINTER; } } else { hr = E_UNEXPECTED; }
//Kill the object if initial creation or Init failed.
if (FAILED(hr)) { delete pObj; } else { InterlockedIncrement(&g_cObj); }
return hr; }
STDMETHODIMP CSysmonPropPageFactory::LockServer(BOOL fLock) { if (fLock) { InterlockedIncrement(&g_cLock); } else { InterlockedDecrement(&g_cLock); }
return NOERROR; }
/*
* CSysmonPropPage implementation */
CSysmonPropPage::CSysmonPropPage(void) : m_cRef ( 0 ), m_hDlg ( NULL ), m_pIPropertyPageSite ( NULL ), m_ppISysmon ( NULL ), m_cObjects ( 0 ), m_cx ( 300 ), // Default width
m_cy ( 100 ), // Default height
m_fDirty ( FALSE ), m_fActive ( FALSE ), m_lcid ( LOCALE_USER_DEFAULT ), m_dwEditControl ( 0 ) { return; }
CSysmonPropPage::~CSysmonPropPage(void) { if (NULL != m_hDlg) DestroyWindow(m_hDlg);
FreeAllObjects(); ReleaseInterface(m_pIPropertyPageSite); return; }
/*
* CSysmonPropPage::QueryInterface * CSysmonPropPage::AddRef * CSysmonPropPage::Release */
STDMETHODIMP CSysmonPropPage::QueryInterface(REFIID riid, PPVOID ppv) { HRESULT hr = S_OK;
try { *ppv=NULL;
if (IID_IUnknown==riid || IID_IPropertyPage==riid) { *ppv=this; AddRef(); } else { hr = E_NOINTERFACE; } } catch (...) { hr = E_POINTER; }
return hr; }
STDMETHODIMP_(ULONG) CSysmonPropPage::AddRef(void) { return ++m_cRef; }
STDMETHODIMP_(ULONG) CSysmonPropPage::Release(void) { if (0 != --m_cRef) return m_cRef;
InterlockedDecrement(&g_cObj); delete this; return 0; }
/*
* CSysmonPropPage::Init * * Purpose: * Performs initialization operations that might fail. * * Parameters: * None * * Return Value: * BOOL TRUE if initialization successful, FALSE * otherwise. */
BOOL CSysmonPropPage::Init(void) { //Nothing to do
return TRUE; }
/*
* CSysmonPropPage::FreeAllObjects * * Purpose: * Releases all the objects from IPropertyPage::SetObjects * * Parameters: * None */
void CSysmonPropPage::FreeAllObjects(void) { UINT i;
if (NULL==m_ppISysmon) return;
for (i=0; i < m_cObjects; i++) ReleaseInterface(m_ppISysmon[i]);
delete [] m_ppISysmon; m_ppISysmon =NULL; m_cObjects = 0; }
/*
* CSysmonPropPage::SetChange * * Purpose: * Set the page dirty flag to indicate a change * If page site is active, send status change to it. * * Parameters: * None */
void CSysmonPropPage::SetChange(void) { if (m_fActive) { m_fDirty=TRUE;
if (NULL != m_pIPropertyPageSite) { m_pIPropertyPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY); } } }
/*
* CSysmonPropPage::SetPageSite * * Purpose: * Provides the property page with the IPropertyPageSite * that contains it. SetPageSite(NULL) will be called as * part of the close sequence. * * Parameters: * pPageSite LPPROPERTYPAGESITE pointer to the site. */
STDMETHODIMP CSysmonPropPage::SetPageSite( LPPROPERTYPAGESITE pPageSite ) { HRESULT hr = S_OK;
if (NULL==pPageSite) ReleaseInterface(m_pIPropertyPageSite) else { HWND hDlg; RECT rc; LCID lcid;
try { m_pIPropertyPageSite=pPageSite; m_pIPropertyPageSite->AddRef();
if (SUCCEEDED(m_pIPropertyPageSite->GetLocaleID(&lcid))) m_lcid=lcid;
/*
* Load the dialog and determine the size it will be to * return through GetPageSize. We just create the dialog * here and destroy it again to retrieve the size, * leaving Activate to create it for real. */
hDlg=CreateDialogParam(g_hInstance, MAKEINTRESOURCE(m_uIDDialog), GetDesktopWindow(), SysmonPropPageProc, 0L);
//
// If creation fails, use default values set in constructor
// and return success status.
if (NULL!=hDlg) { GetWindowRect(hDlg, &rc); m_cx=rc.right-rc.left; m_cy=rc.bottom-rc.top; DestroyWindow(hDlg); } } catch (...) { hr = E_POINTER; } }
return hr; }
/*
* CSysmonPropPage::Activate * * Purpose: * Instructs the property page to create a window in which to * display its contents, using the given parent window and * rectangle. The window should be initially visible. * * Parameters: * hWndParent HWND of the parent window. * prc LPCRECT of the rectangle to use. * fModal BOOL indicating whether the frame is modal. */
STDMETHODIMP CSysmonPropPage::Activate( HWND hWndParent, LPCRECT prc, BOOL /* fModal */ ) { if (NULL!=m_hDlg) return (E_UNEXPECTED);
m_hDlg=CreateDialogParam(g_hInstance, MAKEINTRESOURCE(m_uIDDialog), hWndParent, SysmonPropPageProc, (LPARAM)this);
if (NULL==m_hDlg) { //
// Return E_OUTOFMEMORY because caller of Activate might not
// handle HRESULT_FROM_WIN32(GetLastError());
//
return E_OUTOFMEMORY; }
if (!InitControls()) { return E_OUTOFMEMORY; }
if (!GetProperties()) { return E_OUTOFMEMORY; }
//
//Move the page into position and show it.
//
try { SetWindowPos(m_hDlg, NULL, prc->left, prc->top, 0, 0, SWP_NOSIZE ); } catch (...) { return E_POINTER; }
m_fActive = TRUE; return NOERROR; }
/*
* CSysmonPropPage::Deactivate * * Purpose: * Instructs the property page to destroy its window that was * created in Activate. * * Parameters: * None */
STDMETHODIMP CSysmonPropPage::Deactivate(void) { if (NULL==m_hDlg) return (E_UNEXPECTED);
DeinitControls();
DestroyWindow(m_hDlg); m_hDlg=NULL; m_fActive = FALSE; return NOERROR; }
/*
* CSysmonPropPage::GetPageInfo * * Purpose: * Fills a PROPPAGEINFO structure describing the page's size, * contents, and help information. * * Parameters: * pPageInfo LPPROPPAGEINFO to the structure to fill. */
STDMETHODIMP CSysmonPropPage::GetPageInfo( LPPROPPAGEINFO pPageInfo ) { IMalloc * pIMalloc; LPWSTR pTitle = NULL; ULONG ulTitleLen = 0; LPWSTR pBuf = NULL;
pTitle = ResourceString(m_uIDTitle);
if (pTitle) { ulTitleLen = wcslen(pTitle) + 1;
if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc))) { return (E_FAIL); }
pBuf = (LPWSTR)pIMalloc->Alloc(ulTitleLen * sizeof(WCHAR));
if (NULL != pBuf) { //
// We already reserved an extra position for the null character
//
StringCchCopy(pBuf, ulTitleLen, pTitle); }
pIMalloc->Release(); }
try { pPageInfo->size.cx = m_cx; pPageInfo->size.cy = m_cy; pPageInfo->pszDocString = NULL; pPageInfo->pszHelpFile = NULL; pPageInfo->dwHelpContext= 0; pPageInfo->pszTitle = pBuf; } catch (...) { return E_POINTER; }
return S_OK; }
/*
* CSysmonPropPage::SetObjects * * Purpose: * Identifies the objects that are being affected by this property * page (and all other pages in the frame). These are the object * to which to send new property values in the Apply member. * * Parameters: * cObjects ULONG number of objects * ppUnk IUnknown ** to the array of objects being * passed to the page. */
STDMETHODIMP CSysmonPropPage::SetObjects( IN ULONG cObjects, IN IUnknown **ppUnk ) { HRESULT hr = S_OK;
FreeAllObjects();
if (0 != cObjects) { UINT i;
m_ppISysmon = new ISystemMonitor * [(UINT)cObjects]; if (m_ppISysmon == NULL) return E_OUTOFMEMORY;
try { for (i=0; i < cObjects; i++) { hr=ppUnk[i]->QueryInterface(IID_ISystemMonitor, (void **)&m_ppISysmon[i]);
if (FAILED(hr)) { break; } } } catch (...) { hr = E_POINTER; } }
if ( FAILED ( hr ) && NULL != m_ppISysmon ) { //
// Ref count never incremented, so delete the array.
//
delete [] m_ppISysmon; m_ppISysmon = NULL; }
if ( SUCCEEDED ( hr ) ) { m_cObjects=cObjects; }
return hr; }
/*
* CSysmonPropPage::Show * * Purpose: * Instructs the page to show or hide its window created in * Activate. * * Parameters: * nCmdShow UINT to pass to ShowWindow. */
STDMETHODIMP CSysmonPropPage::Show(UINT nCmdShow) { if (NULL==m_hDlg) (E_UNEXPECTED);
ShowWindow(m_hDlg, nCmdShow);
// If showing page
if (SW_SHOWNORMAL==nCmdShow || SW_SHOW==nCmdShow) {
// Take the focus
// (Have to delay so it isn't taken back)
PostMessage(m_hDlg,WM_SETPAGEFOCUS,0,0); } return NOERROR; }
/*
* CSysmonPropPage::Move * * Purpose: * Instructs the property page to change its position. * * Parameters: * prc LPCRECT containing the new position. */
STDMETHODIMP CSysmonPropPage::Move( LPCRECT prc ) { HRESULT hr = S_OK;
try { SetWindowPos(m_hDlg, NULL, prc->left, prc->top, 0, 0, SWP_NOSIZE ); } catch (...) { hr = E_POINTER; }
return hr; }
/*
* CSysmonPropPage::IsPageDirty * * Purpose: * Asks the page if anything's changed in it, that is, if the * property values in the page are out of sync with the objects * under consideration. * * Parameters: * None * * Return Value: * HRESULT NOERROR if dirty, S_FALSE if not. */
STDMETHODIMP CSysmonPropPage::IsPageDirty(void) { return (m_fDirty ? S_OK : S_FALSE); }
/*
* CSysmonPropPage::Apply * * Purpose: * Instructs the page to send changes in its page to whatever * objects it knows about through SetObjects. This is the only * time the page should change the objects' properties, and not * when the value is changed on the page. * * Parameters: * None */
STDMETHODIMP CSysmonPropPage::Apply(void) { HRESULT hr = NOERROR;
if ( 0 != m_cObjects ) {
// Kill the focus in case a text field has it. This will trigger
// the entry processing code.
SetFocus(NULL);
{ CWaitCursor cursorWait;
if (SetProperties()) { m_fDirty = FALSE; } else { hr = E_FAIL; } } } return hr; }
/*
* CSysmonPropPage::Help * * Purpose: * Invokes help for this property page when the user presses * the Help button. If you return NULLs for the help file * in GetPageInfo, the button will be grayed. Otherwise the * page can perform its own help here. * * Parameters: * pszHelpDir LPCOLESTR identifying the default location of * the help information * * Return Value: * HRESULT NOERROR to tell the frame that we've done our * own help. Returning an error code or S_FALSE * causes the frame to use any help information * in PROPPAGEINFO. */
STDMETHODIMP CSysmonPropPage::Help(LPCOLESTR /* pszHelpDir */ ) { /*
* We can either provide help ourselves, or rely on the * information in PROPPAGEINFO. */ return (S_FALSE); }
/*
* CSysmonPropPage::TranslateAccelerator * * Purpose: * Provides the page with the messages that occur in the frame. * This gives the page to do whatever it wants with the message, * such as handle keyboard mnemonics. * * Parameters: * pMsg LPMSG containing the keyboard message. */
STDMETHODIMP CSysmonPropPage::TranslateAccelerator(LPMSG lpMsg) { BOOL fTakeIt = TRUE; BOOL fHandled = FALSE; HRESULT hr;
HWND hwnd; if (lpMsg == NULL) return E_POINTER; // If TAB key
if (lpMsg->message == WM_KEYDOWN ) { if ( lpMsg->wParam == VK_TAB && GetKeyState(VK_CONTROL) >= 0) {
UINT uDir = GetKeyState(VK_SHIFT) >= 0 ? GW_HWNDNEXT : GW_HWNDPREV;
hwnd = GetFocus();
if (IsChild(m_hDlg, hwnd)) {
// Get top level child for controls with children, like combo.
while (GetParent(hwnd) != m_hDlg) hwnd = GetParent(hwnd);
// If this control is the last enabled tab stop, don't steal the TAB key
do { hwnd = GetWindow(hwnd, uDir); if ( NULL == hwnd ) { fTakeIt = FALSE; break; } } while ((GetWindowLong(hwnd, GWL_STYLE) & (WS_DISABLED | WS_TABSTOP)) != WS_TABSTOP); } }
/*
fTakeIt is already TRUE. // else if Arrow key
else if ( lpMsg->message == WM_KEYDOWN && ( lpMsg->wParam == VK_LEFT || lpMsg->wParam == VK_UP || lpMsg->wParam == VK_RIGHT || lpMsg->wParam == VK_DOWN ) ) { fTakeIt = TRUE; } */
// else if Return or Escape key
else if ( lpMsg->wParam == VK_RETURN || lpMsg->wParam == VK_ESCAPE ) {
fTakeIt = (lpMsg->wParam == VK_RETURN);
if ( fTakeIt ) {
hwnd = GetFocus();
if ( NULL == hwnd ) { fTakeIt = FALSE; } else { fTakeIt = IsChild(m_hDlg, hwnd); if ( fTakeIt ) { fTakeIt = (BOOL) SendMessage(hwnd, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON; } } } } } else if ( ( WM_KEYUP == lpMsg->message ) ) { fTakeIt = FALSE; }
// if we should process the key
if (fTakeIt) {
// if the target is not one of our controls, change it so IsDialogMessage works
if (!IsChild(m_hDlg, lpMsg->hwnd)) { hwnd = lpMsg->hwnd; lpMsg->hwnd = GetWindow(m_hDlg, GW_CHILD); fHandled = IsDialogMessage(m_hDlg, lpMsg); lpMsg->hwnd = hwnd; } else { fHandled = IsDialogMessage(m_hDlg, lpMsg); } }
if (fHandled){ return S_OK; } else{ hr = m_pIPropertyPageSite->TranslateAccelerator(lpMsg); }
return hr; }
/*
* CSysmonPropPage::EditProperty * * Purpose: * Sets focus to the control corresponding to the supplied DISPID. * * Parameters: * dispID DISPID of the property */
STDMETHODIMP CSysmonPropPage::EditProperty(DISPID dispID) { HRESULT hr;
hr = EditPropertyImpl ( dispID );
if ( SUCCEEDED(hr)) { SetFocus ( GetDlgItem ( m_hDlg, m_dwEditControl ) ); m_dwEditControl = 0; } return hr; }
/*
* CSysmonPropPage::WndProc * * Purpose: * This is a default message processor that can be overriden by * a subclass to provide special message handling. * * Parameters: * pMsg LPMSG containing the keyboard message. */ BOOL CSysmonPropPage::WndProc ( UINT, // uMsg,
WPARAM, // wParam,
LPARAM // lParam
) { return FALSE; }
/*
* SysmonPropPageProc * * Purpose: * Dialog procedure for the Sysmon Property Page. */ INT_PTR APIENTRY CALLBACK SysmonPropPageProc( HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam ) { static WCHAR szObj[] = L"Object";
PCSysmonPropPage pObj = NULL; PMEASUREITEMSTRUCT pMI; HWND hwndTabCtrl; HWND hwndPropSheet; INT iCtrlID; WCHAR pszHelpFilePath[MAX_PATH * 2]; LPHELPINFO pInfo; UINT nLen; BOOL bReturn = FALSE;
if ( NULL != hDlg ) { pObj = (PCSysmonPropPage)GetProp(hDlg, szObj); }
switch (iMsg) { case WM_INITDIALOG:
pObj=(PCSysmonPropPage)lParam;
if ( NULL != pObj && NULL != hDlg ) { SetProp(hDlg, szObj, (HANDLE)lParam); hwndTabCtrl = ::GetParent(hDlg); hwndPropSheet = ::GetParent(hwndTabCtrl); SetWindowLongPtr(hwndPropSheet, GWL_EXSTYLE, GetWindowLongPtr(hwndPropSheet,GWL_EXSTYLE)|WS_EX_CONTEXTHELP); } bReturn = TRUE; break;
case WM_DESTROY: if ( NULL != hDlg ) { RemoveProp(hDlg, szObj); } bReturn = TRUE; break;
case WM_MEASUREITEM: pMI = (PMEASUREITEMSTRUCT)lParam; if ( NULL != pMI ) { pMI->itemWidth = 0 ; pMI->itemHeight = 16; } bReturn = TRUE; break; case WM_DRAWITEM: if ( NULL != pObj ) { pObj->DrawItem ((PDRAWITEMSTRUCT) lParam) ; } bReturn = TRUE; break;
case WM_COMMAND: if ( NULL != pObj ) { pObj->DialogItemChange(LOWORD(wParam), HIWORD(wParam)); } bReturn = FALSE; break; case WM_SETPAGEFOCUS: if ( NULL != hDlg ) { SetFocus(hDlg); bReturn = TRUE; } break;
case WM_CONTEXTMENU:
if ( NULL != (HWND) wParam ) { iCtrlID = GetDlgCtrlID ( (HWND) wParam );
if ( 0 != iCtrlID ) {
nLen = ::GetWindowsDirectory(pszHelpFilePath, 2*MAX_PATH); if ( 0 < nLen ) { StringCchCat(pszHelpFilePath, 2* MAX_PATH, L"\\help\\sysmon.hlp" );
bReturn = WinHelp( (HWND) wParam, pszHelpFilePath, HELP_CONTEXTMENU, (DWORD_PTR) aulControlIdToHelpIdMap); } } } // bReturn is FALSE by default
break;
case WM_HELP: if ( NULL != hDlg ) { pInfo = (LPHELPINFO)lParam;
if ( NULL != pInfo ) { // Only display help for known context IDs.
if ( 0 != pInfo->dwContextId ) {
nLen = ::GetWindowsDirectory(pszHelpFilePath, 2*MAX_PATH); if ( 0 < nLen ) { StringCchCat(pszHelpFilePath, 2* MAX_PATH, L"\\help\\sysmon.hlp" ); bReturn = WinHelp ( hDlg, pszHelpFilePath, HELP_CONTEXTPOPUP, pInfo->dwContextId ); } } } } // bReturn is FALSE by default
break;
default: if ( NULL != pObj ) { bReturn = pObj->WndProc(iMsg, wParam, lParam); } }
return bReturn; }
|