mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
674 lines
23 KiB
C
674 lines
23 KiB
C
/*
|
|
* Program Manager
|
|
*
|
|
* Copyright 1996 Ulrich Schmid
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
/*
|
|
* PROJECT: ReactOS Program Manager
|
|
* COPYRIGHT: GPL - See COPYING in the top level directory
|
|
* FILE: base/shell/progman/group.c
|
|
* PURPOSE: Program group files helper functions
|
|
* PROGRAMMERS: Ulrich Schmid
|
|
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
|
*/
|
|
|
|
#include "progman.h"
|
|
|
|
/***********************************************************************
|
|
*
|
|
* UX Theming helpers, dropped from msconfig_new/comctl32ex/uxthemesupp.c
|
|
*
|
|
*/
|
|
|
|
static HMODULE hUxTheme = NULL;
|
|
|
|
typedef HRESULT (WINAPI* ETDTProc)(HWND, DWORD);
|
|
static ETDTProc fnEnableThemeDialogTexture = NULL;
|
|
|
|
typedef HRESULT (WINAPI* SWTProc)(HWND, LPCWSTR, LPCWSTR);
|
|
static SWTProc fnSetWindowTheme = NULL;
|
|
|
|
|
|
static BOOL
|
|
InitUxTheme(VOID)
|
|
{
|
|
if (hUxTheme) return TRUE;
|
|
|
|
hUxTheme = LoadLibraryW(L"uxtheme.dll");
|
|
if (hUxTheme == NULL) return FALSE;
|
|
|
|
fnEnableThemeDialogTexture =
|
|
(ETDTProc)GetProcAddress(hUxTheme, "EnableThemeDialogTexture");
|
|
fnSetWindowTheme =
|
|
(SWTProc)GetProcAddress(hUxTheme, "SetWindowTheme");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#if 0
|
|
static VOID
|
|
CleanupUxTheme(VOID)
|
|
{
|
|
FreeLibrary(hUxTheme);
|
|
hUxTheme = NULL;
|
|
}
|
|
#endif
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Taken from WinSpy++ 1.7
|
|
// http://www.catch22.net/software/winspy
|
|
// Copyright (c) 2002 by J Brown
|
|
//
|
|
|
|
HRESULT
|
|
WINAPI
|
|
EnableThemeDialogTexture(_In_ HWND hwnd,
|
|
_In_ DWORD dwFlags)
|
|
{
|
|
if (!InitUxTheme())
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
if (!fnEnableThemeDialogTexture)
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
return fnEnableThemeDialogTexture(hwnd, dwFlags);
|
|
}
|
|
|
|
HRESULT
|
|
WINAPI
|
|
SetWindowTheme(_In_ HWND hwnd,
|
|
_In_ LPCWSTR pszSubAppName,
|
|
_In_ LPCWSTR pszSubIdList)
|
|
{
|
|
if (!InitUxTheme())
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
if (!fnSetWindowTheme)
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
return fnSetWindowTheme(hwnd, pszSubAppName, pszSubIdList);
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* GROUP_GroupWndProc
|
|
*/
|
|
|
|
static
|
|
LRESULT
|
|
CALLBACK
|
|
GROUP_GroupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
PROGGROUP* group;
|
|
INT iItem;
|
|
LVITEMW lvItem;
|
|
POINT pt;
|
|
|
|
group = (PROGGROUP*)GetWindowLongPtrW(hWnd, 0);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_NCCREATE:
|
|
{
|
|
LPCREATESTRUCTW pcs = (LPCREATESTRUCTW)lParam;
|
|
LPMDICREATESTRUCTW pMDIcs = (LPMDICREATESTRUCTW)pcs->lpCreateParams;
|
|
group = (PROGGROUP*)pMDIcs->lParam;
|
|
SetWindowLongPtrW(hWnd, 0, (LONG_PTR)group);
|
|
|
|
if (group->bIsCommonGroup)
|
|
{
|
|
DefMDIChildProcW(hWnd, WM_SETICON, ICON_BIG,
|
|
(LPARAM)CopyImage(Globals.hCommonGroupIcon,
|
|
IMAGE_ICON,
|
|
GetSystemMetrics(SM_CXICON),
|
|
GetSystemMetrics(SM_CYICON),
|
|
LR_COPYFROMRESOURCE));
|
|
DefMDIChildProcW(hWnd, WM_SETICON, ICON_SMALL,
|
|
(LPARAM)CopyImage(Globals.hCommonGroupIcon,
|
|
IMAGE_ICON,
|
|
GetSystemMetrics(SM_CXSMICON),
|
|
GetSystemMetrics(SM_CYSMICON),
|
|
LR_COPYFROMRESOURCE));
|
|
}
|
|
else
|
|
{
|
|
DefMDIChildProcW(hWnd, WM_SETICON, ICON_BIG,
|
|
(LPARAM)CopyImage(Globals.hPersonalGroupIcon,
|
|
IMAGE_ICON,
|
|
GetSystemMetrics(SM_CXICON),
|
|
GetSystemMetrics(SM_CYICON),
|
|
LR_COPYFROMRESOURCE));
|
|
DefMDIChildProcW(hWnd, WM_SETICON, ICON_SMALL,
|
|
(LPARAM)CopyImage(Globals.hPersonalGroupIcon,
|
|
IMAGE_ICON,
|
|
GetSystemMetrics(SM_CXSMICON),
|
|
GetSystemMetrics(SM_CYSMICON),
|
|
LR_COPYFROMRESOURCE));
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_NCDESTROY:
|
|
SetWindowLongPtrW(hWnd, 0, 0);
|
|
break;
|
|
|
|
case WM_CREATE:
|
|
{
|
|
DWORD dwStyle;
|
|
RECT rect;
|
|
GetClientRect(hWnd, &rect);
|
|
group->hListView = CreateWindowW(WC_LISTVIEW,
|
|
NULL,
|
|
WS_CHILD | WS_VISIBLE | WS_OVERLAPPED,
|
|
0, 0,
|
|
rect.right - rect.left,
|
|
rect.bottom - rect.top,
|
|
hWnd,
|
|
NULL,
|
|
Globals.hInstance,
|
|
NULL);
|
|
dwStyle = (GetWindowLongPtrW(group->hListView, GWL_STYLE) | LVS_SHOWSELALWAYS) & ~LVS_AUTOARRANGE;
|
|
SetWindowLongPtrW(group->hListView, GWL_STYLE, dwStyle);
|
|
dwStyle = SendMessageA(group->hListView, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0) | LVS_EX_BORDERSELECT;
|
|
SendMessageA(group->hListView, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_SNAPTOGRID, dwStyle);
|
|
InitUxTheme();
|
|
SetWindowTheme(group->hListView, L"Explorer", NULL);
|
|
group->hListLarge = ImageList_Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), ILC_COLOR24 | ILC_MASK, 1, 1);
|
|
SendMessageA(group->hListView, LVM_SETIMAGELIST, 0, (LPARAM)group->hListLarge);
|
|
SendMessageA(group->hListView, LVM_SETICONSPACING, 0, MAKELPARAM(80, 64));
|
|
break;
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
SendMessageA(group->hListView, LVM_SETIMAGELIST, 0, 0);
|
|
ImageList_Destroy(group->hListLarge);
|
|
DestroyWindow(group->hListView);
|
|
break;
|
|
}
|
|
|
|
case WM_SIZE:
|
|
{
|
|
RECT rect;
|
|
rect.left = 0;
|
|
rect.top = 0;
|
|
rect.right = LOWORD(lParam);
|
|
rect.bottom = HIWORD(lParam);
|
|
AdjustWindowRectEx(&rect, GetWindowLongPtrW(group->hListView, GWL_STYLE), FALSE, GetWindowLongPtrW(group->hListView, GWL_EXSTYLE));
|
|
MoveWindow(group->hListView, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
|
|
break;
|
|
}
|
|
|
|
case WM_CLOSE:
|
|
SendMessageW(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
|
|
break;
|
|
|
|
case WM_SYSCOMMAND:
|
|
if (wParam == SC_CLOSE) wParam = SC_MINIMIZE;
|
|
break;
|
|
|
|
case WM_CHILDACTIVATE:
|
|
case WM_NCLBUTTONDOWN:
|
|
Globals.hActiveGroup = (PROGGROUP*)GetWindowLongPtrW(hWnd, 0);
|
|
Globals.hActiveGroup->hActiveProgram = NULL;
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
switch (((LPNMHDR)lParam)->code)
|
|
{
|
|
case NM_CLICK:
|
|
{
|
|
iItem = ((LPNMITEMACTIVATE)lParam)->iItem;
|
|
if (iItem == -1)
|
|
{
|
|
group->hActiveProgram = NULL;
|
|
break;
|
|
}
|
|
|
|
lvItem.mask = LVIF_PARAM;
|
|
lvItem.iItem = iItem;
|
|
SendMessageW(group->hListView, LVM_GETITEMW, 0, (LPARAM)&lvItem);
|
|
group->hActiveProgram = (PROGRAM*)lvItem.lParam;
|
|
break;
|
|
}
|
|
|
|
case NM_DBLCLK:
|
|
{
|
|
iItem = ((LPNMITEMACTIVATE)lParam)->iItem;
|
|
if (iItem == -1)
|
|
break;
|
|
|
|
lvItem.mask = LVIF_PARAM;
|
|
lvItem.iItem = iItem;
|
|
SendMessageW(group->hListView, LVM_GETITEMW, 0, (LPARAM)&lvItem);
|
|
/* ... or use group->hActiveProgram */
|
|
PROGRAM_ExecuteProgram((PROGRAM*)lvItem.lParam);
|
|
break;
|
|
}
|
|
|
|
case LVN_BEGINDRAG:
|
|
{
|
|
POINT ptMin;
|
|
|
|
BOOL bFirst = TRUE;
|
|
for (iItem = SendMessageA(group->hListView, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
|
|
iItem != -1;
|
|
iItem = SendMessageA(group->hListView, LVM_GETNEXTITEM, iItem, LVNI_SELECTED))
|
|
{
|
|
if (bFirst)
|
|
{
|
|
group->hDragImageList = (HIMAGELIST)SendMessageA(group->hListView,
|
|
LVM_CREATEDRAGIMAGE,
|
|
iItem,
|
|
(LPARAM)&pt);
|
|
ptMin = pt;
|
|
bFirst = FALSE;
|
|
}
|
|
else
|
|
{
|
|
HIMAGELIST hOneImageList, hTempImageList;
|
|
|
|
hOneImageList = (HIMAGELIST)SendMessageA(group->hListView,
|
|
LVM_CREATEDRAGIMAGE,
|
|
iItem,
|
|
(LPARAM)&pt);
|
|
hTempImageList = ImageList_Merge(group->hDragImageList,
|
|
0,
|
|
hOneImageList,
|
|
0,
|
|
pt.x - ptMin.x,
|
|
pt.y - ptMin.y);
|
|
ImageList_Destroy(group->hDragImageList);
|
|
ImageList_Destroy(hOneImageList);
|
|
group->hDragImageList = hTempImageList;
|
|
ptMin.x = min(ptMin.x, pt.x);
|
|
ptMin.y = min(ptMin.y, pt.y);
|
|
}
|
|
}
|
|
// pt = ((LPNMLISTVIEW)lParam)->ptAction;
|
|
pt.x = ((LPNMLISTVIEW)lParam)->ptAction.x;
|
|
pt.y = ((LPNMLISTVIEW)lParam)->ptAction.y;
|
|
group->ptStart = pt;
|
|
pt.x -= ptMin.x;
|
|
pt.y -= ptMin.y;
|
|
ImageList_BeginDrag(group->hDragImageList, 0, pt.x, pt.y);
|
|
MapWindowPoints(group->hListView, Globals.hMDIWnd, &pt, 1);
|
|
ImageList_DragEnter(Globals.hMDIWnd, pt.x, pt.y);
|
|
group->bDragging = TRUE;
|
|
group->hOldCursor = GetCursor();
|
|
SetCapture(group->hWnd);
|
|
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_MOUSEMOVE:
|
|
if (group->bDragging)
|
|
{
|
|
pt.x = GET_X_LPARAM(lParam);
|
|
pt.y = GET_Y_LPARAM(lParam);
|
|
MapWindowPoints(group->hWnd, Globals.hMDIWnd, &pt, 1);
|
|
ImageList_DragMove(pt.x, pt.y);
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
if (group->bDragging)
|
|
{
|
|
// LVHITTESTINFO lvhti;
|
|
POINT ptHit;
|
|
|
|
group->bDragging = FALSE;
|
|
ImageList_DragLeave(Globals.hMDIWnd);
|
|
ImageList_EndDrag();
|
|
ImageList_Destroy(group->hDragImageList);
|
|
ReleaseCapture();
|
|
SetCursor(group->hOldCursor);
|
|
ptHit.x = GET_X_LPARAM(lParam);
|
|
ptHit.y = GET_Y_LPARAM(lParam);
|
|
MapWindowPoints(group->hWnd, group->hListView, &ptHit, 1);
|
|
for (iItem = SendMessageA(group->hListView, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
|
|
iItem != -1;
|
|
iItem = SendMessageA(group->hListView, LVM_GETNEXTITEM, iItem, LVNI_SELECTED))
|
|
{
|
|
SendMessageA(group->hListView, LVM_GETITEMPOSITION, iItem, (LPARAM)&pt);
|
|
pt.x += ptHit.x - group->ptStart.x;
|
|
pt.y += ptHit.y - group->ptStart.y;
|
|
SendMessageA(group->hListView, LVM_SETITEMPOSITION, iItem, MAKELPARAM(pt.x, pt.y));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return DefMDIChildProcW(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* GROUP_RegisterGroupWinClass
|
|
*/
|
|
|
|
ATOM GROUP_RegisterGroupWinClass(VOID)
|
|
{
|
|
WNDCLASSW wndClass;
|
|
|
|
wndClass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
|
|
wndClass.lpfnWndProc = GROUP_GroupWndProc;
|
|
wndClass.cbClsExtra = 0;
|
|
wndClass.cbWndExtra = sizeof(LONG_PTR);
|
|
wndClass.hInstance = Globals.hInstance;
|
|
wndClass.hIcon = LoadIconW(Globals.hInstance, MAKEINTRESOURCEW(IDI_GROUP_ICON));
|
|
wndClass.hCursor = LoadCursorW(NULL, MAKEINTRESOURCEW(IDC_ARROW));
|
|
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|
wndClass.lpszMenuName = NULL;
|
|
wndClass.lpszClassName = STRING_GROUP_WIN_CLASS_NAME;
|
|
|
|
return RegisterClassW(&wndClass);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* GROUP_NewGroup
|
|
*/
|
|
|
|
VOID GROUP_NewGroup(GROUPFORMAT format, BOOL bIsCommonGroup)
|
|
{
|
|
HANDLE hFile;
|
|
WCHAR szGrpFile[MAX_PATHNAME_LEN] = L"";
|
|
WCHAR szTitle[MAX_PATHNAME_LEN] = L"";
|
|
|
|
// ZeroMemory(szTitle, sizeof(szTitle));
|
|
// ZeroMemory(szGrpFile, sizeof(szGrpFile));
|
|
|
|
if (!DIALOG_GroupAttributes(format, szTitle, szGrpFile, MAX_PATHNAME_LEN))
|
|
return;
|
|
|
|
/*
|
|
* Just check whether the group file does exist. If it does, close the handle, because GRPFILE_ReadGroupFile will
|
|
* reopen the file for loading. If it doesn't exist, we create a new one.
|
|
*/
|
|
hFile = CreateFileW(szGrpFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
/* File doesn't exist */
|
|
PROGGROUP* hGroup = GROUP_AddGroup(format, bIsCommonGroup, szTitle, szGrpFile,
|
|
DEF_GROUP_WIN_XPOS, DEF_GROUP_WIN_YPOS,
|
|
DEF_GROUP_WIN_XPOS + DEF_GROUP_WIN_WIDTH, DEF_GROUP_WIN_YPOS + DEF_GROUP_WIN_HEIGHT,
|
|
0, 0, SW_SHOWNORMAL, 0, 0, FALSE, FALSE);
|
|
if (hGroup)
|
|
GRPFILE_WriteGroupFile(hGroup);
|
|
}
|
|
else
|
|
{
|
|
/* File exist */
|
|
CloseHandle(hFile);
|
|
GRPFILE_ReadGroupFile(szGrpFile, bIsCommonGroup);
|
|
}
|
|
|
|
/* FIXME Update progman.ini */
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* GROUP_AddGroup
|
|
*/
|
|
|
|
PROGGROUP*
|
|
GROUP_AddGroup(GROUPFORMAT format, BOOL bIsCommonGroup, LPCWSTR lpszName, LPCWSTR lpszGrpFile,
|
|
INT left, INT top, INT right, INT bottom, INT xMin, INT yMin, INT nCmdShow,
|
|
WORD cxIcon, WORD cyIcon, BOOL bOverwriteFileOk,
|
|
/* FIXME shouldn't be necessary */
|
|
BOOL bSuppressShowWindow)
|
|
{
|
|
PROGGROUP* hGroup;
|
|
PROGGROUP* hPrior;
|
|
PROGGROUP** p;
|
|
LPWSTR hName;
|
|
LPWSTR hGrpFile;
|
|
LPCWSTR GroupFileName;
|
|
INT skip;
|
|
INT width;
|
|
INT height;
|
|
INT seqnum;
|
|
MDICREATESTRUCTW mcs;
|
|
WINDOWPLACEMENT WndPl;
|
|
|
|
WndPl.length = sizeof(WndPl);
|
|
|
|
// FIXME: Use system default position in case we don't place the window at a given (x,y) coordinate.
|
|
|
|
if (bIsCommonGroup)
|
|
{
|
|
if (swscanf(lpszGrpFile,
|
|
L"%d %d %d %d %d %d %d %n",
|
|
&WndPl.rcNormalPosition.left,
|
|
&WndPl.rcNormalPosition.top,
|
|
&WndPl.rcNormalPosition.right,
|
|
&WndPl.rcNormalPosition.bottom,
|
|
&WndPl.ptMinPosition.x,
|
|
&WndPl.ptMinPosition.y,
|
|
&WndPl.showCmd,
|
|
&skip) == 7)
|
|
{
|
|
WndPl.flags = WPF_SETMINPOSITION;
|
|
width = WndPl.rcNormalPosition.right - WndPl.rcNormalPosition.left;
|
|
height = WndPl.rcNormalPosition.bottom - WndPl.rcNormalPosition.top;
|
|
GroupFileName = &lpszGrpFile[skip];
|
|
}
|
|
else
|
|
{
|
|
#if 0 // FIXME!
|
|
WndPl.rcNormalPosition.top = CW_USEDEFAULT;
|
|
WndPl.rcNormalPosition.left = CW_USEDEFAULT;
|
|
WndPl.rcNormalPosition.right = 0;
|
|
WndPl.rcNormalPosition.bottom = 0;
|
|
width = CW_USEDEFAULT;
|
|
height = CW_USEDEFAULT;
|
|
WndPl.showCmd = SW_SHOWNORMAL;
|
|
GroupFileName = lpszGrpFile;
|
|
#else
|
|
WndPl.flags = WPF_SETMINPOSITION;
|
|
WndPl.ptMinPosition.x = xMin;
|
|
WndPl.ptMinPosition.y = yMin;
|
|
WndPl.rcNormalPosition.left = left;
|
|
WndPl.rcNormalPosition.top = top;
|
|
WndPl.rcNormalPosition.right = right;
|
|
WndPl.rcNormalPosition.bottom = bottom;
|
|
width = right - left;
|
|
height = bottom - top;
|
|
WndPl.showCmd = nCmdShow;
|
|
GroupFileName = lpszGrpFile;
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WndPl.flags = WPF_SETMINPOSITION;
|
|
WndPl.ptMinPosition.x = xMin;
|
|
WndPl.ptMinPosition.y = yMin;
|
|
WndPl.rcNormalPosition.left = left;
|
|
WndPl.rcNormalPosition.top = top;
|
|
WndPl.rcNormalPosition.right = right;
|
|
WndPl.rcNormalPosition.bottom = bottom;
|
|
width = right - left;
|
|
height = bottom - top;
|
|
WndPl.showCmd = nCmdShow;
|
|
GroupFileName = lpszGrpFile;
|
|
}
|
|
|
|
hGroup = Alloc(HEAP_ZERO_MEMORY, sizeof(*hGroup));
|
|
hName = Alloc(HEAP_ZERO_MEMORY, (wcslen(lpszName) + 1) * sizeof(WCHAR));
|
|
hGrpFile = Alloc(HEAP_ZERO_MEMORY, (wcslen(GroupFileName) + 1) * sizeof(WCHAR));
|
|
if (!hGroup || !hName || !hGrpFile)
|
|
{
|
|
MAIN_MessageBoxIDS(IDS_OUT_OF_MEMORY, IDS_ERROR, MB_OK);
|
|
if (hGroup) Free(hGroup);
|
|
if (hName) Free(hName);
|
|
if (hGrpFile) Free(hGrpFile);
|
|
return NULL;
|
|
}
|
|
memcpy(hName , lpszName , (wcslen(lpszName) + 1) * sizeof(WCHAR));
|
|
memcpy(hGrpFile, GroupFileName, (wcslen(GroupFileName) + 1) * sizeof(WCHAR));
|
|
|
|
Globals.hActiveGroup = hGroup;
|
|
|
|
seqnum = 1;
|
|
hPrior = NULL;
|
|
for (p = &Globals.hGroups; *p; p = &hPrior->hNext)
|
|
{
|
|
hPrior = *p;
|
|
if (hPrior->seqnum >= seqnum)
|
|
seqnum = hPrior->seqnum + 1;
|
|
}
|
|
*p = hGroup;
|
|
|
|
hGroup->hPrior = hPrior;
|
|
hGroup->hNext = NULL;
|
|
hGroup->format = format;
|
|
hGroup->bIsCommonGroup = bIsCommonGroup;
|
|
hGroup->hName = hName;
|
|
hGroup->hGrpFile = hGrpFile;
|
|
hGroup->bOverwriteFileOk = bOverwriteFileOk;
|
|
hGroup->seqnum = seqnum;
|
|
hGroup->nCmdShow = nCmdShow;
|
|
#if 0
|
|
hGroup->x = x;
|
|
hGroup->y = y;
|
|
hGroup->width = width;
|
|
hGroup->height = height;
|
|
#endif
|
|
hGroup->iconx = cxIcon;
|
|
hGroup->icony = cyIcon;
|
|
hGroup->hPrograms = NULL;
|
|
hGroup->hActiveProgram = NULL;
|
|
hGroup->TagsSize = 0;
|
|
hGroup->Tags = NULL;
|
|
|
|
mcs.szClass = STRING_GROUP_WIN_CLASS_NAME;
|
|
mcs.szTitle = lpszName;
|
|
mcs.hOwner = NULL;
|
|
mcs.x = WndPl.rcNormalPosition.left;
|
|
mcs.y = WndPl.rcNormalPosition.top;
|
|
mcs.cx = width;
|
|
mcs.cy = height;
|
|
mcs.style = 0;
|
|
mcs.lParam = (LPARAM)hGroup;
|
|
|
|
hGroup->hWnd = (HWND)SendMessageW(Globals.hMDIWnd, WM_MDICREATE, 0, (LPARAM)&mcs);
|
|
|
|
SetWindowPlacement(hGroup->hWnd, &WndPl);
|
|
|
|
#if 1
|
|
if (!bSuppressShowWindow) /* FIXME shouldn't be necessary */
|
|
#endif
|
|
UpdateWindow(hGroup->hWnd);
|
|
|
|
return hGroup;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* GROUP_ModifyGroup
|
|
*/
|
|
|
|
VOID GROUP_ModifyGroup(PROGGROUP* hGroup)
|
|
{
|
|
WCHAR Dest[MAX_PATHNAME_LEN]; // szName
|
|
WCHAR szGrpFile[MAX_PATHNAME_LEN]; // szFile
|
|
|
|
wcsncpy(Dest, hGroup->hName, ARRAYSIZE(Dest));
|
|
wcsncpy(szGrpFile, hGroup->hGrpFile, ARRAYSIZE(szGrpFile));
|
|
|
|
if (!DIALOG_GroupAttributes(hGroup->format, Dest, szGrpFile, MAX_PATHNAME_LEN))
|
|
return;
|
|
|
|
if (wcscmp(szGrpFile, hGroup->hGrpFile))
|
|
hGroup->bOverwriteFileOk = FALSE;
|
|
|
|
MAIN_ReplaceString(&hGroup->hName, Dest);
|
|
MAIN_ReplaceString(&hGroup->hGrpFile, szGrpFile);
|
|
|
|
GRPFILE_WriteGroupFile(hGroup);
|
|
|
|
/* FIXME Delete old GrpFile if GrpFile changed */
|
|
|
|
/* FIXME Update progman.ini */
|
|
|
|
SetWindowTextW(hGroup->hWnd, Dest);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* GROUP_DeleteGroup
|
|
*/
|
|
|
|
VOID GROUP_DeleteGroup(PROGGROUP* hGroup)
|
|
{
|
|
if (Globals.hActiveGroup == hGroup)
|
|
Globals.hActiveGroup = NULL;
|
|
|
|
if (hGroup->hPrior)
|
|
hGroup->hPrior->hNext = hGroup->hNext;
|
|
else
|
|
Globals.hGroups = hGroup->hNext;
|
|
|
|
if (hGroup->hNext)
|
|
hGroup->hNext->hPrior = hGroup->hPrior;
|
|
|
|
while (hGroup->hPrograms)
|
|
PROGRAM_DeleteProgram(hGroup->hPrograms, FALSE);
|
|
|
|
/* FIXME Update progman.ini */
|
|
|
|
SendMessageW(Globals.hMDIWnd, WM_MDIDESTROY, (WPARAM)hGroup->hWnd, 0);
|
|
|
|
if (hGroup->Tags)
|
|
Free(hGroup->Tags);
|
|
Free(hGroup->hName);
|
|
Free(hGroup->hGrpFile);
|
|
Free(hGroup);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* GROUP_ShowGroupWindow
|
|
*/
|
|
|
|
/* FIXME shouldn't be necessary */
|
|
VOID GROUP_ShowGroupWindow(PROGGROUP* hGroup)
|
|
{
|
|
ShowWindow(hGroup->hWnd, hGroup->nCmdShow);
|
|
UpdateWindow(hGroup->hWnd);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* GROUP_ActiveGroup
|
|
*/
|
|
|
|
PROGGROUP* GROUP_ActiveGroup(VOID)
|
|
{
|
|
return Globals.hActiveGroup;
|
|
}
|