4 * Copyright 1996 Ulrich Schmid
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 * PROJECT: ReactOS Program Manager
23 * COPYRIGHT: GPL - See COPYING in the top level directory
24 * FILE: base/shell/progman/group.c
25 * PURPOSE: Program group files helper functions
26 * PROGRAMMERS: Ulrich Schmid
27 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
32 /***********************************************************************
40 GROUP_GroupWndProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
44 group
= (PROGGROUP
*)GetWindowLongPtrW(hWnd
, 0);
50 LPCREATESTRUCTW pcs
= (LPCREATESTRUCTW
)lParam
;
51 LPMDICREATESTRUCTW pMDIcs
= (LPMDICREATESTRUCTW
)pcs
->lpCreateParams
;
52 group
= (PROGGROUP
*)pMDIcs
->lParam
;
53 SetWindowLongPtrW(hWnd
, 0, (LONG_PTR
)group
);
55 if (group
->bIsCommonGroup
)
57 DefMDIChildProcW(hWnd
, WM_SETICON
, ICON_BIG
,
58 (LPARAM
)CopyImage(Globals
.hCommonGroupIcon
,
60 GetSystemMetrics(SM_CXICON
),
61 GetSystemMetrics(SM_CYICON
),
62 LR_COPYFROMRESOURCE
));
63 DefMDIChildProcW(hWnd
, WM_SETICON
, ICON_SMALL
,
64 (LPARAM
)CopyImage(Globals
.hCommonGroupIcon
,
66 GetSystemMetrics(SM_CXSMICON
),
67 GetSystemMetrics(SM_CYSMICON
),
68 LR_COPYFROMRESOURCE
));
72 DefMDIChildProcW(hWnd
, WM_SETICON
, ICON_BIG
,
73 (LPARAM
)CopyImage(Globals
.hPersonalGroupIcon
,
75 GetSystemMetrics(SM_CXICON
),
76 GetSystemMetrics(SM_CYICON
),
77 LR_COPYFROMRESOURCE
));
78 DefMDIChildProcW(hWnd
, WM_SETICON
, ICON_SMALL
,
79 (LPARAM
)CopyImage(Globals
.hPersonalGroupIcon
,
81 GetSystemMetrics(SM_CXSMICON
),
82 GetSystemMetrics(SM_CYSMICON
),
83 LR_COPYFROMRESOURCE
));
89 SetWindowLongPtrW(hWnd
, 0, 0);
93 SendMessageW(hWnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
97 if (wParam
== SC_CLOSE
) wParam
= SC_MINIMIZE
;
100 case WM_CHILDACTIVATE
:
101 case WM_NCLBUTTONDOWN
:
102 Globals
.hActiveGroup
= (PROGGROUP
*)GetWindowLongPtrW(hWnd
, 0);
103 Globals
.hActiveGroup
->hActiveProgram
= NULL
;
107 return DefMDIChildProcW(hWnd
, uMsg
, wParam
, lParam
);
110 /***********************************************************************
112 * GROUP_RegisterGroupWinClass
115 ATOM
GROUP_RegisterGroupWinClass(VOID
)
119 wndClass
.style
= CS_DBLCLKS
| CS_HREDRAW
| CS_VREDRAW
;
120 wndClass
.lpfnWndProc
= GROUP_GroupWndProc
;
121 wndClass
.cbClsExtra
= 0;
122 wndClass
.cbWndExtra
= sizeof(LONG_PTR
);
123 wndClass
.hInstance
= Globals
.hInstance
;
124 wndClass
.hIcon
= LoadIconW(Globals
.hInstance
, MAKEINTRESOURCEW(IDI_GROUP_ICON
));
125 wndClass
.hCursor
= LoadCursorW(NULL
, MAKEINTRESOURCEW(IDC_ARROW
));
126 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
127 wndClass
.lpszMenuName
= NULL
;
128 wndClass
.lpszClassName
= STRING_GROUP_WIN_CLASS_NAME
;
130 return RegisterClassW(&wndClass
);
133 /***********************************************************************
138 VOID
GROUP_NewGroup(GROUPFORMAT format
, BOOL bIsCommonGroup
)
141 WCHAR szGrpFile
[MAX_PATHNAME_LEN
] = L
"";
142 WCHAR szTitle
[MAX_PATHNAME_LEN
] = L
"";
144 // ZeroMemory(szTitle, sizeof(szTitle));
145 // ZeroMemory(szGrpFile, sizeof(szGrpFile));
147 if (!DIALOG_GroupAttributes(format
, szTitle
, szGrpFile
, MAX_PATHNAME_LEN
))
151 * Just check whether the group file does exist. If it does, close the handle, because GRPFILE_ReadGroupFile will
152 * reopen the file for loading. If it doesn't exist, we create a new one.
154 hFile
= CreateFileW(szGrpFile
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
155 if (hFile
== INVALID_HANDLE_VALUE
)
157 /* File doesn't exist */
158 PROGGROUP
* hGroup
= GROUP_AddGroup(format
, bIsCommonGroup
, szTitle
, szGrpFile
,
159 DEF_GROUP_WIN_XPOS
, DEF_GROUP_WIN_YPOS
,
160 DEF_GROUP_WIN_XPOS
+ DEF_GROUP_WIN_WIDTH
, DEF_GROUP_WIN_YPOS
+ DEF_GROUP_WIN_HEIGHT
,
161 0, 0, SW_SHOWNORMAL
, 0, 0, FALSE
, FALSE
);
163 GRPFILE_WriteGroupFile(hGroup
);
169 GRPFILE_ReadGroupFile(szGrpFile
, bIsCommonGroup
);
172 /* FIXME Update progman.ini */
175 /***********************************************************************
181 GROUP_AddGroup(GROUPFORMAT format
, BOOL bIsCommonGroup
, LPCWSTR lpszName
, LPCWSTR lpszGrpFile
,
182 INT left
, INT top
, INT right
, INT bottom
, INT xMin
, INT yMin
, INT nCmdShow
,
183 WORD cxIcon
, WORD cyIcon
, BOOL bOverwriteFileOk
,
184 /* FIXME shouldn't be necessary */
185 BOOL bSuppressShowWindow
)
192 LPCWSTR GroupFileName
;
197 MDICREATESTRUCTW mcs
;
198 WINDOWPLACEMENT WndPl
;
200 WndPl
.length
= sizeof(WndPl
);
202 // FIXME: Use system default position in case we don't place the window at a given (x,y) coordinate.
206 if (swscanf(lpszGrpFile
,
207 L
"%d %d %d %d %d %d %d %n",
208 &WndPl
.rcNormalPosition
.left
,
209 &WndPl
.rcNormalPosition
.top
,
210 &WndPl
.rcNormalPosition
.right
,
211 &WndPl
.rcNormalPosition
.bottom
,
212 &WndPl
.ptMinPosition
,
213 &WndPl
.ptMinPosition
.y
,
217 WndPl
.flags
= WPF_SETMINPOSITION
;
218 width
= WndPl
.rcNormalPosition
.right
- WndPl
.rcNormalPosition
.left
;
219 height
= WndPl
.rcNormalPosition
.bottom
- WndPl
.rcNormalPosition
.top
;
220 GroupFileName
= &lpszGrpFile
[skip
];
225 WndPl
.rcNormalPosition
.top
= CW_USEDEFAULT
;
226 WndPl
.rcNormalPosition
.left
= CW_USEDEFAULT
;
227 WndPl
.rcNormalPosition
.right
= 0;
228 WndPl
.rcNormalPosition
.bottom
= 0;
229 width
= CW_USEDEFAULT
;
230 height
= CW_USEDEFAULT
;
231 WndPl
.showCmd
= SW_SHOWNORMAL
;
232 GroupFileName
= lpszGrpFile
;
234 WndPl
.flags
= WPF_SETMINPOSITION
;
235 WndPl
.ptMinPosition
.x
= xMin
;
236 WndPl
.ptMinPosition
.y
= yMin
;
237 WndPl
.rcNormalPosition
.left
= left
;
238 WndPl
.rcNormalPosition
.top
= top
;
239 WndPl
.rcNormalPosition
.right
= right
;
240 WndPl
.rcNormalPosition
.bottom
= bottom
;
241 width
= right
- left
;
242 height
= bottom
- top
;
243 WndPl
.showCmd
= nCmdShow
;
244 GroupFileName
= lpszGrpFile
;
250 WndPl
.flags
= WPF_SETMINPOSITION
;
251 WndPl
.ptMinPosition
.x
= xMin
;
252 WndPl
.ptMinPosition
.y
= yMin
;
253 WndPl
.rcNormalPosition
.left
= left
;
254 WndPl
.rcNormalPosition
.top
= top
;
255 WndPl
.rcNormalPosition
.right
= right
;
256 WndPl
.rcNormalPosition
.bottom
= bottom
;
257 width
= right
- left
;
258 height
= bottom
- top
;
259 WndPl
.showCmd
= nCmdShow
;
260 GroupFileName
= lpszGrpFile
;
263 hGroup
= Alloc(HEAP_ZERO_MEMORY
, sizeof(*hGroup
));
264 hName
= Alloc(HEAP_ZERO_MEMORY
, (wcslen(lpszName
) + 1) * sizeof(WCHAR
));
265 hGrpFile
= Alloc(HEAP_ZERO_MEMORY
, (wcslen(GroupFileName
) + 1) * sizeof(WCHAR
));
266 if (!hGroup
|| !hName
|| !hGrpFile
)
268 MAIN_MessageBoxIDS(IDS_OUT_OF_MEMORY
, IDS_ERROR
, MB_OK
);
269 if (hGroup
) Free(hGroup
);
270 if (hName
) Free(hName
);
271 if (hGrpFile
) Free(hGrpFile
);
274 memcpy(hName
, lpszName
, (wcslen(lpszName
) + 1) * sizeof(WCHAR
));
275 memcpy(hGrpFile
, GroupFileName
, (wcslen(GroupFileName
) + 1) * sizeof(WCHAR
));
277 Globals
.hActiveGroup
= hGroup
;
281 for (p
= &Globals
.hGroups
; *p
; p
= &hPrior
->hNext
)
284 if (hPrior
->seqnum
>= seqnum
)
285 seqnum
= hPrior
->seqnum
+ 1;
289 hGroup
->hPrior
= hPrior
;
290 hGroup
->hNext
= NULL
;
291 hGroup
->format
= format
;
292 hGroup
->bIsCommonGroup
= bIsCommonGroup
;
293 hGroup
->hName
= hName
;
294 hGroup
->hGrpFile
= hGrpFile
;
295 hGroup
->bOverwriteFileOk
= bOverwriteFileOk
;
296 hGroup
->seqnum
= seqnum
;
297 hGroup
->nCmdShow
= nCmdShow
;
301 hGroup
->width
= width
;
302 hGroup
->height
= height
;
304 hGroup
->iconx
= cxIcon
;
305 hGroup
->icony
= cyIcon
;
306 hGroup
->hPrograms
= NULL
;
307 hGroup
->hActiveProgram
= NULL
;
308 hGroup
->TagsSize
= 0;
311 mcs
.szClass
= STRING_GROUP_WIN_CLASS_NAME
;
312 mcs
.szTitle
= lpszName
;
314 mcs
.x
= WndPl
.rcNormalPosition
.left
;
315 mcs
.y
= WndPl
.rcNormalPosition
.top
;
319 mcs
.lParam
= (LPARAM
)hGroup
;
321 hGroup
->hWnd
= (HWND
)SendMessageW(Globals
.hMDIWnd
, WM_MDICREATE
, 0, (LPARAM
)&mcs
);
323 SetWindowPlacement(hGroup
->hWnd
, &WndPl
);
326 if (!bSuppressShowWindow
) /* FIXME shouldn't be necessary */
328 UpdateWindow(hGroup
->hWnd
);
337 /***********************************************************************
342 VOID
GROUP_ModifyGroup(PROGGROUP
* hGroup
)
344 WCHAR Dest
[MAX_PATHNAME_LEN
]; // szName
345 WCHAR szGrpFile
[MAX_PATHNAME_LEN
]; // szFile
347 wcsncpy(Dest
, hGroup
->hName
, ARRAYSIZE(Dest
));
348 wcsncpy(szGrpFile
, hGroup
->hGrpFile
, ARRAYSIZE(szGrpFile
));
350 if (!DIALOG_GroupAttributes(hGroup
->format
, Dest
, szGrpFile
, MAX_PATHNAME_LEN
))
353 if (wcscmp(szGrpFile
, hGroup
->hGrpFile
))
354 hGroup
->bOverwriteFileOk
= FALSE
;
356 MAIN_ReplaceString(&hGroup
->hName
, Dest
);
357 MAIN_ReplaceString(&hGroup
->hGrpFile
, szGrpFile
);
359 GRPFILE_WriteGroupFile(hGroup
);
361 /* FIXME Delete old GrpFile if GrpFile changed */
363 /* FIXME Update progman.ini */
365 SetWindowTextW(hGroup
->hWnd
, Dest
);
368 /***********************************************************************
373 VOID
GROUP_DeleteGroup(PROGGROUP
* hGroup
)
375 if (Globals
.hActiveGroup
== hGroup
)
376 Globals
.hActiveGroup
= NULL
;
379 hGroup
->hPrior
->hNext
= hGroup
->hNext
;
381 Globals
.hGroups
= hGroup
->hNext
;
384 hGroup
->hNext
->hPrior
= hGroup
->hPrior
;
386 while (hGroup
->hPrograms
)
387 PROGRAM_DeleteProgram(hGroup
->hPrograms
, FALSE
);
389 /* FIXME Update progman.ini */
391 SendMessageW(Globals
.hMDIWnd
, WM_MDIDESTROY
, (WPARAM
)hGroup
->hWnd
, 0);
396 Free(hGroup
->hGrpFile
);
400 /***********************************************************************
402 * GROUP_ShowGroupWindow
405 /* FIXME shouldn't be necessary */
406 VOID
GROUP_ShowGroupWindow(PROGGROUP
* hGroup
)
408 ShowWindow(hGroup
->hWnd
, hGroup
->nCmdShow
);
409 UpdateWindow(hGroup
->hWnd
);
412 /***********************************************************************
417 PROGGROUP
* GROUP_ActiveGroup(VOID
)
419 return Globals
.hActiveGroup
;