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