526efb0f5f0d732605e6f64af0b2142cf64a4695
[reactos.git] / reactos / base / shell / progman / dialog.c
1 /*
2 * Program Manager
3 *
4 * Copyright 1996 Ulrich Schmid
5 * Copyright 2002 Sylvain Petreolle
6 * Copyright 2002 Andriy Palamarchuk
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23 /*
24 * PROJECT: ReactOS Program Manager
25 * COPYRIGHT: GPL - See COPYING in the top level directory
26 * FILE: base/shell/progman/dialog.c
27 * PURPOSE: ProgMan dialog boxes
28 * PROGRAMMERS: Ulrich Schmid
29 * Sylvain Petreolle
30 * Andriy Palamarchuk
31 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
32 */
33
34 #include "progman.h"
35 #include <strsafe.h>
36
37 #include <commdlg.h>
38
39 /***********************************************************************
40 *
41 * DIALOG_AddFilterItem and DIALOG_BrowseXXX
42 */
43
44 static
45 VOID
46 DIALOG_AddFilterItem(LPWSTR* p, UINT ids, LPCWSTR filter)
47 {
48 LoadStringW(Globals.hInstance, ids, *p, MAX_STRING_LEN);
49 *p += wcslen(*p) + 1;
50 lstrcpyW(*p, filter);
51 *p += wcslen(*p) + 1;
52 **p = '\0';
53 }
54
55 static
56 BOOL
57 DIALOG_Browse(HWND hWnd, LPCWSTR lpszzFilter, LPWSTR lpstrFile, INT nMaxFile)
58 {
59 OPENFILENAMEW openfilename;
60 WCHAR szDir[MAX_PATH];
61
62 ZeroMemory(&openfilename, sizeof(openfilename));
63
64 GetCurrentDirectoryW(ARRAYSIZE(szDir), szDir);
65
66 openfilename.lStructSize = sizeof(openfilename);
67 openfilename.hwndOwner = hWnd;
68 openfilename.hInstance = Globals.hInstance;
69 openfilename.lpstrFilter = lpszzFilter;
70 openfilename.lpstrFile = lpstrFile;
71 openfilename.nMaxFile = nMaxFile;
72 openfilename.lpstrInitialDir = szDir;
73 openfilename.Flags = 0;
74 openfilename.lpstrDefExt = L"exe";
75 openfilename.lpstrCustomFilter = NULL;
76 openfilename.nMaxCustFilter = 0;
77 openfilename.nFilterIndex = 0;
78 openfilename.lpstrFileTitle = NULL;
79 openfilename.nMaxFileTitle = 0;
80 openfilename.lpstrTitle = NULL;
81 openfilename.nFileOffset = 0;
82 openfilename.nFileExtension = 0;
83 openfilename.lCustData = 0;
84 openfilename.lpfnHook = NULL;
85 openfilename.lpTemplateName = NULL;
86
87 return GetOpenFileNameW(&openfilename);
88 }
89
90 static
91 BOOL
92 DIALOG_BrowsePrograms(HWND hWnd, LPWSTR lpszFile, INT nMaxFile)
93 {
94 WCHAR szzFilter[2 * MAX_STRING_LEN + 100];
95 LPWSTR p = szzFilter;
96
97 DIALOG_AddFilterItem(&p, IDS_PROGRAMS , L"*.exe;*.pif;*.com;*.bat;*.cmd");
98 DIALOG_AddFilterItem(&p, IDS_ALL_FILES, L"*.*");
99
100 return DIALOG_Browse(hWnd, szzFilter, lpszFile, nMaxFile);
101 }
102
103 static
104 BOOL
105 DIALOG_BrowseSymbols(HWND hWnd, LPWSTR lpszFile, INT nMaxFile)
106 {
107 WCHAR szzFilter[5 * MAX_STRING_LEN + 100];
108 LPWSTR p = szzFilter;
109
110 DIALOG_AddFilterItem(&p, IDS_SYMBOL_FILES, L"*.ico;*.exe;*.dll");
111 DIALOG_AddFilterItem(&p, IDS_PROGRAMS, L"*.exe");
112 DIALOG_AddFilterItem(&p, IDS_LIBRARIES_DLL, L"*.dll");
113 DIALOG_AddFilterItem(&p, IDS_SYMBOLS_ICO, L"*.ico");
114 DIALOG_AddFilterItem(&p, IDS_ALL_FILES, L"*.*");
115
116 return DIALOG_Browse(hWnd, szzFilter, lpszFile, nMaxFile);
117 }
118
119
120
121 /***********************************************************************
122 *
123 * DIALOG_New
124 */
125
126 LPCWSTR GroupFormatToFormatName(GROUPFORMAT Format)
127 {
128 static const LPCWSTR FormatNames[] =
129 {
130 L"Windows 3.1",
131 L"NT Ansi",
132 L"NT Unicode"
133 };
134
135 if (Format > NT_Unicode)
136 return NULL;
137 else
138 return FormatNames[Format];
139 }
140
141 typedef struct _NEW_ITEM_CONTEXT
142 {
143 INT nDefault;
144 INT nResult;
145 } NEW_ITEM_CONTEXT, *PNEW_ITEM_CONTEXT;
146
147 static
148 INT_PTR
149 CALLBACK
150 DIALOG_NEW_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
151 {
152 PNEW_ITEM_CONTEXT pNewItem;
153 GROUPFORMAT format;
154 INT iItem;
155
156 pNewItem = (PNEW_ITEM_CONTEXT)GetWindowLongPtrW(hDlg, 8);
157
158 switch (uMsg)
159 {
160 case WM_INITDIALOG:
161 {
162 pNewItem = (PNEW_ITEM_CONTEXT)lParam;
163 SetWindowLongPtrW(hDlg, 8, lParam);
164
165 for (format = Win_311; format <= NT_Unicode; ++format)
166 {
167 iItem = SendDlgItemMessageW(hDlg, PM_FORMAT, CB_INSERTSTRING, 0, (LPARAM)GroupFormatToFormatName(format));
168 if (iItem != CB_ERR && iItem != CB_ERRSPACE)
169 SendDlgItemMessageW(hDlg, PM_FORMAT, CB_SETITEMDATA, iItem, format);
170 }
171
172 SendDlgItemMessageW(hDlg, PM_FORMAT, CB_SETCURSEL, 0, 0);
173 CheckRadioButton(hDlg, PM_NEW_GROUP, PM_NEW_PROGRAM, pNewItem->nDefault);
174 CheckRadioButton(hDlg, PM_PERSONAL_GROUP, PM_COMMON_GROUP, PM_PERSONAL_GROUP);
175
176 EnableDlgItem(hDlg, PM_NEW_PROGRAM, GROUP_ActiveGroup() != NULL);
177
178 SendMessageW(hDlg, WM_COMMAND, pNewItem->nDefault, 0);
179 break;
180 }
181
182 case WM_COMMAND:
183 switch (LOWORD(wParam))
184 {
185 case PM_NEW_GROUP:
186 {
187 CheckRadioButton(hDlg, PM_NEW_GROUP, PM_NEW_PROGRAM, wParam);
188 EnableDlgItem(hDlg, PM_COMMON_GROUP , TRUE);
189 EnableDlgItem(hDlg, PM_PERSONAL_GROUP, TRUE);
190 EnableDlgItem(hDlg, PM_FORMAT_TXT, TRUE);
191 EnableDlgItem(hDlg, PM_FORMAT , TRUE);
192 return TRUE;
193 }
194
195 case PM_NEW_PROGRAM:
196 {
197 CheckRadioButton(hDlg, PM_NEW_GROUP, PM_NEW_PROGRAM, wParam);
198 EnableDlgItem(hDlg, PM_COMMON_GROUP , FALSE);
199 EnableDlgItem(hDlg, PM_PERSONAL_GROUP, FALSE);
200 EnableDlgItem(hDlg, PM_FORMAT_TXT, FALSE);
201 EnableDlgItem(hDlg, PM_FORMAT , FALSE);
202 return TRUE;
203 }
204
205 case IDHELP:
206 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
207 return TRUE;
208
209 case IDOK:
210 {
211 iItem = SendDlgItemMessageW(hDlg, PM_FORMAT, CB_GETCURSEL, 0, 0);
212
213 format = SendDlgItemMessageW(hDlg, PM_FORMAT, CB_GETITEMDATA, iItem, 0);
214 format = min(max(format, Win_311), NT_Unicode);
215
216 pNewItem->nResult = !!IsDlgButtonChecked(hDlg, PM_NEW_GROUP);
217 pNewItem->nResult |= (!!IsDlgButtonChecked(hDlg, PM_COMMON_GROUP) << 1);
218 pNewItem->nResult |= (format << 2);
219
220 EndDialog(hDlg, IDOK);
221 return TRUE;
222 }
223
224 case IDCANCEL:
225 EndDialog(hDlg, IDCANCEL);
226 return TRUE;
227 }
228 return FALSE;
229 }
230
231 return FALSE;
232 }
233
234 BOOL DIALOG_New(INT nDefault, PINT pnResult)
235 {
236 INT_PTR ret;
237 NEW_ITEM_CONTEXT NewItem;
238
239 *pnResult = 0;
240
241 NewItem.nDefault = nDefault;
242 NewItem.nResult = 0;
243 ret = DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_NEW), Globals.hMainWnd, DIALOG_NEW_DlgProc, (LPARAM)&NewItem);
244 if (ret == IDOK)
245 *pnResult = NewItem.nResult;
246
247 return (ret == IDOK);
248 }
249
250
251 /***********************************************************************
252 *
253 * DIALOG_CopyMove
254 */
255
256 typedef struct _COPY_MOVE_CONTEXT
257 {
258 PROGRAM* Program;
259 PROGGROUP* hToGroup;
260 BOOL bMove;
261 } COPY_MOVE_CONTEXT, *PCOPY_MOVE_CONTEXT;
262
263 static
264 INT_PTR
265 CALLBACK
266 DIALOG_COPY_MOVE_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
267 {
268 PROGGROUP* hGrpItem;
269 PROGGROUP* hGroup;
270
271 PCOPY_MOVE_CONTEXT pCopyMove;
272 INT iItem;
273
274 WCHAR text[MAX_STRING_LEN];
275
276 pCopyMove = (PCOPY_MOVE_CONTEXT)GetWindowLongPtrW(hDlg, 8);
277
278 switch (uMsg)
279 {
280 case WM_INITDIALOG:
281 {
282 pCopyMove = (PCOPY_MOVE_CONTEXT)lParam;
283 SetWindowLongPtrW(hDlg, 8, lParam);
284
285 if (pCopyMove->bMove)
286 {
287 LoadStringW(Globals.hInstance, IDS_MOVE_PROGRAM_1, text, ARRAYSIZE(text));
288 SetWindowTextW(hDlg, text);
289 LoadStringW(Globals.hInstance, IDS_MOVE_PROGRAM_2, text, ARRAYSIZE(text));
290 SetDlgItemTextW(hDlg, PM_COPY_MOVE_TXT, text);
291 }
292
293 /* List all the group names but the source group, in case we are doing a move */
294 for (hGroup = Globals.hGroups; hGroup; hGroup = hGroup->hNext)
295 {
296 if (!pCopyMove->bMove || hGroup != pCopyMove->Program->hGroup)
297 {
298 iItem = SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_ADDSTRING, 0, (LPARAM)hGroup->hName);
299 if (iItem != CB_ERR && iItem != CB_ERRSPACE)
300 SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_SETITEMDATA, iItem, (LPARAM)hGroup);
301 }
302 }
303 SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_SETCURSEL, 0, 0);
304 SetDlgItemTextW(hDlg, PM_PROGRAM , pCopyMove->Program->hName);
305 SetDlgItemTextW(hDlg, PM_FROM_GROUP, pCopyMove->Program->hGroup->hName);
306 break;
307 }
308
309 case WM_COMMAND:
310 switch (LOWORD(wParam))
311 {
312 case IDHELP:
313 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
314 return TRUE;
315
316 case IDOK:
317 {
318 /* Get the selected group */
319 iItem = SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_GETCURSEL, 0, 0);
320 hGrpItem = (PROGGROUP *)SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_GETITEMDATA, iItem, 0);
321 /* Check that it is indeed in the group list */
322 for (hGroup = Globals.hGroups; hGroup && hGroup != hGrpItem; hGroup = hGroup->hNext)
323 ;
324 if (pCopyMove->bMove)
325 {
326 if (hGrpItem == pCopyMove->Program->hGroup)
327 hGrpItem = NULL;
328 }
329 pCopyMove->hToGroup = hGrpItem;
330 EndDialog(hDlg, IDOK);
331 return TRUE;
332 }
333
334 case IDCANCEL:
335 EndDialog(hDlg, IDCANCEL);
336 return TRUE;
337 }
338 return FALSE;
339 }
340
341 return FALSE;
342 }
343
344 PROGGROUP* DIALOG_CopyMove(PROGRAM* hProgram, BOOL bMove)
345 {
346 COPY_MOVE_CONTEXT CopyMove;
347 INT_PTR ret;
348
349 CopyMove.bMove = bMove;
350 CopyMove.Program = hProgram;
351 CopyMove.hToGroup = NULL;
352 ret = DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_COPY_MOVE), Globals.hMainWnd, DIALOG_COPY_MOVE_DlgProc, (LPARAM)&CopyMove);
353
354 return (ret == IDOK ? CopyMove.hToGroup : NULL);
355 }
356
357 /***********************************************************************
358 *
359 * DIALOG_Delete
360 */
361
362 BOOL DIALOG_Delete(UINT ids_text_s, LPCWSTR lpszName)
363 {
364 return (MAIN_MessageBoxIDS_s(ids_text_s, lpszName, IDS_DELETE, MB_YESNO | MB_DEFBUTTON2) == IDYES);
365 }
366
367
368 /* Adapted from dll/win32/shell32/dialogs/dialogs.cpp!EnableOkButtonFromEditContents */
369 BOOL ValidateEditContents(HWND hDlg, INT nIDEditItem)
370 {
371 BOOL Enable = FALSE;
372 LPWSTR psz;
373 INT Length, n;
374 HWND Edit;
375
376 Edit = GetDlgItem(hDlg, nIDEditItem);
377 Length = GetWindowTextLengthW(Edit);
378
379 if (Length <= 0)
380 return FALSE;
381
382 psz = Alloc(0, (Length + 1) * sizeof(WCHAR));
383 if (psz)
384 {
385 GetWindowTextW(Edit, psz, Length + 1);
386 for (n = 0; n < Length && !Enable; ++n)
387 Enable = (psz[n] != ' ');
388 Free(psz);
389 }
390 else
391 {
392 Enable = TRUE;
393 }
394
395 return Enable;
396 }
397
398
399 /***********************************************************************
400 *
401 * DIALOG_GroupAttributes
402 */
403
404 typedef struct _GROUP_ATTRIBUTES_CONTEXT
405 {
406 GROUPFORMAT format;
407 LPWSTR lpszTitle;
408 LPWSTR lpszGrpFile;
409 INT nSize;
410 } GROUP_ATTRIBUTES_CONTEXT, *PGROUP_ATTRIBUTES_CONTEXT;
411
412 static
413 INT_PTR
414 CALLBACK
415 DIALOG_GROUP_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
416 {
417 PGROUP_ATTRIBUTES_CONTEXT pGroupAttributes;
418
419 pGroupAttributes = (PGROUP_ATTRIBUTES_CONTEXT)GetWindowLongPtrW(hDlg, 8);
420
421 switch (uMsg)
422 {
423 case WM_INITDIALOG:
424 {
425 DWORD evMask;
426
427 pGroupAttributes = (PGROUP_ATTRIBUTES_CONTEXT)lParam;
428 SetWindowLongPtrW(hDlg, 8, lParam);
429
430 /* Configure Richedit control for sending notification changes */
431 evMask = SendDlgItemMessageW(hDlg, PM_DESCRIPTION, EM_GETEVENTMASK, 0, 0) | ENM_CHANGE;
432 SendDlgItemMessageW(hDlg, PM_DESCRIPTION, EM_SETEVENTMASK, 0, (LPARAM)evMask);
433
434 SetDlgItemTextW(hDlg, PM_DESCRIPTION, pGroupAttributes->lpszTitle);
435
436 if (pGroupAttributes->format != Win_311)
437 {
438 EnableDlgItem(hDlg, PM_FILE, FALSE);
439 }
440 else
441 {
442 EnableDlgItem(hDlg, PM_FILE, TRUE);
443 SetDlgItemTextW(hDlg, PM_FILE, pGroupAttributes->lpszGrpFile);
444 }
445
446 EnableDlgItem(hDlg, IDOK, ValidateEditContents(hDlg, PM_DESCRIPTION));
447 break;
448 }
449
450 case WM_COMMAND:
451 switch (LOWORD(wParam))
452 {
453 case IDHELP:
454 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
455 return TRUE;
456
457 case PM_DESCRIPTION:
458 {
459 if (HIWORD(wParam) == EN_CHANGE)
460 EnableDlgItem(hDlg, IDOK, ValidateEditContents(hDlg, PM_DESCRIPTION));
461 return FALSE;
462 }
463
464 case IDOK:
465 {
466 GetDlgItemTextW(hDlg, PM_DESCRIPTION, pGroupAttributes->lpszTitle, pGroupAttributes->nSize);
467 if (pGroupAttributes->format)
468 *pGroupAttributes->lpszGrpFile = '\0';
469 else
470 GetDlgItemTextW(hDlg, PM_FILE, pGroupAttributes->lpszGrpFile, pGroupAttributes->nSize);
471 EndDialog(hDlg, IDOK);
472 return TRUE;
473 }
474
475 case IDCANCEL:
476 EndDialog(hDlg, IDCANCEL);
477 return TRUE;
478 }
479 return FALSE;
480 }
481
482 return FALSE;
483 }
484
485 BOOL DIALOG_GroupAttributes(GROUPFORMAT format, LPWSTR lpszTitle, LPWSTR lpszGrpFile, INT nSize)
486 {
487 INT_PTR ret;
488 GROUP_ATTRIBUTES_CONTEXT GroupAttributes;
489
490 GroupAttributes.format = format;
491 GroupAttributes.nSize = nSize;
492 GroupAttributes.lpszTitle = lpszTitle;
493 GroupAttributes.lpszGrpFile = lpszGrpFile;
494
495 ret = DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_GROUP), Globals.hMainWnd, DIALOG_GROUP_DlgProc, (LPARAM)&GroupAttributes);
496
497 return (ret == IDOK);
498 }
499
500
501 /***********************************************************************
502 *
503 * DIALOG_Symbol
504 */
505
506 /* Adapted from dll/win32/shell32/dialogs/dialogs.cpp!EnumPickIconResourceProc */
507 static
508 BOOL
509 CALLBACK
510 EnumPickIconResourceProc(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
511 {
512 HICON hIcon;
513 HWND hDlgCtrl = (HWND)lParam;
514 WCHAR szName[100];
515
516 if (IS_INTRESOURCE(lpszName))
517 swprintf(szName, L"%u", lpszName);
518 else
519 wcscpy(szName, lpszName);
520
521 hIcon = (HICON)LoadImageW(hModule, lpszName, IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
522 if (hIcon == NULL)
523 return TRUE;
524
525 SendMessageW(hDlgCtrl, LB_ADDSTRING, 0, (LPARAM)hIcon);
526 return TRUE;
527 }
528
529 static
530 VOID
531 DestroyIconList(HWND hDlgCtrl)
532 {
533 HICON hIcon;
534 UINT count;
535
536 count = SendMessageA(hDlgCtrl, LB_GETCOUNT, 0, 0);
537 if (count == LB_ERR || count == 0)
538 return;
539
540 while (count-- > 0)
541 {
542 hIcon = (HICON)SendMessageA(hDlgCtrl, LB_GETITEMDATA, 0, 0);
543 DestroyIcon(hIcon);
544 SendMessageA(hDlgCtrl, LB_DELETESTRING, 0, 0);
545 }
546 }
547
548 typedef struct _PICK_ICON_CONTEXT
549 {
550 HMODULE hLibrary;
551 HWND hDlgCtrl;
552 WCHAR szName[MAX_PATH]; // LPWSTR lpszIconFile; // INT nSize;
553 INT Index;
554 HICON hIcon;
555 } PICK_ICON_CONTEXT, *PPICK_ICON_CONTEXT;
556
557 #if 0
558
559 static struct
560 {
561 LPSTR lpszIconFile;
562 INT nSize;
563 HICON *lphIcon;
564 INT *lpnIconIndex;
565 } Symbol;
566
567 #endif
568
569 static
570 INT_PTR
571 CALLBACK
572 DIALOG_SYMBOL_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
573 {
574 WCHAR filename[MAX_PATHNAME_LEN];
575 PPICK_ICON_CONTEXT pIconContext;
576
577 pIconContext = (PPICK_ICON_CONTEXT)GetWindowLongPtrW(hDlg, 8);
578
579 switch (uMsg)
580 {
581 case WM_INITDIALOG:
582 {
583 pIconContext = (PPICK_ICON_CONTEXT)lParam;
584 SetWindowLongPtrW(hDlg, 8, lParam);
585
586 pIconContext->hDlgCtrl = GetDlgItem(hDlg, PM_SYMBOL_LIST);
587 SetDlgItemTextW(hDlg, PM_ICON_FILE, pIconContext->szName);
588 SendMessageA(pIconContext->hDlgCtrl, LB_SETITEMHEIGHT, 0, 32);
589
590 pIconContext->hLibrary = LoadLibraryExW(pIconContext->szName, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE);
591 if (pIconContext->hLibrary)
592 {
593 EnumResourceNamesW(pIconContext->hLibrary,
594 (LPCWSTR)RT_GROUP_ICON,
595 EnumPickIconResourceProc,
596 (LONG_PTR)pIconContext->hDlgCtrl);
597 FreeLibrary(pIconContext->hLibrary);
598 pIconContext->hLibrary = NULL;
599 }
600 SendMessageA(pIconContext->hDlgCtrl, LB_SETCURSEL, pIconContext->Index, 0);
601 return TRUE;
602 }
603
604 case WM_MEASUREITEM:
605 {
606 PMEASUREITEMSTRUCT measure = (PMEASUREITEMSTRUCT)lParam;
607 measure->itemWidth = 32;
608 measure->itemHeight = 32;
609 return TRUE;
610 }
611
612 case WM_DRAWITEM:
613 {
614 PDRAWITEMSTRUCT dis = (PDRAWITEMSTRUCT)lParam;
615
616 if (dis->itemState & ODS_SELECTED)
617 FillRect(dis->hDC, &dis->rcItem, (HBRUSH)(COLOR_HIGHLIGHT + 1));
618 else
619 FillRect(dis->hDC, &dis->rcItem, (HBRUSH)(COLOR_WINDOW + 1));
620
621 DrawIcon(dis->hDC, dis->rcItem.left, dis->rcItem.top, (HICON)dis->itemData);
622 return TRUE;
623 }
624
625 case WM_COMMAND:
626 switch (LOWORD(wParam))
627 {
628 case PM_BROWSE:
629 {
630 filename[0] = '\0';
631 if (!DIALOG_BrowseSymbols(hDlg, filename, ARRAYSIZE(filename)))
632 return TRUE;
633
634 if (_wcsnicmp(pIconContext->szName, filename, ARRAYSIZE(pIconContext->szName)) == 0)
635 return TRUE;
636
637 SetDlgItemTextW(hDlg, PM_ICON_FILE, filename);
638 DestroyIconList(pIconContext->hDlgCtrl);
639 pIconContext->hLibrary = LoadLibraryExW(filename, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE);
640 if (pIconContext->hLibrary)
641 {
642 EnumResourceNamesW(pIconContext->hLibrary,
643 (LPCWSTR)RT_GROUP_ICON,
644 EnumPickIconResourceProc,
645 (LONG_PTR)pIconContext->hDlgCtrl);
646 FreeLibrary(pIconContext->hLibrary);
647 pIconContext->hLibrary = NULL;
648 }
649 SendMessageA(pIconContext->hDlgCtrl, LB_SETCURSEL, 0, 0);
650 return TRUE;
651 }
652
653 case IDHELP:
654 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
655 return TRUE;
656
657 case IDOK:
658 {
659 INT nCurSel = SendMessageW(pIconContext->hDlgCtrl, LB_GETCURSEL, 0, 0);
660 GetDlgItemTextW(hDlg, PM_ICON_FILE, pIconContext->szName, ARRAYSIZE(pIconContext->szName));
661 pIconContext->hIcon = (HICON)SendMessageA(pIconContext->hDlgCtrl, LB_GETITEMDATA, nCurSel, 0);
662 pIconContext->hIcon = CopyIcon(pIconContext->hIcon);
663 DestroyIconList(pIconContext->hDlgCtrl);
664 EndDialog(hDlg, IDOK);
665 return TRUE;
666 }
667
668 case IDCANCEL:
669 DestroyIconList(pIconContext->hDlgCtrl);
670 EndDialog(hDlg, IDCANCEL);
671 return TRUE;
672 }
673 return FALSE;
674 }
675
676 return FALSE;
677 }
678
679 static
680 VOID
681 DIALOG_Symbol(HWND hWnd, HICON *lphIcon, LPWSTR lpszIconFile, INT *lpnIconIndex, INT nSize)
682 {
683 PICK_ICON_CONTEXT IconContext;
684
685 IconContext.Index = *lpnIconIndex;
686 StringCchCopyNW(IconContext.szName, ARRAYSIZE(IconContext.szName), lpszIconFile, nSize);
687
688 if (DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_SYMBOL), hWnd, DIALOG_SYMBOL_DlgProc, (LPARAM)&IconContext) != IDOK)
689 return;
690
691 StringCchCopyNW(lpszIconFile, nSize, IconContext.szName, ARRAYSIZE(IconContext.szName));
692 *lpnIconIndex = IconContext.Index;
693 *lphIcon = IconContext.hIcon;
694 }
695
696
697 /***********************************************************************
698 *
699 * DIALOG_ProgramAttributes
700 */
701
702 typedef struct _PROGRAM_ATTRIBUTES_CONTEXT
703 {
704 LPWSTR lpszTitle;
705 LPWSTR lpszCmdLine;
706 LPWSTR lpszWorkDir;
707 LPWSTR lpszIconFile;
708 LPWSTR lpszTmpIconFile;
709 INT nSize;
710 INT* lpnCmdShow;
711 INT* lpnHotKey;
712 // HWND hSelGroupWnd;
713 BOOL* lpbNewVDM; // unused!
714 HICON* lphIcon;
715 HICON hTmpIcon;
716 INT* lpnIconIndex;
717 INT nTmpIconIndex;
718 BOOL bCheckBinaryType;
719 } PROGRAM_ATTRIBUTES_CONTEXT, *PPROGRAM_ATTRIBUTES_CONTEXT;
720
721 static
722 INT_PTR
723 CALLBACK
724 DIALOG_PROGRAM_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
725 {
726 BOOL bEnable;
727 WCHAR filename[MAX_PATHNAME_LEN];
728 DWORD evMask;
729 DWORD dwBinaryType;
730 PPROGRAM_ATTRIBUTES_CONTEXT pProgramAttributes;
731
732 pProgramAttributes = (PPROGRAM_ATTRIBUTES_CONTEXT)GetWindowLongPtrW(hDlg, 8);
733
734 switch (uMsg)
735 {
736 case WM_INITDIALOG:
737 {
738 pProgramAttributes = (PPROGRAM_ATTRIBUTES_CONTEXT)lParam;
739 SetWindowLongPtrW(hDlg, 8, lParam);
740
741 evMask = SendDlgItemMessageW(hDlg, PM_COMMAND_LINE, EM_GETEVENTMASK, 0, 0) | ENM_CHANGE;
742 SendDlgItemMessageW(hDlg, PM_COMMAND_LINE, EM_SETEVENTMASK, 0, evMask);
743
744 SetDlgItemTextW(hDlg, PM_DESCRIPTION , pProgramAttributes->lpszTitle);
745 SetDlgItemTextW(hDlg, PM_COMMAND_LINE, pProgramAttributes->lpszCmdLine);
746 SetDlgItemTextW(hDlg, PM_DIRECTORY , pProgramAttributes->lpszWorkDir);
747
748 /* 0x0F 0x06 */
749 SendDlgItemMessageW(hDlg, PM_HOT_KEY, HKM_SETRULES, HKCOMB_C | HKCOMB_A | HKCOMB_S | HKCOMB_NONE, HOTKEYF_CONTROL | HOTKEYF_ALT);
750 SendDlgItemMessageW(hDlg, PM_HOT_KEY, HKM_SETHOTKEY, *pProgramAttributes->lpnHotKey, 0);
751
752 bEnable = ValidateEditContents(hDlg, PM_COMMAND_LINE);
753 EnableWindow(GetDlgItem(hDlg, IDOK), bEnable);
754 EnableWindow(GetDlgItem(hDlg, PM_OTHER_SYMBOL), bEnable);
755
756 CheckDlgButton(hDlg, PM_SYMBOL, *pProgramAttributes->lpnCmdShow == SW_SHOWMINNOACTIVE);
757
758 if (pProgramAttributes->bCheckBinaryType &&
759 (!GetBinaryTypeW(pProgramAttributes->lpszCmdLine, &dwBinaryType) || dwBinaryType != SCS_WOW_BINARY) )
760 {
761 EnableWindow(GetDlgItem(hDlg, PM_NEW_VDM), FALSE);
762 CheckDlgButton(hDlg, PM_NEW_VDM, BST_CHECKED);
763 }
764 else
765 {
766 EnableWindow(GetDlgItem(hDlg, PM_NEW_VDM), TRUE);
767 CheckDlgButton(hDlg, PM_NEW_VDM, *pProgramAttributes->lpbNewVDM);
768 }
769 SendDlgItemMessageW(hDlg, PM_ICON, STM_SETICON, (WPARAM)pProgramAttributes->hTmpIcon, 0);
770 break;
771 }
772
773 case WM_COMMAND:
774 switch (LOWORD(wParam))
775 {
776 case PM_NEW_VDM:
777 CheckDlgButton(hDlg, PM_NEW_VDM, !IsDlgButtonChecked(hDlg, PM_NEW_VDM));
778 return TRUE;
779
780 case PM_BROWSE:
781 {
782 filename[0] = '\0';
783 if (DIALOG_BrowsePrograms(hDlg, filename, ARRAYSIZE(filename)))
784 {
785 SetDlgItemTextW(hDlg, PM_COMMAND_LINE, filename);
786 if (pProgramAttributes->bCheckBinaryType &&
787 (!GetBinaryTypeW(filename, &dwBinaryType) || dwBinaryType != SCS_WOW_BINARY))
788 {
789 EnableWindow(GetDlgItem(hDlg, PM_NEW_VDM), FALSE);
790 CheckDlgButton(hDlg, PM_NEW_VDM, BST_CHECKED);
791 }
792 else
793 {
794 EnableWindow(GetDlgItem(hDlg, PM_NEW_VDM), TRUE);
795 CheckDlgButton(hDlg, PM_NEW_VDM, BST_UNCHECKED);
796 }
797 }
798 return TRUE;
799 }
800
801 case IDHELP:
802 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
803 return TRUE;
804
805 case PM_SYMBOL:
806 CheckDlgButton(hDlg, PM_SYMBOL, !IsDlgButtonChecked(hDlg, PM_SYMBOL));
807 return TRUE;
808
809 case PM_OTHER_SYMBOL:
810 {
811 DIALOG_Symbol(hDlg,
812 &pProgramAttributes->hTmpIcon,
813 pProgramAttributes->lpszTmpIconFile,
814 &pProgramAttributes->nTmpIconIndex,
815 MAX_PATHNAME_LEN);
816
817 SendDlgItemMessageW(hDlg, PM_ICON, STM_SETICON, (WPARAM)pProgramAttributes->hTmpIcon, 0);
818 return TRUE;
819 }
820
821 case PM_COMMAND_LINE:
822 {
823 if (HIWORD(wParam) == EN_CHANGE)
824 {
825 bEnable = ValidateEditContents(hDlg, PM_COMMAND_LINE);
826 EnableWindow(GetDlgItem(hDlg, IDOK), bEnable);
827 EnableWindow(GetDlgItem(hDlg, PM_OTHER_SYMBOL), bEnable);
828 }
829 return FALSE;
830 }
831
832 case IDOK:
833 {
834 GetDlgItemTextW(hDlg, PM_DESCRIPTION , pProgramAttributes->lpszTitle , pProgramAttributes->nSize);
835 GetDlgItemTextW(hDlg, PM_COMMAND_LINE, pProgramAttributes->lpszCmdLine, pProgramAttributes->nSize);
836 GetDlgItemTextW(hDlg, PM_DIRECTORY , pProgramAttributes->lpszWorkDir, pProgramAttributes->nSize);
837 if (pProgramAttributes->hTmpIcon)
838 {
839 #if 0
840 if (*pProgramAttributes->lphIcon)
841 DestroyIcon(*pProgramAttributes->lphIcon);
842 #endif
843 *pProgramAttributes->lphIcon = pProgramAttributes->hTmpIcon;
844 *pProgramAttributes->lpnIconIndex = pProgramAttributes->nTmpIconIndex;
845 lstrcpynW(pProgramAttributes->lpszIconFile, pProgramAttributes->lpszTmpIconFile, pProgramAttributes->nSize);
846 }
847 *pProgramAttributes->lpnHotKey = SendDlgItemMessageW(hDlg, PM_HOT_KEY, HKM_GETHOTKEY, 0, 0);
848 *pProgramAttributes->lpnCmdShow = IsDlgButtonChecked(hDlg, PM_SYMBOL) ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL;
849 *pProgramAttributes->lpbNewVDM = IsDlgButtonChecked(hDlg, PM_NEW_VDM);
850 EndDialog(hDlg, IDOK);
851 return TRUE;
852 }
853
854 case IDCANCEL:
855 EndDialog(hDlg, IDCANCEL);
856 return TRUE;
857 }
858 return FALSE;
859 }
860
861 return FALSE;
862 }
863
864 BOOL
865 DIALOG_ProgramAttributes(LPWSTR lpszTitle, LPWSTR lpszCmdLine, LPWSTR lpszWorkDir, LPWSTR lpszIconFile,
866 HICON* lphIcon, INT* lpnIconIndex, INT* lpnHotKey, INT* lpnCmdShow, BOOL* lpbNewVDM, INT nSize)
867 {
868 INT_PTR ret;
869 WCHAR szTmpIconFile[MAX_PATHNAME_LEN];
870 PROGRAM_ATTRIBUTES_CONTEXT ProgramAttributes;
871 DWORD dwSize;
872 DWORD dwType;
873
874 ProgramAttributes.nSize = nSize;
875 ProgramAttributes.lpszTitle = lpszTitle;
876 ProgramAttributes.lpszCmdLine = lpszCmdLine;
877 ProgramAttributes.lpszWorkDir = lpszWorkDir;
878 ProgramAttributes.lpszIconFile = lpszIconFile;
879 ProgramAttributes.lpnCmdShow = lpnCmdShow;
880 ProgramAttributes.lpnHotKey = lpnHotKey;
881 ProgramAttributes.lpbNewVDM = lpbNewVDM;
882 ProgramAttributes.lphIcon = lphIcon;
883 ProgramAttributes.lpnIconIndex = lpnIconIndex;
884
885 dwSize = sizeof(ProgramAttributes.bCheckBinaryType);
886 if (RegQueryValueExW(Globals.hKeyPMSettings,
887 L"CheckBinaryType",
888 0,
889 &dwType,
890 (LPBYTE)&ProgramAttributes.bCheckBinaryType,
891 &dwSize) != ERROR_SUCCESS
892 || dwType != REG_DWORD)
893 {
894 ProgramAttributes.bCheckBinaryType = TRUE;
895 }
896
897 #if 0
898 ProgramAttributes.hTmpIcon = NULL;
899 #else
900 ProgramAttributes.hTmpIcon = *lphIcon;
901 #endif
902 ProgramAttributes.nTmpIconIndex = *lpnIconIndex;
903 ProgramAttributes.lpszTmpIconFile = szTmpIconFile;
904 wcsncpy(szTmpIconFile, lpszIconFile, ARRAYSIZE(szTmpIconFile));
905
906 ret = DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_PROGRAM), Globals.hMainWnd, DIALOG_PROGRAM_DlgProc, (LPARAM)&ProgramAttributes);
907 return (ret == IDOK);
908 }
909
910
911 /***********************************************************************
912 *
913 * DIALOG_Execute
914 */
915
916 typedef struct _EXECUTE_CONTEXT
917 {
918 HKEY hKeyPMRecentFilesList;
919 DWORD dwMaxFiles;
920 BOOL bCheckBinaryType;
921 } EXECUTE_CONTEXT, *PEXECUTE_CONTEXT;
922
923 static
924 INT_PTR
925 CALLBACK
926 DIALOG_EXECUTE_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
927 {
928 WCHAR szFile[MAX_PATHNAME_LEN]; // filename
929 DWORD BinaryType;
930 PEXECUTE_CONTEXT pExecuteContext;
931
932 pExecuteContext = (PEXECUTE_CONTEXT)GetWindowLongPtrW(hDlg, 8);
933
934 switch (uMsg)
935 {
936 case WM_INITDIALOG:
937 {
938 pExecuteContext = (PEXECUTE_CONTEXT)lParam;
939 SetWindowLongPtrW(hDlg, 8, lParam);
940
941 EnableDlgItem(hDlg, IDOK, ValidateEditContents(hDlg, PM_COMMAND));
942
943 if (pExecuteContext->bCheckBinaryType)
944 {
945 EnableDlgItem(hDlg, PM_NEW_VDM, FALSE);
946 CheckDlgButton(hDlg, PM_NEW_VDM, BST_CHECKED);
947 }
948 else
949 {
950 EnableDlgItem(hDlg, PM_NEW_VDM, TRUE);
951 }
952
953 break;
954 }
955
956 case WM_COMMAND:
957 switch (LOWORD(wParam))
958 {
959 case PM_SYMBOL:
960 CheckDlgButton(hDlg, PM_SYMBOL, !IsDlgButtonChecked(hDlg, PM_SYMBOL));
961 return TRUE;
962
963 case PM_NEW_VDM:
964 CheckDlgButton(hDlg, PM_NEW_VDM, !IsDlgButtonChecked(hDlg, PM_NEW_VDM));
965 return TRUE;
966
967 case PM_BROWSE:
968 {
969 szFile[0] = '\0';
970 if (DIALOG_BrowsePrograms(hDlg, szFile, ARRAYSIZE(szFile)))
971 {
972 SetWindowTextW(GetDlgItem(hDlg, PM_COMMAND), szFile);
973 SetFocus(GetDlgItem(hDlg, IDOK));
974 if (pExecuteContext->bCheckBinaryType &&
975 (!GetBinaryTypeW(szFile, &BinaryType) || BinaryType != SCS_WOW_BINARY) )
976 {
977 EnableDlgItem(hDlg, PM_NEW_VDM, FALSE);
978 CheckDlgButton(hDlg, PM_NEW_VDM, BST_CHECKED);
979 }
980 else
981 {
982 EnableDlgItem(hDlg, PM_NEW_VDM, TRUE);
983 CheckDlgButton(hDlg, PM_NEW_VDM, BST_UNCHECKED);
984 }
985 }
986 return TRUE;
987 }
988
989 case PM_COMMAND:
990 {
991 if (HIWORD(wParam) == CBN_EDITCHANGE)
992 {
993 EnableDlgItem(hDlg, IDOK, ValidateEditContents(hDlg, PM_COMMAND));
994 }
995 return FALSE;
996 }
997
998 case IDHELP:
999 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
1000 return TRUE;
1001
1002 case IDOK:
1003 {
1004 GetDlgItemTextW(hDlg, PM_COMMAND, szFile, ARRAYSIZE(szFile));
1005 ShellExecuteW(NULL, NULL, szFile, NULL, NULL, IsDlgButtonChecked(hDlg, PM_SYMBOL) ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL);
1006 if (Globals.bMinOnRun)
1007 CloseWindow(Globals.hMainWnd);
1008 EndDialog(hDlg, IDOK);
1009 return TRUE;
1010 }
1011
1012 case IDCANCEL:
1013 EndDialog(hDlg, IDCANCEL);
1014 return TRUE;
1015 }
1016 return FALSE;
1017 }
1018
1019 return FALSE;
1020 }
1021
1022 VOID DIALOG_Execute(VOID)
1023 {
1024 EXECUTE_CONTEXT ExecuteContext;
1025 LONG lRet;
1026 DWORD dwSize;
1027 DWORD dwType;
1028
1029 lRet = RegCreateKeyExW(Globals.hKeyProgMan,
1030 L"Recent File List",
1031 0,
1032 NULL,
1033 0,
1034 KEY_READ | KEY_WRITE,
1035 NULL,
1036 &ExecuteContext.hKeyPMRecentFilesList,
1037 NULL);
1038
1039 dwSize = sizeof(ExecuteContext.dwMaxFiles);
1040 lRet = RegQueryValueExW(ExecuteContext.hKeyPMRecentFilesList,
1041 L"Max Files",
1042 NULL,
1043 &dwType,
1044 (LPBYTE)&ExecuteContext.dwMaxFiles,
1045 &dwSize);
1046 if (lRet != ERROR_SUCCESS || dwType != REG_DWORD)
1047 {
1048 ExecuteContext.dwMaxFiles = 4;
1049 dwSize = sizeof(ExecuteContext.dwMaxFiles);
1050 lRet = RegSetValueExW(ExecuteContext.hKeyPMRecentFilesList,
1051 L"Max Files",
1052 0,
1053 REG_DWORD,
1054 (LPBYTE)&ExecuteContext.dwMaxFiles,
1055 sizeof(ExecuteContext.dwMaxFiles));
1056 }
1057
1058 dwSize = sizeof(ExecuteContext.bCheckBinaryType);
1059 lRet = RegQueryValueExW(Globals.hKeyPMSettings,
1060 L"CheckBinaryType",
1061 NULL,
1062 &dwType,
1063 (LPBYTE)&ExecuteContext.bCheckBinaryType,
1064 &dwSize);
1065 if (lRet != ERROR_SUCCESS || dwType != REG_DWORD)
1066 {
1067 ExecuteContext.bCheckBinaryType = TRUE;
1068 }
1069
1070 DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_EXECUTE), Globals.hMainWnd, DIALOG_EXECUTE_DlgProc, (LPARAM)&ExecuteContext);
1071
1072 RegCloseKey(ExecuteContext.hKeyPMRecentFilesList);
1073 }