- allow changing the focus of the check boxes in the checklist control

- minor fixes

svn path=/trunk/; revision=16384
This commit is contained in:
Thomas Bluemel 2005-07-03 01:44:25 +00:00
parent d23d39a743
commit 79811989d8
7 changed files with 708 additions and 51 deletions

View file

@ -416,22 +416,31 @@ UpdateControlStates(IN PSECURITY_PAGE sp)
{ {
LPWSTR szLabel; LPWSTR szLabel;
LoadAndFormatString(hDllInstance, if (LoadAndFormatString(hDllInstance,
IDS_PERMISSIONS_FOR, IDS_PERMISSIONS_FOR,
&szLabel, &szLabel,
Selected->AccountName); Selected->AccountName))
{
SetWindowText(sp->hPermissionsForLabel, SetWindowText(sp->hPermissionsForLabel,
szLabel); szLabel);
LocalFree((HLOCAL)szLabel);
LocalFree((HLOCAL)szLabel);
}
/* FIXME - update the checkboxes */ /* FIXME - update the checkboxes */
} }
else else
{ {
SetWindowText(sp->hPermissionsForLabel, WCHAR szPermissions[255];
NULL);
if (LoadString(hDllInstance,
IDS_PERMISSIONS,
szPermissions,
sizeof(szPermissions) / sizeof(szPermissions[0])))
{
SetWindowText(sp->hPermissionsForLabel,
szPermissions);
}
SendMessage(sp->hAceCheckList, SendMessage(sp->hAceCheckList,
CLM_CLEARCHECKBOXES, CLM_CLEARCHECKBOXES,
@ -552,7 +561,7 @@ LoadPermissionsList(IN PSECURITY_PAGE sp,
SendMessage(sp->hAceCheckList, SendMessage(sp->hAceCheckList,
CLM_ADDITEM, CLM_ADDITEM,
CIS_DISABLED | CIS_NONE, CIS_NONE,
(LPARAM)NameStr); (LPARAM)NameStr);
} }
} }
@ -685,7 +694,7 @@ SecurityPageProc(IN HWND hwndDlg,
/* add the special permissions check item */ /* add the special permissions check item */
sp->SpecialPermCheckIndex = (INT)SendMessage(sp->hAceCheckList, sp->SpecialPermCheckIndex = (INT)SendMessage(sp->hAceCheckList,
CLM_ADDITEM, CLM_ADDITEM,
CIS_DISABLED | CIS_NONE, CIS_ALLOWDISABLED | CIS_DENYDISABLED | CIS_NONE,
(LPARAM)szSpecialPermissions); (LPARAM)szSpecialPermissions);
} }
} }

View file

@ -23,4 +23,5 @@ STRINGTABLE DISCARDABLE
IDS_UNKNOWN "Unbekannt" IDS_UNKNOWN "Unbekannt"
IDS_SPECIAL_PERMISSIONS "Spezielle Berechtigungen" IDS_SPECIAL_PERMISSIONS "Spezielle Berechtigungen"
IDS_PERMISSIONS_FOR "Berechtigungen für %1" IDS_PERMISSIONS_FOR "Berechtigungen für %1"
IDS_PERMISSIONS "Berechtigungen"
} }

View file

@ -23,5 +23,6 @@ STRINGTABLE DISCARDABLE
IDS_UNKNOWN "Unknown" IDS_UNKNOWN "Unknown"
IDS_SPECIAL_PERMISSIONS "Special Permissions" IDS_SPECIAL_PERMISSIONS "Special Permissions"
IDS_PERMISSIONS_FOR "Permissions for %1" IDS_PERMISSIONS_FOR "Permissions for %1"
IDS_PERMISSIONS "Permissions"
} }

View file

@ -41,5 +41,6 @@ STRINGTABLE DISCARDABLE
IDS_UNKNOWN "Unknown" IDS_UNKNOWN "Unknown"
IDS_SPECIAL_PERMISSIONS "Special Permissions" IDS_SPECIAL_PERMISSIONS "Special Permissions"
IDS_PERMISSIONS_FOR "Permissions for %1" IDS_PERMISSIONS_FOR "Permissions for %1"
IDS_PERMISSIONS "Permissions"
} }

View file

