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 StringCbPrintfW(caption
, size
, 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 StringCbPrintfW(buffer
, sizeof(buffer
),
587 WndPl
.rcNormalPosition
.left
,
588 WndPl
.rcNormalPosition
.top
,
589 WndPl
.rcNormalPosition
.right
,
590 WndPl
.rcNormalPosition
.bottom
,
593 dwSize
= wcslen(buffer
) * sizeof(WCHAR
);
594 RegSetValueExW(Globals
.hKeyPMSettings
, L
"Window", 0, REG_SZ
, (LPBYTE
)buffer
, dwSize
);
600 /***********************************************************************
605 INT WINAPI
wWinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPWSTR lpCmdLine
, INT nCmdShow
)
608 INITCOMMONCONTROLSEX icex
;
611 * Set our shutdown parameters: we want to shutdown the very last,
612 * but before any TaskMgr instance (which has a shutdown level of 1).
614 SetProcessShutdownParameters(2, 0);
616 Globals
.hInstance
= hInstance
;
617 Globals
.hGroups
= NULL
;
618 Globals
.hActiveGroup
= NULL
;
620 /* Load Program Manager's settings */
623 /* Load the default icons */
624 Globals
.hDefaultIcon
= LoadIconW(NULL
, MAKEINTRESOURCEW(IDI_WINLOGO
));
625 Globals
.hMainIcon
= LoadIconW(Globals
.hInstance
, MAKEINTRESOURCEW(IDI_APPICON
));
626 Globals
.hPersonalGroupIcon
= LoadIconW(Globals
.hInstance
, MAKEINTRESOURCEW(IDI_GROUP_PERSONAL_ICON
));
627 Globals
.hCommonGroupIcon
= LoadIconW(Globals
.hInstance
, MAKEINTRESOURCEW(IDI_GROUP_COMMON_ICON
));
629 /* Initialize the common controls */
630 icex
.dwSize
= sizeof(icex
);
631 icex
.dwICC
= ICC_HOTKEY_CLASS
| ICC_LISTVIEW_CLASSES
; // | ICC_STANDARD_CLASSES;
632 InitCommonControlsEx(&icex
);
634 /* Register the window classes */
635 if (!hPrevInstance
) // FIXME: Unused on Win32!
637 if (!MAIN_RegisterMainWinClass()) goto Quit
;
638 if (!GROUP_RegisterGroupWinClass()) goto Quit
;
641 /* Set up the strings, the main window, the accelerators, the menu, and the MDI child window */
642 STRING_LoadStrings();
643 MAIN_CreateMainWindow();
644 Globals
.hAccel
= LoadAcceleratorsW(Globals
.hInstance
, MAKEINTRESOURCEW(IDA_ACCEL
));
646 MAIN_CreateMDIWindow();
648 /* Load all the groups */
649 // MAIN_CreateGroups();
652 /* Load the Startup group: start the initial applications */
656 while (GetMessageW(&msg
, NULL
, 0, 0))
658 if (!TranslateMDISysAccel(Globals
.hMDIWnd
, &msg
) &&
659 !TranslateAcceleratorW(Globals
.hMainWnd
, Globals
.hAccel
, &msg
))
661 TranslateMessage(&msg
);
662 DispatchMessageW(&msg
);
668 /* Save the settings, close the registry keys and quit */
670 // MAIN_SaveSettings();
671 RegCloseKey(Globals
.hKeyCommonGroups
);
672 RegCloseKey(Globals
.hKeyUnicodeGroups
);
673 RegCloseKey(Globals
.hKeyAnsiGroups
);
674 RegCloseKey(Globals
.hKeyPMUnicodeGroups
);
675 RegCloseKey(Globals
.hKeyPMAnsiGroups
);
676 RegCloseKey(Globals
.hKeyPMCommonGroups
);
677 RegCloseKey(Globals
.hKeyPMSettings
);
678 RegCloseKey(Globals
.hKeyProgMan
);
683 /***********************************************************************
689 static VOID
MAIN_CreateGroups(VOID
)
691 CHAR buffer
[BUFFER_SIZE
];
692 CHAR szPath
[MAX_PATHNAME_LEN
];
695 /* Initialize groups according the `Order' entry of `progman.ini' */
696 GetPrivateProfileStringA("Settings", "Order", "", buffer
, sizeof(buffer
), Globals
.lpszIniFile
);
698 while (ptr
< buffer
+ sizeof(buffer
))
701 ret
= sscanf(ptr
, "%d%n", &num
, &skip
);
703 MAIN_MessageBoxIDS_s(IDS_FILE_READ_ERROR_s
, Globals
.lpszIniFile
, IDS_ERROR
, MB_OK
);
706 sprintf(key
, "Group%d", num
);
707 GetPrivateProfileStringA("Groups", key
, "", szPath
,
708 sizeof(szPath
), Globals
.lpszIniFile
);
709 if (!szPath
[0]) continue;
711 GRPFILE_ReadGroupFile(szPath
);
715 /* FIXME initialize other groups, not enumerated by `Order' */
719 static VOID
MAIN_LoadGroups(VOID
)
723 /***********************************************************************
728 static VOID
MAIN_AutoStart(VOID
)
737 WCHAR buffer
[BUFFER_SIZE
];
739 dwSize
= sizeof(buffer
);
740 lRet
= RegQueryValueExW(Globals
.hKeyPMSettings
, L
"Startup", NULL
, &dwType
, (LPBYTE
)buffer
, &dwSize
);
741 if (lRet
!= ERROR_SUCCESS
|| dwType
!= REG_SZ
)
744 for (hGroup
= Globals
.hGroups
; hGroup
; hGroup
= hGroup
->hNext
)
746 if (_wcsicmp(buffer
, hGroup
->hName
) == 0)
748 for (hProgram
= hGroup
->hPrograms
; hProgram
; hProgram
= hProgram
->hNext
)
749 PROGRAM_ExecuteProgram(hProgram
);
754 /***********************************************************************
759 static LRESULT CALLBACK
MAIN_MainWndProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
765 PROGGROUP
* hActiveGroup
= GROUP_ActiveGroup();
768 if (PROGRAM_ActiveProgram(hActiveGroup
))
770 EnableMenuItem(Globals
.hFileMenu
, PM_OPEN
, MF_ENABLED
);
771 EnableMenuItem(Globals
.hFileMenu
, PM_MOVE
, MF_ENABLED
);
772 EnableMenuItem(Globals
.hFileMenu
, PM_COPY
, MF_ENABLED
);
773 EnableMenuItem(Globals
.hFileMenu
, PM_DELETE
, MF_ENABLED
);
774 EnableMenuItem(Globals
.hFileMenu
, PM_ATTRIBUTES
, MF_ENABLED
);
778 if (!hActiveGroup
->hWnd
|| IsIconic(hActiveGroup
->hWnd
))
779 EnableMenuItem(Globals
.hFileMenu
, PM_OPEN
, MF_ENABLED
);
781 EnableMenuItem(Globals
.hFileMenu
, PM_OPEN
, MF_GRAYED
);
783 EnableMenuItem(Globals
.hFileMenu
, PM_MOVE
, MF_GRAYED
);
784 EnableMenuItem(Globals
.hFileMenu
, PM_COPY
, MF_GRAYED
);
785 EnableMenuItem(Globals
.hFileMenu
, PM_DELETE
, MF_ENABLED
);
786 EnableMenuItem(Globals
.hFileMenu
, PM_ATTRIBUTES
, MF_ENABLED
);
791 EnableMenuItem(Globals
.hFileMenu
, PM_OPEN
, MF_GRAYED
);
792 EnableMenuItem(Globals
.hFileMenu
, PM_MOVE
, MF_GRAYED
);
793 EnableMenuItem(Globals
.hFileMenu
, PM_COPY
, MF_GRAYED
);
794 EnableMenuItem(Globals
.hFileMenu
, PM_DELETE
, MF_GRAYED
);
795 EnableMenuItem(Globals
.hFileMenu
, PM_ATTRIBUTES
, MF_GRAYED
);
798 CheckMenuItem(Globals
.hOptionMenu
, PM_AUTO_ARRANGE
,
799 MF_BYCOMMAND
| (Globals
.bAutoArrange
? MF_CHECKED
: MF_UNCHECKED
));
800 CheckMenuItem(Globals
.hOptionMenu
, PM_MIN_ON_RUN
,
801 MF_BYCOMMAND
| (Globals
.bMinOnRun
? MF_CHECKED
: MF_UNCHECKED
));
802 CheckMenuItem(Globals
.hOptionMenu
, PM_SAVE_SETTINGS
,
803 MF_BYCOMMAND
| (Globals
.bSaveSettings
? MF_CHECKED
: MF_UNCHECKED
));
808 if (Globals
.bSaveSettings
)
814 if (LOWORD(wParam
) < PM_FIRST_CHILD
)
815 MAIN_MenuCommand(hWnd
, LOWORD(wParam
), lParam
);
819 return DefFrameProcW(hWnd
, Globals
.hMDIWnd
, uMsg
, wParam
, lParam
);
823 /***********************************************************************
828 static VOID
MAIN_MenuCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
831 HLOCAL hActiveGroup
= GROUP_ActiveGroup();
832 HLOCAL hActiveProgram
= PROGRAM_ActiveProgram(hActiveGroup
);
833 HWND hActiveGroupWnd
= GROUP_GroupWnd(hActiveGroup
);
839 switch (DIALOG_New((hActiveGroupWnd
&& !IsIconic(hActiveGroupWnd
)) ?
840 PM_NEW_PROGRAM
: PM_NEW_GROUP
))
843 if (hActiveGroup
) PROGRAM_NewProgram(hActiveGroup
);
856 if (DIALOG_Delete(IDS_DELETE_PROGRAM_s
, PROGRAM_ProgramName(hActiveProgram
)))
857 PROGRAM_DeleteProgram(hActiveProgram
, TRUE
);
859 else if (hActiveGroup
)
861 if (DIALOG_Delete(IDS_DELETE_GROUP_s
, GROUP_GroupName(hActiveGroup
)))
862 GROUP_DeleteGroup(hActiveGroup
);
868 case PM_SAVE_SETTINGS
:
869 Globals
.bSaveSettings
= !Globals
.bSaveSettings
;
870 CheckMenuItem(Globals
.hOptionMenu
, PM_SAVE_SETTINGS
,
871 MF_BYCOMMAND
| (Globals
.bSaveSettings
?
872 MF_CHECKED
: MF_UNCHECKED
));
873 WritePrivateProfileStringA("Settings", "SaveSettings",
874 Globals
.bSaveSettings
? "1" : "0",
875 Globals
.lpszIniFile
);
876 WritePrivateProfileStringA(NULL
,NULL
,NULL
,Globals
.lpszIniFile
); /* flush it */
882 if (hActiveGroupWnd
&& !IsIconic(hActiveGroupWnd
))
883 ArrangeIconicWindows(hActiveGroupWnd
);
885 SendMessageW(Globals
.hMDIWnd
, WM_MDIICONARRANGE
, 0, 0);
897 PROGGROUP
* hActiveGroup
;
898 PROGRAM
* hActiveProgram
;
899 HWND hActiveGroupWnd
;
901 hActiveGroup
= GROUP_ActiveGroup();
902 hActiveProgram
= PROGRAM_ActiveProgram(hActiveGroup
);
903 hActiveGroupWnd
= (hActiveGroup
? hActiveGroup
->hWnd
: NULL
);
914 if (!hActiveGroupWnd
|| IsIconic(hActiveGroupWnd
))
915 Success
= DIALOG_New(PM_NEW_GROUP
, &nResult
);
917 Success
= DIALOG_New(PM_NEW_PROGRAM
, &nResult
);
926 format
= (nResult
& 0xC) >> 2;
927 bIsCommonGroup
= (nResult
& 2) != 0;
928 GROUP_NewGroup(format
, bIsCommonGroup
);
930 else if (hActiveGroup
)
932 PROGRAM_NewProgram(hActiveGroup
);
940 PROGRAM_ExecuteProgram(hActiveProgram
);
941 else if (hActiveGroupWnd
)
942 OpenIcon(hActiveGroupWnd
);
948 PROGRAM_CopyMoveProgram(hActiveProgram
, wParam
== PM_MOVE
);
955 if (DIALOG_Delete(IDS_DELETE_PROGRAM_s
, hActiveProgram
->hName
))
956 PROGRAM_DeleteProgram(hActiveProgram
, TRUE
);
958 else if (hActiveGroup
&& DIALOG_Delete(IDS_DELETE_GROUP_s
, hActiveGroup
->hName
))
960 GROUP_DeleteGroup(hActiveGroup
);
967 PROGRAM_ModifyProgram(hActiveProgram
);
968 else if (hActiveGroup
)
969 GROUP_ModifyGroup(hActiveGroup
);
977 // MAIN_SaveSettings();
984 case PM_AUTO_ARRANGE
:
985 Globals
.bAutoArrange
= !Globals
.bAutoArrange
;
986 CheckMenuItem(Globals
.hOptionMenu
, PM_AUTO_ARRANGE
,
987 MF_BYCOMMAND
| (Globals
.bAutoArrange
? MF_CHECKED
: MF_UNCHECKED
));
988 Value
= Globals
.bAutoArrange
;
989 RegSetValueExW(Globals
.hKeyPMSettings
, L
"AutoArrange", 0, REG_DWORD
, (LPBYTE
)&Value
, sizeof(Value
));
993 Globals
.bMinOnRun
= !Globals
.bMinOnRun
;
994 CheckMenuItem(Globals
.hOptionMenu
, PM_MIN_ON_RUN
,
995 MF_BYCOMMAND
| (Globals
.bMinOnRun
? MF_CHECKED
: MF_UNCHECKED
));
996 Value
= Globals
.bMinOnRun
;
997 RegSetValueExW(Globals
.hKeyPMSettings
, L
"MinOnRun", 0, REG_DWORD
, (LPBYTE
)&Value
, sizeof(Value
));
1000 case PM_SAVE_SETTINGS
:
1001 Globals
.bSaveSettings
= !Globals
.bSaveSettings
;
1002 CheckMenuItem(Globals
.hOptionMenu
, PM_SAVE_SETTINGS
,
1003 MF_BYCOMMAND
| (Globals
.bSaveSettings
? MF_CHECKED
: MF_UNCHECKED
));
1004 Value
= Globals
.bSaveSettings
;
1005 RegSetValueExW(Globals
.hKeyPMSettings
, L
"SaveSettings", 0, REG_DWORD
, (LPBYTE
)&Value
, sizeof(Value
));
1008 case PM_SAVE_SETTINGS_NOW
:
1009 MAIN_SaveSettings();
1016 SendMessageW(Globals
.hMDIWnd
, WM_MDICASCADE
, 0, 0);
1019 case PM_SIDE_BY_SIDE
:
1020 SendMessageW(Globals
.hMDIWnd
, WM_MDITILE
, MDITILE_VERTICAL
, 0);
1024 if (!hActiveGroupWnd
|| IsIconic(hActiveGroupWnd
))
1025 SendMessageW(Globals
.hMDIWnd
, WM_MDIICONARRANGE
, 0, 0);
1027 SendMessageA(hActiveGroup
->hListView
, LVM_ARRANGE
, 0, 0);
1034 if (!WinHelpW(Globals
.hMainWnd
, L
"progman.hlp", HELP_CONTENTS
, 0))
1035 MAIN_MessageBoxIDS(IDS_WINHELP_ERROR
, IDS_ERROR
, MB_OK
);
1039 ShellAboutW(hWnd
, szTitle
, NULL
, Globals
.hMainIcon
);
1043 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED
, IDS_ERROR
, MB_OK
);
1049 /***********************************************************************
1051 * MAIN_RegisterMainWinClass
1054 static ATOM
MAIN_RegisterMainWinClass(VOID
)
1058 wndClass
.style
= CS_HREDRAW
| CS_VREDRAW
;
1059 wndClass
.lpfnWndProc
= MAIN_MainWndProc
;
1060 wndClass
.cbClsExtra
= 0;
1061 wndClass
.cbWndExtra
= 0;
1062 wndClass
.hInstance
= Globals
.hInstance
;
1063 wndClass
.hIcon
= Globals
.hMainIcon
;
1064 wndClass
.hCursor
= LoadCursorW(NULL
, MAKEINTRESOURCEW(IDC_ARROW
));
1065 wndClass
.hbrBackground
= (HBRUSH
)GetStockObject(NULL_BRUSH
);
1066 wndClass
.lpszMenuName
= NULL
;
1067 wndClass
.lpszClassName
= STRING_MAIN_WIN_CLASS_NAME
;
1069 return RegisterClassW(&wndClass
);
1072 /***********************************************************************
1074 * MAIN_CreateMainWindow
1077 static VOID
MAIN_CreateMainWindow(VOID
)
1079 INT left
, top
, right
, bottom
;
1088 Globals
.hMDIWnd
= NULL
;
1089 Globals
.hMainMenu
= NULL
;
1091 /* Get the geometry of the main window */
1092 dwSize
= sizeof(buffer
);
1093 lRet
= RegQueryValueExW(Globals
.hKeyPMSettings
, L
"Window", NULL
, &dwType
, (LPBYTE
)buffer
, &dwSize
);
1094 if (lRet
!= ERROR_SUCCESS
|| dwType
!= REG_SZ
)
1097 if (swscanf(buffer
, L
"%d %d %d %d %d", &left
, &top
, &right
, &bottom
, &nCmdShow
) == 5)
1099 width
= right
- left
;
1100 height
= bottom
- top
;
1104 left
= top
= width
= height
= CW_USEDEFAULT
;
1105 nCmdShow
= SW_SHOWNORMAL
;
1108 /* Create the main window */
1110 CreateWindowW(STRING_MAIN_WIN_CLASS_NAME
,
1112 WS_OVERLAPPEDWINDOW
, // /* | WS_CLIPSIBLINGS | WS_CLIPCHILDREN */
1113 left
, top
, width
, height
,
1118 MAIN_SetMainWindowTitle();
1119 ShowWindow(Globals
.hMainWnd
, nCmdShow
);
1120 UpdateWindow(Globals
.hMainWnd
);
1123 /***********************************************************************
1125 * MAIN_CreateMDIWindow
1128 static VOID
MAIN_CreateMDIWindow(VOID
)
1130 CLIENTCREATESTRUCT ccs
;
1133 /* Get the geometry of the MDI window */
1134 GetClientRect(Globals
.hMainWnd
, &rect
);
1136 ccs
.hWindowMenu
= Globals
.hWindowsMenu
;
1137 ccs
.idFirstChild
= PM_FIRST_CHILD
;
1139 /* Create MDI Window */
1141 CreateWindowW(WC_MDICLIENT
, NULL
, WS_CHILD
| WS_CLIPCHILDREN
| WS_VSCROLL
| WS_HSCROLL
, // WS_CHILDWINDOW | ...
1142 rect
.left
, rect
.top
,
1143 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
1144 Globals
.hMainWnd
, 0,
1145 Globals
.hInstance
, &ccs
);
1147 /* Reset the background of the MDI client window (default: COLOR_APPWORKSPACE + 1) */
1148 SetClassLongPtrW(Globals
.hMDIWnd
, GCLP_HBRBACKGROUND
, (COLOR_WINDOW
+ 1));
1150 ShowWindow(Globals
.hMDIWnd
, SW_SHOW
);
1151 UpdateWindow(Globals
.hMDIWnd
);
1154 /**********************************************************************/
1155 /***********************************************************************
1157 * MAIN_MessageBoxIDS
1159 INT
MAIN_MessageBoxIDS(UINT ids_text
, UINT ids_title
, WORD type
)
1161 WCHAR text
[MAX_STRING_LEN
];
1162 WCHAR title
[MAX_STRING_LEN
];
1164 LoadStringW(Globals
.hInstance
, ids_text
, text
, ARRAYSIZE(text
));
1165 LoadStringW(Globals
.hInstance
, ids_title
, title
, ARRAYSIZE(title
));
1167 return MessageBoxW(Globals
.hMainWnd
, text
, title
, type
);
1170 /***********************************************************************
1172 * MAIN_MessageBoxIDS_s
1174 INT
MAIN_MessageBoxIDS_s(UINT ids_text
, LPCWSTR str
, UINT ids_title
, WORD type
)
1176 WCHAR text
[MAX_STRING_LEN
];
1177 WCHAR title
[MAX_STRING_LEN
];
1178 WCHAR newtext
[MAX_STRING_LEN
+ MAX_PATHNAME_LEN
];
1180 LoadStringW(Globals
.hInstance
, ids_text
, text
, ARRAYSIZE(text
));
1181 LoadStringW(Globals
.hInstance
, ids_title
, title
, ARRAYSIZE(title
));
1182 wsprintfW(newtext
, text
, str
);
1184 return MessageBoxW(Globals
.hMainWnd
, newtext
, title
, type
);
1187 /***********************************************************************
1189 * MAIN_ReplaceString
1192 VOID
MAIN_ReplaceString(LPWSTR
* string
, LPWSTR replace
)
1196 newstring
= Alloc(HEAP_ZERO_MEMORY
, (wcslen(replace
) + 1) * sizeof(WCHAR
));
1199 wcscpy(newstring
, replace
);
1200 *string
= newstring
;
1204 MAIN_MessageBoxIDS(IDS_OUT_OF_MEMORY
, IDS_ERROR
, MB_OK
);