4 * Copyright 1996 Ulrich Schmid
5 * Copyright 2002 Sylvain Petreolle
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * PROJECT: ReactOS Program Manager
24 * COPYRIGHT: GPL - See COPYING in the top level directory
25 * FILE: base/shell/progman/main.c
26 * PURPOSE: ProgMan entry point & MDI window
27 * PROGRAMMERS: Ulrich Schmid
29 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
36 #define WC_MDICLIENTA "MDICLIENT"
37 #define WC_MDICLIENTW L"MDICLIENT"
40 #define WC_MDICLIENT WC_MDICLIENTW
42 #define WC_MDICLIENT WC_MDICLIENTA
47 static VOID
MAIN_LoadGroups(VOID
);
48 static VOID
MAIN_MenuCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
);
49 static ATOM
MAIN_RegisterMainWinClass(VOID
);
50 static VOID
MAIN_CreateMainWindow(VOID
);
51 static VOID
MAIN_CreateMDIWindow(VOID
);
52 static VOID
MAIN_AutoStart(VOID
);
55 #define BUFFER_SIZE 1024
60 * Memory management functions
63 Alloc(IN DWORD dwFlags
,
66 return HeapAlloc(GetProcessHeap(), dwFlags
, dwBytes
);
72 return HeapFree(GetProcessHeap(), 0, lpMem
);
76 ReAlloc(IN DWORD dwFlags
,
80 return HeapReAlloc(GetProcessHeap(), dwFlags
, lpMem
, dwBytes
);
84 AppendToBuffer(IN PVOID pBuffer
,
85 IN PSIZE_T pdwBufferSize
,
92 dwBufferSize
= dwDataSize
+ *pdwBufferSize
;
95 pTmp
= ReAlloc(0, pBuffer
, dwBufferSize
);
97 pTmp
= Alloc(0, dwBufferSize
);
102 memcpy((PVOID
)((ULONG_PTR
)pTmp
+ *pdwBufferSize
), pData
, dwDataSize
);
103 *pdwBufferSize
= dwBufferSize
;
114 PrintStringV(IN LPCWSTR szStr
,
119 _vsnwprintf(Buffer
, ARRAYSIZE(Buffer
), szStr
, args
);
120 MessageBoxW(Globals
.hMainWnd
, Buffer
, L
"Information", MB_OK
);
124 PrintString(IN LPCWSTR szStr
, ...)
128 va_start(args
, szStr
);
129 PrintStringV(szStr
, args
);
134 PrintResourceString(IN UINT uID
, ...)
140 LoadStringW(Globals
.hInstance
, uID
, Buffer
, ARRAYSIZE(Buffer
));
141 PrintStringV(Buffer
, args
);
146 PrintWin32Error(IN LPWSTR Message
, IN DWORD ErrorCode
)
150 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
151 NULL
, ErrorCode
, MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
152 (LPWSTR
)&lpMsgBuf
, 0, NULL
);
154 PrintString(L
"%s: %s\n", Message
, lpMsgBuf
);
158 int ShowLastWin32Error(VOID
)
161 LPWSTR lpMsgBuf
= NULL
;
164 dwError
= GetLastError();
166 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
167 NULL
, dwError
, MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
168 (LPWSTR
)&lpMsgBuf
, 0, NULL
);
169 _snwprintf(Buffer
, ARRAYSIZE(Buffer
), L
"Error %d: %s\n", dwError
, lpMsgBuf
);
171 return MessageBoxW(Globals
.hMainWnd
, Buffer
, L
"Error", MB_OK
);
180 /* Copied and adapted from dll/win32/userenv/environment.c!GetUserAndDomainName */
183 GetUserAndDomainName(OUT LPWSTR
* UserName
,
184 OUT LPWSTR
* DomainName
)
188 DWORD cbTokenBuffer
= 0;
189 PTOKEN_USER pUserToken
;
191 LPWSTR lpUserName
= NULL
;
192 LPWSTR lpDomainName
= NULL
;
193 DWORD cbUserName
= 0;
194 DWORD cbDomainName
= 0;
196 SID_NAME_USE SidNameUse
;
198 /* Get the process token */
199 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
202 /* Retrieve token's information */
203 if (!GetTokenInformation(hToken
, TokenUser
, NULL
, 0, &cbTokenBuffer
))
205 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
212 pUserToken
= Alloc(HEAP_ZERO_MEMORY
, cbTokenBuffer
);
219 if (!GetTokenInformation(hToken
, TokenUser
, pUserToken
, cbTokenBuffer
, &cbTokenBuffer
))
228 /* Retrieve the domain and user name */
229 if (!LookupAccountSidW(NULL
,
230 pUserToken
->User
.Sid
,
237 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
244 lpUserName
= Alloc(HEAP_ZERO_MEMORY
, cbUserName
* sizeof(WCHAR
));
245 if (lpUserName
== NULL
)
251 lpDomainName
= Alloc(HEAP_ZERO_MEMORY
, cbDomainName
* sizeof(WCHAR
));
252 if (lpDomainName
== NULL
)
258 if (!LookupAccountSidW(NULL
,
259 pUserToken
->User
.Sid
,
270 *UserName
= lpUserName
;
271 *DomainName
= lpDomainName
;
276 if (lpUserName
!= NULL
)
279 if (lpDomainName
!= NULL
)
295 MAIN_SetMainWindowTitle(VOID
)
300 LPWSTR lpDomainName
= NULL
;
301 LPWSTR lpUserName
= NULL
;
303 if (GetUserAndDomainName(&lpUserName
, &lpDomainName
) && lpUserName
&& lpDomainName
)
305 size
= (256 + 3 + wcslen(lpDomainName
) + wcslen(lpUserName
) + 1) * sizeof(WCHAR
);
306 caption
= Alloc(HEAP_ZERO_MEMORY
, size
);
309 swprintf(caption
, L
"%s - %s\\%s", szTitle
, lpDomainName
, lpUserName
);
310 SetWindowTextW(Globals
.hMainWnd
, caption
);
315 SetWindowTextW(Globals
.hMainWnd
, szTitle
);
320 SetWindowTextW(Globals
.hMainWnd
, szTitle
);
323 if (lpUserName
) Free(lpUserName
);
324 if (lpDomainName
) Free(lpDomainName
);
332 MAIN_LoadSettings(VOID
)
339 const LPCWSTR lpszIniFile
= L
"progman.ini";
340 WCHAR szWinDir
[MAX_PATH
];
352 bIsIniMigrated
= FALSE
;
356 /* Try to create/open the Program Manager user key */
357 if (RegCreateKeyExW(HKEY_CURRENT_USER
,
358 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager",
361 REG_OPTION_NON_VOLATILE
,
362 KEY_READ
| KEY_WRITE
,
364 &Globals
.hKeyProgMan
,
365 NULL
) != ERROR_SUCCESS
)
371 * TODO: Add the explanation for the migration...
373 dwSize
= sizeof(Value
);
374 lRet
= RegQueryValueExW(Globals
.hKeyProgMan
, L
"IniMigrated", NULL
, &dwType
, (LPBYTE
)&Value
, &dwSize
);
375 if (lRet
!= ERROR_SUCCESS
|| dwType
!= REG_DWORD
)
377 bIsIniMigrated
= !!Value
;
381 /* The migration was already done, just load the settings */
385 /* Perform the migration */
387 bIsIniMigrated
= TRUE
;
388 dwSize
= ARRAYSIZE(dummy
);
390 GetPrivateProfileSectionW(L
"Settings", dummy
, dwSize
, lpszIniFile
);
391 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
395 GetPrivateProfileSectionW(L
"Groups", dummy
, dwSize
, lpszIniFile
);
396 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
399 GetWindowsDirectoryW(szWinDir
, ARRAYSIZE(szWinDir
));
400 // NOTE: GCC complains we cannot use the "\u2022" (UNICODE Code Point) notation for specifying the bullet character,
401 // because it's only available in C++ or in C99. On the contrary MSVC is fine with it.
402 // Instead we use a hex specification for the character: "\x2022".
403 // Note also that the character "\x07" gives also a bullet, but a larger one.
405 L
"The Program Manager has detected the presence of a legacy settings file PROGMAN.INI in the directory '%s' "
406 L
"and is going to migrate its contents into the current-user Program Manager settings registry key:\n"
407 L
"HKCU\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager"
409 L
"\x2022 The migration operation will potentially overwrite all the existing current-user Program Manager settings in the registry by those stored in the PROGMAN.INI file.\n"
411 L
"\x2022 The migration is done once, so that, at the next launch of the Program Manager, the new migrated settings are directly used.\n"
413 L
"\x2022 It is possible to trigger later the migration by manually deleting the registry value \"IniMigrated\" under the current-user Program Manager settings registry key (specified above).\n"
415 L
"Would you like to migrate its contents into the registry?",
418 for (dwSize
= BUFFER_SIZE
; ; dwSize
+= BUFFER_SIZE
)
420 lpszSections
= Alloc(0, dwSize
* sizeof(WCHAR
));
421 dwRet
= GetPrivateProfileSectionNamesW(lpszSections
, dwSize
, lpszIniFile
);
422 if (dwRet
< dwSize
- 2)
426 lpszSection
= lpszSections
;
429 lRet
= RegCreateKeyExW(Globals
.hKeyProgMan
,
433 REG_OPTION_NON_VOLATILE
,
438 if (lRet
== ERROR_SUCCESS
)
440 for (dwSize
= BUFFER_SIZE
; ; dwSize
+= BUFFER_SIZE
)
442 lpszData
= Alloc(0, dwSize
* sizeof(WCHAR
));
443 dwRet
= GetPrivateProfileSectionW(lpszSection
, lpszData
, dwSize
, lpszIniFile
);
444 if (dwRet
< dwSize
- 2)
448 lpszKeyValue
= lpszData
;
449 while (*lpszKeyValue
)
451 lpszKey
= lpszKeyValue
;
452 lpszValue
= wcschr(lpszKeyValue
, L
'=');
453 lpszKeyValue
+= (wcslen(lpszKeyValue
) + 1);
458 Value
= wcstoul(lpszValue
, &lpszTmp
, 0);
459 if (lpszTmp
- lpszValue
>= wcslen(lpszValue
))
461 lpszValue
= (LPWSTR
)&Value
;
462 dwSize
= sizeof(Value
);
467 dwSize
= wcslen(lpszValue
) * sizeof(WCHAR
);
476 lRet
= RegSetValueExW(hKey
, lpszKey
, 0, dwType
, (LPBYTE
)lpszValue
, dwSize
);
480 lpszSection
+= (wcslen(lpszSection
) + 1);
487 RegSetValueExW(Globals
.hKeyProgMan
, L
"IniMigrated", 0, REG_DWORD
, (LPBYTE
)&Value
, sizeof(Value
));
491 /* Create the necessary registry keys for the Program Manager and load its settings from the registry */
493 lRet
= RegCreateKeyExW(Globals
.hKeyProgMan
,
497 REG_OPTION_NON_VOLATILE
,
498 KEY_READ
| KEY_WRITE
,
500 &Globals
.hKeyPMSettings
,
503 lRet
= RegCreateKeyExW(Globals
.hKeyProgMan
,
507 REG_OPTION_NON_VOLATILE
,
508 KEY_READ
| KEY_WRITE
,
510 &Globals
.hKeyPMCommonGroups
,
513 lRet
= RegCreateKeyExW(Globals
.hKeyProgMan
,
517 REG_OPTION_NON_VOLATILE
,
518 KEY_READ
| KEY_WRITE
,
520 &Globals
.hKeyPMAnsiGroups
,
523 lRet
= RegCreateKeyExW(Globals
.hKeyProgMan
,
527 REG_OPTION_NON_VOLATILE
,
528 KEY_READ
| KEY_WRITE
,
530 &Globals
.hKeyPMUnicodeGroups
,
533 lRet
= RegCreateKeyExW(HKEY_CURRENT_USER
,
537 REG_OPTION_NON_VOLATILE
,
538 KEY_READ
| KEY_WRITE
,
540 &Globals
.hKeyAnsiGroups
,
543 lRet
= RegCreateKeyExW(HKEY_CURRENT_USER
,
544 L
"UNICODE Program Groups",
547 REG_OPTION_NON_VOLATILE
,
548 KEY_READ
| KEY_WRITE
,
550 &Globals
.hKeyUnicodeGroups
,
553 lRet
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
554 L
"SOFTWARE\\Program Groups",
557 REG_OPTION_NON_VOLATILE
,
558 KEY_READ
| KEY_WRITE
,
560 &Globals
.hKeyCommonGroups
,
563 dwSize
= sizeof(Globals
.bAutoArrange
);
564 RegQueryValueExW(Globals
.hKeyPMSettings
, L
"AutoArrange", NULL
, &dwType
, (LPBYTE
)&Globals
.bAutoArrange
, &dwSize
);
566 dwSize
= sizeof(Globals
.bMinOnRun
);
567 RegQueryValueExW(Globals
.hKeyPMSettings
, L
"MinOnRun", NULL
, &dwType
, (LPBYTE
)&Globals
.bMinOnRun
, &dwSize
);
569 dwSize
= sizeof(Globals
.bSaveSettings
);
570 RegQueryValueExW(Globals
.hKeyPMSettings
, L
"SaveSettings", NULL
, &dwType
, (LPBYTE
)&Globals
.bSaveSettings
, &dwSize
);
577 MAIN_SaveSettings(VOID
)
579 WINDOWPLACEMENT WndPl
;
583 WndPl
.length
= sizeof(WndPl
);
584 GetWindowPlacement(Globals
.hMainWnd
, &WndPl
);
585 swprintf(buffer
, L
"%d %d %d %d %d",
586 WndPl
.rcNormalPosition
.left
,
587 WndPl
.rcNormalPosition
.top
,
588 WndPl
.rcNormalPosition
.right
,
589 WndPl
.rcNormalPosition
.bottom
,
592 dwSize
= wcslen(buffer
) * sizeof(WCHAR
);
593 RegSetValueExW(Globals
.hKeyPMSettings
, L
"Window", 0, REG_SZ
, (LPBYTE
)buffer
, dwSize
);
599 /***********************************************************************
604 INT WINAPI
wWinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPWSTR lpCmdLine
, INT nCmdShow
)
607 INITCOMMONCONTROLSEX icex
;
610 * Set our shutdown parameters: we want to shutdown the very last,
611 * but before any TaskMgr instance (which has a shutdown level of 1).
613 SetProcessShutdownParameters(2, 0);
615 Globals
.hInstance
= hInstance
;
616 Globals
.hGroups
= NULL
;
617 Globals
.hActiveGroup
= NULL
;
619 /* Load Program Manager's settings */
622 /* Load the default icons */
623 Globals
.hDefaultIcon
= LoadIconW(NULL
, MAKEINTRESOURCEW(IDI_WINLOGO
));
624 Globals
.hMainIcon
= LoadIconW(Globals
.hInstance
, MAKEINTRESOURCEW(IDI_APPICON
));
625 Globals
.hPersonalGroupIcon
= LoadIconW(Globals
.hInstance
, MAKEINTRESOURCEW(IDI_GROUP_PERSONAL_ICON
));
626 Globals
.hCommonGroupIcon
= LoadIconW(Globals
.hInstance
, MAKEINTRESOURCEW(IDI_GROUP_COMMON_ICON
));
628 /* Initialize the common controls */
629 icex
.dwSize
= sizeof(icex
);
630 icex
.dwICC
= ICC_HOTKEY_CLASS
| ICC_LISTVIEW_CLASSES
; // | ICC_STANDARD_CLASSES;
631 InitCommonControlsEx(&icex
);
633 /* Register the window classes */
634 if (!hPrevInstance
) // FIXME: Unused on Win32!
636 if (!MAIN_RegisterMainWinClass()) goto Quit
;
637 if (!GROUP_RegisterGroupWinClass()) goto Quit
;
640 /* Set up the strings, the main window, the accelerators, the menu, and the MDI child window */
641 STRING_LoadStrings();
642 MAIN_CreateMainWindow();
643 Globals
.hAccel
= LoadAcceleratorsW(Globals
.hInstance
, MAKEINTRESOURCEW(IDA_ACCEL
));
645 MAIN_CreateMDIWindow();
647 /* Load all the groups */
648 // MAIN_CreateGroups();
651 /* Load the Startup group: start the initial applications */
655 while (GetMessageW(&msg
, NULL
, 0, 0))
657 if (!TranslateMDISysAccel(Globals
.hMDIWnd
, &msg
) &&
658 !TranslateAcceleratorW(Globals
.hMainWnd
, Globals
.hAccel
, &msg
))
660 TranslateMessage(&msg
);
661 DispatchMessageW(&msg
);
667 /* Save the settings, close the registry keys and quit */
669 // MAIN_SaveSettings();
670 RegCloseKey(Globals
.hKeyCommonGroups
);
671 RegCloseKey(Globals
.hKeyUnicodeGroups
);
672 RegCloseKey(Globals
.hKeyAnsiGroups
);
673 RegCloseKey(Globals
.hKeyPMUnicodeGroups
);
674 RegCloseKey(Globals
.hKeyPMAnsiGroups
);
675 RegCloseKey(Globals
.hKeyPMCommonGroups
);
676 RegCloseKey(Globals
.hKeyPMSettings
);
677 RegCloseKey(Globals
.hKeyProgMan
);
682 /***********************************************************************
688 static VOID
MAIN_CreateGroups(VOID
)
690 CHAR buffer
[BUFFER_SIZE
];
691 CHAR szPath
[MAX_PATHNAME_LEN
];
694 /* Initialize groups according the `Order' entry of `progman.ini' */
695 GetPrivateProfileStringA("Settings", "Order", "", buffer
, sizeof(buffer
), Globals
.lpszIniFile
);
697 while (ptr
< buffer
+ sizeof(buffer
))
700 ret
= sscanf(ptr
, "%d%n", &num
, &skip
);
702 MAIN_MessageBoxIDS_s(IDS_FILE_READ_ERROR_s
, Globals
.lpszIniFile
, IDS_ERROR
, MB_OK
);
705 sprintf(key
, "Group%d", num
);
706 GetPrivateProfileStringA("Groups", key
, "", szPath
,
707 sizeof(szPath
), Globals
.lpszIniFile
);
708 if (!szPath
[0]) continue;
710 GRPFILE_ReadGroupFile(szPath
);
714 /* FIXME initialize other groups, not enumerated by `Order' */
718 static VOID
MAIN_LoadGroups(VOID
)
722 /***********************************************************************
727 static VOID
MAIN_AutoStart(VOID
)
736 WCHAR buffer
[BUFFER_SIZE
];
738 dwSize
= sizeof(buffer
);
739 lRet
= RegQueryValueExW(Globals
.hKeyPMSettings
, L
"Startup", NULL
, &dwType
, (LPBYTE
)buffer
, &dwSize
);
740 if (lRet
!= ERROR_SUCCESS
|| dwType
!= REG_SZ
)
743 for (hGroup
= Globals
.hGroups
; hGroup
; hGroup
= hGroup
->hNext
)
745 if (_wcsicmp(buffer
, hGroup
->hName
) == 0)
747 for (hProgram
= hGroup
->hPrograms
; hProgram
; hProgram
= hProgram
->hNext
)
748 PROGRAM_ExecuteProgram(hProgram
);
753 /***********************************************************************
758 static LRESULT CALLBACK
MAIN_MainWndProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
764 PROGGROUP
* hActiveGroup
= GROUP_ActiveGroup();
767 if (PROGRAM_ActiveProgram(hActiveGroup
))
769 EnableMenuItem(Globals
.hFileMenu
, PM_OPEN
, MF_ENABLED
);
770 EnableMenuItem(Globals
.hFileMenu
, PM_MOVE
, MF_ENABLED
);
771 EnableMenuItem(Globals
.hFileMenu
, PM_COPY
, MF_ENABLED
);
772 EnableMenuItem(Globals
.hFileMenu
, PM_DELETE
, MF_ENABLED
);
773 EnableMenuItem(Globals
.hFileMenu
, PM_ATTRIBUTES
, MF_ENABLED
);
777 if (!hActiveGroup
->hWnd
|| IsIconic(hActiveGroup
->hWnd
))
778 EnableMenuItem(Globals
.hFileMenu
, PM_OPEN
, MF_ENABLED
);
780 EnableMenuItem(Globals
.hFileMenu
, PM_OPEN
, MF_GRAYED
);
782 EnableMenuItem(Globals
.hFileMenu
, PM_MOVE
, MF_GRAYED
);
783 EnableMenuItem(Globals
.hFileMenu
, PM_COPY
, MF_GRAYED
);
784 EnableMenuItem(Globals
.hFileMenu
, PM_DELETE
, MF_ENABLED
);
785 EnableMenuItem(Globals
.hFileMenu
, PM_ATTRIBUTES
, MF_ENABLED
);
790 EnableMenuItem(Globals
.hFileMenu
, PM_OPEN
, MF_GRAYED
);
791 EnableMenuItem(Globals
.hFileMenu
, PM_MOVE
, MF_GRAYED
);
792 EnableMenuItem(Globals
.hFileMenu
, PM_COPY
, MF_GRAYED
);
793 EnableMenuItem(Globals
.hFileMenu
, PM_DELETE
, MF_GRAYED
);
794 EnableMenuItem(Globals
.hFileMenu
, PM_ATTRIBUTES
, MF_GRAYED
);
797 CheckMenuItem(Globals
.hOptionMenu
, PM_AUTO_ARRANGE
,
798 MF_BYCOMMAND
| (Globals
.bAutoArrange
? MF_CHECKED
: MF_UNCHECKED
));
799 CheckMenuItem(Globals
.hOptionMenu
, PM_MIN_ON_RUN
,
800 MF_BYCOMMAND
| (Globals
.bMinOnRun
? MF_CHECKED
: MF_UNCHECKED
));
801 CheckMenuItem(Globals
.hOptionMenu
, PM_SAVE_SETTINGS
,
802 MF_BYCOMMAND
| (Globals
.bSaveSettings
? MF_CHECKED
: MF_UNCHECKED
));
807 if (Globals
.bSaveSettings
)
813 if (LOWORD(wParam
) < PM_FIRST_CHILD
)
814 MAIN_MenuCommand(hWnd
, LOWORD(wParam
), lParam
);
818 return DefFrameProcW(hWnd
, Globals
.hMDIWnd
, uMsg
, wParam
, lParam
);
822 /***********************************************************************
827 static VOID
MAIN_MenuCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
830 HLOCAL hActiveGroup
= GROUP_ActiveGroup();
831 HLOCAL hActiveProgram
= PROGRAM_ActiveProgram(hActiveGroup
);
832 HWND hActiveGroupWnd
= GROUP_GroupWnd(hActiveGroup
);
838 switch (DIALOG_New((hActiveGroupWnd
&& !IsIconic(hActiveGroupWnd
)) ?
839 PM_NEW_PROGRAM
: PM_NEW_GROUP
))
842 if (hActiveGroup
) PROGRAM_NewProgram(hActiveGroup
);
855 if (DIALOG_Delete(IDS_DELETE_PROGRAM_s
, PROGRAM_ProgramName(hActiveProgram
)))
856 PROGRAM_DeleteProgram(hActiveProgram
, TRUE
);
858 else if (hActiveGroup
)
860 if (DIALOG_Delete(IDS_DELETE_GROUP_s
, GROUP_GroupName(hActiveGroup
)))
861 GROUP_DeleteGroup(hActiveGroup
);
867 case PM_SAVE_SETTINGS
:
868 Globals
.bSaveSettings
= !Globals
.bSaveSettings
;
869 CheckMenuItem(Globals
.hOptionMenu
, PM_SAVE_SETTINGS
,
870 MF_BYCOMMAND
| (Globals
.bSaveSettings
?
871 MF_CHECKED
: MF_UNCHECKED
));
872 WritePrivateProfileStringA("Settings", "SaveSettings",
873 Globals
.bSaveSettings
? "1" : "0",
874 Globals
.lpszIniFile
);
875 WritePrivateProfileStringA(NULL
,NULL
,NULL
,Globals
.lpszIniFile
); /* flush it */
881 if (hActiveGroupWnd
&& !IsIconic(hActiveGroupWnd
))
882 ArrangeIconicWindows(hActiveGroupWnd
);
884 SendMessageW(Globals
.hMDIWnd
, WM_MDIICONARRANGE
, 0, 0);
896 PROGGROUP
* hActiveGroup
;
897 PROGRAM
* hActiveProgram
;
898 HWND hActiveGroupWnd
;
900 hActiveGroup
= GROUP_ActiveGroup();
901 hActiveProgram
= PROGRAM_ActiveProgram(hActiveGroup
);
902 hActiveGroupWnd
= (hActiveGroup
? hActiveGroup
->hWnd
: NULL
);
913 if (!hActiveGroupWnd
|| IsIconic(hActiveGroupWnd
))
914 Success
= DIALOG_New(PM_NEW_GROUP
, &nResult
);
916 Success
= DIALOG_New(PM_NEW_PROGRAM
, &nResult
);
925 format
= (nResult
& 0xC) >> 2;
926 bIsCommonGroup
= (nResult
& 2) != 0;
927 GROUP_NewGroup(format
, bIsCommonGroup
);
929 else if (hActiveGroup
)
931 PROGRAM_NewProgram(hActiveGroup
);
939 PROGRAM_ExecuteProgram(hActiveProgram
);
940 else if (hActiveGroupWnd
)
941 OpenIcon(hActiveGroupWnd
);
947 PROGRAM_CopyMoveProgram(hActiveProgram
, wParam
== PM_MOVE
);
954 if (DIALOG_Delete(IDS_DELETE_PROGRAM_s
, hActiveProgram
->hName
))
955 PROGRAM_DeleteProgram(hActiveProgram
, TRUE
);
957 else if (hActiveGroup
&& DIALOG_Delete(IDS_DELETE_GROUP_s
, hActiveGroup
->hName
))
959 GROUP_DeleteGroup(hActiveGroup
);
966 PROGRAM_ModifyProgram(hActiveProgram
);
967 else if (hActiveGroup
)
968 GROUP_ModifyGroup(hActiveGroup
);
976 // MAIN_SaveSettings();
983 case PM_AUTO_ARRANGE
:
984 Globals
.bAutoArrange
= !Globals
.bAutoArrange
;
985 CheckMenuItem(Globals
.hOptionMenu
, PM_AUTO_ARRANGE
,
986 MF_BYCOMMAND
| (Globals
.bAutoArrange
? MF_CHECKED
: MF_UNCHECKED
));
987 Value
= Globals
.bAutoArrange
;
988 RegSetValueExW(Globals
.hKeyPMSettings
, L
"AutoArrange", 0, REG_DWORD
, (LPBYTE
)&Value
, sizeof(Value
));
992 Globals
.bMinOnRun
= !Globals
.bMinOnRun
;
993 CheckMenuItem(Globals
.hOptionMenu
, PM_MIN_ON_RUN
,
994 MF_BYCOMMAND
| (Globals
.bMinOnRun
? MF_CHECKED
: MF_UNCHECKED
));
995 Value
= Globals
.bMinOnRun
;
996 RegSetValueExW(Globals
.hKeyPMSettings
, L
"MinOnRun", 0, REG_DWORD
, (LPBYTE
)&Value
, sizeof(Value
));
999 case PM_SAVE_SETTINGS
:
1000 Globals
.bSaveSettings
= !Globals
.bSaveSettings
;
1001 CheckMenuItem(Globals
.hOptionMenu
, PM_SAVE_SETTINGS
,
1002 MF_BYCOMMAND
| (Globals
.bSaveSettings
? MF_CHECKED
: MF_UNCHECKED
));
1003 Value
= Globals
.bSaveSettings
;
1004 RegSetValueExW(Globals
.hKeyPMSettings
, L
"SaveSettings", 0, REG_DWORD
, (LPBYTE
)&Value
, sizeof(Value
));
1007 case PM_SAVE_SETTINGS_NOW
:
1008 MAIN_SaveSettings();
1015 SendMessageW(Globals
.hMDIWnd
, WM_MDICASCADE
, 0, 0);
1018 case PM_SIDE_BY_SIDE
:
1019 SendMessageW(Globals
.hMDIWnd
, WM_MDITILE
, MDITILE_VERTICAL
, 0);
1023 if (!hActiveGroupWnd
|| IsIconic(hActiveGroupWnd
))
1024 SendMessageW(Globals
.hMDIWnd
, WM_MDIICONARRANGE
, 0, 0);
1026 SendMessageA(hActiveGroup
->hListView
, LVM_ARRANGE
, 0, 0);
1033 if (!WinHelpW(Globals
.hMainWnd
, L
"progman.hlp", HELP_CONTENTS
, 0))
1034 MAIN_MessageBoxIDS(IDS_WINHELP_ERROR
, IDS_ERROR
, MB_OK
);
1038 ShellAboutW(hWnd
, szTitle
, NULL
, Globals
.hMainIcon
);
1042 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED
, IDS_ERROR
, MB_OK
);
1048 /***********************************************************************
1050 * MAIN_RegisterMainWinClass
1053 static ATOM
MAIN_RegisterMainWinClass(VOID
)
1057 wndClass
.style
= CS_HREDRAW
| CS_VREDRAW
;
1058 wndClass
.lpfnWndProc
= MAIN_MainWndProc
;
1059 wndClass
.cbClsExtra
= 0;
1060 wndClass
.cbWndExtra
= 0;
1061 wndClass
.hInstance
= Globals
.hInstance
;
1062 wndClass
.hIcon
= Globals
.hMainIcon
;
1063 wndClass
.hCursor
= LoadCursorW(NULL
, MAKEINTRESOURCEW(IDC_ARROW
));
1064 wndClass
.hbrBackground
= (HBRUSH
)GetStockObject(NULL_BRUSH
);
1065 wndClass
.lpszMenuName
= NULL
;
1066 wndClass
.lpszClassName
= STRING_MAIN_WIN_CLASS_NAME
;
1068 return RegisterClassW(&wndClass
);
1071 /***********************************************************************
1073 * MAIN_CreateMainWindow
1076 static VOID
MAIN_CreateMainWindow(VOID
)
1078 INT left
, top
, right
, bottom
;
1087 Globals
.hMDIWnd
= NULL
;
1088 Globals
.hMainMenu
= NULL
;
1090 /* Get the geometry of the main window */
1091 dwSize
= sizeof(buffer
);
1092 lRet
= RegQueryValueExW(Globals
.hKeyPMSettings
, L
"Window", NULL
, &dwType
, (LPBYTE
)buffer
, &dwSize
);
1093 if (lRet
!= ERROR_SUCCESS
|| dwType
!= REG_SZ
)
1096 if (swscanf(buffer
, L
"%d %d %d %d %d", &left
, &top
, &right
, &bottom
, &nCmdShow
) == 5)
1098 width
= right
- left
;
1099 height
= bottom
- top
;
1103 left
= top
= width
= height
= CW_USEDEFAULT
;
1104 nCmdShow
= SW_SHOWNORMAL
;
1107 /* Create the main window */
1109 CreateWindowW(STRING_MAIN_WIN_CLASS_NAME
,
1111 WS_OVERLAPPEDWINDOW
, // /* | WS_CLIPSIBLINGS | WS_CLIPCHILDREN */
1112 left
, top
, width
, height
,
1117 MAIN_SetMainWindowTitle();
1118 ShowWindow(Globals
.hMainWnd
, nCmdShow
);
1119 UpdateWindow(Globals
.hMainWnd
);
1122 /***********************************************************************
1124 * MAIN_CreateMDIWindow
1127 static VOID
MAIN_CreateMDIWindow(VOID
)
1129 CLIENTCREATESTRUCT ccs
;
1132 /* Get the geometry of the MDI window */
1133 GetClientRect(Globals
.hMainWnd
, &rect
);
1135 ccs
.hWindowMenu
= Globals
.hWindowsMenu
;
1136 ccs
.idFirstChild
= PM_FIRST_CHILD
;
1138 /* Create MDI Window */
1140 CreateWindowW(WC_MDICLIENT
, NULL
, WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
, // WS_CHILDWINDOW | ...
1141 rect
.left
, rect
.top
,
1142 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
1143 Globals
.hMainWnd
, 0,
1144 Globals
.hInstance
, &ccs
);
1146 /* Reset the background of the MDI client window (default: COLOR_APPWORKSPACE + 1) */
1147 SetClassLongPtrW(Globals
.hMDIWnd
, GCLP_HBRBACKGROUND
, (COLOR_WINDOW
+ 1));
1149 ShowWindow(Globals
.hMDIWnd
, SW_SHOW
);
1150 UpdateWindow(Globals
.hMDIWnd
);
1153 /**********************************************************************/
1154 /***********************************************************************
1156 * MAIN_MessageBoxIDS
1158 INT
MAIN_MessageBoxIDS(UINT ids_text
, UINT ids_title
, WORD type
)
1160 WCHAR text
[MAX_STRING_LEN
];
1161 WCHAR title
[MAX_STRING_LEN
];
1163 LoadStringW(Globals
.hInstance
, ids_text
, text
, ARRAYSIZE(text
));
1164 LoadStringW(Globals
.hInstance
, ids_title
, title
, ARRAYSIZE(title
));
1166 return MessageBoxW(Globals
.hMainWnd
, text
, title
, type
);
1169 /***********************************************************************
1171 * MAIN_MessageBoxIDS_s
1173 INT
MAIN_MessageBoxIDS_s(UINT ids_text
, LPCWSTR str
, UINT ids_title
, WORD type
)
1175 WCHAR text
[MAX_STRING_LEN
];
1176 WCHAR title
[MAX_STRING_LEN
];
1177 WCHAR newtext
[MAX_STRING_LEN
+ MAX_PATHNAME_LEN
];
1179 LoadStringW(Globals
.hInstance
, ids_text
, text
, ARRAYSIZE(text
));
1180 LoadStringW(Globals
.hInstance
, ids_title
, title
, ARRAYSIZE(title
));
1181 wsprintfW(newtext
, text
, str
);
1183 return MessageBoxW(Globals
.hMainWnd
, newtext
, title
, type
);
1186 /***********************************************************************
1188 * MAIN_ReplaceString
1191 VOID
MAIN_ReplaceString(LPWSTR
* string
, LPWSTR replace
)
1195 newstring
= Alloc(HEAP_ZERO_MEMORY
, (wcslen(replace
) + 1) * sizeof(WCHAR
));
1198 wcscpy(newstring
, replace
);
1199 *string
= newstring
;
1203 MAIN_MessageBoxIDS(IDS_OUT_OF_MEMORY
, IDS_ERROR
, MB_OK
);