[RAPPS]
[reactos.git] / reactos / base / applications / rapps / winmain.c
1 /*
2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/rapps/winmain.c
5 * PURPOSE: Main program
6 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
7 */
8
9 #include "rapps.h"
10
11 #include <shellapi.h>
12
13 HWND hMainWnd;
14 HINSTANCE hInst;
15 HIMAGELIST hImageTreeView = NULL;
16 INT SelectedEnumType = ENUM_ALL_COMPONENTS;
17 SETTINGS_INFO SettingsInfo;
18
19 VOID
20 FillDefaultSettings(PSETTINGS_INFO pSettingsInfo)
21 {
22 pSettingsInfo->bSaveWndPos = TRUE;
23 pSettingsInfo->bUpdateAtStart = FALSE;
24 pSettingsInfo->bLogEnabled = TRUE;
25 StringCbCopyW(pSettingsInfo->szDownloadDir,
26 sizeof(pSettingsInfo->szDownloadDir),
27 L"C:\\Downloads");
28 pSettingsInfo->bDelInstaller = FALSE;
29
30 pSettingsInfo->Maximized = FALSE;
31 pSettingsInfo->Left = 0;
32 pSettingsInfo->Top = 0;
33 pSettingsInfo->Right = 680;
34 pSettingsInfo->Bottom = 450;
35 }
36
37 static BOOL
38 LoadSettings(VOID)
39 {
40 HKEY hKey;
41 DWORD dwSize;
42
43 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\ReactOS\\rapps", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
44 {
45 dwSize = sizeof(SETTINGS_INFO);
46 if (RegQueryValueExW(hKey, L"Settings", NULL, NULL, (LPBYTE)&SettingsInfo, &dwSize) == ERROR_SUCCESS)
47 {
48 RegCloseKey(hKey);
49 return TRUE;
50 }
51
52 RegCloseKey(hKey);
53 }
54
55 return FALSE;
56 }
57
58 VOID
59 SaveSettings(HWND hwnd)
60 {
61 WINDOWPLACEMENT wp;
62 HKEY hKey;
63
64 if (SettingsInfo.bSaveWndPos)
65 {
66 wp.length = sizeof(WINDOWPLACEMENT);
67 GetWindowPlacement(hwnd, &wp);
68
69 SettingsInfo.Left = wp.rcNormalPosition.left;
70 SettingsInfo.Top = wp.rcNormalPosition.top;
71 SettingsInfo.Right = wp.rcNormalPosition.right;
72 SettingsInfo.Bottom = wp.rcNormalPosition.bottom;
73 SettingsInfo.Maximized = (IsZoomed(hwnd) || (wp.flags & WPF_RESTORETOMAXIMIZED));
74 }
75
76 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"Software\\ReactOS\\rapps", 0, NULL,
77 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
78 {
79 RegSetValueExW(hKey, L"Settings", 0, REG_BINARY, (LPBYTE)&SettingsInfo, sizeof(SETTINGS_INFO));
80 RegCloseKey(hKey);
81 }
82 }
83
84 VOID
85 FreeInstalledAppList(VOID)
86 {
87 INT Count = ListView_GetItemCount(hListView) - 1;
88 PINSTALLED_INFO Info;
89
90 while (Count >= 0)
91 {
92 Info = ListViewGetlParam(Count);
93 if (Info)
94 {
95 RegCloseKey(Info->hSubKey);
96 HeapFree(GetProcessHeap(), 0, Info);
97 }
98 Count--;
99 }
100 }
101
102 BOOL
103 CALLBACK
104 EnumInstalledAppProc(INT ItemIndex, LPWSTR lpName, INSTALLED_INFO Info)
105 {
106 PINSTALLED_INFO ItemInfo;
107 WCHAR szText[MAX_PATH];
108 INT Index;
109
110 ItemInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(INSTALLED_INFO));
111 if (!ItemInfo) return FALSE;
112
113 *ItemInfo = Info;
114
115 Index = ListViewAddItem(ItemIndex, 0, lpName, (LPARAM)ItemInfo);
116
117 /* Get version info */
118 GetApplicationString((HKEY)ItemInfo->hSubKey, L"DisplayVersion", szText);
119 ListView_SetItemText(hListView, Index, 1, szText);
120 /* Get comments */
121 GetApplicationString((HKEY)ItemInfo->hSubKey, L"Comments", szText);
122 ListView_SetItemText(hListView, Index, 2, szText);
123
124 return TRUE;
125 }
126
127 VOID
128 FreeAvailableAppList(VOID)
129 {
130 INT Count = ListView_GetItemCount(hListView) - 1;
131 PVOID Info;
132
133 while (Count >= 0)
134 {
135 Info = ListViewGetlParam(Count);
136 if (Info)
137 HeapFree(GetProcessHeap(), 0, Info);
138 Count--;
139 }
140 }
141
142 BOOL
143 CALLBACK
144 EnumAvailableAppProc(APPLICATION_INFO Info)
145 {
146 PAPPLICATION_INFO ItemInfo;
147 INT Index;
148
149 /* Only add a ListView entry if...
150 - no RegName was supplied (so we cannot determine whether the application is installed or not) or
151 - a RegName was supplied and the application is not installed
152 */
153 if (!*Info.szRegName || (!IsInstalledApplication(Info.szRegName, FALSE) && !IsInstalledApplication(Info.szRegName, TRUE)))
154 {
155 ItemInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(APPLICATION_INFO));
156 if (!ItemInfo) return FALSE;
157
158 *ItemInfo = Info;
159
160 Index = ListViewAddItem(Info.Category, 0, Info.szName, (LPARAM)ItemInfo);
161 ListView_SetItemText(hListView, Index, 1, Info.szVersion);
162 ListView_SetItemText(hListView, Index, 2, Info.szDesc);
163 }
164
165 return TRUE;
166 }
167
168 VOID
169 UpdateApplicationsList(INT EnumType)
170 {
171 WCHAR szBuffer1[MAX_STR_LEN], szBuffer2[MAX_STR_LEN];
172 HICON hIcon;
173 HIMAGELIST hImageListView;
174
175 (VOID) ListView_DeleteAllItems(hListView);
176
177 /* Create image list */
178 hImageListView = ImageList_Create(LISTVIEW_ICON_SIZE,
179 LISTVIEW_ICON_SIZE,
180 GetSystemColorDepth() | ILC_MASK,
181 0, 1);
182
183 hIcon = LoadImage(hInst,
184 MAKEINTRESOURCE(IDI_MAIN),
185 IMAGE_ICON,
186 LISTVIEW_ICON_SIZE,
187 LISTVIEW_ICON_SIZE,
188 LR_CREATEDIBSECTION);
189
190 ImageList_AddIcon(hImageListView, hIcon);
191 DestroyIcon(hIcon);
192
193 if (EnumType == -1) EnumType = SelectedEnumType;
194
195 if (IS_INSTALLED_ENUM(SelectedEnumType))
196 FreeInstalledAppList();
197 else if (IS_AVAILABLE_ENUM(SelectedEnumType))
198 FreeAvailableAppList();
199
200 if (IS_INSTALLED_ENUM(EnumType))
201 {
202 /* Enum installed applications and updates */
203 EnumInstalledApplications(EnumType, TRUE, EnumInstalledAppProc);
204 EnumInstalledApplications(EnumType, FALSE, EnumInstalledAppProc);
205 }
206 else if (IS_AVAILABLE_ENUM(EnumType))
207 {
208 /* Enum availabled applications */
209 EnumAvailableApplications(EnumType, EnumAvailableAppProc);
210 }
211
212 /* Set image list for ListView */
213 hImageListView = ListView_SetImageList(hListView, hImageListView, LVSIL_SMALL);
214
215 /* Destroy old image list */
216 if (hImageListView)
217 ImageList_Destroy(hImageListView);
218
219 SelectedEnumType = EnumType;
220
221 LoadStringW(hInst, IDS_APPS_COUNT, szBuffer2, sizeof(szBuffer2) / sizeof(WCHAR));
222 StringCbPrintfW(szBuffer1, sizeof(szBuffer1),
223 szBuffer2,
224 ListView_GetItemCount(hListView));
225 SetStatusBarText(szBuffer1);
226
227 SetWelcomeText();
228 }
229
230 VOID
231 InitApplicationsList(VOID)
232 {
233 WCHAR szText[MAX_STR_LEN];
234
235 /* Add columns to ListView */
236 LoadStringW(hInst, IDS_APP_NAME, szText, sizeof(szText) / sizeof(WCHAR));
237 ListViewAddColumn(0, szText, 200, LVCFMT_LEFT);
238
239 LoadStringW(hInst, IDS_APP_INST_VERSION, szText, sizeof(szText) / sizeof(WCHAR));
240 ListViewAddColumn(1, szText, 90, LVCFMT_RIGHT);
241
242 LoadStringW(hInst, IDS_APP_DESCRIPTION, szText, sizeof(szText) / sizeof(WCHAR));
243 ListViewAddColumn(3, szText, 250, LVCFMT_LEFT);
244
245 UpdateApplicationsList(ENUM_ALL_COMPONENTS);
246 }
247
248 HTREEITEM
249 AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex)
250 {
251 WCHAR szText[MAX_STR_LEN];
252 INT Index;
253 HICON hIcon;
254
255 hIcon = LoadImage(hInst,
256 MAKEINTRESOURCE(IconIndex),
257 IMAGE_ICON,
258 TREEVIEW_ICON_SIZE,
259 TREEVIEW_ICON_SIZE,
260 LR_CREATEDIBSECTION);
261
262 Index = ImageList_AddIcon(hImageTreeView, hIcon);
263 DestroyIcon(hIcon);
264
265 LoadStringW(hInst, TextIndex, szText, sizeof(szText) / sizeof(TCHAR));
266
267 return TreeViewAddItem(hRootItem, szText, Index, Index, TextIndex);
268 }
269
270 VOID
271 InitCategoriesList(VOID)
272 {
273 HTREEITEM hRootItem1, hRootItem2;
274
275 /* Create image list */
276 hImageTreeView = ImageList_Create(TREEVIEW_ICON_SIZE,
277 TREEVIEW_ICON_SIZE,
278 GetSystemColorDepth() | ILC_MASK,
279 0, 1);
280
281 hRootItem1 = AddCategory(TVI_ROOT, IDS_INSTALLED, IDI_CATEGORY);
282 AddCategory(hRootItem1, IDS_APPLICATIONS, IDI_APPS);
283 AddCategory(hRootItem1, IDS_UPDATES, IDI_APPUPD);
284
285 hRootItem2 = AddCategory(TVI_ROOT, IDS_AVAILABLEFORINST, IDI_CATEGORY);
286 AddCategory(hRootItem2, IDS_CAT_AUDIO, IDI_CAT_AUDIO);
287 AddCategory(hRootItem2, IDS_CAT_VIDEO, IDI_CAT_VIDEO);
288 AddCategory(hRootItem2, IDS_CAT_GRAPHICS, IDI_CAT_GRAPHICS);
289 AddCategory(hRootItem2, IDS_CAT_GAMES, IDI_CAT_GAMES);
290 AddCategory(hRootItem2, IDS_CAT_INTERNET, IDI_CAT_INTERNET);
291 AddCategory(hRootItem2, IDS_CAT_OFFICE, IDI_CAT_OFFICE);
292 AddCategory(hRootItem2, IDS_CAT_DEVEL, IDI_CAT_DEVEL);
293 AddCategory(hRootItem2, IDS_CAT_EDU, IDI_CAT_EDU);
294 AddCategory(hRootItem2, IDS_CAT_ENGINEER, IDI_CAT_ENGINEER);
295 AddCategory(hRootItem2, IDS_CAT_FINANCE, IDI_CAT_FINANCE);
296 AddCategory(hRootItem2, IDS_CAT_SCIENCE, IDI_CAT_SCIENCE);
297 AddCategory(hRootItem2, IDS_CAT_TOOLS, IDI_CAT_TOOLS);
298 AddCategory(hRootItem2, IDS_CAT_DRIVERS, IDI_CAT_DRIVERS);
299 AddCategory(hRootItem2, IDS_CAT_LIBS, IDI_CAT_LIBS);
300 AddCategory(hRootItem2, IDS_CAT_OTHER, IDI_CAT_OTHER);
301
302 (VOID) TreeView_SetImageList(hTreeView, hImageTreeView, TVSIL_NORMAL);
303
304 (VOID) TreeView_Expand(hTreeView, hRootItem2, TVE_EXPAND);
305 (VOID) TreeView_Expand(hTreeView, hRootItem1, TVE_EXPAND);
306
307 (VOID) TreeView_SelectItem(hTreeView, hRootItem1);
308 }
309
310 BOOL
311 InitControls(HWND hwnd)
312 {
313 if (SettingsInfo.bSaveWndPos)
314 {
315 MoveWindow(hwnd, SettingsInfo.Left, SettingsInfo.Top,
316 SettingsInfo.Right - SettingsInfo.Left,
317 SettingsInfo.Bottom - SettingsInfo.Top, TRUE);
318
319 if (SettingsInfo.Maximized) ShowWindow(hwnd, SW_MAXIMIZE);
320 }
321
322 if (CreateStatusBar(hwnd) &&
323 CreateToolBar(hwnd) &&
324 CreateListView(hwnd) &&
325 CreateTreeView(hwnd) &&
326 CreateRichEdit(hwnd) &&
327 CreateVSplitBar(hwnd) &&
328 CreateHSplitBar(hwnd))
329 {
330 WCHAR szBuffer1[MAX_STR_LEN], szBuffer2[MAX_STR_LEN];
331
332 InitApplicationsList();
333
334 InitCategoriesList();
335
336 LoadStringW(hInst, IDS_APPS_COUNT, szBuffer2, sizeof(szBuffer2) / sizeof(WCHAR));
337 StringCbPrintfW(szBuffer1, sizeof(szBuffer1),
338 szBuffer2,
339 ListView_GetItemCount(hListView));
340 SetStatusBarText(szBuffer1);
341 return TRUE;
342 }
343
344 return FALSE;
345 }
346
347 VOID
348 MainWndOnCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
349 {
350 WORD wCommand = LOWORD(wParam);
351
352 if (lParam == (LPARAM)hSearchBar)
353 {
354 WCHAR szBuf[MAX_STR_LEN];
355
356 switch (HIWORD(wParam))
357 {
358 case EN_SETFOCUS:
359 {
360 WCHAR szWndText[MAX_STR_LEN];
361
362 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
363 GetWindowTextW(hSearchBar, szWndText, MAX_STR_LEN);
364 if (wcscmp(szBuf, szWndText) == 0) SetWindowTextW(hSearchBar, L"");
365 }
366 break;
367
368 case EN_KILLFOCUS:
369 {
370 GetWindowTextW(hSearchBar, szBuf, MAX_STR_LEN);
371 if (wcslen(szBuf) < 1)
372 {
373 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
374 SetWindowTextW(hSearchBar, szBuf);
375 }
376 }
377 break;
378
379 case EN_CHANGE:
380 /* TODO: Implement search */
381 break;
382 }
383
384 return;
385 }
386
387 switch (wCommand)
388 {
389 case ID_OPEN_LINK:
390 ShellExecuteW(hwnd, L"open", pLink, NULL, NULL, SW_SHOWNOACTIVATE);
391 HeapFree(GetProcessHeap(), 0, pLink);
392 break;
393
394 case ID_COPY_LINK:
395 CopyTextToClipboard(pLink);
396 HeapFree(GetProcessHeap(), 0, pLink);
397 break;
398
399 case ID_SETTINGS:
400 CreateSettingsDlg(hwnd);
401 break;
402
403 case ID_EXIT:
404 PostMessageW(hwnd, WM_CLOSE, 0, 0);
405 break;
406
407 case ID_INSTALL:
408 if (DownloadApplication(-1))
409 /* TODO: Implement install dialog
410 * if (InstallApplication(-1))
411 */
412 UpdateApplicationsList(-1);
413 break;
414
415 case ID_UNINSTALL:
416 if (UninstallApplication(-1, FALSE))
417 UpdateApplicationsList(-1);
418 break;
419
420 case ID_MODIFY:
421 if (UninstallApplication(-1, TRUE))
422 UpdateApplicationsList(-1);
423 break;
424
425 case ID_REGREMOVE:
426 RemoveAppFromRegistry(-1);
427 break;
428
429 case ID_REFRESH:
430 UpdateApplicationsList(-1);
431 break;
432
433 case ID_RESETDB:
434 UpdateAppsDB();
435 UpdateApplicationsList(-1);
436 break;
437
438 case ID_HELP:
439 MessageBoxW(hwnd, L"Help not implemented yet", NULL, MB_OK);
440 break;
441
442 case ID_ABOUT:
443 ShowAboutDialog();
444 break;
445 }
446 }
447
448 VOID
449 MainWndOnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
450 {
451 HDWP hdwp = BeginDeferWindowPos(5);
452 INT SearchBarWidth = GetWindowWidth(hSearchBar);
453 INT RichPos = GetWindowHeight(hRichEdit);
454 INT NewPos = HIWORD(lParam) - (RichPos + SPLIT_WIDTH + GetWindowHeight(hStatusBar));
455 INT VSplitterPos;
456
457 /* Size status bar */
458 SendMessage(hStatusBar, WM_SIZE, 0, 0);
459
460 /* Size tool bar */
461 SendMessage(hToolBar, TB_AUTOSIZE, 0, 0);
462
463 /* Size SearchBar */
464 MoveWindow(hSearchBar, LOWORD(lParam) - SearchBarWidth - 4, 5, SearchBarWidth, 22, TRUE);
465
466 /*
467 * HIWORD(lParam) - Height of main window
468 * LOWORD(lParam) - Width of main window
469 */
470
471 /* Size vertical splitter bar */
472 DeferWindowPos(hdwp,
473 hVSplitter,
474 0,
475 (VSplitterPos = GetWindowWidth(hTreeView)),
476 GetWindowHeight(hToolBar),
477 SPLIT_WIDTH,
478 HIWORD(lParam) - GetWindowHeight(hToolBar) - GetWindowHeight(hStatusBar),
479 SWP_NOZORDER|SWP_NOACTIVATE);
480
481 /* Size TreeView */
482 DeferWindowPos(hdwp,
483 hTreeView,
484 0,
485 0,
486 GetWindowHeight(hToolBar),
487 VSplitterPos,
488 HIWORD(lParam) - GetWindowHeight(hToolBar) - GetWindowHeight(hStatusBar),
489 SWP_NOZORDER|SWP_NOACTIVATE);
490
491 while (NewPos < SPLIT_WIDTH + GetWindowHeight(hToolBar))
492 {
493 RichPos--;
494 NewPos = HIWORD(lParam) - (RichPos +
495 SPLIT_WIDTH + GetWindowHeight(hStatusBar));
496 }
497 SetHSplitterPos(NewPos);
498
499 /* Size ListView */
500 DeferWindowPos(hdwp,
501 hListView,
502 0,
503 VSplitterPos + SPLIT_WIDTH,
504 GetWindowHeight(hToolBar),
505 LOWORD(lParam) - (VSplitterPos + SPLIT_WIDTH),
506 GetHSplitterPos() - GetWindowHeight(hToolBar),
507 SWP_NOZORDER|SWP_NOACTIVATE);
508
509 /* Size RichEdit */
510 DeferWindowPos(hdwp,
511 hRichEdit,
512 0,
513 VSplitterPos + SPLIT_WIDTH,
514 GetHSplitterPos() + SPLIT_WIDTH,
515 LOWORD(lParam) - (VSplitterPos + SPLIT_WIDTH),
516 RichPos,
517 SWP_NOZORDER|SWP_NOACTIVATE);
518
519 /* Size horizontal splitter bar */
520 DeferWindowPos(hdwp,
521 hHSplitter,
522 0,
523 VSplitterPos + SPLIT_WIDTH,
524 GetHSplitterPos(),
525 LOWORD(lParam) - (VSplitterPos + SPLIT_WIDTH),
526 SPLIT_WIDTH,
527 SWP_NOZORDER|SWP_NOACTIVATE);
528
529 EndDeferWindowPos(hdwp);
530 }
531
532 LRESULT CALLBACK
533 MainWindowProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
534 {
535 switch (Msg)
536 {
537 case WM_CREATE:
538 if (!InitControls(hwnd))
539 PostMessage(hwnd, WM_CLOSE, 0, 0);
540
541 if (SettingsInfo.bUpdateAtStart)
542 UpdateAppsDB();
543 break;
544
545 case WM_COMMAND:
546 MainWndOnCommand(hwnd, wParam, lParam);
547 break;
548
549 case WM_NOTIFY:
550 {
551 LPNMHDR data = (LPNMHDR)lParam;
552
553 switch (data->code)
554 {
555 case TVN_SELCHANGED:
556 {
557 if (data->hwndFrom == hTreeView)
558 {
559 switch (((LPNMTREEVIEW)lParam)->itemNew.lParam)
560 {
561 case IDS_INSTALLED:
562 UpdateApplicationsList(ENUM_ALL_COMPONENTS);
563 break;
564
565 case IDS_APPLICATIONS:
566 UpdateApplicationsList(ENUM_APPLICATIONS);
567 break;
568
569 case IDS_UPDATES:
570 UpdateApplicationsList(ENUM_UPDATES);
571 break;
572
573 case IDS_AVAILABLEFORINST:
574 UpdateApplicationsList(ENUM_ALL_AVAILABLE);
575 break;
576
577 case IDS_CAT_AUDIO:
578 UpdateApplicationsList(ENUM_CAT_AUDIO);
579 break;
580
581 case IDS_CAT_DEVEL:
582 UpdateApplicationsList(ENUM_CAT_DEVEL);
583 break;
584
585 case IDS_CAT_DRIVERS:
586 UpdateApplicationsList(ENUM_CAT_DRIVERS);
587 break;
588
589 case IDS_CAT_EDU:
590 UpdateApplicationsList(ENUM_CAT_EDU);
591 break;
592
593 case IDS_CAT_ENGINEER:
594 UpdateApplicationsList(ENUM_CAT_ENGINEER);
595 break;
596
597 case IDS_CAT_FINANCE:
598 UpdateApplicationsList(ENUM_CAT_FINANCE);
599 break;
600
601 case IDS_CAT_GAMES:
602 UpdateApplicationsList(ENUM_CAT_GAMES);
603 break;
604
605 case IDS_CAT_GRAPHICS:
606 UpdateApplicationsList(ENUM_CAT_GRAPHICS);
607 break;
608
609 case IDS_CAT_INTERNET:
610 UpdateApplicationsList(ENUM_CAT_INTERNET);
611 break;
612
613 case IDS_CAT_LIBS:
614 UpdateApplicationsList(ENUM_CAT_LIBS);
615 break;
616
617 case IDS_CAT_OFFICE:
618 UpdateApplicationsList(ENUM_CAT_OFFICE);
619 break;
620
621 case IDS_CAT_OTHER:
622 UpdateApplicationsList(ENUM_CAT_OTHER);
623 break;
624
625 case IDS_CAT_SCIENCE:
626 UpdateApplicationsList(ENUM_CAT_SCIENCE);
627 break;
628
629 case IDS_CAT_TOOLS:
630 UpdateApplicationsList(ENUM_CAT_TOOLS);
631 break;
632
633 case IDS_CAT_VIDEO:
634 UpdateApplicationsList(ENUM_CAT_VIDEO);
635 break;
636 }
637 }
638 }
639 break;
640
641 case LVN_ITEMCHANGED:
642 {
643 LPNMLISTVIEW pnic = (LPNMLISTVIEW) lParam;
644
645 if (pnic->hdr.hwndFrom == hListView)
646 {
647 /* Check if this is a valid item
648 * (technically, it can be also an unselect) */
649 INT ItemIndex = pnic->iItem;
650 if (ItemIndex == -1 ||
651 ItemIndex >= ListView_GetItemCount(pnic->hdr.hwndFrom))
652 {
653 break;
654 }
655
656 /* Check if the focus has been moved to another item */
657 if ((pnic->uChanged & LVIF_STATE) &&
658 (pnic->uNewState & LVIS_FOCUSED) &&
659 !(pnic->uOldState & LVIS_FOCUSED))
660 {
661 if (IS_INSTALLED_ENUM(SelectedEnumType))
662 ShowInstalledAppInfo(ItemIndex);
663 if (IS_AVAILABLE_ENUM(SelectedEnumType))
664 ShowAvailableAppInfo(ItemIndex);
665 }
666 }
667 }
668 break;
669
670 case LVN_COLUMNCLICK:
671 {
672 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
673
674 (VOID) ListView_SortItems(hListView, ListViewCompareFunc, pnmv->iSubItem);
675 bAscending = !bAscending;
676 }
677 break;
678
679 case NM_CLICK:
680 if (data->hwndFrom == hListView)
681 {
682 if (IS_INSTALLED_ENUM(SelectedEnumType))
683 ShowInstalledAppInfo(-1);
684 if (IS_AVAILABLE_ENUM(SelectedEnumType))
685 ShowAvailableAppInfo(-1);
686 }
687 break;
688
689 case NM_RCLICK:
690 if (data->hwndFrom == hListView)
691 ShowPopupMenu(hListView, IDR_APPLICATIONMENU);
692 break;
693
694 case EN_LINK:
695 RichEditOnLink(hwnd, (ENLINK*)lParam);
696 break;
697
698 case TTN_GETDISPINFO:
699 ToolBarOnGetDispInfo((LPTOOLTIPTEXT)lParam);
700 break;
701 }
702 }
703 break;
704
705 case WM_PAINT:
706 break;
707
708 case WM_SIZE:
709 {
710 if ((GetClientWindowHeight(hMainWnd) - GetWindowHeight(hStatusBar) - SPLIT_WIDTH) < GetHSplitterPos())
711 {
712 INT NewSplitPos = GetClientWindowHeight(hwnd) - 100 - GetWindowHeight(hStatusBar) - SPLIT_WIDTH;
713 if (NewSplitPos > GetWindowHeight(hToolBar) + SPLIT_WIDTH)
714 SetHSplitterPos(NewSplitPos);
715 }
716
717 MainWndOnSize(hwnd, wParam, lParam);
718 }
719 break;
720
721 case WM_SIZING:
722 {
723 int RichEditHeight = GetWindowHeight(hRichEdit);
724 LPRECT pRect = (LPRECT)lParam;
725
726 while (RichEditHeight <= 100)
727 {
728 if (GetHSplitterPos() - 1 < GetWindowHeight(hToolBar) + GetWindowHeight(hListView) + SPLIT_WIDTH)
729 break;
730 SetHSplitterPos(GetHSplitterPos() - 1);
731 RichEditHeight++;
732 }
733
734 if (pRect->right-pRect->left < 565)
735 pRect->right = pRect->left + 565;
736
737 if (pRect->bottom-pRect->top < 300)
738 pRect->bottom = pRect->top + 300;
739 return TRUE;
740 }
741
742 case WM_SYSCOLORCHANGE:
743 {
744 /* Forward WM_SYSCOLORCHANGE to common controls */
745 SendMessage(hListView, WM_SYSCOLORCHANGE, 0, 0);
746 SendMessage(hTreeView, WM_SYSCOLORCHANGE, 0, 0);
747 SendMessage(hToolBar, WM_SYSCOLORCHANGE, 0, 0);
748 SendMessageW(hRichEdit, EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
749 }
750 break;
751
752 case WM_DESTROY:
753 {
754 ShowWindow(hwnd, SW_HIDE);
755 SaveSettings(hwnd);
756
757 FreeLogs();
758
759 if (IS_AVAILABLE_ENUM(SelectedEnumType))
760 FreeAvailableAppList();
761 if (IS_INSTALLED_ENUM(SelectedEnumType))
762 FreeInstalledAppList();
763 if (hImageTreeView) ImageList_Destroy(hImageTreeView);
764
765 PostQuitMessage(0);
766 return 0;
767 }
768 break;
769 }
770
771 return DefWindowProc(hwnd, Msg, wParam, lParam);
772 }
773
774 int WINAPI
775 wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
776 {
777 WNDCLASSEXW WndClass = {0};
778 WCHAR szWindowClass[] = L"ROSAPPMGR";
779 WCHAR szWindowName[MAX_STR_LEN];
780 HANDLE hMutex = NULL;
781 MSG Msg;
782
783 switch (GetUserDefaultUILanguage())
784 {
785 case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT):
786 SetProcessDefaultLayout(LAYOUT_RTL);
787 break;
788
789 default:
790 break;
791 }
792
793 hInst = hInstance;
794
795 hMutex = CreateMutexW(NULL, FALSE, szWindowClass);
796 if ((!hMutex) || (GetLastError() == ERROR_ALREADY_EXISTS))
797 {
798 /* If already started, it is found its window */
799 HWND hWindow = FindWindowW(szWindowClass, NULL);
800
801 /* Activate window */
802 ShowWindow(hWindow, SW_SHOWNORMAL);
803 SetForegroundWindow(hWindow);
804 return 1;
805 }
806
807 if (!LoadSettings())
808 {
809 FillDefaultSettings(&SettingsInfo);
810 }
811
812 InitLogs();
813
814 InitCommonControls();
815
816 /* Create the window */
817 WndClass.cbSize = sizeof(WNDCLASSEXW);
818 WndClass.lpszClassName = szWindowClass;
819 WndClass.lpfnWndProc = MainWindowProc;
820 WndClass.hInstance = hInstance;
821 WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN));
822 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
823 WndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
824 WndClass.lpszMenuName = MAKEINTRESOURCEW(IDR_MAINMENU);
825
826 if (RegisterClassExW(&WndClass) == (ATOM)0) goto Exit;
827
828 LoadStringW(hInst, IDS_APPTITLE, szWindowName, sizeof(szWindowName) / sizeof(WCHAR));
829
830 hMainWnd = CreateWindowExW(WS_EX_WINDOWEDGE,
831 szWindowClass,
832 szWindowName,
833 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
834 CW_USEDEFAULT,
835 CW_USEDEFAULT,
836 680,
837 450,
838 NULL,
839 NULL,
840 hInstance,
841 NULL);
842
843 if (!hMainWnd) goto Exit;
844
845 /* Show it */
846 ShowWindow(hMainWnd, SW_SHOW);
847 UpdateWindow(hMainWnd);
848
849 /* Message Loop */
850 while (GetMessage(&Msg, NULL, 0, 0))
851 {
852 TranslateMessage(&Msg);
853 DispatchMessage(&Msg);
854 }
855
856 Exit:
857 if (hMutex) CloseHandle(hMutex);
858
859 return 0;
860 }