windows-nt/Source/XPSP1/NT/multimedia/directx/gamectrl/client/applock.cpp
2020-09-26 16:20:57 +08:00

894 lines
25 KiB
C++

/*
File: AppLock.cpp
Project:
Author: ScottLe
Date: 1/31/00
Comments:
AppMan application locking (pinning) Tab in Game Control Panel.
Copyright (c) 1999, 2000 Microsoft Corporation
*/
// This is necessary LVS_EX_INFOTIP
#if (_WIN32_IE < 0x400)
#undef _WIN32_IE
#define _WIN32_IE 0x400
#if 0
typedef struct tagNMITEMACTIVATE{
NMHDR hdr;
int iItem;
int iSubItem;
UINT uNewState;
UINT uOldState;
UINT uChanged;
POINT ptAction;
LPARAM lParam;
UINT uKeyFlags;
} NMITEMACTIVATE, FAR *LPNMITEMACTIVATE;
#endif
#endif
#include <afxcmn.h>
#include <windowsx.h>
#include <cpl.h>
#include <winuser.h> // For RegisterDeviceNotification stuff!
#include <dbt.h> // for DBT_ defines!!!
#include <commctrl.h> // for listview
#include <tchar.h> // for TCHAR
#include <malloc.h> // for _alloca
#include "hsvrguid.h"
#include "cpanel.h"
#include "resource.h"
#include "joyarray.h"
#ifdef MAX_DEVICES // The control panel and the addman both define MAX_DEVICES, we'll use the AppMan supplied version
#undef MAX_DEVICES
#endif
#include <AppManAdmin.h>
#if _DEBUG
#define Assert(x) { if(!(x)) { DebugBreak(); }}
#else
#define Assert(x)
#endif
static HWND ghDlg;
static HWND hAppManCheckBox;
extern const DWORD gaHelpIDs[];
extern HINSTANCE ghInstance;
//
// GLOBALS
//
static BOOL g_ListPopulated = FALSE;
static int g_nm_click = -1;
static BOOL g_nm_click_state = FALSE;
static BOOL g_DlgInitialized = FALSE;
static BOOL g_ChkBoxUpdate = FALSE;
static GUID *g_lpsGUID = NULL;
extern IApplicationManagerAdmin *g_IAppManAdmin;
static struct {
BOOL isValid;
int iItem;
BOOL isClicked;
} g_ItemChanged;
// constants
const short NO_ITEM = -1;
static short iItem = NO_ITEM; // index of selected item
// Forwards
//
// local forwards
//
static BOOL OnInitDialog(HWND hDlg, HWND hWnd, LPARAM lParam);
static void OnCommand(HWND hDlg, int id, HWND hWndCtl, UINT code);
static BOOL OnNotify(HWND hDlg, WPARAM idFrom, LPARAM lParam);
static void OnScroll(HWND hDlg, WPARAM wParam);
static void OnListCtrl_Select(HWND hDlg);
static void OnListCtrl_DblClick(HWND hDlg);
static void OnListCtrl_UpdateFromCheckBoxes( HWND hDlg );
static void OnAdvHelp (LPARAM);
//static void OnContextMenu (WPARAM wParam, LPARAM lParam);
static void OnListviewContextMenu (HWND hWnd, LPARAM lParam );
// util fcns
static int MyInsertItem( HWND hCtrl, LPTSTR lpszBuff, int iItem ); // replaced from cpanel.cpp
static void PostDlgItemEnableWindow( HWND hDlg, USHORT nItem, BOOL bEnabled );
static void EnableDiskManageControls( HWND hDlg, BOOL bEnable );
static void EnableScrollBarAndText( HWND hDlg, BOOL bEnable );
//static void EnableAllControls( HWND hDlg, BOOL bEnable );
DWORD GetCurrentDeviceFromList( HWND hDlg, BYTE *nItem = NULL );
static void ConfigureListControl( HWND hDlg );
static void PopulateListControl( HWND hDlg, BYTE nItem );
void UpdateCurrentDeviceFromScrollBar( HWND hDlg, DWORD newPos );
//void UpdateListAndScrollBar( HWND hDlg, BOOL bJustScrollBar = FALSE );
// From AppMan.cpp
extern HRESULT AppManShutdown();
extern HRESULT AppManInit();
extern BOOL AppManInitialized();
//
// from cpanel.cpp
//
extern void SetItemText( HWND hCtrl, BYTE nItem, BYTE nSubItem, LPTSTR lpStr);
extern void InsertColumn(HWND hCtrl, BYTE nColumn, USHORT nStrID, USHORT nWidth);
extern BOOL SetItemData( HWND hCtrl, BYTE nItem, DWORD dwFlag );
extern DWORD GetItemData(HWND hCtrl, BYTE nItem );
extern void SetListCtrlItemFocus ( HWND hCtrl, BYTE nItem );
///////////////////////////////////////////////////////////////////////////////
// FUNCTION: AppManLockProc(HWND hDlg, ULONG uMsg, WPARAM wParam, LPARAM lParam)
//
// PARAMETERS: hDlg -
// uMsg -
// wParam -
// lParam -
//
// PURPOSE: Main callback function for "Appman" sheet
///////////////////////////////////////////////////////////////////////////////
BOOL WINAPI AppManLockProc(HWND hDlg, ULONG uMsg, WPARAM wParam, LPARAM lParam)
{
switch( uMsg )
{
case WM_ACTIVATEAPP:
if( wParam ) {
HWND hListCtrl = NULL;
hListCtrl = GetDlgItem((HWND) wParam, IDC_APPMAN_DRIVE_LIST);
SetListCtrlItemFocus(hListCtrl, (BYTE)iItem);
}
break;
case WM_DEVICECHANGE:
switch( (UINT)wParam )
{
case DBT_DEVICEARRIVAL:
// case DBT_DEVICEREMOVECOMPLETE:
break;
}
break;
case WM_LBUTTONDOWN:
// Click Drag service for PropSheets!
//PostMessage(GetParent(hDlg), WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lParam);
break;
case WM_INITDIALOG:
if( !HANDLE_WM_INITDIALOG(hDlg, wParam, lParam, OnInitDialog) )
{
// Fix #108983 NT, Remove Flash on Error condition.
SetWindowPos(::GetParent(hDlg), HWND_BOTTOM, 0, 0, 0, 0, SWP_HIDEWINDOW);
DestroyWindow(hDlg);
}
return(TRUE);
case WM_COMMAND:
HANDLE_WM_COMMAND(hDlg, wParam, lParam, OnCommand);
return(TRUE);
case WM_DESTROY:
//return(HANDLE_WM_DESTROY(hDlg, wParam, lParam, OnDestroy));
//jchauvin 04/10/2000 Fix Build break in Win64
free( g_lpsGUID );
g_lpsGUID = NULL;
return(TRUE);
case WM_NOTIFY:
return OnNotify(hDlg, wParam, lParam);
case WM_HELP:
// OnAdvHelp(lParam);
return(TRUE);
case WM_CONTEXTMENU:
// OnContextMenu(wParam, lParam);
return(TRUE);
default:
break;
}
return(0);
}
///////////////////////////////////////////////////////////////////////////////
// FUNCTION: OnInitDialog(HWND hDlg, HWND hWnd, LPARAM lParam)
//
// PARAMETERS: hDlg -
// hWnd -
// lParam -
//
// PURPOSE: WM_INITDIALOG message handler
///////////////////////////////////////////////////////////////////////////////
BOOL OnInitDialog(HWND hDlg, HWND hWnd, LPARAM lParam)
{
HRESULT hr = S_OK;
hr = AppManInit();
//
// init globals
//
ZeroMemory( &g_ItemChanged, sizeof(g_ItemChanged));
g_DlgInitialized = FALSE;
if( FAILED(hr) ) {
//
// Disable everything
//
// EnableAllControls(hDlg, FALSE);
//
// popup saying: hey you need appman installed ?
//
} else {
ghDlg = hDlg;
//
// Set defaults
//
//
// Configure the List control, and then fill it in
//
ConfigureListControl( hDlg );
PopulateListControl( hDlg, 0 );
g_DlgInitialized = TRUE;
}
return(TRUE);
}
///////////////////////////////////////////////////////////////////////////////
// FUNCTION: OnCommand(HWND hDlg, int id, HWND hWndCtl, UINT code)
//
// PARAMETERS: hDlg -
// id -
// hWndCtl -
// code -
//
// PURPOSE: WM_COMMAND message handler
///////////////////////////////////////////////////////////////////////////////
void OnCommand(HWND hDlg, int id, HWND hWndCtl, UINT code)
{
HRESULT hr = S_OK;
#if 0
switch( id )
{
case IDS_WHATSTHIS:
{
// point to help file
LPTSTR pszHelpFileName = new TCHAR[STR_LEN_32];
ASSERT (pszHelpFileName);
if( LoadString(ghInstance, IDS_HELPFILENAME, pszHelpFileName, STR_LEN_32) )
WinHelp((HWND)hDlg, pszHelpFileName, HELP_WM_HELP, (ULONG_PTR)gaHelpIDs);
#ifdef _DEBUG
else OutputDebugString(TEXT("JOY.CPL: AppMan.cpp: OnCommand: LoadString Failed to find IDS_HELPFILENAME!\n"));
#endif // _DEBUG
if( pszHelpFileName )
delete[] (pszHelpFileName);
}
break;
/*
case IDC_APPMAN_MANAGE_DISK:
{
BOOL isChecked = (IsDlgButtonChecked(hDlg, id)) ? TRUE : FALSE;
EnableDiskManageControls( hDlg, !isChecked );
}
break;
*/
default:
break;
}
#endif
}
////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION: OnNotify(HWND hDlg, WPARAM idFrom, NMHDR* pnmhdr)
//
// PARAMETERS: hDlg -
// idFrom - ID of control sending WM_NOTIFY message
// pnmhdr -
//
// PURPOSE: WM_NOTIFY message handler
////////////////////////////////////////////////////////////////////////////////
static DWORD ct=0L;
BOOL OnNotify(HWND hDlg, WPARAM idFrom, LPARAM lParam)
{
NMLISTVIEW *pnmv = NULL;
LPNMHDR pnmhdr = (LPNMHDR)lParam;
switch (pnmhdr->code)
{
// 4/13/2000(RichGr): Repopulate the List Control if we reacquire the focus.
// This keeps the data in sync with installs and uninstalls.
case NM_SETFOCUS:
{
PopulateListControl(hDlg, 0);
break;
}
case LVN_ITEMCHANGED:
pnmv = (LPNMLISTVIEW) lParam;
if( idFrom == IDC_APPMAN_PIN_LIST )
{
// this is called if a new item has been selected
// or if the user clicked on the checkbox, changing state
#ifdef _DEBUG
{
TCHAR tstring[256];
NMITEMACTIVATE *pitemact = (LPNMITEMACTIVATE)lParam;
_stprintf(tstring, TEXT("JOY.CPL: AppLock.cpp: OnNotify: LVN_ITEMCHANGED, ct=%ld,idFrom=%lx, item=%lx uChanged=%lx uNewState=%lx uOldState=%lx lParam=%lx\n"),
++ct,idFrom,pitemact->iItem,pitemact->uChanged,pitemact->uNewState,pitemact->uOldState,pitemact->lParam);
OutputDebugString(tstring);
}
#endif // _DEBUG
if ( AppManInitialized() &&
g_DlgInitialized &&
(pnmv->uNewState & LVIS_SELECTED ||
pnmv->uNewState == 0x1000 || pnmv->uNewState == 0x2000) &&
// TODO: Find definitions for x1000 and x2000 (check box state change in a list view control)
g_ChkBoxUpdate )
{
NMITEMACTIVATE *ll = (LPNMITEMACTIVATE)lParam;
HWND hLC = GetDlgItem(hDlg, IDC_APPMAN_PIN_LIST);
g_ItemChanged.isValid = TRUE;
g_ItemChanged.iItem = ll->iItem;
g_ItemChanged.isClicked = FALSE;
//
// this flag is VERY important for consistent state changes
// and eliminating race conditions
//
g_ChkBoxUpdate = FALSE;
OnListCtrl_UpdateFromCheckBoxes( hDlg );
g_ChkBoxUpdate = TRUE;
g_ItemChanged.isValid = FALSE;
g_ItemChanged.iItem = ll->iItem;
OnListCtrl_Select( hDlg );
}
return TRUE;
break;
} // if
} // switch
return(0);
}
void OnListCtrl_UpdateFromCheckBoxes( HWND hDlg )
{
#if 1
HRESULT hResult;
BOOL bIsAppManPinned = FALSE;
BOOL bDoToggle = FALSE;
BYTE nItem = 0;
GUID *pGuid = NULL;
IApplicationManager * lpApplicationManager;
IApplicationEntry * lpApplicationEntry;
DWORD dwIndex;
//
// go through each item, check the box & set pinning
//
HWND hLC = GetDlgItem(hDlg, IDC_APPMAN_PIN_LIST);
if( !hLC ) return;
int iItem = -1;
//while( (iItem = ListView_GetNextItem( hLC, iItem, LVNI_ALL )) >= 0 )
if( g_ItemChanged.isValid )
{
//
// very important: tell the system that this information is no longer
// valid. Hence we won't recurse mysteriously or unpredictably.
//
g_ItemChanged.isValid = FALSE;
iItem = g_ItemChanged.iItem;
BOOL bIsCheckBoxPinned = !(ListView_GetCheckState( hLC, iItem )); // Check box has the new state NOW
// Set the pin state using the GUID to identify the app
//JWC 4/10/2000 Added to fix Win64 Build problem
dwIndex = (DWORD) GetItemData(hLC, (BYTE)iItem );
pGuid = (GUID *) ((ULONG_PTR)g_lpsGUID + (ULONG_PTR)dwIndex*sizeof(GUID));
// Find out what the pin state is in AppMan
// Get an Application Manager interface
hResult = CoCreateInstance(CLSID_ApplicationManager, NULL, CLSCTX_INPROC_SERVER, IID_ApplicationManager, (LPVOID *) &lpApplicationManager);
if (SUCCEEDED(hResult))
{
// Get an application entry object.
hResult = lpApplicationManager->CreateApplicationEntry(&lpApplicationEntry);
if (SUCCEEDED(hResult))
{
// Set the app's GUID
hResult = lpApplicationEntry->SetProperty(APP_PROPERTY_GUID, pGuid, sizeof(GUID));
if (SUCCEEDED(hResult))
{
// Populate the app info structure
hResult = lpApplicationManager->GetApplicationInfo(lpApplicationEntry);
if (SUCCEEDED(hResult))
{
// Get the current PIN state of the app
hResult = lpApplicationEntry->GetProperty(APP_PROPERTY_PIN, &bIsAppManPinned, sizeof(bIsAppManPinned));
if (SUCCEEDED(hResult))
{
// bIsAppManPinned is the state appman has for the application.
// bIsCheckBoxPinned is the check box state (checked = true = not pinned)
// Since AppMan's pinning state for an app is a toggle we could get out of sync
// due to redraw or timing issues with the list view control -- so,
// we need to make sure that the check box's state is insync with AppMan.
// When in doubt, force it to the displayed state of the check box.
// Truth table:
//
// AppManPinned CheckBoxPinned (T=not checked) DoToggle Reason
// T T No Same State Already (sync error!)
// F F No Same State Already (sync error!)
// T F Yes New State Selected
// F T Yes New State Selected
//
if (bIsAppManPinned != bIsCheckBoxPinned)
bDoToggle = TRUE;
else
{
// ERR: BUG BUG: The control panel and appman are out of sync, this is an error.
bDoToggle = FALSE;
#ifdef _DEBUG
OutputDebugString(TEXT("JOY.CPL: AppLock.cpp: Pinning Update, AppMan and Check box states are out of sync!\n"));
#endif // _DEBUG
}
if (bDoToggle && pGuid && g_IAppManAdmin) // Toggle the pin state
hResult = g_IAppManAdmin->DoApplicationAction(ACTION_APP_PIN, pGuid, 0, (LPVOID) NULL, sizeof(DWORD));
// ERR: Handle error conditions
}
}
}
lpApplicationEntry->Release();
}
lpApplicationManager->Release();
}
}
g_ChkBoxUpdate = TRUE;
#endif
}
void OnListCtrl_Select(HWND hDlg)
{
//
// set focus on that item
//
HWND hLC = GetDlgItem(hDlg, IDC_APPMAN_PIN_LIST);
SetListCtrlItemFocus( hLC, (BYTE)g_ItemChanged.iItem );
}
int MyInsertItem( HWND hCtrl, LPTSTR lpszBuff, int iItem )
{
LPLVITEM plvItem = (LPLVITEM)_alloca(sizeof(LVITEM));
ASSERT (plvItem);
ZeroMemory( plvItem, sizeof( LVITEM ) );
plvItem->mask = LVIF_TEXT;
plvItem->pszText = lpszBuff;
plvItem->cchTextMax = lstrlen(lpszBuff);
plvItem->iItem = iItem;
return ListView_InsertItem(hCtrl, (const LPLVITEM)plvItem);
}
#define APPMAN_ADV_PIN_CHECKBOX 0
#define APPMAN_ADV_PIN_TITLENAME 1
#define IDS_APPMANPIN_CHECKBOX 40043
#define IDS_APPMANPIN_TITLENAME 40044
void ConfigureListControl( HWND hDlg )
{
#if 1
HWND hLC;
hLC = GetDlgItem(hDlg, IDC_APPMAN_PIN_LIST);
::SendMessage( hLC , LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
LVS_EX_FULLROWSELECT
| LVS_EX_CHECKBOXES
| LVS_EX_HEADERDRAGDROP
// LVS_EX_TWOCLICKACTIVATE // LVN_ITEMACTIVATE (WM_NOTIFY)
);
RECT rc;
GetClientRect(hLC, &rc);
DWORD w = rc.right-rc.left;
DWORD w1 = w / 3; // 1/3 of width
DWORD w2 = w - w1; // 2/3 of the width
InsertColumn(hLC, APPMAN_ADV_PIN_CHECKBOX, IDS_APPMANPIN_CHECKBOX, (USHORT)(w1));
InsertColumn(hLC, APPMAN_ADV_PIN_TITLENAME,IDS_APPMANPIN_TITLENAME, (USHORT)(w2));
#endif
}
//STDMETHODIMP CApplicationManagerAdmin::DoApplicationAction(const DWORD dwAction, const GUID * lpGuid, LPVOID lpData, const DWORD dwDataLen)
//STDMETHODIMP CApplicationManagerAdmin::EnumApplications(const DWORD dwApplicationIndex, IApplicationEntry * lpObject)
// populates from appman state
void PopulateListControl( HWND hDlg, BYTE nItem )
{
#if 1
HRESULT hr = S_OK;
BOOL isExcluded = FALSE;
UCHAR listIndex = (UCHAR)0;
IApplicationManager *lpApplicationManager;
IApplicationEntry *lpApplicationEntry;
HRESULT hResult;
DWORD dwIndex = 0L;
TCHAR szString[MAX_PATH];
GUID sGuid;
g_ListPopulated = FALSE;
g_ChkBoxUpdate = FALSE;
Assert( AppManInitialized() );
HWND hLC = GetDlgItem(hDlg, IDC_APPMAN_PIN_LIST);
// Turn Redraw off here else it will flicker!
::SendMessage(hLC, WM_SETREDRAW, (WPARAM)FALSE, 0);
// Out with the old...
::SendMessage(hLC, LVM_DELETEALLITEMS, 0, 0);
//JWC 04/10/2000 Fixing build break in Win64 code
g_lpsGUID = (GUID *)malloc(sizeof(GUID));
if (g_lpsGUID == NULL)
{
//Cannot allocate memory
hResult = E_UNEXPECTED;
}
// Get an Application Manager interface
hResult = CoCreateInstance(CLSID_ApplicationManager, NULL, CLSCTX_INPROC_SERVER, IID_ApplicationManager, (LPVOID *) &lpApplicationManager);
if (SUCCEEDED(hResult) && g_IAppManAdmin)
{
// Get an application entry object. This will be populated during the Enumeration loop
hResult = lpApplicationManager->CreateApplicationEntry(&lpApplicationEntry);
if (SUCCEEDED(hResult))
{
// Enumerate all the applications AppMan knows about
dwIndex = 0;
while (SUCCEEDED(g_IAppManAdmin->EnumApplications(dwIndex, lpApplicationEntry)))
{
// For each app, get information about it (Pinning state, title, GUID etc) and put in the list
DWORD dwState = 0L;
// App must be in a good state
hResult = lpApplicationEntry->GetProperty(APP_PROPERTY_STATE, &dwState, sizeof(dwState));
dwState &= APP_STATE_MASK;
if (!SUCCEEDED(hResult) ||
dwState == APP_STATE_INSTALLING ||
dwState == APP_STATE_UNSTABLE)
{
dwIndex++;
continue; // Skip bad apps
}
else // Good app...
{
// Create the check box
int actualListIndex = MyInsertItem( hLC, _T(""), dwIndex );
// Get the app's GUID
hResult = lpApplicationEntry->GetProperty(APP_PROPERTY_GUID, &sGuid, sizeof(sGuid));
if (SUCCEEDED(hResult))
{
// Allocate a GUID
// ISSUE-2001/03/29-timgill Need error handling
//JWC 04/10/2000 Fixing problem with GUID for Win64
g_lpsGUID = (GUID *)realloc((void*)g_lpsGUID,(dwIndex+1)* sizeof(GUID));
*(GUID *)((ULONG_PTR)g_lpsGUID+((ULONG_PTR)(dwIndex)*sizeof(GUID)))= sGuid;
SetItemData(hLC, (BYTE)actualListIndex, dwIndex );
}
// Get Pin state
{
DWORD bPinned = FALSE;
hResult = lpApplicationEntry->GetProperty(APP_PROPERTY_PIN, &bPinned, sizeof(bPinned));
if (SUCCEEDED(hResult))
ListView_SetCheckState( hLC, actualListIndex, (BOOL)!bPinned ); // Checked=not pinned
}
// TODO: Company name and/or signature...?
// hResult = lpApplicationEntry->GetProperty(APP_PROPERTY_COMPANYNAME | APP_PROPERTY_STR_ANSI, &szString, sizeof(szString));
#ifdef _UNICODE
hResult = lpApplicationEntry->GetProperty(APP_PROPERTY_SIGNATURE | APP_PROPERTY_STR_UNICODE, &szString, sizeof(szString));
#else
hResult = lpApplicationEntry->GetProperty(APP_PROPERTY_SIGNATURE | APP_PROPERTY_STR_ANSI, &szString, sizeof(szString));
#endif
// Set the title name in the "title column"
if (SUCCEEDED(hResult))
SetItemText(hLC, (BYTE)actualListIndex, APPMAN_ADV_PIN_TITLENAME, szString);
}
dwIndex++;
}
}
lpApplicationEntry->Release();
}
lpApplicationManager->Release();
//
// set focus on that item
//
SetListCtrlItemFocus( hLC, nItem );
//
// Turn the redraw flag back on!
//
::SendMessage (hLC, WM_SETREDRAW, (WPARAM)TRUE, 0);
g_ListPopulated = TRUE;
g_ChkBoxUpdate = TRUE;
#endif
}
void EnableScrollBarAndText( HWND hDlg, BOOL bEnable )
{
#if 0
HWND hwnd;
// SCROLLBAR
//PostDlgItemEnableWindow( hDlg, IDC_APPMAN_SCROLLBAR, enableManageDiskSpace );
hwnd = GetDlgItem(hDlg, IDC_APPMAN_SCROLLBAR);
EnableWindow( hwnd, bEnable );
// TEXT
hwnd = GetDlgItem(hDlg, IDC_APPMAN_TEXT_PERCENT_DISK_USED);
EnableWindow( hwnd, bEnable );
#endif
}
///////////////////////////////////////////////////////////////////
// AppMan functions
///////////////////////////////////////////////////////////////////
#define RELEASE(p) { if((p)) { (p)->Release(); p = NULL; } }
#if 0
////////////////////////////////////////////////////////////////////////////////////////
// FUNCTION: OnAdvHelp ( LPARAM lParam )
//
// PARAMETERS: lParam - Pointer to HELPINFO struct
//
// PURPOSE: WM_HELP message handler
////////////////////////////////////////////////////////////////////////////////////////
void OnAdvHelp(LPARAM lParam)
{
ASSERT (lParam);
// point to help file
LPTSTR pszHelpFileName = new TCHAR[STR_LEN_32];
ASSERT (pszHelpFileName);
if( LoadString(ghInstance, IDS_HELPFILENAME, pszHelpFileName, STR_LEN_32) )
{
if( ((LPHELPINFO)lParam)->iContextType == HELPINFO_WINDOW )
WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, pszHelpFileName, HELP_WM_HELP, (ULONG_PTR)gaHelpIDs);
}
#ifdef _DEBUG
else OutputDebugString(TEXT("JOY.CPL: AppMan.cpp: OnAdvHelp: LoadString Failed to find IDS_HELPFILENAME!\n"));
#endif // _DEBUG
if( pszHelpFileName )
delete[] (pszHelpFileName);
}
////////////////////////////////////////////////////////////////////////////////////////
// FUNCTION: OnContextMenu ( WPARAM wParam )
//
// PARAMETERS: wParam - HWND of window under the pointer
//
// PURPOSE: Handle WM_RBUTTONDOWN over all client windows
// (except the list control... that's OnListviewContextMenu() job)
////////////////////////////////////////////////////////////////////////////////////////
void OnContextMenu(WPARAM wParam, LPARAM lParam)
{
// HWND hListCtrl = NULL
ASSERT (wParam);
#if 0
hListCtrl = GetDlgItem((HWND) wParam, IDC_APPMAN_DRIVE_LIST);
// If you are on the ListCtrl...
if( (HWND)wParam == hListCtrl )
{
SetFocus(hListCtrl);
// Don't attempt if nothing selected
if( iItem != NO_ITEM )
OnListviewContextMenu(hListCtrl,lParam);
} else
#endif
{
// point to help file
LPTSTR pszHelpFileName = new TCHAR[STR_LEN_32];
ASSERT (pszHelpFileName);
if( LoadString(ghInstance, IDS_HELPFILENAME, pszHelpFileName, STR_LEN_32) )
WinHelp((HWND)wParam, pszHelpFileName, HELP_CONTEXTMENU, (ULONG_PTR)gaHelpIDs);
#ifdef _DEBUG
else OutputDebugString(TEXT("JOY.CPL: appman.cpp: OnContextMenu: LoadString Failed to find IDS_HELPFILENAME!\n"));
#endif // _DEBUG
if( pszHelpFileName )
delete[] (pszHelpFileName);
}
}
///////////////////////////////////////////////////////////////////////////////
// FUNCTION: OnListviewContextMenu( void )
//
// PURPOSE: Handle Context menu in Listview
//
// RETURN: TRUE if successfull, FALSE otherwise
///////////////////////////////////////////////////////////////////////////////
static void OnListviewContextMenu( HWND hWnd, LPARAM lParam )
{
HMENU hPopupMenu = CreatePopupMenu();
HWND hListCtrl = NULL;
hListCtrl = GetDlgItem(hWnd, IDC_APPMAN_DRIVE_LIST);
ASSERT (hPopupMenu);
// unlike life, bRet defaults to bliss
BOOL bRet = TRUE;
LPTSTR pszText = new TCHAR[STR_LEN_32];
ASSERT (pszText);
// Don't display Rename/Change if on (none) entry
if( !(GetItemData(hListCtrl, (BYTE)iItem) & ID_NONE) )
{
if( TRUE ) // Borrowed code...
{
// add the "Change..." string
::SendDlgItemMessage(GetParent(hListCtrl), IDC_ADV_CHANGE, WM_GETTEXT, (WPARAM)STR_LEN_32, (LPARAM)(LPCTSTR)pszText);
bRet = AppendMenu(hPopupMenu, MF_ENABLED, IDC_ADV_CHANGE, pszText);
#ifdef _DEBUG
if( !bRet )
TRACE(TEXT("JOY.CPL: OnListviewCOntextMenu: AppendMenu Failed to insert %s\n"), pszText);
#endif //_DEBUG
// Add the Rename text
VERIFY(LoadString(ghInstance, IDS_RENAME, pszText, STR_LEN_32));
bRet = AppendMenu(hPopupMenu, MF_ENABLED, IDC_RENAME, pszText);
#ifdef _DEBUG
if( !bRet )
TRACE(TEXT("JOY.CPL: OnListviewCOntextMenu: AppendMenu Failed to insert %s\n"), pszText);
#endif //_DEBUG
// Add the SEPERATOR and "What's this?"
bRet = AppendMenu(hPopupMenu, MF_SEPARATOR, 0, 0);
#ifdef _DEBUG
if( !bRet )
TRACE(TEXT("JOY.CPL: OnListviewCOntextMenu: AppendMenu Failed to insert SEPERATOR!\n"));
#endif //_DEBUG
}
}
VERIFY(LoadString(ghInstance, IDS_WHATSTHIS, pszText, STR_LEN_32));
bRet = AppendMenu(hPopupMenu, MF_ENABLED, IDS_WHATSTHIS, pszText);
#ifdef _DEBUG
if( !bRet )
TRACE(TEXT("JOY.CPL: OnListviewCOntextMenu: AppendMenu Failed to insert %s\n"), pszText);
#endif //_DEBUG
if( pszText ) delete[] (pszText);
POINT pt;
// lParam is -1 if we got here via Shift+F10
if( lParam > 0 )
{
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
} else
{
// Centre the popup on the selected item!
// This get's a good X pos, but the y is the start of the control!
::SendMessage(hListCtrl, LVM_GETITEMPOSITION, iItem, (LPARAM)&pt);
RECT rc;
::GetClientRect(hListCtrl, &rc);
pt.x = rc.right>>1;
ClientToScreen(hListCtrl, &pt);
}
bRet = TrackPopupMenu (hPopupMenu, TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON, pt.x, pt.y, 0, ghDlg, NULL);
#ifdef _DEBUG
if( !bRet )
TRACE (TEXT("JOY.CPL: OnListviewContextMenu: TrackPopupMenu Failed!\n"));
#endif //_DEBUG
DestroyMenu (hPopupMenu);
}
#endif