windows-nt/Source/XPSP1/NT/ds/security/gina/policy/poledit/treectrl.c
2020-09-26 16:20:57 +08:00

347 lines
8.2 KiB
C

//*********************************************************************
//* Microsoft Windows **
//* Copyright(c) Microsoft Corp., 1993 **
//*********************************************************************
#include "admincfg.h"
HTREEITEM hItemPressed = NULL;
VOID ProcessMouseDown(HWND hDlg,HWND hwndTree);
VOID ProcessMouseUp(HWND hDlg,HWND hwndTree);
BOOL ProcessExpand(HWND hDlg,HWND hwndTree,TV_ITEM * ptvi,
BOOL fExpanding);
BOOL ProcessSelection(HWND hDlg,HWND hwndTree,NM_TREEVIEW * pntv);
VOID ProcessPolicyCheckbox(HWND hDlg,HWND hwndTree,HTREEITEM hItem,BOOL fHasSel);
UINT AdvanceCheckboxState(UINT uImage);
BOOL IsAncestorOfSelection(HWND hwndTree,HTREEITEM hParent);
BOOL IsSelectedItemChecked(HWND hwndTree);
BOOL ProcessCheckboxFromKeyboard(HWND hDlg,HWND hwndTree);
BOOL OnTreeNotify(HWND hDlg,HWND hwndTree,NM_TREEVIEW *pntv)
{
switch (pntv->hdr.code) {
case NM_CLICK:
ProcessMouseUp(hDlg,hwndTree);
return 0;
break;
case TVN_ITEMEXPANDING:
// if we're collapsing a branch that contains the current
// selection, validate its controls
if ( ((pntv->action & TVE_ACTIONMASK) == TVE_COLLAPSE)
&& IsSelectedItemChecked(hwndTree)
&& IsAncestorOfSelection(hwndTree,pntv->itemNew.hItem)
&& !ProcessSettingsControls(hDlg,PSC_VALIDATENOISY))
return TRUE; // invalid stuff in ctrls, don't allow collapse
return ProcessExpand(hDlg,hwndTree,&pntv->itemNew,
((pntv->action & TVE_ACTIONMASK) == TVE_EXPAND) );
break;
case TVN_SELCHANGING:
return ProcessSelection(hDlg,hwndTree,pntv);
break;
case TVN_KEYDOWN:
{
WORD wKey = ( (TV_KEYDOWN *) pntv)->wVKey;
if (wKey == VK_SPACE) {
return ProcessCheckboxFromKeyboard(hDlg,hwndTree);
}
return FALSE;
}
break;
}
return 0;
}
VOID ProcessMouseDown(HWND hDlg,HWND hwndTree)
{
TV_HITTESTINFO ht;
TV_ITEM tvi;
POLICYDLGINFO * pdi;
TABLEENTRY * pTableEntry;
if (!(pdi = (POLICYDLGINFO *) GetWindowLongPtr(hDlg,DWLP_USER)))
return;
GetCursorPos(&ht.pt);
ScreenToClient(hwndTree,&ht.pt);
if (TreeView_HitTest(hwndTree,&ht) && ht.flags & TVHT_ONITEMICON) {
tvi.mask = TVIF_HANDLE;
tvi.hItem = ht.hItem;
if (!TreeView_GetItem(hwndTree,&tvi)) return;
pTableEntry = (TABLEENTRY *) tvi.lParam;
if (!pTableEntry || pTableEntry->dwType != ETYPE_POLICY) return;
hItemPressed = tvi.hItem;
}
}
VOID ProcessMouseUp(HWND hDlg,HWND hwndTree)
{
BOOL fHasSel = TRUE;
if (hItemPressed) {
// if checkbox for item other than selected item is being changed,
// validate setting controls for current selection because selection
// will change.
if (hItemPressed != TreeView_GetSelection(hwndTree)) {
if (!ProcessSettingsControls(hDlg,PSC_NOVALIDATE)) {
hItemPressed = NULL;
return;
}
fHasSel = FALSE;
}
ProcessPolicyCheckbox(hDlg,hwndTree,hItemPressed,fHasSel);
hItemPressed = NULL;
}
}
BOOL ProcessCheckboxFromKeyboard(HWND hDlg,HWND hwndTree)
{
TV_ITEM tvi;
TABLEENTRY * pTableEntry;
if (!(tvi.hItem = TreeView_GetSelection(hwndTree)))
return FALSE;
tvi.mask = TVIF_PARAM;
if (!TreeView_GetItem(hwndTree,&tvi))
return FALSE;
pTableEntry = (TABLEENTRY *) tvi.lParam;
if (!pTableEntry || pTableEntry->dwType != ETYPE_POLICY)
return FALSE;
ProcessPolicyCheckbox(hDlg,hwndTree,tvi.hItem,TRUE);
return TRUE;
}
VOID ProcessMouseMove(HWND hwndDlg,HWND hwndTree)
{
if (!hItemPressed) return;
{
TV_HITTESTINFO ht;
GetCursorPos(&ht.pt);
ScreenToClient(hwndDlg,&ht.pt);
if (TreeView_HitTest(hwndTree,&ht) &&
((ht.flags & TVHT_ONITEMICON )
&& (ht.hItem == hItemPressed)) )
return;
hItemPressed=NULL;
}
}
VOID ProcessPolicyCheckbox(HWND hDlg,HWND hwndTree,HTREEITEM hItem,BOOL fHasSel)
{
TV_ITEM tvi;
BOOL fPrevEnabled;
POLICYDLGINFO * pdi;
if (!(pdi = (POLICYDLGINFO *) GetWindowLongPtr(hDlg,DWLP_USER)))
return;
tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
tvi.hItem = hItem;
if (!TreeView_GetItem(hwndTree,&tvi) || !tvi.lParam) return;
fPrevEnabled = (tvi.iImage == IMG_CHECKED);
tvi.iSelectedImage=tvi.iImage = AdvanceCheckboxState(tvi.iImage);
SetPolicyState(hDlg,(TABLEENTRY *) tvi.lParam,tvi.iImage);
tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
TreeView_SetItem(hwndTree,&tvi);
if (fHasSel && pdi->nControls) {
if (fPrevEnabled)
ProcessSettingsControls(hDlg,PSC_NOVALIDATE);
EnableSettingsControls( hDlg,(tvi.iImage == IMG_CHECKED) );
}
}
BOOL ProcessExpand(HWND hDlg,HWND hwndTree,TV_ITEM * ptvi,BOOL fExpanding)
{
DWORD dwType;
HTREEITEM hItem;
POLICYDLGINFO * pdi;
if (!(pdi = (POLICYDLGINFO *) GetWindowLongPtr(hDlg,DWLP_USER)) || !ptvi->lParam)
return 0;
dwType = ((TABLEENTRY *) ptvi->lParam)->dwType;
if (dwType == ETYPE_ROOT) {
// OK to expand (which happens right after root item is added),
// not OK to collapse
return !fExpanding;
}
if (dwType == ETYPE_POLICY) {
return 0;
}
ptvi->iSelectedImage=ptvi->iImage = GetImageIndex(dwType,fExpanding,TRUE);
ptvi->mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
TreeView_SetItem(hwndTree,ptvi);
// if collapsing, set all children's images to "collapsed"
if (!fExpanding && (hItem = TreeView_GetChild(hwndTree,ptvi->hItem))) {
TV_ITEM tvi;
do {
tvi.hItem = hItem;
tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
if (!TreeView_GetItem(hwndTree,&tvi)) return 0;
ProcessExpand(hDlg,hwndTree,&tvi,fExpanding);
hItem = TreeView_GetNextSibling(hwndTree,hItem);
} while (hItem);
}
return 0; // OK to proceed
}
UINT AdvanceCheckboxState(UINT uImage)
{
switch (uImage) {
case IMG_CHECKED:
return IMG_UNCHECKED;
break;
case IMG_UNCHECKED:
return (dwAppState & AS_POLICYFILE ? IMG_INDETERMINATE :
IMG_CHECKED);
break;
case IMG_INDETERMINATE:
return IMG_CHECKED;
break;
}
return IMG_UNCHECKED;
}
BOOL ProcessSelection(HWND hDlg,HWND hwndTree,NM_TREEVIEW * pntv)
{
TABLEENTRY * pTableEntry = (TABLEENTRY *) pntv->itemNew.lParam;
POLICY * pPolicy;
CHAR szText[MAXSTRLEN+SMALLBUF+1];
TV_ITEM tvi;
POLICYDLGINFO * pdi;
if (!(pdi = (POLICYDLGINFO *) GetWindowLongPtr(hDlg,DWLP_USER)) ||
!pTableEntry)
return FALSE;
tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
if (tvi.hItem = pntv->itemOld.hItem) {
if (TreeView_GetItem(hwndTree,&tvi) && tvi.iImage == IMG_CHECKED)
if (!ProcessSettingsControls(hDlg,PSC_VALIDATENOISY)) return TRUE;
}
FreeSettingsControls(hDlg);
tvi.hItem = pntv->itemNew.hItem;
if (!TreeView_GetItem(hwndTree,&tvi)) return FALSE;
if ( (pTableEntry->dwType==ETYPE_POLICY)) {
pPolicy = (POLICY *) pTableEntry;
if (pPolicy->pChild) {
BOOL fEnabled = (tvi.iImage == IMG_CHECKED);
wsprintf(szText,LoadSz(IDS_SETTINGSFOR,szSmallBuf,sizeof(szSmallBuf)),
(CHAR *) (GETNAMEPTR(pPolicy)));
SetDlgItemText(hDlg,IDD_TXSETTINGS,szText);
CreateSettingsControls(hDlg,(SETTINGS *) pPolicy->pChild,fEnabled);
EnableSettingsControls(hDlg,fEnabled);
} else {
SetDlgItemText(hDlg,IDD_TXSETTINGS,szNull);
}
} else {
SetDlgItemText(hDlg,IDD_TXSETTINGS,szNull);
}
return FALSE;
}
/*******************************************************************
NAME: IsAncestorOfSelection
SYNOPSIS: For specified tree control, checks to see if specified
item is an ancestor of the currently selected item
in the tree control.
NOTES: Used to figure out if a tree collapse is going to hide
the selected item
********************************************************************/
BOOL IsAncestorOfSelection(HWND hwndTree,HTREEITEM hParent)
{
HTREEITEM hItem;
hItem= TreeView_GetSelection(hwndTree);
while (hItem) {
if (hItem == hParent) return TRUE;
hItem = TreeView_GetParent(hwndTree,hItem);
}
return FALSE;
}
/*******************************************************************
NAME: IsSelectedItemChecked
SYNOPSIS: Returns true if selected treeview item is checked
********************************************************************/
BOOL IsSelectedItemChecked(HWND hwndTree)
{
HTREEITEM hItem= TreeView_GetSelection(hwndTree);
if (hItem) {
TV_ITEM tvi;
tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
tvi.hItem = hItem;
if (TreeView_GetItem(hwndTree,&tvi) && tvi.iImage == IMG_CHECKED)
return TRUE;
}
return FALSE;
}