[RAPPS_NEW][EXPLORER][RSHELL][BROWSEUI]
[reactos.git] / reactos / base / applications / rapps_new / gui.cpp
1 /* PROJECT: ReactOS CE Applications Manager
2 * LICENSE: GPL - See COPYING in the top level directory
3 * AUTHORS: David Quintana <gigaherz@gmail.com>
4 */
5
6 #include "rapps.h"
7
8 #include <shlobj_undoc.h>
9 #include <shlguid_undoc.h>
10
11 #include <atlbase.h>
12 #include <atlcom.h>
13 #include <atlwin.h>
14 #include <wininet.h>
15 #include <shellutils.h>
16
17 #include <rosctrls.h>
18
19 #include "rosui.h"
20 #include "crichedit.h"
21
22 #define SEARCH_TIMER_ID 'SR'
23
24 HWND hListView = NULL;
25
26 class CMainToolbar :
27 public CUiWindow< CToolbar<> >
28 {
29 #define TOOLBAR_HEIGHT 24
30
31 WCHAR szInstallBtn[MAX_STR_LEN];
32 WCHAR szUninstallBtn[MAX_STR_LEN];
33 WCHAR szModifyBtn[MAX_STR_LEN];
34
35 VOID AddImageToImageList(HIMAGELIST hImageList, UINT ImageIndex)
36 {
37 HICON hImage;
38
39 if (!(hImage = (HICON) LoadImage(hInst,
40 MAKEINTRESOURCE(ImageIndex),
41 IMAGE_ICON,
42 TOOLBAR_HEIGHT,
43 TOOLBAR_HEIGHT,
44 0)))
45 {
46 /* TODO: Error message */
47 }
48
49 ImageList_AddIcon(hImageList, hImage);
50 DeleteObject(hImage);
51 }
52
53 HIMAGELIST InitImageList(VOID)
54 {
55 HIMAGELIST hImageList;
56
57 /* Create the toolbar icon image list */
58 hImageList = ImageList_Create(TOOLBAR_HEIGHT,//GetSystemMetrics(SM_CXSMICON),
59 TOOLBAR_HEIGHT,//GetSystemMetrics(SM_CYSMICON),
60 ILC_MASK | GetSystemColorDepth(),
61 1,
62 1);
63 if (!hImageList)
64 {
65 /* TODO: Error message */
66 return NULL;
67 }
68
69 AddImageToImageList(hImageList, IDI_INSTALL);
70 AddImageToImageList(hImageList, IDI_UNINSTALL);
71 AddImageToImageList(hImageList, IDI_MODIFY);
72 AddImageToImageList(hImageList, IDI_REFRESH);
73 AddImageToImageList(hImageList, IDI_SETTINGS);
74 AddImageToImageList(hImageList, IDI_EXIT);
75
76 return hImageList;
77 }
78
79 public:
80 VOID OnGetDispInfo(LPTOOLTIPTEXT lpttt)
81 {
82 UINT idButton = (UINT) lpttt->hdr.idFrom;
83
84 switch (idButton)
85 {
86 case ID_EXIT:
87 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_EXIT);
88 break;
89
90 case ID_INSTALL:
91 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_INSTALL);
92 break;
93
94 case ID_UNINSTALL:
95 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_UNINSTALL);
96 break;
97
98 case ID_MODIFY:
99 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_MODIFY);
100 break;
101
102 case ID_SETTINGS:
103 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_SETTINGS);
104 break;
105
106 case ID_REFRESH:
107 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH);
108 break;
109 }
110 }
111
112 HWND Create(HWND hwndParent)
113 {
114 static TBBUTTON Buttons [] =
115 { /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
116 { 0, ID_INSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szInstallBtn },
117 { 1, ID_UNINSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szUninstallBtn },
118 { 2, ID_MODIFY, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szModifyBtn },
119 { 5, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
120 { 3, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
121 { 5, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
122 { 4, ID_SETTINGS, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
123 { 5, ID_EXIT, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 }
124 };
125
126 INT NumButtons = sizeof(Buttons) / sizeof(Buttons[0]);
127 HIMAGELIST hImageList;
128
129 LoadStringW(hInst, IDS_INSTALL, szInstallBtn, sizeof(szInstallBtn) / sizeof(WCHAR));
130 LoadStringW(hInst, IDS_UNINSTALL, szUninstallBtn, sizeof(szUninstallBtn) / sizeof(WCHAR));
131 LoadStringW(hInst, IDS_MODIFY, szModifyBtn, sizeof(szModifyBtn) / sizeof(WCHAR));
132
133 m_hWnd = CreateWindowExW(0,
134 TOOLBARCLASSNAMEW,
135 NULL,
136 WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | TBSTYLE_LIST,
137 0, 0, 0, 0,
138 hwndParent,
139 0,
140 hInst,
141 NULL);
142
143 if (!m_hWnd)
144 {
145 /* TODO: Show error message */
146 return FALSE;
147 }
148
149 SendMessageW(TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS);
150 SetButtonStructSize();
151
152 hImageList = InitImageList();
153
154 if (!hImageList)
155 {
156 /* TODO: Show error message */
157 return FALSE;
158 }
159
160 ImageList_Destroy((HIMAGELIST) SetImageList(hImageList));
161
162 AddButtons(NumButtons, Buttons);
163
164 return m_hWnd;
165 }
166 };
167
168 class CAppsListView :
169 public CUiWindow<CListView>
170 {
171 struct SortContext
172 {
173 CAppsListView * lvw;
174 int iSubItem;
175 };
176
177 public:
178 BOOL bAscending;
179
180 CAppsListView()
181 {
182 bAscending = TRUE;
183 }
184
185 VOID ColumnClick(LPNMLISTVIEW pnmv)
186 {
187 SortContext ctx = { this, pnmv->iSubItem };
188
189 SortItems(s_CompareFunc, &ctx);
190
191 bAscending = !bAscending;
192 }
193
194 PVOID GetLParam(INT Index)
195 {
196 INT ItemIndex;
197 LVITEM Item;
198
199 if (Index == -1)
200 {
201 ItemIndex = (INT) SendMessage(LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
202 if (ItemIndex == -1)
203 return NULL;
204 }
205 else
206 {
207 ItemIndex = Index;
208 }
209
210 ZeroMemory(&Item, sizeof(LVITEM));
211
212 Item.mask = LVIF_PARAM;
213 Item.iItem = ItemIndex;
214 if (!GetItem(&Item))
215 return NULL;
216
217 return (PVOID) Item.lParam;
218 }
219
220 BOOL AddColumn(INT Index, LPWSTR lpText, INT Width, INT Format)
221 {
222 LV_COLUMN Column;
223
224 ZeroMemory(&Column, sizeof(LV_COLUMN));
225
226 Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
227 Column.iSubItem = Index;
228 Column.pszText = (LPTSTR) lpText;
229 Column.cx = Width;
230 Column.fmt = Format;
231
232 return (InsertColumn(Index, &Column) == -1) ? FALSE : TRUE;
233 }
234
235 INT AddItem(INT ItemIndex, INT IconIndex, LPWSTR lpText, LPARAM lParam)
236 {
237 LV_ITEMW Item;
238
239 ZeroMemory(&Item, sizeof(LV_ITEM));
240
241 Item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
242 Item.pszText = lpText;
243 Item.lParam = lParam;
244 Item.iItem = ItemIndex;
245 Item.iImage = IconIndex;
246
247 return InsertItem(&Item);
248 }
249
250 static INT CALLBACK s_CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
251 {
252 SortContext * ctx = ((SortContext*) lParamSort);
253 return ctx->lvw->CompareFunc(lParam1, lParam2, ctx->iSubItem);
254 }
255
256 INT CompareFunc(LPARAM lParam1, LPARAM lParam2, INT iSubItem)
257 {
258 WCHAR Item1[MAX_STR_LEN], Item2[MAX_STR_LEN];
259 LVFINDINFO IndexInfo;
260 INT Index;
261
262 IndexInfo.flags = LVFI_PARAM;
263
264 IndexInfo.lParam = lParam1;
265 Index = FindItem(-1, &IndexInfo);
266 GetItemText(Index, iSubItem, Item1, sizeof(Item1) / sizeof(WCHAR));
267
268 IndexInfo.lParam = lParam2;
269 Index = FindItem(-1, &IndexInfo);
270 GetItemText(Index, iSubItem, Item2, sizeof(Item2) / sizeof(WCHAR));
271
272 if (bAscending)
273 return wcscmp(Item2, Item1);
274 else
275 return wcscmp(Item1, Item2);
276
277 return 0;
278 }
279
280 HWND Create(HWND hwndParent)
281 {
282 RECT r = { 205, 28, 465, 250 };
283 DWORD style = WS_CHILD | WS_VISIBLE | LVS_SORTASCENDING | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS;
284 HMENU menu = GetSubMenu(LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_APPLICATIONMENU)), 0);
285
286 HWND hwnd = CListView::Create(hwndParent, r, NULL, style, WS_EX_CLIENTEDGE, menu);
287
288 if (hwnd)
289 SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
290
291 return hwnd;
292 }
293
294 };
295
296 class CMainWindow :
297 public CWindowImpl<CMainWindow, CWindow, CFrameWinTraits>
298 {
299 CUiPanel * m_ClientPanel;
300 CUiSplitPanel * m_VSplitter;
301 CUiSplitPanel * m_HSplitter;
302
303 CMainToolbar * m_Toolbar;
304 CAppsListView * m_ListView;
305
306 CUiWindow<CTreeView> * m_TreeView;
307 CUiWindow<CStatusBar> * m_StatusBar;
308 CUiWindow<CRichEdit> * m_RichEdit;
309
310 CUiWindow<> * m_SearchBar;
311
312 HIMAGELIST hImageTreeView;
313
314 PWSTR pLink;
315
316 BOOL SearchEnabled;
317
318 public:
319 CMainWindow() :
320 m_ClientPanel(NULL),
321 hImageTreeView(NULL),
322 pLink(NULL),
323 SearchEnabled(TRUE)
324 {
325 }
326
327 private:
328
329 VOID InitApplicationsList(VOID)
330 {
331 WCHAR szText[MAX_STR_LEN];
332
333 /* Add columns to ListView */
334 LoadStringW(hInst, IDS_APP_NAME, szText, _countof(szText));
335 m_ListView->AddColumn(0, szText, 200, LVCFMT_LEFT);
336
337 LoadStringW(hInst, IDS_APP_INST_VERSION, szText, _countof(szText));
338 m_ListView->AddColumn(1, szText, 90, LVCFMT_RIGHT);
339
340 LoadStringW(hInst, IDS_APP_DESCRIPTION, szText, _countof(szText));
341 m_ListView->AddColumn(3, szText, 250, LVCFMT_LEFT);
342
343 UpdateApplicationsList(ENUM_ALL_COMPONENTS);
344 }
345
346 HTREEITEM AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex)
347 {
348 WCHAR szText[MAX_STR_LEN];
349 INT Index;
350 HICON hIcon;
351
352 hIcon = (HICON) LoadImage(hInst,
353 MAKEINTRESOURCE(IconIndex),
354 IMAGE_ICON,
355 TREEVIEW_ICON_SIZE,
356 TREEVIEW_ICON_SIZE,
357 LR_CREATEDIBSECTION);
358
359 Index = ImageList_AddIcon(hImageTreeView, hIcon);
360 DestroyIcon(hIcon);
361
362 LoadStringW(hInst, TextIndex, szText, _countof(szText));
363
364 return m_TreeView->AddItem(hRootItem, szText, Index, Index, TextIndex);
365 }
366
367 VOID InitCategoriesList(VOID)
368 {
369 HTREEITEM hRootItem1, hRootItem2;
370
371 hRootItem1 = AddCategory(TVI_ROOT, IDS_INSTALLED, IDI_CATEGORY);
372 AddCategory(hRootItem1, IDS_APPLICATIONS, IDI_APPS);
373 AddCategory(hRootItem1, IDS_UPDATES, IDI_APPUPD);
374
375 hRootItem2 = AddCategory(TVI_ROOT, IDS_AVAILABLEFORINST, IDI_CATEGORY);
376 AddCategory(hRootItem2, IDS_CAT_AUDIO, IDI_CAT_AUDIO);
377 AddCategory(hRootItem2, IDS_CAT_VIDEO, IDI_CAT_VIDEO);
378 AddCategory(hRootItem2, IDS_CAT_GRAPHICS, IDI_CAT_GRAPHICS);
379 AddCategory(hRootItem2, IDS_CAT_GAMES, IDI_CAT_GAMES);
380 AddCategory(hRootItem2, IDS_CAT_INTERNET, IDI_CAT_INTERNET);
381 AddCategory(hRootItem2, IDS_CAT_OFFICE, IDI_CAT_OFFICE);
382 AddCategory(hRootItem2, IDS_CAT_DEVEL, IDI_CAT_DEVEL);
383 AddCategory(hRootItem2, IDS_CAT_EDU, IDI_CAT_EDU);
384 AddCategory(hRootItem2, IDS_CAT_ENGINEER, IDI_CAT_ENGINEER);
385 AddCategory(hRootItem2, IDS_CAT_FINANCE, IDI_CAT_FINANCE);
386 AddCategory(hRootItem2, IDS_CAT_SCIENCE, IDI_CAT_SCIENCE);
387 AddCategory(hRootItem2, IDS_CAT_TOOLS, IDI_CAT_TOOLS);
388 AddCategory(hRootItem2, IDS_CAT_DRIVERS, IDI_CAT_DRIVERS);
389 AddCategory(hRootItem2, IDS_CAT_LIBS, IDI_CAT_LIBS);
390 AddCategory(hRootItem2, IDS_CAT_OTHER, IDI_CAT_OTHER);
391
392 m_TreeView->SetImageList(hImageTreeView, TVSIL_NORMAL);
393 m_TreeView->Expand(hRootItem2, TVE_EXPAND);
394 m_TreeView->Expand(hRootItem1, TVE_EXPAND);
395 m_TreeView->SelectItem(hRootItem1);
396 }
397
398 BOOL CreateStatusBar()
399 {
400 m_StatusBar = new CUiWindow<CStatusBar>();
401 m_StatusBar->m_VerticalAlignment = UiAlign_RightBtm;
402 m_StatusBar->m_HorizontalAlignment = UiAlign_Stretch;
403 m_ClientPanel->Children().Append(m_StatusBar);
404
405 return m_StatusBar->Create(m_hWnd, (HMENU)IDC_STATUSBAR) != NULL;
406 }
407
408 BOOL CreateToolbar()
409 {
410 m_Toolbar = new CMainToolbar();
411 m_Toolbar->m_VerticalAlignment = UiAlign_LeftTop;
412 m_Toolbar->m_HorizontalAlignment = UiAlign_Stretch;
413 m_ClientPanel->Children().Append(m_Toolbar);
414
415 return m_Toolbar->Create(m_hWnd) != NULL;
416 }
417
418 BOOL CreateTreeView()
419 {
420 m_TreeView = new CUiWindow<CTreeView>();
421 m_TreeView->m_VerticalAlignment = UiAlign_Stretch;
422 m_TreeView->m_HorizontalAlignment = UiAlign_Stretch;
423 m_VSplitter->First().Append(m_TreeView);
424
425 return m_TreeView->Create(m_hWnd) != NULL;
426 }
427
428 BOOL CreateListView()
429 {
430 m_ListView = new CAppsListView();
431 m_ListView->m_VerticalAlignment = UiAlign_Stretch;
432 m_ListView->m_HorizontalAlignment = UiAlign_Stretch;
433 m_HSplitter->First().Append(m_ListView);
434
435 hListView = m_ListView->Create(m_hWnd);
436 return hListView != NULL;
437 }
438
439 BOOL CreateRichEdit()
440 {
441 m_RichEdit = new CUiWindow<CRichEdit>();
442 m_RichEdit->m_VerticalAlignment = UiAlign_Stretch;
443 m_RichEdit->m_HorizontalAlignment = UiAlign_Stretch;
444 m_HSplitter->Second().Append(m_RichEdit);
445
446 return m_RichEdit->Create(m_hWnd) != NULL;
447 }
448
449 BOOL CreateVSplitter()
450 {
451 m_VSplitter = new CUiSplitPanel();
452 m_VSplitter->m_VerticalAlignment = UiAlign_Stretch;
453 m_VSplitter->m_HorizontalAlignment = UiAlign_Stretch;
454 m_VSplitter->m_DynamicFirst = FALSE;
455 m_VSplitter->m_Horizontal = FALSE;
456 m_VSplitter->m_MinFirst = 240;
457 m_VSplitter->m_MinSecond = 300;
458 m_ClientPanel->Children().Append(m_VSplitter);
459
460 return m_VSplitter->Create(m_hWnd) != NULL;
461 }
462
463 BOOL CreateHSplitter()
464 {
465 m_HSplitter = new CUiSplitPanel();
466 m_HSplitter->m_VerticalAlignment = UiAlign_Stretch;
467 m_HSplitter->m_HorizontalAlignment = UiAlign_Stretch;
468 m_HSplitter->m_DynamicFirst = TRUE;
469 m_HSplitter->m_Horizontal = TRUE;
470 m_HSplitter->m_Pos = 32768;
471 m_HSplitter->m_MinFirst = 300;
472 m_HSplitter->m_MinSecond = 80;
473 m_VSplitter->Second().Append(m_HSplitter);
474
475 return m_HSplitter->Create(m_hWnd) != NULL;
476 }
477
478 BOOL CreateSearchBar(VOID)
479 {
480 WCHAR szBuf[MAX_STR_LEN];
481
482 // TODO: WRAPPER
483 m_SearchBar = new CUiWindow<>();
484 m_SearchBar->m_VerticalAlignment = UiAlign_LeftTop;
485 m_SearchBar->m_HorizontalAlignment = UiAlign_RightBtm;
486 m_SearchBar->m_Margin.top = 6;
487 m_SearchBar->m_Margin.right = 6;
488 //m_ClientPanel->Children().Append(m_SearchBar);
489
490 HWND hwnd = CreateWindowExW(WS_EX_CLIENTEDGE,
491 L"Edit",
492 NULL,
493 WS_CHILD | WS_VISIBLE | ES_LEFT | ES_AUTOHSCROLL,
494 0,
495 0,
496 200,
497 22,
498 m_Toolbar->m_hWnd,
499 (HMENU) 0,
500 hInst,
501 0);
502
503 m_SearchBar->m_hWnd = hwnd;
504
505 m_SearchBar->SendMessageW(WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0);
506
507 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
508 m_SearchBar->SetWindowTextW(szBuf);
509
510 return hwnd != NULL;
511 }
512
513 BOOL CreateLayout()
514 {
515 bool b = TRUE;
516
517 m_ClientPanel = new CUiPanel();
518 m_ClientPanel->m_VerticalAlignment = UiAlign_Stretch;
519 m_ClientPanel->m_HorizontalAlignment = UiAlign_Stretch;
520
521 // Top level
522 b = b && CreateStatusBar();
523 b = b && CreateToolbar();
524 b = b && CreateSearchBar();
525 b = b && CreateVSplitter();
526
527 // Inside V Splitter
528 b = b && CreateHSplitter();
529 b = b && CreateTreeView();
530
531 // Inside H Splitter
532 b = b && CreateListView();
533 b = b && CreateRichEdit();
534
535 if (b)
536 {
537 RECT rTop;
538 RECT rBottom;
539
540 /* Size status bar */
541 m_StatusBar->SendMessage(WM_SIZE, 0, 0);
542
543 /* Size tool bar */
544 m_Toolbar->AutoSize();
545
546 ::GetWindowRect(m_Toolbar->m_hWnd, &rTop);
547 ::GetWindowRect(m_StatusBar->m_hWnd, &rBottom);
548
549 m_VSplitter->m_Margin.top = rTop.bottom - rTop.top;
550 m_VSplitter->m_Margin.bottom = rBottom.bottom-rBottom.top;
551 }
552
553 return b;
554 }
555
556 BOOL InitControls()
557 {
558 /* Create image list */
559 hImageTreeView = ImageList_Create(TREEVIEW_ICON_SIZE, TREEVIEW_ICON_SIZE,
560 GetSystemColorDepth() | ILC_MASK,
561 0, 1);
562
563 if (CreateLayout())
564 {
565 WCHAR szBuffer1[MAX_STR_LEN], szBuffer2[MAX_STR_LEN];
566
567 InitApplicationsList();
568
569 InitCategoriesList();
570
571 LoadStringW(hInst, IDS_APPS_COUNT, szBuffer2, _countof(szBuffer2));
572 StringCbPrintfW(szBuffer1, sizeof(szBuffer1),
573 szBuffer2,
574 m_ListView->GetItemCount());
575 m_StatusBar->SetText(szBuffer1);
576 return TRUE;
577 }
578
579 return FALSE;
580 }
581
582 VOID OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
583 {
584 /* Size status bar */
585 m_StatusBar->SendMessage(WM_SIZE, 0, 0);
586
587 /* Size tool bar */
588 m_Toolbar->AutoSize();
589
590
591 RECT r = { 0, 0, LOWORD(lParam), HIWORD(lParam) };
592
593 HDWP hdwp = NULL;
594
595 int count = m_ClientPanel->CountSizableChildren();
596 hdwp = BeginDeferWindowPos(count);
597 hdwp = m_ClientPanel->OnParentSize(r, hdwp);
598 EndDeferWindowPos(hdwp);
599
600 // TODO: Sub-layouts for children of children
601 count = m_SearchBar->CountSizableChildren();
602 hdwp = BeginDeferWindowPos(count);
603 hdwp = m_SearchBar->OnParentSize(r, hdwp);
604 EndDeferWindowPos(hdwp);
605 }
606
607 BOOL ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT& theResult, DWORD dwMapId)
608 {
609 theResult = 0;
610 switch (Msg)
611 {
612 case WM_CREATE:
613 if (!InitControls())
614 ::PostMessage(hwnd, WM_CLOSE, 0, 0);
615 break;
616
617 case WM_DESTROY:
618 {
619 ShowWindow(SW_HIDE);
620 SaveSettings(hwnd);
621
622 FreeLogs();
623
624 FreeCachedAvailableEntries();
625
626 if (IS_INSTALLED_ENUM(SelectedEnumType))
627 FreeInstalledAppList();
628
629 if (hImageTreeView)
630 ImageList_Destroy(hImageTreeView);
631
632 delete m_ClientPanel;
633
634 PostQuitMessage(0);
635 return 0;
636 }
637
638 case WM_COMMAND:
639 OnCommand(wParam, lParam);
640 break;
641
642 case WM_NOTIFY:
643 {
644 LPNMHDR data = (LPNMHDR) lParam;
645
646 switch (data->code)
647 {
648 case TVN_SELCHANGED:
649 {
650 if (data->hwndFrom == m_TreeView->m_hWnd)
651 {
652 switch (((LPNMTREEVIEW) lParam)->itemNew.lParam)
653 {
654 case IDS_INSTALLED:
655 UpdateApplicationsList(ENUM_ALL_COMPONENTS);
656 break;
657
658 case IDS_APPLICATIONS:
659 UpdateApplicationsList(ENUM_APPLICATIONS);
660 break;
661
662 case IDS_UPDATES:
663 UpdateApplicationsList(ENUM_UPDATES);
664 break;
665
666 case IDS_AVAILABLEFORINST:
667 UpdateApplicationsList(ENUM_ALL_AVAILABLE);
668 break;
669
670 case IDS_CAT_AUDIO:
671 UpdateApplicationsList(ENUM_CAT_AUDIO);
672 break;
673
674 case IDS_CAT_DEVEL:
675 UpdateApplicationsList(ENUM_CAT_DEVEL);
676 break;
677
678 case IDS_CAT_DRIVERS:
679 UpdateApplicationsList(ENUM_CAT_DRIVERS);
680 break;
681
682 case IDS_CAT_EDU:
683 UpdateApplicationsList(ENUM_CAT_EDU);
684 break;
685
686 case IDS_CAT_ENGINEER:
687 UpdateApplicationsList(ENUM_CAT_ENGINEER);
688 break;
689
690 case IDS_CAT_FINANCE:
691 UpdateApplicationsList(ENUM_CAT_FINANCE);
692 break;
693
694 case IDS_CAT_GAMES:
695 UpdateApplicationsList(ENUM_CAT_GAMES);
696 break;
697
698 case IDS_CAT_GRAPHICS:
699 UpdateApplicationsList(ENUM_CAT_GRAPHICS);
700 break;
701
702 case IDS_CAT_INTERNET:
703 UpdateApplicationsList(ENUM_CAT_INTERNET);
704 break;
705
706 case IDS_CAT_LIBS:
707 UpdateApplicationsList(ENUM_CAT_LIBS);
708 break;
709
710 case IDS_CAT_OFFICE:
711 UpdateApplicationsList(ENUM_CAT_OFFICE);
712 break;
713
714 case IDS_CAT_OTHER:
715 UpdateApplicationsList(ENUM_CAT_OTHER);
716 break;
717
718 case IDS_CAT_SCIENCE:
719 UpdateApplicationsList(ENUM_CAT_SCIENCE);
720 break;
721
722 case IDS_CAT_TOOLS:
723 UpdateApplicationsList(ENUM_CAT_TOOLS);
724 break;
725
726 case IDS_CAT_VIDEO:
727 UpdateApplicationsList(ENUM_CAT_VIDEO);
728 break;
729 }
730 }
731
732 HMENU mainMenu = ::GetMenu(hwnd);
733 HMENU lvwMenu = ::GetMenu(m_ListView->m_hWnd);
734
735 /* Disable/enable items based on treeview selection */
736 if (IsSelectedNodeInstalled())
737 {
738 EnableMenuItem(mainMenu, ID_REGREMOVE, MF_ENABLED);
739 EnableMenuItem(mainMenu, ID_INSTALL, MF_GRAYED);
740 EnableMenuItem(mainMenu, ID_UNINSTALL, MF_ENABLED);
741 EnableMenuItem(mainMenu, ID_MODIFY, MF_ENABLED);
742
743 EnableMenuItem(lvwMenu, ID_REGREMOVE, MF_ENABLED);
744 EnableMenuItem(lvwMenu, ID_INSTALL, MF_GRAYED);
745 EnableMenuItem(lvwMenu, ID_UNINSTALL, MF_ENABLED);
746 EnableMenuItem(lvwMenu, ID_MODIFY, MF_ENABLED);
747
748 m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_REGREMOVE, TRUE);
749 m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_INSTALL, FALSE);
750 m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_UNINSTALL, TRUE);
751 m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_MODIFY, TRUE);
752 }
753 else
754 {
755 EnableMenuItem(mainMenu, ID_REGREMOVE, MF_GRAYED);
756 EnableMenuItem(mainMenu, ID_INSTALL, MF_ENABLED);
757 EnableMenuItem(mainMenu, ID_UNINSTALL, MF_GRAYED);
758 EnableMenuItem(mainMenu, ID_MODIFY, MF_GRAYED);
759
760 EnableMenuItem(lvwMenu, ID_REGREMOVE, MF_GRAYED);
761 EnableMenuItem(lvwMenu, ID_INSTALL, MF_ENABLED);
762 EnableMenuItem(lvwMenu, ID_UNINSTALL, MF_GRAYED);
763 EnableMenuItem(lvwMenu, ID_MODIFY, MF_GRAYED);
764
765 m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_REGREMOVE, FALSE);
766 m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_INSTALL, TRUE);
767 m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_UNINSTALL, FALSE);
768 m_Toolbar->SendMessage(TB_ENABLEBUTTON, ID_MODIFY, FALSE);
769 }
770 }
771 break;
772
773 case LVN_ITEMCHANGED:
774 {
775 LPNMLISTVIEW pnic = (LPNMLISTVIEW) lParam;
776
777 if (pnic->hdr.hwndFrom == m_ListView->m_hWnd)
778 {
779 /* Check if this is a valid item
780 * (technically, it can be also an unselect) */
781 INT ItemIndex = pnic->iItem;
782 if (ItemIndex == -1 ||
783 ItemIndex >= ListView_GetItemCount(pnic->hdr.hwndFrom))
784 {
785 break;
786 }
787
788 /* Check if the focus has been moved to another item */
789 if ((pnic->uChanged & LVIF_STATE) &&
790 (pnic->uNewState & LVIS_FOCUSED) &&
791 !(pnic->uOldState & LVIS_FOCUSED))
792 {
793 if (IS_INSTALLED_ENUM(SelectedEnumType))
794 ShowInstalledAppInfo(ItemIndex);
795 if (IS_AVAILABLE_ENUM(SelectedEnumType))
796 ShowAvailableAppInfo(ItemIndex);
797 }
798 }
799 }
800 break;
801
802 case LVN_COLUMNCLICK:
803 {
804 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
805
806 m_ListView->ColumnClick(pnmv);
807 }
808 break;
809
810 case NM_CLICK:
811 {
812 if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
813 {
814 if (IS_INSTALLED_ENUM(SelectedEnumType))
815 ShowInstalledAppInfo(-1);
816 if (IS_AVAILABLE_ENUM(SelectedEnumType))
817 ShowAvailableAppInfo(-1);
818 }
819 }
820 break;
821
822 case NM_DBLCLK:
823 {
824 if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
825 {
826 /* this won't do anything if the program is already installed */
827 SendMessage(hwnd, WM_COMMAND, ID_INSTALL, 0);
828 }
829 }
830 break;
831
832 case NM_RCLICK:
833 {
834 if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
835 {
836 ShowPopupMenu(m_ListView->m_hWnd, 0, ID_INSTALL);
837 }
838 }
839 break;
840
841 case EN_LINK:
842 OnLink((ENLINK*) lParam);
843 break;
844
845 case TTN_GETDISPINFO:
846 m_Toolbar->OnGetDispInfo((LPTOOLTIPTEXT) lParam);
847 break;
848 }
849 }
850 break;
851
852 case WM_SIZE:
853 OnSize(hwnd, wParam, lParam);
854 break;
855
856 case WM_SIZING:
857 {
858 LPRECT pRect = (LPRECT) lParam;
859
860 if (pRect->right - pRect->left < 565)
861 pRect->right = pRect->left + 565;
862
863 if (pRect->bottom - pRect->top < 300)
864 pRect->bottom = pRect->top + 300;
865
866 return TRUE;
867 }
868
869 case WM_SYSCOLORCHANGE:
870 {
871 /* Forward WM_SYSCOLORCHANGE to common controls */
872 m_ListView->SendMessage(WM_SYSCOLORCHANGE, 0, 0);
873 m_TreeView->SendMessage(WM_SYSCOLORCHANGE, 0, 0);
874 m_Toolbar->SendMessage(WM_SYSCOLORCHANGE, 0, 0);
875 m_ListView->SendMessage(EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
876 }
877 break;
878
879 case WM_TIMER:
880 if (wParam == SEARCH_TIMER_ID)
881 {
882 ::KillTimer(hwnd, SEARCH_TIMER_ID);
883 UpdateApplicationsList(-1);
884 }
885 break;
886 }
887
888 return FALSE;
889 }
890
891 virtual VOID OnLink(ENLINK *Link)
892 {
893 switch (Link->msg)
894 {
895 case WM_LBUTTONUP:
896 case WM_RBUTTONUP:
897 {
898 if (pLink) HeapFree(GetProcessHeap(), 0, pLink);
899
900 pLink = (PWSTR) HeapAlloc(GetProcessHeap(), 0,
901 (max(Link->chrg.cpMin, Link->chrg.cpMax) -
902 min(Link->chrg.cpMin, Link->chrg.cpMax) + 1) * sizeof(WCHAR));
903 if (!pLink)
904 {
905 /* TODO: Error message */
906 return;
907 }
908
909 m_RichEdit->SendMessageW(EM_SETSEL, Link->chrg.cpMin, Link->chrg.cpMax);
910 m_RichEdit->SendMessageW(EM_GETSELTEXT, 0, (LPARAM) pLink);
911
912 ShowPopupMenu(m_RichEdit->m_hWnd, IDR_LINKMENU, -1);
913 }
914 break;
915 }
916 }
917
918 BOOL IsSelectedNodeInstalled(void)
919 {
920 HTREEITEM hSelectedItem = m_TreeView->GetSelection();
921 TV_ITEM tItem;
922
923 tItem.mask = TVIF_PARAM | TVIF_HANDLE;
924 tItem.hItem = hSelectedItem;
925 m_TreeView->GetItem(&tItem);
926 switch (tItem.lParam)
927 {
928 case IDS_INSTALLED:
929 case IDS_APPLICATIONS:
930 case IDS_UPDATES:
931 return TRUE;
932 default:
933 return FALSE;
934 }
935 }
936
937 VOID OnCommand(WPARAM wParam, LPARAM lParam)
938 {
939 WORD wCommand = LOWORD(wParam);
940
941 if (lParam == (LPARAM) m_SearchBar->m_hWnd)
942 {
943 WCHAR szBuf[MAX_STR_LEN];
944
945 switch (HIWORD(wParam))
946 {
947 case EN_SETFOCUS:
948 {
949 WCHAR szWndText[MAX_STR_LEN];
950
951 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, _countof(szBuf));
952 m_SearchBar->GetWindowTextW(szWndText, MAX_STR_LEN);
953 if (wcscmp(szBuf, szWndText) == 0)
954 {
955 SearchEnabled = FALSE;
956 m_SearchBar->SetWindowTextW(L"");
957 }
958 }
959 break;
960
961 case EN_KILLFOCUS:
962 {
963 m_SearchBar->GetWindowTextW(szBuf, MAX_STR_LEN);
964 if (wcslen(szBuf) < 1)
965 {
966 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, _countof(szBuf));
967 SearchEnabled = FALSE;
968 m_SearchBar->SetWindowTextW(szBuf);
969 }
970 }
971 break;
972
973 case EN_CHANGE:
974 {
975 WCHAR szWndText[MAX_STR_LEN];
976
977 if (!SearchEnabled)
978 {
979 SearchEnabled = TRUE;
980 break;
981 }
982
983 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, _countof(szBuf));
984 m_SearchBar->GetWindowTextW(szWndText, MAX_STR_LEN);
985 if (wcscmp(szBuf, szWndText) != 0)
986 {
987 StringCbCopy(szSearchPattern, sizeof(szSearchPattern),
988 szWndText);
989 }
990 else
991 {
992 szSearchPattern[0] = UNICODE_NULL;
993 }
994
995 DWORD dwDelay;
996 SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &dwDelay, 0);
997 SetTimer(SEARCH_TIMER_ID, dwDelay);
998 }
999 break;
1000 }
1001
1002 return;
1003 }
1004
1005 switch (wCommand)
1006 {
1007 case ID_OPEN_LINK:
1008 ShellExecuteW(m_hWnd, L"open", pLink, NULL, NULL, SW_SHOWNOACTIVATE);
1009 HeapFree(GetProcessHeap(), 0, pLink);
1010 break;
1011
1012 case ID_COPY_LINK:
1013 CopyTextToClipboard(pLink);
1014 HeapFree(GetProcessHeap(), 0, pLink);
1015 break;
1016
1017 case ID_SETTINGS:
1018 CreateSettingsDlg(m_hWnd);
1019 break;
1020
1021 case ID_EXIT:
1022 PostMessageW(WM_CLOSE, 0, 0);
1023 break;
1024
1025 case ID_INSTALL:
1026 if (DownloadApplication(-1))
1027 /* TODO: Implement install dialog
1028 * if (InstallApplication(-1))
1029 */
1030 UpdateApplicationsList(-1);
1031 break;
1032
1033 case ID_UNINSTALL:
1034 if (UninstallApplication(-1, FALSE))
1035 UpdateApplicationsList(-1);
1036 break;
1037
1038 case ID_MODIFY:
1039 if (UninstallApplication(-1, TRUE))
1040 UpdateApplicationsList(-1);
1041 break;
1042
1043 case ID_REGREMOVE:
1044 RemoveAppFromRegistry(-1);
1045 break;
1046
1047 case ID_REFRESH:
1048 UpdateApplicationsList(-1);
1049 break;
1050
1051 case ID_RESETDB:
1052 UpdateAppsDB();
1053 UpdateApplicationsList(-1);
1054 break;
1055
1056 case ID_HELP:
1057 MessageBoxW(L"Help not implemented yet", NULL, MB_OK);
1058 break;
1059
1060 case ID_ABOUT:
1061 ShowAboutDialog();
1062 break;
1063 }
1064 }
1065
1066 VOID FreeInstalledAppList(VOID)
1067 {
1068 INT Count = ListView_GetItemCount(hListView) - 1;
1069 PINSTALLED_INFO Info;
1070
1071 while (Count >= 0)
1072 {
1073 Info = (PINSTALLED_INFO) ListViewGetlParam(Count);
1074 if (Info)
1075 {
1076 RegCloseKey(Info->hSubKey);
1077 HeapFree(GetProcessHeap(), 0, Info);
1078 }
1079 Count--;
1080 }
1081 }
1082
1083 static BOOL SearchPatternMatch(PCWSTR szHaystack, PCWSTR szNeedle)
1084 {
1085 if (!*szNeedle)
1086 return TRUE;
1087 /* TODO: Improve pattern search beyond a simple case-insensitive substring search. */
1088 return StrStrIW(szHaystack, szNeedle) != NULL;
1089 }
1090
1091 static BOOL CALLBACK s_EnumInstalledAppProc(INT ItemIndex, LPWSTR lpName, PINSTALLED_INFO Info)
1092 {
1093 PINSTALLED_INFO ItemInfo;
1094 WCHAR szText[MAX_PATH];
1095 INT Index;
1096
1097 if (!SearchPatternMatch(lpName, szSearchPattern))
1098 {
1099 RegCloseKey(Info->hSubKey);
1100 return TRUE;
1101 }
1102
1103 ItemInfo = (PINSTALLED_INFO) HeapAlloc(GetProcessHeap(), 0, sizeof(INSTALLED_INFO));
1104 if (!ItemInfo)
1105 {
1106 RegCloseKey(Info->hSubKey);
1107 return FALSE;
1108 }
1109
1110 RtlCopyMemory(ItemInfo, Info, sizeof(INSTALLED_INFO));
1111
1112 Index = ListViewAddItem(ItemIndex, 0, lpName, (LPARAM) ItemInfo);
1113
1114 /* Get version info */
1115 GetApplicationString(ItemInfo->hSubKey, L"DisplayVersion", szText);
1116 ListView_SetItemText(hListView, Index, 1, szText);
1117
1118 /* Get comments */
1119 GetApplicationString(ItemInfo->hSubKey, L"Comments", szText);
1120 ListView_SetItemText(hListView, Index, 2, szText);
1121
1122 return TRUE;
1123 }
1124
1125 static BOOL CALLBACK s_EnumAvailableAppProc(PAPPLICATION_INFO Info)
1126 {
1127 INT Index;
1128
1129 if (!SearchPatternMatch(Info->szName, szSearchPattern) &&
1130 !SearchPatternMatch(Info->szDesc, szSearchPattern))
1131 {
1132 return TRUE;
1133 }
1134
1135 /* Only add a ListView entry if...
1136 - no RegName was supplied (so we cannot determine whether the application is installed or not) or
1137 - a RegName was supplied and the application is not installed
1138 */
1139 if (!*Info->szRegName || (!IsInstalledApplication(Info->szRegName, FALSE) && !IsInstalledApplication(Info->szRegName, TRUE)))
1140 {
1141 Index = ListViewAddItem(Info->Category, 0, Info->szName, (LPARAM) Info);
1142
1143 ListView_SetItemText(hListView, Index, 1, Info->szVersion);
1144 ListView_SetItemText(hListView, Index, 2, Info->szDesc);
1145 }
1146
1147 return TRUE;
1148 }
1149
1150 VOID UpdateApplicationsList(INT EnumType)
1151 {
1152 WCHAR szBuffer1[MAX_STR_LEN], szBuffer2[MAX_STR_LEN];
1153 HICON hIcon;
1154 HIMAGELIST hImageListView;
1155
1156 m_ListView->SendMessage(WM_SETREDRAW, FALSE, 0);
1157
1158 if (EnumType == -1) EnumType = SelectedEnumType;
1159
1160 if (IS_INSTALLED_ENUM(SelectedEnumType))
1161 FreeInstalledAppList();
1162
1163 (VOID) ListView_DeleteAllItems(hListView);
1164
1165 /* Create image list */
1166 hImageListView = ImageList_Create(LISTVIEW_ICON_SIZE,
1167 LISTVIEW_ICON_SIZE,
1168 GetSystemColorDepth() | ILC_MASK,
1169 0, 1);
1170
1171 hIcon = (HICON) LoadImage(hInst,
1172 MAKEINTRESOURCE(IDI_MAIN),
1173 IMAGE_ICON,
1174 LISTVIEW_ICON_SIZE,
1175 LISTVIEW_ICON_SIZE,
1176 LR_CREATEDIBSECTION);
1177
1178 ImageList_AddIcon(hImageListView, hIcon);
1179 DestroyIcon(hIcon);
1180
1181 if (IS_INSTALLED_ENUM(EnumType))
1182 {
1183 /* Enum installed applications and updates */
1184 EnumInstalledApplications(EnumType, TRUE, s_EnumInstalledAppProc);
1185 EnumInstalledApplications(EnumType, FALSE, s_EnumInstalledAppProc);
1186 }
1187 else if (IS_AVAILABLE_ENUM(EnumType))
1188 {
1189 /* Enum availabled applications */
1190 EnumAvailableApplications(EnumType, s_EnumAvailableAppProc);
1191 }
1192
1193 /* Set image list for ListView */
1194 hImageListView = ListView_SetImageList(hListView, hImageListView, LVSIL_SMALL);
1195
1196 /* Destroy old image list */
1197 if (hImageListView)
1198 ImageList_Destroy(hImageListView);
1199
1200 SelectedEnumType = EnumType;
1201
1202 LoadStringW(hInst, IDS_APPS_COUNT, szBuffer2, _countof(szBuffer2));
1203 StringCbPrintfW(szBuffer1, sizeof(szBuffer1),
1204 szBuffer2,
1205 ListView_GetItemCount(hListView));
1206 SetStatusBarText(szBuffer1);
1207
1208 SetWelcomeText();
1209
1210 /* set automatic column width for program names if the list is not empty */
1211 if (ListView_GetItemCount(hListView) > 0)
1212 ListView_SetColumnWidth(hListView, 0, LVSCW_AUTOSIZE);
1213
1214 SendMessage(hListView, WM_SETREDRAW, TRUE, 0);
1215 }
1216
1217 public:
1218 static ATL::CWndClassInfo& GetWndClassInfo()
1219 {
1220 DWORD csStyle = CS_VREDRAW |CS_HREDRAW;
1221 static ATL::CWndClassInfo wc =
1222 {
1223 { sizeof(WNDCLASSEX), csStyle, StartWindowProc,
1224 0, 0, NULL,
1225 LoadIcon(_AtlBaseModule.GetModuleInstance(), MAKEINTRESOURCE(IDI_MAIN)),
1226 LoadCursor(NULL, IDC_ARROW),
1227 (HBRUSH) (COLOR_BTNFACE + 1), NULL,
1228 L"RAppsWnd", NULL },
1229 NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
1230 };
1231 return wc;
1232 }
1233
1234 HWND Create()
1235 {
1236 WCHAR szWindowName[MAX_STR_LEN];
1237
1238 LoadStringW(hInst, IDS_APPTITLE, szWindowName, _countof(szWindowName));
1239
1240 RECT r = {
1241 (SettingsInfo.bSaveWndPos ? SettingsInfo.Left : CW_USEDEFAULT),
1242 (SettingsInfo.bSaveWndPos ? SettingsInfo.Top : CW_USEDEFAULT),
1243 (SettingsInfo.bSaveWndPos ? SettingsInfo.Width : 680),
1244 (SettingsInfo.bSaveWndPos ? SettingsInfo.Height : 450)
1245 };
1246 r.right += r.left;
1247 r.bottom += r.top;
1248
1249 return CWindowImpl::Create(NULL, r, szWindowName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
1250 }
1251
1252 CStatusBar * GetStatusBar()
1253 {
1254 return m_StatusBar;
1255 }
1256
1257 CAppsListView * GetListView()
1258 {
1259 return m_ListView;
1260 }
1261
1262 CRichEdit * GetRichEdit()
1263 {
1264 return m_RichEdit;
1265 }
1266 };
1267
1268 CMainWindow * g_MainWindow;
1269
1270 HWND CreateMainWindow()
1271 {
1272 g_MainWindow = new CMainWindow();
1273 return g_MainWindow->Create();
1274 }
1275
1276 DWORD_PTR ListViewGetlParam(INT item)
1277 {
1278 if (item < 0)
1279 {
1280 item = g_MainWindow->GetListView()->GetSelectionMark();
1281 }
1282 return g_MainWindow->GetListView()->GetItemData(item);
1283 }
1284
1285 VOID SetStatusBarText(PCWSTR szText)
1286 {
1287 g_MainWindow->GetStatusBar()->SetText(szText);
1288 }
1289
1290 INT ListViewAddItem(INT ItemIndex, INT IconIndex, PWSTR lpName, LPARAM lParam)
1291 {
1292 return g_MainWindow->GetListView()->AddItem(ItemIndex, IconIndex, lpName, lParam);
1293 }
1294
1295 VOID NewRichEditText(PCWSTR szText, DWORD flags)
1296 {
1297 g_MainWindow->GetRichEdit()->SetText(szText, flags);
1298 }
1299
1300 VOID InsertRichEditText(PCWSTR szText, DWORD flags)
1301 {
1302 g_MainWindow->GetRichEdit()->InsertText(szText, flags);
1303 }