@ -76,11 +76,14 @@ ListViewSelectItem(IN HWND hwnd,
/* CHECKLIST CONTROL **********************************************************/ /* CHECKLIST CONTROL **********************************************************/
#define CIS_DISABLED (0x4) #define CIS_DENYDISABLED (0x8)
#define CIS_ENABLED (0x0) #define CIS_DENYENABLED (0x0)
#define CIS_ALLOWDISABLED (0x4)
#define CIS_ALLOWENABLED (0x0)
#define CIS_ALLOW (0x2) #define CIS_ALLOW (0x2)
#define CIS_DENY (0x1) #define CIS_DENY (0x1)
#define CIS_NONE (0x0) #define CIS_NONE (0x0)
#define CIS_DISABLED (CIS_ALLOWDISABLED | CIS_DENYDISABLED)
#define CLB_ALLOW (0x1) #define CLB_ALLOW (0x1)
#define CLB_DENY (0x0) #define CLB_DENY (0x0)

View file

@ -24,7 +24,7 @@
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com> * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
* *
* UPDATE HISTORY: * UPDATE HISTORY:
* 08/10/2004 Created * 07/01/2005 Created
*/ */
#include "acluilib.h" #include "acluilib.h"
@ -39,19 +39,24 @@ typedef struct _CHECKLISTWND
{ {
HWND hSelf; HWND hSelf;
HWND hNotify; HWND hNotify;
DWORD Style;
HFONT hFont; HFONT hFont;
PCHECKITEM CheckItemListHead; PCHECKITEM CheckItemListHead;
UINT CheckItemCount; UINT CheckItemCount;
INT ItemHeight; INT ItemHeight;
BOOL HasFocus; BOOL HasFocus;
PCHECKITEM FocusedCheckItem;
UINT FocusedCheckItemBox;
COLORREF TextColor[2]; COLORREF TextColor[2];
UINT CheckBoxLeft[2]; UINT CheckBoxLeft[2];
} CHECKLISTWND, *PCHECKLISTWND; } CHECKLISTWND, *PCHECKLISTWND;
#define CI_TEXT_MARGIN_WIDTH (6)
#define CI_TEXT_MARGIN_HEIGHT (2)
static PCHECKITEM static PCHECKITEM
FindCheckItemByIndex(IN PCHECKLISTWND infoPtr, FindCheckItemByIndex(IN PCHECKLISTWND infoPtr,
IN UINT Index) IN UINT Index)
@ -74,6 +79,248 @@ FindCheckItemByIndex(IN PCHECKLISTWND infoPtr,
return Found; return Found;
} }
static INT
CheckItemToIndex(IN PCHECKLISTWND infoPtr,
IN PCHECKITEM Item)
{
PCHECKITEM CurItem;
INT Index;
for (CurItem = infoPtr->CheckItemListHead, Index = 0;
CurItem != NULL;
CurItem = CurItem->Next, Index++)
{
if (CurItem == Item)
{
return Index;
}
}
return -1;
}
static PCHECKITEM
FindFirstEnabledCheckBox(IN PCHECKLISTWND infoPtr,
OUT UINT *CheckBox)
{
PCHECKITEM CurItem;
for (CurItem = infoPtr->CheckItemListHead;
CurItem != NULL;
CurItem = CurItem->Next)
{
if ((CurItem->State & CIS_DISABLED) != CIS_DISABLED)
{
/* return the Allow checkbox in case both check boxes are enabled! */
*CheckBox = ((!(CurItem->State & CIS_ALLOWDISABLED)) ? CLB_ALLOW : CLB_DENY);
return CurItem;
}
}
return NULL;
}
static PCHECKITEM
FindLastEnabledCheckBox(IN PCHECKLISTWND infoPtr,
OUT UINT *CheckBox)
{
PCHECKITEM CurItem;
PCHECKITEM LastEnabledItem = NULL;
for (CurItem = infoPtr->CheckItemListHead;
CurItem != NULL;
CurItem = CurItem->Next)
{
if ((CurItem->State & CIS_DISABLED) != CIS_DISABLED)
{
LastEnabledItem = CurItem;
}
}
if (LastEnabledItem != NULL)
{
/* return the Deny checkbox in case both check boxes are enabled! */
*CheckBox = ((!(LastEnabledItem->State & CIS_DENYDISABLED)) ? CLB_DENY : CLB_ALLOW);
return LastEnabledItem;
}
return NULL;
}
static PCHECKITEM
FindPreviousEnabledCheckBox(IN PCHECKLISTWND infoPtr,
OUT UINT *CheckBox)
{
PCHECKITEM Item;
if (infoPtr->FocusedCheckItem != NULL)
{
Item = infoPtr->FocusedCheckItem;
if (infoPtr->FocusedCheckItemBox == CLB_DENY &&
!(Item->State & CIS_ALLOWDISABLED))
{
/* currently an Deny checkbox is focused. return the Allow checkbox
if it's enabled */
*CheckBox = CLB_ALLOW;
}
else
{
PCHECKITEM CurItem;
Item = NULL;
for (CurItem = infoPtr->CheckItemListHead;
CurItem != infoPtr->FocusedCheckItem;
CurItem = CurItem->Next)
{
if ((CurItem->State & CIS_DISABLED) != CIS_DISABLED)
{
Item = CurItem;
}
}
if (Item != NULL)
{
/* return the Deny checkbox in case both check boxes are enabled! */
*CheckBox = ((!(Item->State & CIS_DENYDISABLED)) ? CLB_DENY : CLB_ALLOW);
}
}
}
else
{
Item = FindLastEnabledCheckBox(infoPtr,
CheckBox);
}
return Item;
}
static PCHECKITEM
FindNextEnabledCheckBox(IN PCHECKLISTWND infoPtr,
OUT UINT *CheckBox)
{
PCHECKITEM Item;
if (infoPtr->FocusedCheckItem != NULL)
{
Item = infoPtr->FocusedCheckItem;
if (infoPtr->FocusedCheckItemBox != CLB_DENY &&
!(Item->State & CIS_DENYDISABLED))
{
/* currently an Allow checkbox is focused. return the Deny checkbox
if it's enabled */
*CheckBox = CLB_DENY;
}
else
{
Item = Item->Next;
while (Item != NULL)
{
if ((Item->State & CIS_DISABLED) != CIS_DISABLED)
{
/* return the Allow checkbox in case both check boxes are enabled! */
*CheckBox = ((!(Item->State & CIS_ALLOWDISABLED)) ? CLB_ALLOW : CLB_DENY);
break;
}
Item = Item->Next;
}
}
}
else
{
Item = FindFirstEnabledCheckBox(infoPtr,
CheckBox);
}
return Item;
}
static PCHECKITEM
FindEnabledCheckBox(IN PCHECKLISTWND infoPtr,
IN BOOL ReverseSearch,
OUT UINT *CheckBox)
{
PCHECKITEM Item;
if (ReverseSearch)
{
Item = FindPreviousEnabledCheckBox(infoPtr,
CheckBox);
}
else
{
Item = FindNextEnabledCheckBox(infoPtr,
CheckBox);
}
return Item;
}
static PCHECKITEM
PtToCheckItemBox(IN PCHECKLISTWND infoPtr,
IN PPOINT ppt,
OUT UINT *CheckBox,
OUT BOOL *DirectlyInCheckBox)
{
LONG Style;
INT FirstVisible, Index;
PCHECKITEM Item;
Style = GetWindowLong(infoPtr->hSelf,
GWL_STYLE);
if (Style & WS_VSCROLL)
{
FirstVisible = GetScrollPos(infoPtr->hSelf,
SB_VERT);
}
else
{
FirstVisible = 0;
}
Index = FirstVisible + (ppt->y / infoPtr->ItemHeight);
Item = FindCheckItemByIndex(infoPtr,
Index);
if (Item != NULL)
{
INT cx;
cx = infoPtr->CheckBoxLeft[CLB_ALLOW] +
((infoPtr->CheckBoxLeft[CLB_DENY] - infoPtr->CheckBoxLeft[CLB_ALLOW]) / 2);
*CheckBox = ((ppt->x <= cx) ? CLB_ALLOW : CLB_DENY);
if (DirectlyInCheckBox != NULL)
{
INT y = ppt->y % infoPtr->ItemHeight;
if ((y >= CI_TEXT_MARGIN_HEIGHT &&
y <= infoPtr->ItemHeight - CI_TEXT_MARGIN_HEIGHT) &&
(((ppt->x >= (infoPtr->CheckBoxLeft[CLB_ALLOW] - (infoPtr->ItemHeight / 2))) &&
(ppt->x <= (infoPtr->CheckBoxLeft[CLB_ALLOW] - (infoPtr->ItemHeight / 2) + infoPtr->ItemHeight)))
||
((ppt->x >= (infoPtr->CheckBoxLeft[CLB_DENY] - (infoPtr->ItemHeight / 2))) &&
(ppt->x <= (infoPtr->CheckBoxLeft[CLB_DENY] - (infoPtr->ItemHeight / 2) + infoPtr->ItemHeight)))))
{
*DirectlyInCheckBox = TRUE;
}
else
{
*DirectlyInCheckBox = FALSE;
}
}
}
return Item;
}
static VOID static VOID
ClearCheckItems(IN PCHECKLISTWND infoPtr) ClearCheckItems(IN PCHECKLISTWND infoPtr)
{ {
@ -185,6 +432,7 @@ UpdateControl(IN PCHECKLISTWND infoPtr,
{ {
RECT rcClient; RECT rcClient;
SCROLLINFO ScrollInfo; SCROLLINFO ScrollInfo;
LONG Style;
GetClientRect(infoPtr->hSelf, GetClientRect(infoPtr->hSelf,
&rcClient); &rcClient);
@ -199,20 +447,23 @@ UpdateControl(IN PCHECKLISTWND infoPtr,
if (AllowChangeStyle) if (AllowChangeStyle)
{ {
Style = GetWindowLong(infoPtr->hSelf,
GWL_STYLE);
/* determine whether the vertical scrollbar has to be visible or not */ /* determine whether the vertical scrollbar has to be visible or not */
if (ScrollInfo.nMax > ScrollInfo.nPage && if (ScrollInfo.nMax > ScrollInfo.nPage &&
!(infoPtr->Style & WS_VSCROLL)) !(Style & WS_VSCROLL))
{ {
SetWindowLong(infoPtr->hSelf, SetWindowLong(infoPtr->hSelf,
GWL_STYLE, GWL_STYLE,
infoPtr->Style | WS_VSCROLL); Style | WS_VSCROLL);
} }
else if (ScrollInfo.nMax < ScrollInfo.nPage && else if (ScrollInfo.nMax < ScrollInfo.nPage &&
infoPtr->Style & WS_VSCROLL) Style & WS_VSCROLL)
{ {
SetWindowLong(infoPtr->hSelf, SetWindowLong(infoPtr->hSelf,
GWL_STYLE, GWL_STYLE,
infoPtr->Style & ~WS_VSCROLL); Style & ~WS_VSCROLL);
} }
} }
@ -227,6 +478,127 @@ UpdateControl(IN PCHECKLISTWND infoPtr,
RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN); RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN);
} }
static VOID
UpdateCheckItem(IN PCHECKLISTWND infoPtr,
IN PCHECKITEM Item)
{
LONG Style;
RECT rcClient;
INT VisibleFirst, VisibleItems;
INT Index = CheckItemToIndex(infoPtr,
Item);
if (Index != -1)
{
Style = GetWindowLong(infoPtr->hSelf,
GWL_STYLE);
if (Style & WS_VSCROLL)
{
VisibleFirst = GetScrollPos(infoPtr->hSelf,
SB_VERT);
}
else
{
VisibleFirst = 0;
}
if (Index >= VisibleFirst)
{
GetClientRect(infoPtr->hSelf,
&rcClient);
VisibleItems = ((rcClient.bottom - rcClient.top) + infoPtr->ItemHeight - 1) / infoPtr->ItemHeight;
if (Index < VisibleFirst + VisibleItems)
{
RECT rcUpdate;
rcUpdate.left = rcClient.left;
rcUpdate.right = rcClient.right;
rcUpdate.top = (Index - VisibleFirst) * infoPtr->ItemHeight;
rcUpdate.bottom = rcUpdate.top + infoPtr->ItemHeight;
RedrawWindow(infoPtr->hSelf,
&rcUpdate,
NULL,
RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN);
}
}
}
}
static VOID
MakeCheckItemVisible(IN PCHECKLISTWND infoPtr,
IN PCHECKITEM Item)
{
LONG Style;
RECT rcClient;
INT VisibleFirst, VisibleItems, NewPos;
INT Index = CheckItemToIndex(infoPtr,
Item);
if (Index != -1)
{
Style = GetWindowLong(infoPtr->hSelf,
GWL_STYLE);
if (Style & WS_VSCROLL)
{
VisibleFirst = GetScrollPos(infoPtr->hSelf,
SB_VERT);
if (Index <= VisibleFirst)
{
NewPos = Index;
}
else
{
GetClientRect(infoPtr->hSelf,
&rcClient);
VisibleItems = (rcClient.bottom - rcClient.top) / infoPtr->ItemHeight;
if (Index - VisibleItems + 1 > VisibleFirst)
{
NewPos = Index - VisibleItems + 1;
}
else
{
NewPos = VisibleFirst;
}
}
if (VisibleFirst != NewPos)
{
SCROLLINFO ScrollInfo;
ScrollInfo.cbSize = sizeof(ScrollInfo);
ScrollInfo.fMask = SIF_POS;
ScrollInfo.nPos = NewPos;
NewPos = SetScrollInfo(infoPtr->hSelf,
SB_VERT,
&ScrollInfo,
TRUE);
if (VisibleFirst != NewPos)
{
ScrollWindowEx(infoPtr->hSelf,
0,
(NewPos - VisibleFirst) * infoPtr->ItemHeight,
NULL,
NULL,
NULL,
NULL,
SW_INVALIDATE);
RedrawWindow(infoPtr->hSelf,
NULL,
NULL,
RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN);
}
}
}
}
}
static UINT static UINT
GetIdealItemHeight(IN PCHECKLISTWND infoPtr) GetIdealItemHeight(IN PCHECKLISTWND infoPtr)
{ {
@ -286,6 +658,7 @@ PaintControl(IN PCHECKLISTWND infoPtr,
INT ScrollPos; INT ScrollPos;
PCHECKITEM FirstItem, Item; PCHECKITEM FirstItem, Item;
RECT rcClient; RECT rcClient;
LONG Style;
UINT VisibleFirstIndex = rcUpdate->top / infoPtr->ItemHeight; UINT VisibleFirstIndex = rcUpdate->top / infoPtr->ItemHeight;
UINT LastTouchedIndex = rcUpdate->bottom / infoPtr->ItemHeight; UINT LastTouchedIndex = rcUpdate->bottom / infoPtr->ItemHeight;
@ -295,7 +668,10 @@ PaintControl(IN PCHECKLISTWND infoPtr,
GetClientRect(infoPtr->hSelf, &rcClient); GetClientRect(infoPtr->hSelf, &rcClient);
if (infoPtr->Style & WS_VSCROLL) Style = GetWindowLong(infoPtr->hSelf,
GWL_STYLE);
if (Style & WS_VSCROLL)
{ {
ScrollPos = GetScrollPos(infoPtr->hSelf, ScrollPos = GetScrollPos(infoPtr->hSelf,
SB_VERT); SB_VERT);
@ -314,6 +690,7 @@ PaintControl(IN PCHECKLISTWND infoPtr,
DWORD CurrentIndex; DWORD CurrentIndex;
COLORREF OldTextColor; COLORREF OldTextColor;
BOOL Enabled, PrevEnabled; BOOL Enabled, PrevEnabled;
POINT hOldBrushOrg;
Enabled = IsWindowEnabled(infoPtr->hSelf); Enabled = IsWindowEnabled(infoPtr->hSelf);
PrevEnabled = Enabled; PrevEnabled = Enabled;
@ -322,9 +699,14 @@ PaintControl(IN PCHECKLISTWND infoPtr,
ItemRect.right = rcClient.right; ItemRect.right = rcClient.right;
ItemRect.top = VisibleFirstIndex * infoPtr->ItemHeight; ItemRect.top = VisibleFirstIndex * infoPtr->ItemHeight;
TextRect.left = ItemRect.left + 6; TextRect.left = ItemRect.left + CI_TEXT_MARGIN_WIDTH;
TextRect.right = ItemRect.right - 6; TextRect.right = ItemRect.right - CI_TEXT_MARGIN_WIDTH;
TextRect.top = ItemRect.top + 2; TextRect.top = ItemRect.top + CI_TEXT_MARGIN_HEIGHT;
SetBrushOrgEx(hDC,
ItemRect.left,
ItemRect.top,
&hOldBrushOrg);
OldTextColor = SetTextColor(hDC, OldTextColor = SetTextColor(hDC,
infoPtr->TextColor[Enabled]); infoPtr->TextColor[Enabled]);
@ -337,10 +719,16 @@ PaintControl(IN PCHECKLISTWND infoPtr,
Item = Item->Next, CurrentIndex++) Item = Item->Next, CurrentIndex++)
{ {
TextRect.bottom = TextRect.top + infoPtr->ItemHeight; TextRect.bottom = TextRect.top + infoPtr->ItemHeight;
ItemRect.bottom = ItemRect.top + infoPtr->ItemHeight;
if (Enabled && PrevEnabled != ((Item->State & CIS_DISABLED) == 0)) SetBrushOrgEx(hDC,
ItemRect.left,
ItemRect.top,
NULL);
if (Enabled && PrevEnabled != ((Item->State & CIS_DISABLED) != CIS_DISABLED))
{ {
PrevEnabled = ((Item->State & CIS_DISABLED) == 0); PrevEnabled = ((Item->State & CIS_DISABLED) != CIS_DISABLED);
SetTextColor(hDC, SetTextColor(hDC,
infoPtr->TextColor[PrevEnabled]); infoPtr->TextColor[PrevEnabled]);
@ -355,27 +743,54 @@ PaintControl(IN PCHECKLISTWND infoPtr,
/* draw the Allow checkbox */ /* draw the Allow checkbox */
CheckBox.left = infoPtr->CheckBoxLeft[CLB_ALLOW] - ((TextRect.bottom - TextRect.top) / 2); CheckBox.left = infoPtr->CheckBoxLeft[CLB_ALLOW] - ((TextRect.bottom - TextRect.top) / 2);
CheckBox.right = CheckBox.left + (TextRect.bottom - TextRect.top) - 4; CheckBox.right = CheckBox.left + (TextRect.bottom - TextRect.top) - (2 * CI_TEXT_MARGIN_HEIGHT);
CheckBox.top = TextRect.top; CheckBox.top = TextRect.top;
CheckBox.bottom = CheckBox.top + (TextRect.bottom - TextRect.top) - 4; CheckBox.bottom = CheckBox.top + (TextRect.bottom - TextRect.top) - (2 * CI_TEXT_MARGIN_HEIGHT);
DrawFrameControl(hDC, DrawFrameControl(hDC,
&CheckBox, &CheckBox,
DFC_BUTTON, DFC_BUTTON,
DFCS_BUTTONCHECK | DFCS_FLAT | DFCS_BUTTONCHECK | DFCS_FLAT |
((Item->State & CIS_DISABLED) && Enabled ? DFCS_INACTIVE : 0) | ((Item->State & CIS_ALLOWDISABLED) || !Enabled ? DFCS_INACTIVE : 0) |
((Item->State & CIS_ALLOW) ? DFCS_CHECKED : 0)); ((Item->State & CIS_ALLOW) ? DFCS_CHECKED : 0));
if (infoPtr->HasFocus &&
Item == infoPtr->FocusedCheckItem &&
infoPtr->FocusedCheckItemBox != CLB_DENY)
{
RECT rcFocus = CheckBox;
InflateRect (&rcFocus,
CI_TEXT_MARGIN_HEIGHT,
CI_TEXT_MARGIN_HEIGHT);
DrawFocusRect(hDC,
&rcFocus);
}
/* draw the Deny checkbox */ /* draw the Deny checkbox */
CheckBox.left = infoPtr->CheckBoxLeft[CLB_DENY] - ((TextRect.bottom - TextRect.top) / 2); CheckBox.left = infoPtr->CheckBoxLeft[CLB_DENY] - ((TextRect.bottom - TextRect.top) / 2);
CheckBox.right = CheckBox.left + (TextRect.bottom - TextRect.top) - 4; CheckBox.right = CheckBox.left + (TextRect.bottom - TextRect.top) - (2 * CI_TEXT_MARGIN_HEIGHT);
DrawFrameControl(hDC, DrawFrameControl(hDC,
&CheckBox, &CheckBox,
DFC_BUTTON, DFC_BUTTON,
DFCS_BUTTONCHECK | DFCS_FLAT | DFCS_BUTTONCHECK | DFCS_FLAT |
((Item->State & CIS_DISABLED) && Enabled ? DFCS_INACTIVE : 0) | ((Item->State & CIS_DENYDISABLED) || !Enabled ? DFCS_INACTIVE : 0) |
((Item->State & CIS_DENY) ? DFCS_CHECKED : 0)); ((Item->State & CIS_DENY) ? DFCS_CHECKED : 0));
if (infoPtr->HasFocus &&
Item == infoPtr->FocusedCheckItem &&
infoPtr->FocusedCheckItemBox == CLB_DENY)
{
RECT rcFocus = CheckBox;
InflateRect (&rcFocus,
CI_TEXT_MARGIN_HEIGHT,
CI_TEXT_MARGIN_HEIGHT);
DrawFocusRect(hDC,
&rcFocus);
}
TextRect.top += infoPtr->ItemHeight; TextRect.top += infoPtr->ItemHeight;
ItemRect.top += infoPtr->ItemHeight;
} }
SelectObject(hDC, SelectObject(hDC,
@ -383,10 +798,46 @@ PaintControl(IN PCHECKLISTWND infoPtr,
SetTextColor(hDC, SetTextColor(hDC,
OldTextColor); OldTextColor);
SetBrushOrgEx(hDC,
hOldBrushOrg.x,
hOldBrushOrg.y,
NULL);
} }
} }
LRESULT CALLBACK static VOID
ChangeCheckItemFocus(IN PCHECKLISTWND infoPtr,
IN PCHECKITEM NewFocus,
IN INT NewFocusBox)
{
if (NewFocus != infoPtr->FocusedCheckItem)
{
PCHECKITEM OldFocus = infoPtr->FocusedCheckItem;
infoPtr->FocusedCheckItem = NewFocus;
infoPtr->FocusedCheckItemBox = NewFocusBox;
if (OldFocus != NULL)
{
UpdateCheckItem(infoPtr,
OldFocus);
}
}
else
{
infoPtr->FocusedCheckItemBox = NewFocusBox;
}
if (NewFocus != NULL)
{
MakeCheckItemVisible(infoPtr,
NewFocus);
UpdateCheckItem(infoPtr,
NewFocus);
}
}
static LRESULT CALLBACK
CheckListWndProc(IN HWND hwnd, CheckListWndProc(IN HWND hwnd,
IN UINT uMsg, IN UINT uMsg,
IN WPARAM wParam, IN WPARAM wParam,
@ -440,7 +891,7 @@ CheckListWndProc(IN HWND hwnd,
SCROLLINFO ScrollInfo; SCROLLINFO ScrollInfo;
ScrollInfo.cbSize = sizeof(ScrollInfo); ScrollInfo.cbSize = sizeof(ScrollInfo);
ScrollInfo.fMask = SIF_PAGE | SIF_RANGE | SIF_POS | SIF_TRACKPOS; ScrollInfo.fMask = SIF_RANGE | SIF_POS;
if (GetScrollInfo(hwnd, if (GetScrollInfo(hwnd,
SB_VERT, SB_VERT,
@ -469,36 +920,57 @@ CheckListWndProc(IN HWND hwnd,
break; break;
case SB_PAGEDOWN: case SB_PAGEDOWN:
if (ScrollInfo.nPos + ScrollInfo.nPage <= ScrollInfo.nMax) {
RECT rcClient;
INT ScrollLines;
/* don't use ScrollInfo.nPage because we should only scroll
down by the number of completely visible list entries.
nPage however also includes the partly cropped list
item at the bottom of the control */
GetClientRect(hwnd, &rcClient);
ScrollLines = max(1, (rcClient.bottom - rcClient.top) / infoPtr->ItemHeight);
if (ScrollInfo.nPos + ScrollLines <= ScrollInfo.nMax)
{ {
ScrollInfo.nPos += ScrollInfo.nPage; ScrollInfo.nPos += ScrollLines;
} }
else else
{ {
ScrollInfo.nPos = ScrollInfo.nMax; ScrollInfo.nPos = ScrollInfo.nMax;
} }
break; break;
}
case SB_PAGEUP: case SB_PAGEUP:
if (ScrollInfo.nPos >= ScrollInfo.nPage) {
RECT rcClient;
INT ScrollLines;
/* don't use ScrollInfo.nPage because we should only scroll
down by the number of completely visible list entries.
nPage however also includes the partly cropped list
item at the bottom of the control */
GetClientRect(hwnd, &rcClient);
ScrollLines = max(1, (rcClient.bottom - rcClient.top) / infoPtr->ItemHeight);
if (ScrollInfo.nPos >= ScrollLines)
{ {
ScrollInfo.nPos -= ScrollInfo.nPage; ScrollInfo.nPos -= ScrollLines;
} }
else else
{ {
ScrollInfo.nPos = 0; ScrollInfo.nPos = 0;
} }
break; break;
}
case SB_THUMBPOSITION: case SB_THUMBPOSITION:
{
ScrollInfo.nPos = HIWORD(wParam);
break;
}
case SB_THUMBTRACK: case SB_THUMBTRACK:
{ {
ScrollInfo.nPos = ScrollInfo.nTrackPos; ScrollInfo.nPos = HIWORD(wParam);
break; break;
} }
@ -589,6 +1061,27 @@ CheckListWndProc(IN HWND hwnd,
if (Item->State != OldState) if (Item->State != OldState)
{ {
/* revert the focus if the currently focused item is about
to be disabled */
if (Item == infoPtr->FocusedCheckItem &&
(Item->State & CIS_DISABLED))
{
if (infoPtr->FocusedCheckItemBox == CLB_DENY)
{
if (Item->State & CIS_DENYDISABLED)
{
infoPtr->FocusedCheckItem = NULL;
}
}
else
{
if (Item->State & CIS_ALLOWDISABLED)
{
infoPtr->FocusedCheckItem = NULL;
}
}
}
UpdateControl(infoPtr, UpdateControl(infoPtr,
TRUE); TRUE);
} }
@ -659,13 +1152,25 @@ CheckListWndProc(IN HWND hwnd,
if (wParam == GWL_STYLE) if (wParam == GWL_STYLE)
{ {
infoPtr->Style = Style->styleNew; BOOL AllowChangeStyle;
/* don't allow the control to enable/disable the vertical scrollbar
if this message was invoked due to such a window style change! */
AllowChangeStyle = ((Style->styleNew & WS_VSCROLL) == (Style->styleOld & WS_VSCROLL));
UpdateControl(infoPtr, UpdateControl(infoPtr,
FALSE); AllowChangeStyle);
} }
break; break;
} }
case WM_ENABLE:
{
UpdateControl(infoPtr,
TRUE);
break;
}
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
{ {
SHORT ScrollDelta; SHORT ScrollDelta;
@ -731,12 +1236,33 @@ CheckListWndProc(IN HWND hwnd,
case WM_SETFOCUS: case WM_SETFOCUS:
{ {
infoPtr->HasFocus = TRUE; infoPtr->HasFocus = TRUE;
if (infoPtr->FocusedCheckItem == NULL)
{
BOOL Shift = GetKeyState(VK_SHIFT) & 0x8000;
infoPtr->FocusedCheckItem = FindEnabledCheckBox(infoPtr,
Shift,
&infoPtr->FocusedCheckItemBox);
}
if (infoPtr->FocusedCheckItem != NULL)
{
MakeCheckItemVisible(infoPtr,
infoPtr->FocusedCheckItem);
UpdateCheckItem(infoPtr,
infoPtr->FocusedCheckItem);
}
break; break;
} }
case WM_KILLFOCUS: case WM_KILLFOCUS:
{ {
infoPtr->HasFocus = FALSE; infoPtr->HasFocus = FALSE;
if (infoPtr->FocusedCheckItem != NULL)
{
UpdateCheckItem(infoPtr,
infoPtr->FocusedCheckItem);
}
break; break;
} }
@ -744,9 +1270,125 @@ CheckListWndProc(IN HWND hwnd,
case WM_MBUTTONDOWN: case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN: case WM_RBUTTONDOWN:
{ {
if (!infoPtr->HasFocus && IsWindowEnabled(hwnd)) if (IsWindowEnabled(hwnd))
{ {
SetFocus(hwnd); PCHECKITEM NewFocus;
INT NewFocusBox = 0;
BOOL InCheckBox;
POINT pt;
BOOL ChangeFocus;
pt.x = (LONG)LOWORD(lParam);
pt.y = (LONG)HIWORD(lParam);
if (!infoPtr->HasFocus)
{
SetFocus(hwnd);
}
NewFocus = PtToCheckItemBox(infoPtr,
&pt,
&NewFocusBox,
&InCheckBox);
if (NewFocus != NULL)
{
if (NewFocus->State & ((NewFocusBox != CLB_DENY) ? CIS_ALLOWDISABLED : CIS_DENYDISABLED))
{
/* the user clicked on a disabled checkbox, try to set
the focus to the other one or not change it at all */
InCheckBox = FALSE;
ChangeFocus = ((NewFocus->State & CIS_DISABLED) != CIS_DISABLED);
if (ChangeFocus)
{
NewFocusBox = ((NewFocusBox != CLB_DENY) ? CLB_DENY : CLB_ALLOW);
}
}
else
{
ChangeFocus = TRUE;
}
}
else
{
ChangeFocus = TRUE;
}
if (ChangeFocus)
{
ChangeCheckItemFocus(infoPtr,
NewFocus,
NewFocusBox);
}
}
break;
}
case WM_KEYDOWN:
{
switch (wParam)
{
case VK_RETURN:
{
/* FIXME */
break;
}
case VK_TAB:
{
PCHECKITEM NewFocus;
UINT NewFocusBox = 0;
BOOL Shift = GetKeyState(VK_SHIFT) & 0x8000;
NewFocus = FindEnabledCheckBox(infoPtr,
Shift,
&NewFocusBox);
ChangeCheckItemFocus(infoPtr,
NewFocus,
NewFocusBox);
break;
}
default:
{
Ret = DefWindowProc(hwnd,
uMsg,
wParam,
lParam);
break;
}
}
break;
}
case WM_GETDLGCODE:
{
INT virtKey;
Ret = DLGC_HASSETSEL;
virtKey = (lParam != 0 ? (INT)((LPMSG)lParam)->wParam : 0);
switch (virtKey)
{
case VK_RETURN:
{
Ret |= DLGC_WANTMESSAGE;
break;
}
case VK_TAB:
{
INT CheckBox;
BOOL EnabledBox;
BOOL Shift = GetKeyState(VK_SHIFT) & 0x8000;
EnabledBox = FindEnabledCheckBox(infoPtr,
Shift,
&CheckBox) != NULL;
Ret |= (EnabledBox ? DLGC_WANTTAB : DLGC_WANTCHARS);
break;
}
} }
break; break;
} }
@ -769,7 +1411,6 @@ CheckListWndProc(IN HWND hwnd,
infoPtr->hSelf = hwnd; infoPtr->hSelf = hwnd;
infoPtr->hNotify = ((LPCREATESTRUCTW)lParam)->hwndParent; infoPtr->hNotify = ((LPCREATESTRUCTW)lParam)->hwndParent;
infoPtr->Style = ((LPCREATESTRUCTW)lParam)->style;
SetWindowLongPtr(hwnd, SetWindowLongPtr(hwnd,
0, 0,
@ -781,6 +1422,8 @@ CheckListWndProc(IN HWND hwnd,
infoPtr->ItemHeight = 10; infoPtr->ItemHeight = 10;
infoPtr->HasFocus = FALSE; infoPtr->HasFocus = FALSE;
infoPtr->FocusedCheckItem = NULL;
infoPtr->FocusedCheckItemBox = 0;
infoPtr->TextColor[0] = GetSysColor(COLOR_GRAYTEXT); infoPtr->TextColor[0] = GetSysColor(COLOR_GRAYTEXT);
infoPtr->TextColor[1] = GetSysColor(COLOR_WINDOWTEXT); infoPtr->TextColor[1] = GetSysColor(COLOR_WINDOWTEXT);

View file

@ -13,12 +13,11 @@
#define IDC_LABEL_ADVANCED 1008 #define IDC_LABEL_ADVANCED 1008
#define IDC_LABEL_PERMISSIONS_FOR 1009 #define IDC_LABEL_PERMISSIONS_FOR 1009
#define IDI_DEVMGR 100
#define IDS_PSP_TITLE 1001 #define IDS_PSP_TITLE 1001
#define IDS_UNKNOWN 1002 #define IDS_UNKNOWN 1002
#define IDS_SPECIAL_PERMISSIONS 1003 #define IDS_SPECIAL_PERMISSIONS 1003
#define IDS_PERMISSIONS_FOR 1004 #define IDS_PERMISSIONS_FOR 1004
#define IDS_PERMISSIONS 1005
#define IDB_USRGRPIMAGES 1001 #define IDB_USRGRPIMAGES 1001