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