[RAPPS] CMainWindow: make szSearchPattern a member
[reactos.git] / base / applications / rapps / gui.cpp
1 /*
2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * FILE: base/applications/rapps/gui.cpp
5 * PURPOSE: GUI classes for RAPPS
6 * COPYRIGHT: Copyright 2015 David Quintana (gigaherz@gmail.com)
7 * Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
8 */
9 #include "rapps.h"
10
11 #include "rapps.h"
12 #include "rosui.h"
13 #include "crichedit.h"
14
15 #include <shlobj_undoc.h>
16 #include <shlguid_undoc.h>
17
18 #include <atlbase.h>
19 #include <atlcom.h>
20 #include <atlwin.h>
21 #include <wininet.h>
22 #include <shellutils.h>
23 #include <rosctrls.h>
24
25 #define SEARCH_TIMER_ID 'SR'
26 #define LISTVIEW_ICON_SIZE 24
27 #define TREEVIEW_ICON_SIZE 24
28
29 HWND hListView = NULL;
30
31 INT GetSystemColorDepth()
32 {
33 DEVMODEW pDevMode;
34 INT ColorDepth;
35
36 pDevMode.dmSize = sizeof(pDevMode);
37 pDevMode.dmDriverExtra = 0;
38
39 if (!EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &pDevMode))
40 {
41 /* TODO: Error message */
42 return ILC_COLOR;
43 }
44
45 switch (pDevMode.dmBitsPerPel)
46 {
47 case 32: ColorDepth = ILC_COLOR32; break;
48 case 24: ColorDepth = ILC_COLOR24; break;
49 case 16: ColorDepth = ILC_COLOR16; break;
50 case 8: ColorDepth = ILC_COLOR8; break;
51 case 4: ColorDepth = ILC_COLOR4; break;
52 default: ColorDepth = ILC_COLOR; break;
53 }
54
55 return ColorDepth;
56 }
57
58 class CAppRichEdit:
59 public CUiWindow<CRichEdit>
60 {
61 private:
62 VOID LoadAndInsertText(UINT uStringID,
63 const ATL::CStringW& szText,
64 DWORD StringFlags,
65 DWORD TextFlags)
66 {
67 ATL::CStringW szLoadedText;
68 if (!szText.IsEmpty() && szLoadedText.LoadStringW(uStringID))
69 {
70 InsertText(szLoadedText, StringFlags);
71 InsertText(szText, TextFlags);
72 }
73 }
74
75 VOID LoadAndInsertText(UINT uStringID,
76 DWORD StringFlags)
77 {
78 ATL::CStringW szLoadedText;
79 if (szLoadedText.LoadStringW(uStringID))
80 {
81 InsertText(L"\n", 0);
82 InsertText(szLoadedText, StringFlags);
83 InsertText(L"\n", 0);
84 }
85 }
86
87 VOID InsertVersionInfo(CAvailableApplicationInfo* Info)
88 {
89 if (Info->IsInstalled())
90 {
91 if (Info->HasInstalledVersion())
92 {
93 if (Info->HasUpdate())
94 LoadAndInsertText(IDS_STATUS_UPDATE_AVAILABLE, CFE_ITALIC);
95 else
96 LoadAndInsertText(IDS_STATUS_INSTALLED, CFE_ITALIC);
97
98 LoadAndInsertText(IDS_AINFO_VERSION, Info->m_szInstalledVersion, CFE_BOLD, 0);
99 }
100 else
101 {
102 LoadAndInsertText(IDS_STATUS_INSTALLED, CFE_ITALIC);
103 }
104 }
105 else
106 {
107 LoadAndInsertText(IDS_STATUS_NOTINSTALLED, CFE_ITALIC);
108 }
109
110 LoadAndInsertText(IDS_AINFO_AVAILABLEVERSION, Info->m_szVersion, CFE_BOLD, 0);
111 }
112
113 VOID InsertLicenseInfo(CAvailableApplicationInfo* Info)
114 {
115 ATL::CStringW szLicense;
116 switch (Info->m_LicenseType)
117 {
118 case LICENSE_OPENSOURCE:
119 szLicense.LoadStringW(IDS_LICENSE_OPENSOURCE);
120 break;
121 case LICENSE_FREEWARE:
122 szLicense.LoadStringW(IDS_LICENSE_FREEWARE);
123 break;
124 case LICENSE_TRIAL:
125 szLicense.LoadStringW(IDS_LICENSE_TRIAL);
126 break;
127 default:
128 LoadAndInsertText(IDS_AINFO_LICENSE, Info->m_szLicense, CFE_BOLD, 0);
129 return;
130 }
131
132 szLicense += L" (" + Info->m_szLicense + L")";
133 LoadAndInsertText(IDS_AINFO_LICENSE, szLicense, CFE_BOLD, 0);
134 }
135
136 VOID InsertLanguageInfo(CAvailableApplicationInfo* Info)
137 {
138 if (!Info->HasLanguageInfo())
139 {
140 return;
141 }
142
143 const INT nTranslations = Info->m_LanguageLCIDs.GetSize();
144 ATL::CStringW szLangInfo;
145 ATL::CStringW szLoadedTextAvailability;
146 ATL::CStringW szLoadedAInfoText;
147
148 szLoadedAInfoText.LoadStringW(IDS_AINFO_LANGUAGES);
149
150 if (Info->HasNativeLanguage())
151 {
152 szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_AVAILABLE_TRANSLATION);
153 if (nTranslations > 1)
154 {
155 ATL::CStringW buf;
156 buf.LoadStringW(IDS_LANGUAGE_MORE_PLACEHOLDER);
157 szLangInfo.Format(buf, nTranslations - 1);
158 }
159 else
160 {
161 szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE);
162 szLangInfo = L" (" + szLangInfo + L")";
163 }
164 }
165 else if (Info->HasEnglishLanguage())
166 {
167 szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_ENGLISH_TRANSLATION);
168 if (nTranslations > 1)
169 {
170 ATL::CStringW buf;
171 buf.LoadStringW(IDS_LANGUAGE_AVAILABLE_PLACEHOLDER);
172 szLangInfo.Format(buf, nTranslations - 1);
173 }
174 else
175 {
176 szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE);
177 szLangInfo = L" (" + szLangInfo + L")";
178 }
179 }
180 else
181 {
182 szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_NO_TRANSLATION);
183 }
184
185 InsertText(szLoadedAInfoText, CFE_BOLD);
186 InsertText(szLoadedTextAvailability, NULL);
187 InsertText(szLangInfo, CFE_ITALIC);
188 }
189
190 public:
191 BOOL ShowAvailableAppInfo(CAvailableApplicationInfo* Info)
192 {
193 if (!Info) return FALSE;
194
195 SetText(Info->m_szName, CFE_BOLD);
196 InsertVersionInfo(Info);
197 InsertLicenseInfo(Info);
198 InsertLanguageInfo(Info);
199
200 LoadAndInsertText(IDS_AINFO_SIZE, Info->m_szSize, CFE_BOLD, 0);
201 LoadAndInsertText(IDS_AINFO_URLSITE, Info->m_szUrlSite, CFE_BOLD, CFE_LINK);
202 LoadAndInsertText(IDS_AINFO_DESCRIPTION, Info->m_szDesc, CFE_BOLD, 0);
203 LoadAndInsertText(IDS_AINFO_URLDOWNLOAD, Info->m_szUrlDownload, CFE_BOLD, CFE_LINK);
204
205 return TRUE;
206 }
207
208 BOOL ShowInstalledAppInfo(PINSTALLED_INFO Info)
209 {
210 ATL::CStringW szText;
211 ATL::CStringW szInfo;
212
213 if (!Info || !Info->hSubKey)
214 return FALSE;
215
216 Info->GetApplicationString(L"DisplayName", szText);
217 SetText(szText, CFE_BOLD);
218 InsertText(L"\n", 0);
219
220 #define GET_INFO(a, b, c, d) \
221 if (Info->GetApplicationString(a, szInfo)) \
222 { \
223 LoadAndInsertText(b, szInfo, c, d); \
224 }
225
226 GET_INFO(L"DisplayVersion", IDS_INFO_VERSION, CFE_BOLD, 0);
227 GET_INFO(L"Publisher", IDS_INFO_PUBLISHER, CFE_BOLD, 0);
228 GET_INFO(L"RegOwner", IDS_INFO_REGOWNER, CFE_BOLD, 0);
229 GET_INFO(L"ProductID", IDS_INFO_PRODUCTID, CFE_BOLD, 0);
230 GET_INFO(L"HelpLink", IDS_INFO_HELPLINK, CFE_BOLD, CFM_LINK);
231 GET_INFO(L"HelpTelephone", IDS_INFO_HELPPHONE, CFE_BOLD, 0);
232 GET_INFO(L"Readme", IDS_INFO_README, CFE_BOLD, 0);
233 GET_INFO(L"Contact", IDS_INFO_CONTACT, CFE_BOLD, 0);
234 GET_INFO(L"URLUpdateInfo", IDS_INFO_UPDATEINFO, CFE_BOLD, CFM_LINK);
235 GET_INFO(L"URLInfoAbout", IDS_INFO_INFOABOUT, CFE_BOLD, CFM_LINK);
236 GET_INFO(L"Comments", IDS_INFO_COMMENTS, CFE_BOLD, 0);
237 GET_INFO(L"InstallDate", IDS_INFO_INSTALLDATE, CFE_BOLD, 0);
238 GET_INFO(L"InstallLocation", IDS_INFO_INSTLOCATION, CFE_BOLD, 0);
239 GET_INFO(L"InstallSource", IDS_INFO_INSTALLSRC, CFE_BOLD, 0);
240 GET_INFO(L"UninstallString", IDS_INFO_UNINSTALLSTR, CFE_BOLD, 0);
241 GET_INFO(L"InstallSource", IDS_INFO_INSTALLSRC, CFE_BOLD, 0);
242 GET_INFO(L"ModifyPath", IDS_INFO_MODIFYPATH, CFE_BOLD, 0);
243
244 return TRUE;
245 }
246
247 VOID SetWelcomeText()
248 {
249 ATL::CStringW szText;
250
251 szText.LoadStringW(IDS_WELCOME_TITLE);
252 SetText(szText, CFE_BOLD);
253
254 szText.LoadStringW(IDS_WELCOME_TEXT);
255 InsertText(szText, 0);
256
257 szText.LoadStringW(IDS_WELCOME_URL);
258 InsertText(szText, CFM_LINK);
259 }
260 };
261
262 class CMainToolbar :
263 public CUiWindow< CToolbar<> >
264 {
265 const INT m_iToolbarHeight;
266 DWORD m_dButtonsWidthMax;
267
268 WCHAR szInstallBtn[MAX_STR_LEN];
269 WCHAR szUninstallBtn[MAX_STR_LEN];
270 WCHAR szModifyBtn[MAX_STR_LEN];
271 WCHAR szSelectAll[MAX_STR_LEN];
272
273 VOID AddImageToImageList(HIMAGELIST hImageList, UINT ImageIndex)
274 {
275 HICON hImage;
276
277 if (!(hImage = (HICON) LoadImageW(hInst,
278 MAKEINTRESOURCE(ImageIndex),
279 IMAGE_ICON,
280 m_iToolbarHeight,
281 m_iToolbarHeight,
282 0)))
283 {
284 /* TODO: Error message */
285 }
286
287 ImageList_AddIcon(hImageList, hImage);
288 DeleteObject(hImage);
289 }
290
291 HIMAGELIST InitImageList()
292 {
293 HIMAGELIST hImageList;
294
295 /* Create the toolbar icon image list */
296 hImageList = ImageList_Create(m_iToolbarHeight,//GetSystemMetrics(SM_CXSMICON),
297 m_iToolbarHeight,//GetSystemMetrics(SM_CYSMICON),
298 ILC_MASK | GetSystemColorDepth(),
299 1, 1);
300 if (!hImageList)
301 {
302 /* TODO: Error message */
303 return NULL;
304 }
305
306 AddImageToImageList(hImageList, IDI_INSTALL);
307 AddImageToImageList(hImageList, IDI_UNINSTALL);
308 AddImageToImageList(hImageList, IDI_MODIFY);
309 AddImageToImageList(hImageList, IDI_CHECK_ALL);
310 AddImageToImageList(hImageList, IDI_REFRESH);
311 AddImageToImageList(hImageList, IDI_UPDATE_DB);
312 AddImageToImageList(hImageList, IDI_SETTINGS);
313 AddImageToImageList(hImageList, IDI_EXIT);
314
315 return hImageList;
316 }
317
318 public:
319 CMainToolbar() : m_iToolbarHeight(24)
320 {
321 }
322
323 VOID OnGetDispInfo(LPTOOLTIPTEXT lpttt)
324 {
325 UINT idButton = (UINT) lpttt->hdr.idFrom;
326
327 switch (idButton)
328 {
329 case ID_EXIT:
330 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_EXIT);
331 break;
332
333 case ID_INSTALL:
334 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_INSTALL);
335 break;
336
337 case ID_UNINSTALL:
338 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_UNINSTALL);
339 break;
340
341 case ID_MODIFY:
342 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_MODIFY);
343 break;
344
345 case ID_SETTINGS:
346 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_SETTINGS);
347 break;
348
349 case ID_REFRESH:
350 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_REFRESH);
351 break;
352
353 case ID_RESETDB:
354 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_UPDATE_DB);
355 break;
356 }
357 }
358
359 HWND Create(HWND hwndParent)
360 {
361 /* Create buttons */
362 TBBUTTON Buttons[] =
363 { /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
364 { 0, ID_INSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szInstallBtn },
365 { 1, ID_UNINSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szUninstallBtn },
366 { 2, ID_MODIFY, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szModifyBtn },
367 { 3, ID_CHECK_ALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szSelectAll },
368 { -1, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
369 { 4, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
370 { 5, ID_RESETDB, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
371 { -1, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
372 { 6, ID_SETTINGS, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
373 { 7, ID_EXIT, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
374 };
375
376 LoadStringW(hInst, IDS_INSTALL, szInstallBtn, _countof(szInstallBtn));
377 LoadStringW(hInst, IDS_UNINSTALL, szUninstallBtn, _countof(szUninstallBtn));
378 LoadStringW(hInst, IDS_MODIFY, szModifyBtn, _countof(szModifyBtn));
379 LoadStringW(hInst, IDS_SELECT_ALL, szSelectAll, _countof(szSelectAll));
380
381 m_hWnd = CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL,
382 WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | TBSTYLE_LIST,
383 0, 0, 0, 0,
384 hwndParent,
385 0, hInst, NULL);
386
387 if (!m_hWnd)
388 {
389 /* TODO: Show error message */
390 return FALSE;
391 }
392
393 SendMessageW(TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS);
394 SetButtonStructSize();
395
396 /* Set image list */
397 HIMAGELIST hImageList = InitImageList();
398
399 if (!hImageList)
400 {
401 /* TODO: Show error message */
402 return FALSE;
403 }
404
405 ImageList_Destroy(SetImageList(hImageList));
406
407 AddButtons(_countof(Buttons), Buttons);
408
409 /* Remember ideal width to use as a max width of buttons */
410 SIZE size;
411 GetIdealSize(FALSE, &size);
412 m_dButtonsWidthMax = size.cx;
413
414 return m_hWnd;
415 }
416
417 VOID HideButtonCaption()
418 {
419 DWORD dCurrentExStyle = (DWORD) SendMessageW(TB_GETEXTENDEDSTYLE, 0, 0);
420 SendMessageW(TB_SETEXTENDEDSTYLE, 0, dCurrentExStyle | TBSTYLE_EX_MIXEDBUTTONS);
421 }
422
423 VOID ShowButtonCaption()
424 {
425 DWORD dCurrentExStyle = (DWORD) SendMessageW(TB_GETEXTENDEDSTYLE, 0, 0);
426 SendMessageW(TB_SETEXTENDEDSTYLE, 0, dCurrentExStyle & ~TBSTYLE_EX_MIXEDBUTTONS);
427 }
428
429 DWORD GetMaxButtonsWidth() const
430 {
431 return m_dButtonsWidthMax;
432 }
433 };
434
435 class CAppsListView :
436 public CUiWindow<CListView>
437 {
438 struct SortContext
439 {
440 CAppsListView * lvw;
441 INT iSubItem;
442 };
443
444 BOOL bHasAllChecked;
445 BOOL bIsAscending;
446 BOOL bHasCheckboxes;
447
448 INT nLastHeaderID;
449
450 public:
451 CAppsListView() :
452 bHasAllChecked(FALSE),
453 bIsAscending(TRUE),
454 bHasCheckboxes(FALSE),
455 nLastHeaderID(-1)
456 {
457 }
458
459 VOID SetCheckboxesVisible(BOOL bIsVisible)
460 {
461 if (bIsVisible)
462 {
463 SetExtendedListViewStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
464 }
465 else
466 {
467 SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
468 }
469
470 bHasCheckboxes = bIsVisible;
471 }
472
473 VOID ColumnClick(LPNMLISTVIEW pnmv)
474 {
475 HWND hHeader;
476 HDITEMW hColumn;
477 INT nHeaderID = pnmv->iSubItem;
478
479 if ((GetWindowLongPtr(GWL_STYLE) & ~LVS_NOSORTHEADER) == 0)
480 return;
481
482 hHeader = (HWND) SendMessage(LVM_GETHEADER, 0, 0);
483 ZeroMemory(&hColumn, sizeof(hColumn));
484
485 /* If the sorting column changed, remove the sorting style from the old column */
486 if ((nLastHeaderID != -1) && (nLastHeaderID != nHeaderID))
487 {
488 hColumn.mask = HDI_FORMAT;
489 Header_GetItem(hHeader, nLastHeaderID, &hColumn);
490 hColumn.fmt &= ~(HDF_SORTUP | HDF_SORTDOWN);
491 Header_SetItem(hHeader, nLastHeaderID, &hColumn);
492 }
493
494 /* Set the sorting style to the new column */
495 hColumn.mask = HDI_FORMAT;
496 Header_GetItem(hHeader, nHeaderID, &hColumn);
497
498 hColumn.fmt &= (bIsAscending ? ~HDF_SORTDOWN : ~HDF_SORTUP);
499 hColumn.fmt |= (bIsAscending ? HDF_SORTUP : HDF_SORTDOWN);
500 Header_SetItem(hHeader, nHeaderID, &hColumn);
501
502 /* Sort the list, using the current values of nHeaderID and bIsAscending */
503 SortContext ctx = {this, nHeaderID};
504 SortItems(s_CompareFunc, &ctx);
505
506 /* Save new values */
507 nLastHeaderID = nHeaderID;
508 bIsAscending = !bIsAscending;
509 }
510
511 PVOID GetLParam(INT Index)
512 {
513 INT ItemIndex;
514 LVITEMW Item;
515
516 if (Index == -1)
517 {
518 ItemIndex = (INT) SendMessage(LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
519 if (ItemIndex == -1)
520 return NULL;
521 }
522 else
523 {
524 ItemIndex = Index;
525 }
526
527 ZeroMemory(&Item, sizeof(Item));
528
529 Item.mask = LVIF_PARAM;
530 Item.iItem = ItemIndex;
531 if (!GetItem(&Item))
532 return NULL;
533
534 return (PVOID) Item.lParam;
535 }
536
537 BOOL AddColumn(INT Index, ATL::CStringW& Text, INT Width, INT Format)
538 {
539 return AddColumn(Index, const_cast<LPWSTR>(Text.GetString()), Width, Format);
540 }
541
542 BOOL AddColumn(INT Index, LPWSTR lpText, INT Width, INT Format)
543 {
544 LVCOLUMNW Column;
545
546 ZeroMemory(&Column, sizeof(Column));
547
548 Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
549 Column.iSubItem = Index;
550 Column.pszText = lpText;
551 Column.cx = Width;
552 Column.fmt = Format;
553
554 return (InsertColumn(Index, &Column) == -1) ? FALSE : TRUE;
555 }
556
557 INT AddItem(INT ItemIndex, INT IconIndex, LPCWSTR lpText, LPARAM lParam)
558 {
559 LVITEMW Item;
560
561 ZeroMemory(&Item, sizeof(Item));
562
563 Item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
564 Item.pszText = const_cast<LPWSTR>(lpText);
565 Item.lParam = lParam;
566 Item.iItem = ItemIndex;
567 Item.iImage = IconIndex;
568
569 return InsertItem(&Item);
570 }
571
572 static INT CALLBACK s_CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
573 {
574 SortContext * ctx = ((SortContext*) lParamSort);
575 return ctx->lvw->CompareFunc(lParam1, lParam2, ctx->iSubItem);
576 }
577
578 INT CompareFunc(LPARAM lParam1, LPARAM lParam2, INT iSubItem)
579 {
580 ATL::CStringW Item1, Item2;
581 LVFINDINFOW IndexInfo;
582 INT Index;
583
584 IndexInfo.flags = LVFI_PARAM;
585
586 IndexInfo.lParam = lParam1;
587 Index = FindItem(-1, &IndexInfo);
588 GetItemText(Index, iSubItem, Item1.GetBuffer(MAX_STR_LEN), MAX_STR_LEN);
589 Item1.ReleaseBuffer();
590
591 IndexInfo.lParam = lParam2;
592 Index = FindItem(-1, &IndexInfo);
593 GetItemText(Index, iSubItem, Item2.GetBuffer(MAX_STR_LEN), MAX_STR_LEN);
594 Item2.ReleaseBuffer();
595
596 return bIsAscending ? Item1.Compare(Item2) : Item2.Compare(Item1);
597 }
598
599 HWND Create(HWND hwndParent)
600 {
601 RECT r = {205, 28, 465, 250};
602 DWORD style = WS_CHILD | WS_VISIBLE | LVS_SORTASCENDING | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS;
603 HMENU menu = GetSubMenu(LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_APPLICATIONMENU)), 0);
604
605 HWND hwnd = CListView::Create(hwndParent, r, NULL, style, WS_EX_CLIENTEDGE, menu);
606
607 if (hwnd)
608 {
609 SetCheckboxesVisible(FALSE);
610 }
611
612 return hwnd;
613 }
614
615 BOOL GetCheckState(INT item)
616 {
617 return (BOOL) (GetItemState(item, LVIS_STATEIMAGEMASK) >> 12) - 1;
618 }
619
620 VOID SetCheckState(INT item, BOOL fCheck)
621 {
622 if (bHasCheckboxes)
623 {
624 SetItemState(item, INDEXTOSTATEIMAGEMASK((fCheck) ? 2 : 1), LVIS_STATEIMAGEMASK);
625 SetSelected(item, fCheck);
626 }
627 }
628
629 VOID SetSelected(INT item, BOOL value)
630 {
631 if (item < 0)
632 {
633 for (INT i = 0; i >= 0; i = GetNextItem(i, LVNI_ALL))
634 {
635 CAvailableApplicationInfo* pAppInfo = (CAvailableApplicationInfo*) GetItemData(i);
636 if (pAppInfo)
637 {
638 pAppInfo->m_IsSelected = value;
639 }
640 }
641 }
642 else
643 {
644 CAvailableApplicationInfo* pAppInfo = (CAvailableApplicationInfo*) GetItemData(item);
645 if (pAppInfo)
646 {
647 pAppInfo->m_IsSelected = value;
648 }
649 }
650 }
651
652 VOID CheckAll()
653 {
654 if (bHasCheckboxes)
655 {
656 bHasAllChecked = !bHasAllChecked;
657 SetCheckState(-1, bHasAllChecked);
658 }
659 }
660
661 ATL::CSimpleArray<CAvailableApplicationInfo> GetCheckedItems()
662 {
663 if (!bHasCheckboxes)
664 {
665 return ATL::CSimpleArray<CAvailableApplicationInfo>();
666 }
667
668 ATL::CSimpleArray<CAvailableApplicationInfo> list;
669 for (INT i = 0; i >= 0; i = GetNextItem(i, LVNI_ALL))
670 {
671 if (GetCheckState(i) != FALSE)
672 {
673 CAvailableApplicationInfo* pAppInfo = (CAvailableApplicationInfo*) GetItemData(i);
674 list.Add(*pAppInfo);
675 }
676 }
677 return list;
678 }
679
680 CAvailableApplicationInfo* GetSelectedData()
681 {
682 INT item = GetSelectionMark();
683 return (CAvailableApplicationInfo*) GetItemData(item);
684 }
685 };
686
687 class CSideTreeView :
688 public CUiWindow<CTreeView>
689 {
690 HIMAGELIST hImageTreeView;
691
692 public:
693 CSideTreeView() :
694 CUiWindow(),
695 hImageTreeView(ImageList_Create(TREEVIEW_ICON_SIZE, TREEVIEW_ICON_SIZE,
696 GetSystemColorDepth() | ILC_MASK,
697 0, 1))
698 {
699 }
700
701 HTREEITEM AddItem(HTREEITEM hParent, ATL::CStringW &Text, INT Image, INT SelectedImage, LPARAM lParam)
702 {
703 return CUiWindow<CTreeView>::AddItem(hParent, const_cast<LPWSTR>(Text.GetString()), Image, SelectedImage, lParam);
704 }
705
706 HTREEITEM AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex)
707 {
708 ATL::CStringW szText;
709 INT Index;
710 HICON hIcon;
711
712 hIcon = (HICON) LoadImageW(hInst,
713 MAKEINTRESOURCE(IconIndex),
714 IMAGE_ICON,
715 TREEVIEW_ICON_SIZE,
716 TREEVIEW_ICON_SIZE,
717 LR_CREATEDIBSECTION);
718 if (hIcon)
719 {
720 Index = ImageList_AddIcon(hImageTreeView, hIcon);
721 DestroyIcon(hIcon);
722 }
723
724 szText.LoadStringW(TextIndex);
725 return AddItem(hRootItem, szText, Index, Index, TextIndex);
726 }
727
728 HIMAGELIST SetImageList()
729 {
730 return CUiWindow<CTreeView>::SetImageList(hImageTreeView, TVSIL_NORMAL);
731 }
732
733 VOID DestroyImageList()
734 {
735 if (hImageTreeView)
736 ImageList_Destroy(hImageTreeView);
737 }
738
739 ~CSideTreeView()
740 {
741 DestroyImageList();
742 }
743 };
744
745 class CSearchBar :
746 public CWindow
747 {
748 public:
749 const INT m_Width;
750 const INT m_Height;
751
752 CSearchBar() : m_Width(200), m_Height(22)
753 {
754 }
755
756 VOID SetText(LPCWSTR lpszText)
757 {
758 SendMessageW(SB_SETTEXT, SBT_NOBORDERS, (LPARAM) lpszText);
759 }
760
761 HWND Create(HWND hwndParent)
762 {
763 ATL::CStringW szBuf;
764 m_hWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"Edit", NULL,
765 WS_CHILD | WS_VISIBLE | ES_LEFT | ES_AUTOHSCROLL,
766 0, 0, m_Width, m_Height,
767 hwndParent, (HMENU) NULL,
768 hInst, 0);
769
770 SendMessageW(WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0);
771 szBuf.LoadStringW(IDS_SEARCH_TEXT);
772 SetWindowTextW(szBuf);
773 return m_hWnd;
774 }
775
776 };
777
778 class CMainWindow :
779 public CWindowImpl<CMainWindow, CWindow, CFrameWinTraits>
780 {
781 CUiPanel* m_ClientPanel;
782 CUiSplitPanel* m_VSplitter;
783 CUiSplitPanel* m_HSplitter;
784
785 CMainToolbar* m_Toolbar;
786 CAppsListView* m_ListView;
787
788 CSideTreeView* m_TreeView;
789 CUiWindow<CStatusBar>* m_StatusBar;
790 CAppRichEdit* m_RichEdit;
791
792 CUiWindow<CSearchBar>* m_SearchBar;
793 CAvailableApps m_AvailableApps;
794
795 LPWSTR pLink;
796
797 INT nSelectedApps;
798
799 BOOL bSearchEnabled;
800 BOOL bUpdating;
801
802 ATL::CStringW szSearchPattern;
803
804 public:
805 CMainWindow() :
806 m_ClientPanel(NULL),
807 pLink(NULL),
808 bSearchEnabled(FALSE)
809 {
810 }
811
812 private:
813 VOID InitApplicationsList()
814 {
815 ATL::CStringW szText;
816
817 /* Add columns to ListView */
818 szText.LoadStringW(IDS_APP_NAME);
819 m_ListView->AddColumn(0, szText, 250, LVCFMT_LEFT);
820
821 szText.LoadStringW(IDS_APP_INST_VERSION);
822 m_ListView->AddColumn(1, szText, 90, LVCFMT_RIGHT);
823
824 szText.LoadStringW(IDS_APP_DESCRIPTION);
825 m_ListView->AddColumn(3, szText, 300, LVCFMT_LEFT);
826
827 // Unnesesary since the list updates on every TreeView selection
828 // UpdateApplicationsList(ENUM_ALL_COMPONENTS);
829 }
830
831 HTREEITEM AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex)
832 {
833 return m_TreeView->AddCategory(hRootItem, TextIndex, IconIndex);
834 }
835
836 VOID InitCategoriesList()
837 {
838 HTREEITEM hRootItemInstalled, hRootItemAvailable;
839
840 hRootItemInstalled = AddCategory(TVI_ROOT, IDS_INSTALLED, IDI_CATEGORY);
841 AddCategory(hRootItemInstalled, IDS_APPLICATIONS, IDI_APPS);
842 AddCategory(hRootItemInstalled, IDS_UPDATES, IDI_APPUPD);
843
844 AddCategory(TVI_ROOT, IDS_SELECTEDFORINST, IDI_SELECTEDFORINST);
845
846 hRootItemAvailable = AddCategory(TVI_ROOT, IDS_AVAILABLEFORINST, IDI_CATEGORY);
847 AddCategory(hRootItemAvailable, IDS_CAT_AUDIO, IDI_CAT_AUDIO);
848 AddCategory(hRootItemAvailable, IDS_CAT_VIDEO, IDI_CAT_VIDEO);
849 AddCategory(hRootItemAvailable, IDS_CAT_GRAPHICS, IDI_CAT_GRAPHICS);
850 AddCategory(hRootItemAvailable, IDS_CAT_GAMES, IDI_CAT_GAMES);
851 AddCategory(hRootItemAvailable, IDS_CAT_INTERNET, IDI_CAT_INTERNET);
852 AddCategory(hRootItemAvailable, IDS_CAT_OFFICE, IDI_CAT_OFFICE);
853 AddCategory(hRootItemAvailable, IDS_CAT_DEVEL, IDI_CAT_DEVEL);
854 AddCategory(hRootItemAvailable, IDS_CAT_EDU, IDI_CAT_EDU);
855 AddCategory(hRootItemAvailable, IDS_CAT_ENGINEER, IDI_CAT_ENGINEER);
856 AddCategory(hRootItemAvailable, IDS_CAT_FINANCE, IDI_CAT_FINANCE);
857 AddCategory(hRootItemAvailable, IDS_CAT_SCIENCE, IDI_CAT_SCIENCE);
858 AddCategory(hRootItemAvailable, IDS_CAT_TOOLS, IDI_CAT_TOOLS);
859 AddCategory(hRootItemAvailable, IDS_CAT_DRIVERS, IDI_CAT_DRIVERS);
860 AddCategory(hRootItemAvailable, IDS_CAT_LIBS, IDI_CAT_LIBS);
861 AddCategory(hRootItemAvailable, IDS_CAT_THEMES, IDI_CAT_THEMES);
862 AddCategory(hRootItemAvailable, IDS_CAT_OTHER, IDI_CAT_OTHER);
863
864 m_TreeView->SetImageList();
865 m_TreeView->Expand(hRootItemInstalled, TVE_EXPAND);
866 m_TreeView->Expand(hRootItemAvailable, TVE_EXPAND);
867 m_TreeView->SelectItem(hRootItemAvailable);
868 }
869
870 BOOL CreateStatusBar()
871 {
872 m_StatusBar = new CUiWindow<CStatusBar>();
873 m_StatusBar->m_VerticalAlignment = UiAlign_RightBtm;
874 m_StatusBar->m_HorizontalAlignment = UiAlign_Stretch;
875 m_ClientPanel->Children().Append(m_StatusBar);
876
877 return m_StatusBar->Create(m_hWnd, (HMENU) IDC_STATUSBAR) != NULL;
878 }
879
880 BOOL CreateToolbar()
881 {
882 m_Toolbar = new CMainToolbar();
883 m_Toolbar->m_VerticalAlignment = UiAlign_LeftTop;
884 m_Toolbar->m_HorizontalAlignment = UiAlign_Stretch;
885 m_ClientPanel->Children().Append(m_Toolbar);
886
887 return m_Toolbar->Create(m_hWnd) != NULL;
888 }
889
890 BOOL CreateTreeView()
891 {
892 m_TreeView = new CSideTreeView();
893 m_TreeView->m_VerticalAlignment = UiAlign_Stretch;
894 m_TreeView->m_HorizontalAlignment = UiAlign_Stretch;
895 m_VSplitter->First().Append(m_TreeView);
896
897 return m_TreeView->Create(m_hWnd) != NULL;
898 }
899
900 BOOL CreateListView()
901 {
902 m_ListView = new CAppsListView();
903 m_ListView->m_VerticalAlignment = UiAlign_Stretch;
904 m_ListView->m_HorizontalAlignment = UiAlign_Stretch;
905 m_HSplitter->First().Append(m_ListView);
906
907 hListView = m_ListView->Create(m_hWnd);
908 return hListView != NULL;
909 }
910
911 BOOL CreateRichEdit()
912 {
913 m_RichEdit = new CAppRichEdit();
914 m_RichEdit->m_VerticalAlignment = UiAlign_Stretch;
915 m_RichEdit->m_HorizontalAlignment = UiAlign_Stretch;
916 m_HSplitter->Second().Append(m_RichEdit);
917
918 return m_RichEdit->Create(m_hWnd) != NULL;
919 }
920
921 BOOL CreateVSplitter()
922 {
923 m_VSplitter = new CUiSplitPanel();
924 m_VSplitter->m_VerticalAlignment = UiAlign_Stretch;
925 m_VSplitter->m_HorizontalAlignment = UiAlign_Stretch;
926 m_VSplitter->m_DynamicFirst = FALSE;
927 m_VSplitter->m_Horizontal = FALSE;
928 m_VSplitter->m_MinFirst = 0;
929 m_VSplitter->m_MinSecond = 320;
930 m_VSplitter->m_Pos = 240;
931 m_ClientPanel->Children().Append(m_VSplitter);
932
933 return m_VSplitter->Create(m_hWnd) != NULL;
934 }
935
936 BOOL CreateHSplitter()
937 {
938 m_HSplitter = new CUiSplitPanel();
939 m_HSplitter->m_VerticalAlignment = UiAlign_Stretch;
940 m_HSplitter->m_HorizontalAlignment = UiAlign_Stretch;
941 m_HSplitter->m_DynamicFirst = TRUE;
942 m_HSplitter->m_Horizontal = TRUE;
943 m_HSplitter->m_Pos = INT_MAX; //set INT_MAX to use lowest possible position (m_MinSecond)
944 m_HSplitter->m_MinFirst = 10;
945 m_HSplitter->m_MinSecond = 140;
946 m_VSplitter->Second().Append(m_HSplitter);
947
948 return m_HSplitter->Create(m_hWnd) != NULL;
949 }
950
951 BOOL CreateSearchBar()
952 {
953 m_SearchBar = new CUiWindow<CSearchBar>();
954 m_SearchBar->m_VerticalAlignment = UiAlign_LeftTop;
955 m_SearchBar->m_HorizontalAlignment = UiAlign_RightBtm;
956 m_SearchBar->m_Margin.top = 4;
957 m_SearchBar->m_Margin.right = 6;
958
959 return m_SearchBar->Create(m_Toolbar->m_hWnd) != NULL;
960 }
961
962 BOOL CreateLayout()
963 {
964 BOOL b = TRUE;
965 bUpdating = TRUE;
966
967 m_ClientPanel = new CUiPanel();
968 m_ClientPanel->m_VerticalAlignment = UiAlign_Stretch;
969 m_ClientPanel->m_HorizontalAlignment = UiAlign_Stretch;
970
971 // Top level
972 b = b && CreateStatusBar();
973 b = b && CreateToolbar();
974 b = b && CreateSearchBar();
975 b = b && CreateVSplitter();
976
977 // Inside V Splitter
978 b = b && CreateHSplitter();
979 b = b && CreateTreeView();
980
981 // Inside H Splitter
982 b = b && CreateListView();
983 b = b && CreateRichEdit();
984
985 if (b)
986 {
987 RECT rTop;
988 RECT rBottom;
989
990 /* Size status bar */
991 m_StatusBar->SendMessageW(WM_SIZE, 0, 0);
992
993 /* Size tool bar */
994 m_Toolbar->AutoSize();
995
996 ::GetWindowRect(m_Toolbar->m_hWnd, &rTop);
997 ::GetWindowRect(m_StatusBar->m_hWnd, &rBottom);
998
999 m_VSplitter->m_Margin.top = rTop.bottom - rTop.top;
1000 m_VSplitter->m_Margin.bottom = rBottom.bottom - rBottom.top;
1001 }
1002
1003 bUpdating = FALSE;
1004 return b;
1005 }
1006
1007 BOOL InitControls()
1008 {
1009 if (CreateLayout())
1010 {
1011
1012 InitApplicationsList();
1013 InitCategoriesList();
1014
1015 nSelectedApps = 0;
1016 UpdateStatusBarText();
1017
1018 return TRUE;
1019 }
1020
1021 return FALSE;
1022 }
1023
1024 VOID ShowAppInfo(INT Index)
1025 {
1026 if (IsInstalledEnum(SelectedEnumType))
1027 {
1028 if (Index == -1)
1029 Index = m_ListView->GetSelectionMark();
1030
1031 PINSTALLED_INFO Info = (PINSTALLED_INFO) m_ListView->GetItemData(Index);
1032
1033 m_RichEdit->ShowInstalledAppInfo(Info);
1034 }
1035 else if (IsAvailableEnum(SelectedEnumType))
1036 {
1037 if (Index == -1)
1038 return;
1039
1040 CAvailableApplicationInfo* Info = (CAvailableApplicationInfo*) m_ListView->GetItemData(Index);
1041
1042 m_RichEdit->ShowAvailableAppInfo(Info);
1043 }
1044 }
1045
1046 VOID OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
1047 {
1048 if (wParam == SIZE_MINIMIZED)
1049 return;
1050
1051 /* Size status bar */
1052 m_StatusBar->SendMessage(WM_SIZE, 0, 0);
1053
1054 /* Size tool bar */
1055 m_Toolbar->AutoSize();
1056
1057 /* Automatically hide captions */
1058 DWORD dToolbarTreshold = m_Toolbar->GetMaxButtonsWidth();
1059 DWORD dSearchbarMargin = (LOWORD(lParam) - m_SearchBar->m_Width);
1060
1061 if (dSearchbarMargin > dToolbarTreshold)
1062 {
1063 m_Toolbar->ShowButtonCaption();
1064 }
1065 else if (dSearchbarMargin < dToolbarTreshold)
1066 {
1067 m_Toolbar->HideButtonCaption();
1068 }
1069
1070 RECT r = {0, 0, LOWORD(lParam), HIWORD(lParam)};
1071 HDWP hdwp = NULL;
1072 INT count = m_ClientPanel->CountSizableChildren();
1073
1074 hdwp = BeginDeferWindowPos(count);
1075 if (hdwp)
1076 {
1077 hdwp = m_ClientPanel->OnParentSize(r, hdwp);
1078 if (hdwp)
1079 {
1080 EndDeferWindowPos(hdwp);
1081 }
1082
1083 }
1084
1085 // TODO: Sub-layouts for children of children
1086 count = m_SearchBar->CountSizableChildren();
1087 hdwp = BeginDeferWindowPos(count);
1088 if (hdwp)
1089 {
1090 hdwp = m_SearchBar->OnParentSize(r, hdwp);
1091 if (hdwp)
1092 {
1093 EndDeferWindowPos(hdwp);
1094 }
1095 }
1096
1097 }
1098
1099 VOID RemoveSelectedAppFromRegistry()
1100 {
1101 PINSTALLED_INFO Info;
1102 WCHAR szFullName[MAX_PATH] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
1103 ATL::CStringW szMsgText, szMsgTitle;
1104 INT ItemIndex = m_ListView->GetNextItem(-1, LVNI_FOCUSED);
1105
1106 if (!IsInstalledEnum(SelectedEnumType))
1107 return;
1108
1109 Info = reinterpret_cast<PINSTALLED_INFO>(m_ListView->GetItemData(ItemIndex));
1110 if (!Info || !Info->hSubKey || (ItemIndex == -1))
1111 return;
1112
1113 if (!szMsgText.LoadStringW(IDS_APP_REG_REMOVE) ||
1114 !szMsgTitle.LoadStringW(IDS_INFORMATION))
1115 return;
1116
1117 if (MessageBoxW(szMsgText, szMsgTitle, MB_YESNO | MB_ICONQUESTION) == IDYES)
1118 {
1119 ATL::CStringW::CopyChars(szFullName,
1120 MAX_PATH,
1121 Info->szKeyName.GetString(),
1122 MAX_PATH - wcslen(szFullName));
1123
1124 if (RegDeleteKeyW(Info->hRootKey, szFullName) == ERROR_SUCCESS)
1125 {
1126 m_ListView->DeleteItem(ItemIndex);
1127 return;
1128 }
1129
1130 if (!szMsgText.LoadStringW(IDS_UNABLE_TO_REMOVE))
1131 return;
1132
1133 MessageBoxW(szMsgText.GetString(), NULL, MB_OK | MB_ICONERROR);
1134 }
1135 }
1136
1137 BOOL ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT& theResult, DWORD dwMapId)
1138 {
1139 theResult = 0;
1140 switch (Msg)
1141 {
1142 case WM_CREATE:
1143 if (!InitControls())
1144 ::PostMessageW(hwnd, WM_CLOSE, 0, 0);
1145 break;
1146
1147 case WM_DESTROY:
1148 {
1149 ShowWindow(SW_HIDE);
1150 SaveSettings(hwnd);
1151
1152 FreeLogs();
1153 m_AvailableApps.FreeCachedEntries();
1154
1155 if (IsInstalledEnum(SelectedEnumType))
1156 FreeInstalledAppList();
1157
1158 delete m_ClientPanel;
1159
1160 PostQuitMessage(0);
1161 return 0;
1162 }
1163
1164 case WM_COMMAND:
1165 OnCommand(wParam, lParam);
1166 break;
1167
1168 case WM_NOTIFY:
1169 {
1170 LPNMHDR data = (LPNMHDR) lParam;
1171
1172 switch (data->code)
1173 {
1174 case TVN_SELCHANGED:
1175 {
1176 if (data->hwndFrom == m_TreeView->m_hWnd)
1177 {
1178 switch (((LPNMTREEVIEW) lParam)->itemNew.lParam)
1179 {
1180 case IDS_INSTALLED:
1181 UpdateApplicationsList(ENUM_ALL_INSTALLED);
1182 break;
1183
1184 case IDS_APPLICATIONS:
1185 UpdateApplicationsList(ENUM_INSTALLED_APPLICATIONS);
1186 break;
1187
1188 case IDS_UPDATES:
1189 UpdateApplicationsList(ENUM_UPDATES);
1190 break;
1191
1192 case IDS_AVAILABLEFORINST:
1193 UpdateApplicationsList(ENUM_ALL_AVAILABLE);
1194 break;
1195
1196 case IDS_CAT_AUDIO:
1197 UpdateApplicationsList(ENUM_CAT_AUDIO);
1198 break;
1199
1200 case IDS_CAT_DEVEL:
1201 UpdateApplicationsList(ENUM_CAT_DEVEL);
1202 break;
1203
1204 case IDS_CAT_DRIVERS:
1205 UpdateApplicationsList(ENUM_CAT_DRIVERS);
1206 break;
1207
1208 case IDS_CAT_EDU:
1209 UpdateApplicationsList(ENUM_CAT_EDU);
1210 break;
1211
1212 case IDS_CAT_ENGINEER:
1213 UpdateApplicationsList(ENUM_CAT_ENGINEER);
1214 break;
1215
1216 case IDS_CAT_FINANCE:
1217 UpdateApplicationsList(ENUM_CAT_FINANCE);
1218 break;
1219
1220 case IDS_CAT_GAMES:
1221 UpdateApplicationsList(ENUM_CAT_GAMES);
1222 break;
1223
1224 case IDS_CAT_GRAPHICS:
1225 UpdateApplicationsList(ENUM_CAT_GRAPHICS);
1226 break;
1227
1228 case IDS_CAT_INTERNET:
1229 UpdateApplicationsList(ENUM_CAT_INTERNET);
1230 break;
1231
1232 case IDS_CAT_LIBS:
1233 UpdateApplicationsList(ENUM_CAT_LIBS);
1234 break;
1235
1236 case IDS_CAT_OFFICE:
1237 UpdateApplicationsList(ENUM_CAT_OFFICE);
1238 break;
1239
1240 case IDS_CAT_OTHER:
1241 UpdateApplicationsList(ENUM_CAT_OTHER);
1242 break;
1243
1244 case IDS_CAT_SCIENCE:
1245 UpdateApplicationsList(ENUM_CAT_SCIENCE);
1246 break;
1247
1248 case IDS_CAT_TOOLS:
1249 UpdateApplicationsList(ENUM_CAT_TOOLS);
1250 break;
1251
1252 case IDS_CAT_VIDEO:
1253 UpdateApplicationsList(ENUM_CAT_VIDEO);
1254 break;
1255
1256 case IDS_CAT_THEMES:
1257 UpdateApplicationsList(ENUM_CAT_THEMES);
1258 break;
1259
1260 case IDS_SELECTEDFORINST:
1261 UpdateApplicationsList(ENUM_CAT_SELECTED);
1262 break;
1263 }
1264 }
1265
1266 HMENU mainMenu = ::GetMenu(hwnd);
1267 HMENU lvwMenu = ::GetMenu(m_ListView->m_hWnd);
1268
1269 /* Disable/enable items based on treeview selection */
1270 if (IsSelectedNodeInstalled())
1271 {
1272 EnableMenuItem(mainMenu, ID_REGREMOVE, MF_ENABLED);
1273 EnableMenuItem(mainMenu, ID_INSTALL, MF_GRAYED);
1274 EnableMenuItem(mainMenu, ID_UNINSTALL, MF_ENABLED);
1275 EnableMenuItem(mainMenu, ID_MODIFY, MF_ENABLED);
1276
1277 EnableMenuItem(lvwMenu, ID_REGREMOVE, MF_ENABLED);
1278 EnableMenuItem(lvwMenu, ID_INSTALL, MF_GRAYED);
1279 EnableMenuItem(lvwMenu, ID_UNINSTALL, MF_ENABLED);
1280 EnableMenuItem(lvwMenu, ID_MODIFY, MF_ENABLED);
1281
1282 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_REGREMOVE, TRUE);
1283 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_INSTALL, FALSE);
1284 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_UNINSTALL, TRUE);
1285 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_MODIFY, TRUE);
1286 }
1287 else
1288 {
1289 EnableMenuItem(mainMenu, ID_REGREMOVE, MF_GRAYED);
1290 EnableMenuItem(mainMenu, ID_INSTALL, MF_ENABLED);
1291 EnableMenuItem(mainMenu, ID_UNINSTALL, MF_GRAYED);
1292 EnableMenuItem(mainMenu, ID_MODIFY, MF_GRAYED);
1293
1294 EnableMenuItem(lvwMenu, ID_REGREMOVE, MF_GRAYED);
1295 EnableMenuItem(lvwMenu, ID_INSTALL, MF_ENABLED);
1296 EnableMenuItem(lvwMenu, ID_UNINSTALL, MF_GRAYED);
1297 EnableMenuItem(lvwMenu, ID_MODIFY, MF_GRAYED);
1298
1299 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_REGREMOVE, FALSE);
1300 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_INSTALL, TRUE);
1301 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_UNINSTALL, FALSE);
1302 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_MODIFY, FALSE);
1303 }
1304 }
1305 break;
1306
1307 case LVN_ITEMCHANGED:
1308 {
1309 LPNMLISTVIEW pnic = (LPNMLISTVIEW) lParam;
1310
1311 if (pnic->hdr.hwndFrom == m_ListView->m_hWnd)
1312 {
1313 /* Check if this is a valid item
1314 * (technically, it can be also an unselect) */
1315 INT ItemIndex = pnic->iItem;
1316 if (ItemIndex == -1 ||
1317 ItemIndex >= ListView_GetItemCount(pnic->hdr.hwndFrom))
1318 {
1319 break;
1320 }
1321
1322 /* Check if the focus has been moved to another item */
1323 if ((pnic->uChanged & LVIF_STATE) &&
1324 (pnic->uNewState & LVIS_FOCUSED) &&
1325 !(pnic->uOldState & LVIS_FOCUSED))
1326 {
1327 ShowAppInfo(ItemIndex);
1328 }
1329 /* Check if the item is checked */
1330 if ((pnic->uNewState & LVIS_STATEIMAGEMASK) && !bUpdating)
1331 {
1332 BOOL checked = m_ListView->GetCheckState(pnic->iItem);
1333 /* FIXME: HAX!
1334 - preventing decremention below zero as a safeguard for ReactOS
1335 In ReactOS this action is triggered whenever user changes *selection*, but should be only when *checkbox* state toggled
1336 Maybe LVIS_STATEIMAGEMASK is set incorrectly
1337 */
1338 nSelectedApps +=
1339 (checked)
1340 ? 1
1341 : ((nSelectedApps > 0)
1342 ? -1
1343 : 0);
1344
1345 /* Update item's selection status */
1346 m_ListView->SetSelected(pnic->iItem, checked);
1347
1348 UpdateStatusBarText();
1349 }
1350 }
1351 }
1352 break;
1353
1354 case LVN_COLUMNCLICK:
1355 {
1356 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
1357
1358 m_ListView->ColumnClick(pnmv);
1359 }
1360 break;
1361
1362 case NM_CLICK:
1363 {
1364 if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
1365 {
1366 ShowAppInfo(-1);
1367 }
1368 }
1369 break;
1370
1371 case NM_DBLCLK:
1372 {
1373 if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
1374 {
1375 /* this won't do anything if the program is already installed */
1376 SendMessageW(hwnd, WM_COMMAND, ID_INSTALL, 0);
1377 }
1378 }
1379 break;
1380
1381 case NM_RCLICK:
1382 {
1383 if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
1384 {
1385 ShowPopupMenu(m_ListView->m_hWnd, 0, ID_INSTALL);
1386 }
1387 }
1388 break;
1389
1390 case EN_LINK:
1391 OnLink((ENLINK*) lParam);
1392 break;
1393
1394 case TTN_GETDISPINFO:
1395 m_Toolbar->OnGetDispInfo((LPTOOLTIPTEXT) lParam);
1396 break;
1397 }
1398 }
1399 break;
1400
1401 case WM_SIZE:
1402 OnSize(hwnd, wParam, lParam);
1403 break;
1404
1405 case WM_SIZING:
1406 {
1407 LPRECT pRect = (LPRECT) lParam;
1408
1409 if (pRect->right - pRect->left < 565)
1410 pRect->right = pRect->left + 565;
1411
1412 if (pRect->bottom - pRect->top < 300)
1413 pRect->bottom = pRect->top + 300;
1414
1415 return TRUE;
1416 }
1417
1418 case WM_SYSCOLORCHANGE:
1419 {
1420 /* Forward WM_SYSCOLORCHANGE to common controls */
1421 m_ListView->SendMessageW(WM_SYSCOLORCHANGE, 0, 0);
1422 m_TreeView->SendMessageW(WM_SYSCOLORCHANGE, 0, 0);
1423 m_Toolbar->SendMessageW(WM_SYSCOLORCHANGE, 0, 0);
1424 m_ListView->SendMessageW(EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
1425 }
1426 break;
1427
1428 case WM_TIMER:
1429 if (wParam == SEARCH_TIMER_ID)
1430 {
1431 ::KillTimer(hwnd, SEARCH_TIMER_ID);
1432 if (bSearchEnabled)
1433 UpdateApplicationsList(-1);
1434 }
1435 break;
1436 }
1437
1438 return FALSE;
1439 }
1440
1441 virtual VOID OnLink(ENLINK *Link)
1442 {
1443 switch (Link->msg)
1444 {
1445 case WM_LBUTTONUP:
1446 case WM_RBUTTONUP:
1447 {
1448 if (pLink) HeapFree(GetProcessHeap(), 0, pLink);
1449
1450 pLink = (LPWSTR) HeapAlloc(GetProcessHeap(), 0,
1451 (max(Link->chrg.cpMin, Link->chrg.cpMax) -
1452 min(Link->chrg.cpMin, Link->chrg.cpMax) + 1) * sizeof(WCHAR));
1453 if (!pLink)
1454 {
1455 /* TODO: Error message */
1456 return;
1457 }
1458
1459 m_RichEdit->SendMessageW(EM_SETSEL, Link->chrg.cpMin, Link->chrg.cpMax);
1460 m_RichEdit->SendMessageW(EM_GETSELTEXT, 0, (LPARAM) pLink);
1461
1462 ShowPopupMenu(m_RichEdit->m_hWnd, IDR_LINKMENU, -1);
1463 }
1464 break;
1465 }
1466 }
1467
1468 BOOL IsSelectedNodeInstalled()
1469 {
1470 HTREEITEM hSelectedItem = m_TreeView->GetSelection();
1471 TV_ITEM tItem;
1472
1473 tItem.mask = TVIF_PARAM | TVIF_HANDLE;
1474 tItem.hItem = hSelectedItem;
1475 m_TreeView->GetItem(&tItem);
1476 switch (tItem.lParam)
1477 {
1478 case IDS_INSTALLED:
1479 case IDS_APPLICATIONS:
1480 case IDS_UPDATES:
1481 return TRUE;
1482 default:
1483 return FALSE;
1484 }
1485 }
1486
1487 VOID OnCommand(WPARAM wParam, LPARAM lParam)
1488 {
1489 WORD wCommand = LOWORD(wParam);
1490
1491 if (lParam == (LPARAM) m_SearchBar->m_hWnd)
1492 {
1493 ATL::CStringW szBuf;
1494
1495 switch (HIWORD(wParam))
1496 {
1497 case EN_SETFOCUS:
1498 {
1499 ATL::CStringW szWndText;
1500
1501 szBuf.LoadStringW(IDS_SEARCH_TEXT);
1502 m_SearchBar->GetWindowTextW(szWndText);
1503 if (szBuf == szWndText)
1504 {
1505 bSearchEnabled = FALSE;
1506 m_SearchBar->SetWindowTextW(L"");
1507 }
1508 }
1509 break;
1510
1511 case EN_KILLFOCUS:
1512 {
1513 m_SearchBar->GetWindowTextW(szBuf);
1514 if (szBuf.IsEmpty())
1515 {
1516 szBuf.LoadStringW(IDS_SEARCH_TEXT);
1517 bSearchEnabled = FALSE;
1518 m_SearchBar->SetWindowTextW(szBuf.GetString());
1519 }
1520 }
1521 break;
1522
1523 case EN_CHANGE:
1524 {
1525 ATL::CStringW szWndText;
1526
1527 if (!bSearchEnabled)
1528 {
1529 bSearchEnabled = TRUE;
1530 break;
1531 }
1532
1533 szBuf.LoadStringW(IDS_SEARCH_TEXT);
1534 m_SearchBar->GetWindowTextW(szWndText);
1535 if (szBuf == szWndText)
1536 {
1537 szSearchPattern.Empty();
1538 }
1539 else
1540 {
1541 szSearchPattern = szWndText;
1542 }
1543
1544 DWORD dwDelay;
1545 SystemParametersInfoW(SPI_GETMENUSHOWDELAY, 0, &dwDelay, 0);
1546 SetTimer(SEARCH_TIMER_ID, dwDelay);
1547 }
1548 break;
1549 }
1550
1551 return;
1552 }
1553
1554 switch (wCommand)
1555 {
1556 case ID_OPEN_LINK:
1557 ShellExecuteW(m_hWnd, L"open", pLink, NULL, NULL, SW_SHOWNOACTIVATE);
1558 HeapFree(GetProcessHeap(), 0, pLink);
1559 break;
1560
1561 case ID_COPY_LINK:
1562 CopyTextToClipboard(pLink);
1563 HeapFree(GetProcessHeap(), 0, pLink);
1564 break;
1565
1566 case ID_SETTINGS:
1567 CreateSettingsDlg(m_hWnd);
1568 break;
1569
1570 case ID_EXIT:
1571 PostMessageW(WM_CLOSE, 0, 0);
1572 break;
1573
1574 case ID_SEARCH:
1575 ::SetFocus(m_SearchBar->m_hWnd);
1576 break;
1577
1578 case ID_INSTALL:
1579 if (IsAvailableEnum(SelectedEnumType))
1580 {
1581 if (nSelectedApps > 0)
1582 {
1583 DownloadListOfApplications(m_AvailableApps.GetSelected(), FALSE);
1584 UpdateApplicationsList(-1);
1585 m_ListView->SetSelected(-1, FALSE);
1586 }
1587 else if (DownloadApplication(m_ListView->GetSelectedData(), FALSE))
1588 {
1589 UpdateApplicationsList(-1);
1590 }
1591
1592 }
1593 break;
1594
1595 case ID_UNINSTALL:
1596 if (UninstallApplication(-1, FALSE))
1597 UpdateApplicationsList(-1);
1598 break;
1599
1600 case ID_MODIFY:
1601 if (UninstallApplication(-1, TRUE))
1602 UpdateApplicationsList(-1);
1603 break;
1604
1605 case ID_REGREMOVE:
1606 RemoveSelectedAppFromRegistry();
1607 break;
1608
1609 case ID_REFRESH:
1610 UpdateApplicationsList(-1);
1611 break;
1612
1613 case ID_RESETDB:
1614 CAvailableApps::ForceUpdateAppsDB();
1615 UpdateApplicationsList(-1);
1616 break;
1617
1618 case ID_HELP:
1619 MessageBoxW(L"Help not implemented yet", NULL, MB_OK);
1620 break;
1621
1622 case ID_ABOUT:
1623 ShowAboutDialog();
1624 break;
1625
1626 case ID_CHECK_ALL:
1627 m_ListView->CheckAll();
1628 break;
1629 }
1630 }
1631
1632 VOID FreeInstalledAppList()
1633 {
1634 INT Count = m_ListView->GetItemCount() - 1;
1635 PINSTALLED_INFO Info;
1636
1637 while (Count >= 0)
1638 {
1639 Info = (PINSTALLED_INFO) ListViewGetlParam(Count);
1640 if (Info)
1641 {
1642 RegCloseKey(Info->hSubKey);
1643 delete Info;
1644 }
1645 Count--;
1646 }
1647 }
1648
1649 static BOOL SearchPatternMatch(LPCWSTR szHaystack, LPCWSTR szNeedle)
1650 {
1651 if (!*szNeedle)
1652 return TRUE;
1653 /* TODO: Improve pattern search beyond a simple case-insensitive substring search. */
1654 return StrStrIW(szHaystack, szNeedle) != NULL;
1655 }
1656
1657 BOOL CALLBACK EnumInstalledAppProc(INT ItemIndex, ATL::CStringW &m_szName, PINSTALLED_INFO Info)
1658 {
1659 PINSTALLED_INFO ItemInfo;
1660 ATL::CStringW szText;
1661 INT Index;
1662
1663 if (!SearchPatternMatch(m_szName.GetString(), szSearchPattern))
1664 {
1665 RegCloseKey(Info->hSubKey);
1666 return TRUE;
1667 }
1668
1669 ItemInfo = new INSTALLED_INFO(*Info);
1670 if (!ItemInfo)
1671 {
1672 RegCloseKey(Info->hSubKey);
1673 return FALSE;
1674 }
1675
1676 Index = m_ListView->AddItem(ItemIndex, 0, m_szName.GetString(), (LPARAM) ItemInfo);
1677
1678 /* Get version info */
1679 ItemInfo->GetApplicationString(L"DisplayVersion", szText);
1680 m_ListView->SetItemText(Index, 1, szText.GetString());
1681
1682 /* Get comments */
1683 ItemInfo->GetApplicationString(L"Comments", szText);
1684 m_ListView->SetItemText(Index, 2, szText.GetString());
1685
1686 return TRUE;
1687 }
1688
1689 BOOL EnumAvailableAppProc(CAvailableApplicationInfo* Info, LPCWSTR szFolderPath)
1690 {
1691 INT Index;
1692 HICON hIcon = NULL;
1693
1694 HIMAGELIST hImageListView = ListView_GetImageList(hListView, LVSIL_SMALL);
1695
1696 if (!SearchPatternMatch(Info->m_szName.GetString(), szSearchPattern) &&
1697 !SearchPatternMatch(Info->m_szDesc.GetString(), szSearchPattern))
1698 {
1699 return TRUE;
1700 }
1701
1702 /* Load icon from file */
1703 ATL::CStringW szIconPath;
1704 szIconPath.Format(L"%lsicons\\%ls.ico", szFolderPath, Info->m_szName.GetString());
1705 hIcon = (HICON) LoadImageW(NULL,
1706 szIconPath.GetString(),
1707 IMAGE_ICON,
1708 LISTVIEW_ICON_SIZE,
1709 LISTVIEW_ICON_SIZE,
1710 LR_LOADFROMFILE);
1711
1712 if (!hIcon || GetLastError() != ERROR_SUCCESS)
1713 {
1714 /* Load default icon */
1715 hIcon = (HICON) LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN));
1716 }
1717
1718 Index = ImageList_AddIcon(hImageListView, hIcon);
1719 DestroyIcon(hIcon);
1720
1721 Index = m_ListView->AddItem(Info->m_Category, Index, Info->m_szName.GetString(), (LPARAM) Info);
1722 m_ListView->SetImageList(hImageListView, LVSIL_SMALL);
1723 m_ListView->SetItemText(Index, 1, Info->m_szVersion.GetString());
1724 m_ListView->SetItemText(Index, 2, Info->m_szDesc.GetString());
1725 m_ListView->SetCheckState(Index, Info->m_IsSelected);
1726
1727 return TRUE;
1728 }
1729
1730 static BOOL CALLBACK s_EnumInstalledAppProc(INT ItemIndex, ATL::CStringW &m_szName, PINSTALLED_INFO Info, PVOID param)
1731 {
1732 CMainWindow* pThis = (CMainWindow*)param;
1733 return pThis->EnumInstalledAppProc(ItemIndex, m_szName, Info);
1734 }
1735
1736 static BOOL CALLBACK s_EnumAvailableAppProc(CAvailableApplicationInfo* Info, LPCWSTR szFolderPath, PVOID param)
1737 {
1738 CMainWindow* pThis = (CMainWindow*)param;
1739 return pThis->EnumAvailableAppProc(Info, szFolderPath);
1740 }
1741
1742 VOID UpdateStatusBarText()
1743 {
1744 if (m_StatusBar)
1745 {
1746 ATL::CStringW szBuffer;
1747
1748 szBuffer.Format(IDS_APPS_COUNT, m_ListView->GetItemCount(), nSelectedApps);
1749 m_StatusBar->SetText(szBuffer);
1750 }
1751 }
1752
1753 VOID UpdateApplicationsList(INT EnumType)
1754 {
1755 ATL::CStringW szBuffer1, szBuffer2;
1756 HIMAGELIST hImageListView;
1757 BOOL bWasInInstalled = IsInstalledEnum(SelectedEnumType);
1758
1759 bUpdating = TRUE;
1760 m_ListView->SetRedraw(FALSE);
1761
1762 if (EnumType < 0)
1763 {
1764 EnumType = SelectedEnumType;
1765 }
1766
1767 //if previous one was INSTALLED purge the list
1768 //TODO: make the Installed category a separate class to avoid doing this
1769 if (bWasInInstalled)
1770 {
1771 FreeInstalledAppList();
1772 }
1773
1774 m_ListView->DeleteAllItems();
1775
1776 // Create new ImageList
1777 hImageListView = ImageList_Create(LISTVIEW_ICON_SIZE,
1778 LISTVIEW_ICON_SIZE,
1779 GetSystemColorDepth() | ILC_MASK,
1780 0, 1);
1781 HIMAGELIST hImageListBuf = m_ListView->SetImageList(hImageListView, LVSIL_SMALL);
1782 if (hImageListBuf)
1783 {
1784 ImageList_Destroy(hImageListBuf);
1785 }
1786
1787 if (IsInstalledEnum(EnumType))
1788 {
1789 if (!bWasInInstalled)
1790 {
1791 m_ListView->SetCheckboxesVisible(FALSE);
1792 }
1793
1794 HICON hIcon = (HICON) LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN));
1795 ImageList_AddIcon(hImageListView, hIcon);
1796 DestroyIcon(hIcon);
1797
1798 // Enum installed applications and updates
1799 EnumInstalledApplications(EnumType, TRUE, s_EnumInstalledAppProc, this);
1800 EnumInstalledApplications(EnumType, FALSE, s_EnumInstalledAppProc, this);
1801 }
1802 else if (IsAvailableEnum(EnumType))
1803 {
1804 if (bWasInInstalled)
1805 {
1806 m_ListView->SetCheckboxesVisible(TRUE);
1807 }
1808
1809 // Enum available applications
1810 m_AvailableApps.Enum(EnumType, s_EnumAvailableAppProc, this);
1811 }
1812
1813 SelectedEnumType = EnumType;
1814 UpdateStatusBarText();
1815 m_RichEdit->SetWelcomeText();
1816
1817 // Set automatic column width for program names if the list is not empty
1818 if (m_ListView->GetItemCount() > 0)
1819 {
1820 ListView_SetColumnWidth(m_ListView->GetWindow(), 0, LVSCW_AUTOSIZE);
1821 }
1822
1823 bUpdating = FALSE;
1824 m_ListView->SetRedraw(TRUE);
1825 }
1826
1827 public:
1828 static ATL::CWndClassInfo& GetWndClassInfo()
1829 {
1830 DWORD csStyle = CS_VREDRAW | CS_HREDRAW;
1831 static ATL::CWndClassInfo wc =
1832 {
1833 {
1834 sizeof(WNDCLASSEX),
1835 csStyle,
1836 StartWindowProc,
1837 0,
1838 0,
1839 NULL,
1840 LoadIconW(_AtlBaseModule.GetModuleInstance(), MAKEINTRESOURCEW(IDI_MAIN)),
1841 LoadCursorW(NULL, IDC_ARROW),
1842 (HBRUSH) (COLOR_BTNFACE + 1),
1843 MAKEINTRESOURCEW(IDR_MAINMENU),
1844 L"RAppsWnd",
1845 NULL
1846 },
1847 NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
1848 };
1849 return wc;
1850 }
1851
1852 HWND Create()
1853 {
1854 ATL::CStringW szWindowName;
1855 szWindowName.LoadStringW(IDS_APPTITLE);
1856
1857 RECT r = {
1858 (SettingsInfo.bSaveWndPos ? SettingsInfo.Left : CW_USEDEFAULT),
1859 (SettingsInfo.bSaveWndPos ? SettingsInfo.Top : CW_USEDEFAULT),
1860 (SettingsInfo.bSaveWndPos ? SettingsInfo.Width : 680),
1861 (SettingsInfo.bSaveWndPos ? SettingsInfo.Height : 450)
1862 };
1863 r.right += r.left;
1864 r.bottom += r.top;
1865
1866 return CWindowImpl::Create(NULL, r, szWindowName.GetString(), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
1867 }
1868
1869 CStatusBar * GetStatusBar()
1870 {
1871 return m_StatusBar;
1872 }
1873
1874 CAppsListView * GetListView()
1875 {
1876 return m_ListView;
1877 }
1878
1879 CRichEdit * GetRichEdit()
1880 {
1881 return m_RichEdit;
1882 }
1883
1884 CAvailableApps * GetAvailableApps()
1885 {
1886 return &m_AvailableApps;
1887 }
1888 };
1889
1890 // global interface
1891 CMainWindow * g_MainWindow;
1892
1893 HWND CreateMainWindow()
1894 {
1895 g_MainWindow = new CMainWindow();
1896 return g_MainWindow->Create();
1897 }
1898
1899 DWORD_PTR ListViewGetlParam(INT item)
1900 {
1901 if (item < 0)
1902 {
1903 item = g_MainWindow->GetListView()->GetSelectionMark();
1904 }
1905 return g_MainWindow->GetListView()->GetItemData(item);
1906 }
1907
1908 VOID SetStatusBarText(LPCWSTR szText)
1909 {
1910 g_MainWindow->GetStatusBar()->SetText(szText);
1911 }
1912
1913 INT ListViewAddItem(INT ItemIndex, INT IconIndex, LPWSTR lpName, LPARAM lParam)
1914 {
1915 return g_MainWindow->GetListView()->AddItem(ItemIndex, IconIndex, lpName, lParam);
1916 }
1917
1918 VOID NewRichEditText(LPCWSTR szText, DWORD flags)
1919 {
1920 g_MainWindow->GetRichEdit()->SetText(szText, flags);
1921 }
1922
1923 VOID InsertRichEditText(LPCWSTR szText, DWORD flags)
1924 {
1925 g_MainWindow->GetRichEdit()->InsertText(szText, flags);
1926 }
1927
1928 CAvailableApps* GetAvailableApps()
1929 {
1930 return g_MainWindow->GetAvailableApps();
1931 }
1932
1933 // ATL version of functions above
1934 VOID SetStatusBarText(const ATL::CStringW& szText)
1935 {
1936 SetStatusBarText(szText.GetString());
1937 }
1938
1939 INT ListViewAddItem(INT ItemIndex, INT IconIndex, const ATL::CStringW& Name, LPARAM lParam)
1940 {
1941 return ListViewAddItem(ItemIndex, IconIndex, const_cast<LPWSTR>(Name.GetString()), lParam);
1942 }
1943
1944 VOID NewRichEditText(const ATL::CStringW& szText, DWORD flags)
1945 {
1946 NewRichEditText(szText.GetString(), flags);
1947 }
1948
1949 VOID InsertRichEditText(const ATL::CStringW& szText, DWORD flags)
1950 {
1951 InsertRichEditText(szText.GetString(), flags);
1952 }
1953
1954 VOID ShowMainWindow(INT nShowCmd)
1955 {
1956 HACCEL KeyBrd;
1957 MSG Msg;
1958
1959 hMainWnd = CreateMainWindow();
1960
1961 if (hMainWnd)
1962 {
1963 /* Maximize it if we must */
1964 ShowWindow(hMainWnd, ((SettingsInfo.bSaveWndPos && SettingsInfo.Maximized) ? SW_MAXIMIZE : nShowCmd));
1965 UpdateWindow(hMainWnd);
1966
1967 /* Load the menu hotkeys */
1968 KeyBrd = LoadAcceleratorsW(NULL, MAKEINTRESOURCEW(HOTKEYS));
1969
1970 /* Message Loop */
1971 while (GetMessageW(&Msg, NULL, 0, 0))
1972 {
1973 if (!TranslateAcceleratorW(hMainWnd, KeyBrd, &Msg))
1974 {
1975 TranslateMessage(&Msg);
1976 DispatchMessageW(&Msg);
1977 }
1978 }
1979 }
1980 }