3e6d6364deb058762776598a29bd9c27e3550b02
[reactos.git] / reactos / base / applications / rapps / winmain.c
1 /*
2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/rapps/winmain.c
5 * PURPOSE: Main program
6 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
7 */
8
9 #include "rapps.h"
10
11 HWND hMainWnd;
12 HINSTANCE hInst;
13 HIMAGELIST hImageListView = NULL;
14 HIMAGELIST hImageTreeView = NULL;
15 INT SelectedEnumType = ENUM_ALL_COMPONENTS;
16
17
18 CALLBACK
19 BOOL
20 EnumInstalledAppProc(INT ItemIndex, LPWSTR lpName, LPWSTR lpKeyName, LPARAM lParam)
21 {
22 WCHAR szText[MAX_PATH];
23 INT Index;
24
25 Index = ListViewAddItem(ItemIndex, 0, lpName, lParam);
26
27 /* Get version info */
28 GetApplicationString((HKEY)lParam, L"DisplayVersion", szText);
29 ListView_SetItemText(hListView, Index, 1, szText);
30 /* Get comments */
31 GetApplicationString((HKEY)lParam, L"Comments", szText);
32 ListView_SetItemText(hListView, Index, 2, szText);
33
34 return TRUE;
35 }
36
37 VOID
38 FreeAvailableAppList(VOID)
39 {
40 INT Count = ListView_GetItemCount(hListView) - 1;
41 PVOID Info;
42
43 while (Count >= 0)
44 {
45 Info = ListViewGetlParam(Count);
46 if (Info)
47 HeapFree(GetProcessHeap(), 0, Info);
48 Count--;
49 }
50 }
51
52 CALLBACK
53 BOOL
54 EnumAvailableAppProc(APPLICATION_INFO Info)
55 {
56 PAPPLICATION_INFO ItemInfo;
57 INT Index;
58
59 if (!IsInstalledApplication(Info.szRegName))
60 {
61 ItemInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(APPLICATION_INFO));
62 if (!ItemInfo) return FALSE;
63
64 *ItemInfo = Info;
65
66 Index = ListViewAddItem(Info.Category, 0, Info.szName, (LPARAM)ItemInfo);
67 ListView_SetItemText(hListView, Index, 1, Info.szVersion);
68 ListView_SetItemText(hListView, Index, 2, Info.szDesc);
69 }
70
71 return TRUE;
72 }
73
74 VOID
75 UpdateApplicationsList(INT EnumType)
76 {
77 WCHAR szBuffer1[MAX_STR_LEN], szBuffer2[MAX_STR_LEN];
78 HICON hIcon;
79
80 if (hImageListView) ImageList_Destroy(hImageListView);
81 (VOID) ListView_DeleteAllItems(hListView);
82
83 /* Create image list */
84 hImageListView = ImageList_Create(LISTVIEW_ICON_SIZE,
85 LISTVIEW_ICON_SIZE,
86 GetSystemColorDepth() | ILC_MASK,
87 0, 1);
88
89 hIcon = LoadImage(hInst,
90 MAKEINTRESOURCE(IDI_MAIN),
91 IMAGE_ICON,
92 LISTVIEW_ICON_SIZE,
93 LISTVIEW_ICON_SIZE,
94 LR_CREATEDIBSECTION);
95
96 ImageList_AddIcon(hImageListView, hIcon);
97 DestroyIcon(hIcon);
98
99 if (EnumType == -1) EnumType = SelectedEnumType;
100
101 if (IS_INSTALLED_ENUM(EnumType))
102 {
103 /* Enum installed applications and updates */
104 EnumInstalledApplications(EnumType, EnumInstalledAppProc);
105 }
106 else if (IS_AVAILABLE_ENUM(EnumType))
107 {
108 if (IS_AVAILABLE_ENUM(SelectedEnumType))
109 FreeAvailableAppList();
110
111 /* Enum availabled applications */
112 EnumAvailableApplications(EnumType, EnumAvailableAppProc);
113 }
114
115 /* Set image list for ListView */
116 (VOID) ListView_SetImageList(hListView, hImageListView, LVSIL_SMALL);
117
118 SelectedEnumType = EnumType;
119
120 LoadStringW(hInst, IDS_APPS_COUNT, szBuffer2, sizeof(szBuffer2) / sizeof(WCHAR));
121 swprintf(szBuffer1, szBuffer2, ListView_GetItemCount(hListView));
122 SetStatusBarText(szBuffer1);
123
124 SetWelcomeText();
125 }
126
127 VOID
128 InitApplicationsList(VOID)
129 {
130 WCHAR szText[MAX_STR_LEN];
131
132 /* Add columns to ListView */
133 LoadStringW(hInst, IDS_APP_NAME, szText, sizeof(szText) / sizeof(WCHAR));
134 ListViewAddColumn(0, szText, 200, LVCFMT_LEFT);
135
136 LoadStringW(hInst, IDS_APP_INST_VERSION, szText, sizeof(szText) / sizeof(WCHAR));
137 ListViewAddColumn(1, szText, 90, LVCFMT_RIGHT);
138
139 LoadStringW(hInst, IDS_APP_DESCRIPTION, szText, sizeof(szText) / sizeof(WCHAR));
140 ListViewAddColumn(3, szText, 250, LVCFMT_LEFT);
141
142 UpdateApplicationsList(ENUM_ALL_COMPONENTS);
143 }
144
145 HTREEITEM
146 AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex)
147 {
148 WCHAR szText[MAX_STR_LEN];
149 INT Index;
150 HICON hIcon;
151
152 hIcon = LoadImage(hInst,
153 MAKEINTRESOURCE(IconIndex),
154 IMAGE_ICON,
155 TREEVIEW_ICON_SIZE,
156 TREEVIEW_ICON_SIZE,
157 LR_CREATEDIBSECTION);
158
159 Index = ImageList_AddIcon(hImageTreeView, hIcon);
160 DestroyIcon(hIcon);
161
162 LoadStringW(hInst, TextIndex, szText, sizeof(szText) / sizeof(TCHAR));
163
164 return TreeViewAddItem(hRootItem, szText, Index, Index, TextIndex);
165 }
166
167 VOID
168 InitCategoriesList(VOID)
169 {
170 HTREEITEM hRootItem1, hRootItem2;
171
172 /* Create image list */
173 hImageTreeView = ImageList_Create(TREEVIEW_ICON_SIZE,
174 TREEVIEW_ICON_SIZE,
175 GetSystemColorDepth() | ILC_MASK,
176 0, 1);
177
178 hRootItem1 = AddCategory(TVI_ROOT, IDS_INSTALLED, IDI_CATEGORY);
179 AddCategory(hRootItem1, IDS_APPLICATIONS, IDI_APPS);
180 AddCategory(hRootItem1, IDS_UPDATES, IDI_APPUPD);
181
182 hRootItem2 = AddCategory(TVI_ROOT, IDS_AVAILABLEFORINST, IDI_CATEGORY);
183 AddCategory(hRootItem2, IDS_CAT_AUDIO, IDI_CAT_AUDIO);
184 AddCategory(hRootItem2, IDS_CAT_VIDEO, IDI_CAT_VIDEO);
185 AddCategory(hRootItem2, IDS_CAT_GRAPHICS, IDI_CAT_GRAPHICS);
186 AddCategory(hRootItem2, IDS_CAT_GAMES, IDI_CAT_GAMES);
187 AddCategory(hRootItem2, IDS_CAT_INTERNET, IDI_CAT_INTERNET);
188 AddCategory(hRootItem2, IDS_CAT_OFFICE, IDI_CAT_OFFICE);
189 AddCategory(hRootItem2, IDS_CAT_DEVEL, IDI_CAT_DEVEL);
190 AddCategory(hRootItem2, IDS_CAT_EDU, IDI_CAT_EDU);
191 AddCategory(hRootItem2, IDS_CAT_ENGINEER, IDI_CAT_ENGINEER);
192 AddCategory(hRootItem2, IDS_CAT_FINANCE, IDI_CAT_FINANCE);
193 AddCategory(hRootItem2, IDS_CAT_SCIENCE, IDI_CAT_SCIENCE);
194 AddCategory(hRootItem2, IDS_CAT_TOOLS, IDI_CAT_TOOLS);
195 AddCategory(hRootItem2, IDS_CAT_DRIVERS, IDI_CAT_DRIVERS);
196 AddCategory(hRootItem2, IDS_CAT_LIBS, IDI_CAT_LIBS);
197 AddCategory(hRootItem2, IDS_CAT_OTHER, IDI_CAT_OTHER);
198
199 (VOID) TreeView_SetImageList(hTreeView, hImageTreeView, TVSIL_NORMAL);
200
201 (VOID) TreeView_Expand(hTreeView, hRootItem2, TVE_EXPAND);
202 (VOID) TreeView_Expand(hTreeView, hRootItem1, TVE_EXPAND);
203
204 (VOID) TreeView_SelectItem(hTreeView, hRootItem1);
205 }
206
207 BOOL
208 InitControls(HWND hwnd)
209 {
210 if (CreateStatusBar(hwnd) &&
211 CreateToolBar(hwnd) &&
212 CreateListView(hwnd) &&
213 CreateTreeView(hwnd) &&
214 CreateRichEdit(hwnd) &&
215 CreateVSplitBar(hwnd) &&
216 CreateHSplitBar(hwnd))
217 {
218 WCHAR szBuffer1[MAX_STR_LEN], szBuffer2[MAX_STR_LEN];
219
220 InitApplicationsList();
221
222 InitCategoriesList();
223
224 LoadStringW(hInst, IDS_APPS_COUNT, szBuffer2, sizeof(szBuffer2) / sizeof(WCHAR));
225 swprintf(szBuffer1, szBuffer2, ListView_GetItemCount(hListView));
226 SetStatusBarText(szBuffer1);
227 return TRUE;
228 }
229
230 return FALSE;
231 }
232
233 VOID
234 MainWndOnCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
235 {
236 WORD wCommand = LOWORD(wParam);
237
238 if (lParam == (LPARAM)hSearchBar)
239 {
240 WCHAR szBuf[MAX_STR_LEN];
241
242 switch (HIWORD(wParam))
243 {
244 case EN_SETFOCUS:
245 {
246 WCHAR szWndText[MAX_STR_LEN];
247
248 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
249 GetWindowTextW(hSearchBar, szWndText, MAX_STR_LEN);
250 if (wcscmp(szBuf, szWndText) == 0) SetWindowTextW(hSearchBar, L"");
251 }
252 break;
253
254 case EN_KILLFOCUS:
255 {
256 GetWindowTextW(hSearchBar, szBuf, MAX_STR_LEN);
257 if (wcslen(szBuf) < 1)
258 {
259 LoadStringW(hInst, IDS_SEARCH_TEXT, szBuf, sizeof(szBuf) / sizeof(WCHAR));
260 SetWindowTextW(hSearchBar, szBuf);
261 }
262 }
263 break;
264
265 case EN_CHANGE:
266 /* TODO: Implement search */
267 break;
268 }
269
270 return;
271 }
272
273 switch (wCommand)
274 {
275 case ID_OPEN_LINK:
276 ShellExecuteW(hwnd, L"open", pLink, NULL, NULL, SW_SHOWNOACTIVATE);
277 HeapFree(GetProcessHeap(), 0, pLink);
278 break;
279
280 case ID_COPY_LINK:
281 CopyTextToClipboard(pLink);
282 HeapFree(GetProcessHeap(), 0, pLink);
283 break;
284
285 case ID_SETTINGS:
286 CreateSettingsDlg(hwnd);
287 break;
288
289 case ID_EXIT:
290 PostMessageW(hwnd, WM_CLOSE, 0, 0);
291 break;
292
293 case ID_INSTALL:
294 if (DownloadApplication(-1))
295 /* TODO: Implement install dialog
296 * if (InstallApplication(-1))
297 */
298 UpdateApplicationsList(-1);
299 break;
300
301 case ID_UNINSTALL:
302 if (UninstallApplication(-1, FALSE))
303 UpdateApplicationsList(-1);
304 break;
305
306 case ID_MODIFY:
307 if (UninstallApplication(-1, TRUE))
308 UpdateApplicationsList(-1);
309 break;
310
311 case ID_REFRESH:
312 UpdateApplicationsList(-1);
313 break;
314
315 case ID_HELP:
316 MessageBoxW(hwnd, L"Help not implemented yet", NULL, MB_OK);
317 break;
318
319 case ID_ABOUT:
320 ShowAboutDialog();
321 break;
322 }
323 }
324
325 VOID
326 MainWndOnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
327 {
328 HDWP hdwp = BeginDeferWindowPos(5);
329 INT SearchBarWidth = GetWindowWidth(hSearchBar);
330 INT RichPos = GetWindowHeight(hRichEdit);
331 INT NewPos = GetClientWindowHeight(hMainWnd) - (RichPos + SPLIT_WIDTH + GetWindowHeight(hStatusBar));
332 INT VSplitterPos;
333
334 /* Size status bar */
335 SendMessage(hStatusBar, WM_SIZE, 0, 0);
336
337 /* Size tool bar */
338 SendMessage(hToolBar, TB_AUTOSIZE, 0, 0);
339
340 /* Size SearchBar */
341 MoveWindow(hSearchBar, LOWORD(lParam) - SearchBarWidth - 4, 5, SearchBarWidth, 22, TRUE);
342
343 /*
344 * HIWORD(lParam) - Height of main window
345 * LOWORD(lParam) - Width of main window
346 */
347
348 /* Size vertical splitter bar */
349 DeferWindowPos(hdwp,
350 hVSplitter,
351 0,
352 (VSplitterPos = GetWindowWidth(hTreeView)),
353 GetWindowHeight(hToolBar),
354 SPLIT_WIDTH,
355 HIWORD(lParam) - GetWindowHeight(hToolBar) - GetWindowHeight(hStatusBar),
356 SWP_NOZORDER|SWP_NOACTIVATE);
357
358 /* Size TreeView */
359 DeferWindowPos(hdwp,
360 hTreeView,
361 0,
362 0,
363 GetWindowHeight(hToolBar),
364 VSplitterPos,
365 HIWORD(lParam) - GetWindowHeight(hToolBar) - GetWindowHeight(hStatusBar),
366 SWP_NOZORDER|SWP_NOACTIVATE);
367
368 while (NewPos < SPLIT_WIDTH + GetWindowHeight(hToolBar))
369 {
370 RichPos--;
371 NewPos = GetClientWindowHeight(hMainWnd) - (RichPos +
372 SPLIT_WIDTH + GetWindowHeight(hStatusBar));
373 }
374 SetHSplitterPos(NewPos);
375
376 /* Size ListView */
377 DeferWindowPos(hdwp,
378 hListView,
379 0,
380 VSplitterPos + SPLIT_WIDTH,
381 GetWindowHeight(hToolBar),
382 LOWORD(lParam) - (VSplitterPos + SPLIT_WIDTH),
383 GetHSplitterPos() - GetWindowHeight(hToolBar),
384 SWP_NOZORDER|SWP_NOACTIVATE);
385
386 /* Size RichEdit */
387 DeferWindowPos(hdwp,
388 hRichEdit,
389 0,
390 VSplitterPos + SPLIT_WIDTH,
391 GetHSplitterPos() + SPLIT_WIDTH,
392 GetClientWindowWidth(hMainWnd) - (VSplitterPos + SPLIT_WIDTH),
393 RichPos,
394 SWP_NOZORDER|SWP_NOACTIVATE);
395
396 /* Size horizontal splitter bar */
397 DeferWindowPos(hdwp,
398 hHSplitter,
399 0,
400 VSplitterPos + SPLIT_WIDTH,
401 GetHSplitterPos(),
402 GetClientWindowWidth(hMainWnd) - (VSplitterPos + SPLIT_WIDTH),
403 SPLIT_WIDTH,
404 SWP_NOZORDER|SWP_NOACTIVATE);
405
406 EndDeferWindowPos(hdwp);
407 }
408
409 LRESULT CALLBACK
410 MainWindowProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
411 {
412 switch (Msg)
413 {
414 case WM_CREATE:
415 if (!InitControls(hwnd))
416 PostMessage(hwnd, WM_CLOSE, 0, 0);
417 break;
418
419 case WM_COMMAND:
420 MainWndOnCommand(hwnd, wParam, lParam);
421 break;
422
423 case WM_NOTIFY:
424 {
425 LPNMHDR data = (LPNMHDR)lParam;
426
427 switch (data->code)
428 {
429 case TVN_SELCHANGED:
430 {
431 if (data->hwndFrom == hTreeView)
432 {
433 switch (((LPNMTREEVIEW)lParam)->itemNew.lParam)
434 {
435 case IDS_INSTALLED:
436 UpdateApplicationsList(ENUM_ALL_COMPONENTS);
437 break;
438
439 case IDS_APPLICATIONS:
440 UpdateApplicationsList(ENUM_APPLICATIONS);
441 break;
442
443 case IDS_UPDATES:
444 UpdateApplicationsList(ENUM_UPDATES);
445 break;
446
447 case IDS_AVAILABLEFORINST:
448 UpdateApplicationsList(ENUM_ALL_AVAILABLE);
449 break;
450
451 case IDS_CAT_AUDIO:
452 UpdateApplicationsList(ENUM_CAT_AUDIO);
453 break;
454
455 case IDS_CAT_DEVEL:
456 UpdateApplicationsList(ENUM_CAT_DEVEL);
457 break;
458
459 case IDS_CAT_DRIVERS:
460 UpdateApplicationsList(ENUM_CAT_DRIVERS);
461 break;
462
463 case IDS_CAT_EDU:
464 UpdateApplicationsList(ENUM_CAT_EDU);
465 break;
466
467 case IDS_CAT_ENGINEER:
468 UpdateApplicationsList(ENUM_CAT_ENGINEER);
469 break;
470
471 case IDS_CAT_FINANCE:
472 UpdateApplicationsList(ENUM_CAT_FINANCE);
473 break;
474
475 case IDS_CAT_GAMES:
476 UpdateApplicationsList(ENUM_CAT_GAMES);
477 break;
478
479 case IDS_CAT_GRAPHICS:
480 UpdateApplicationsList(ENUM_CAT_GRAPHICS);
481 break;
482
483 case IDS_CAT_INTERNET:
484 UpdateApplicationsList(ENUM_CAT_INTERNET);
485 break;
486
487 case IDS_CAT_LIBS:
488 UpdateApplicationsList(ENUM_CAT_LIBS);
489 break;
490
491 case IDS_CAT_OFFICE:
492 UpdateApplicationsList(ENUM_CAT_OFFICE);
493 break;
494
495 case IDS_CAT_OTHER:
496 UpdateApplicationsList(ENUM_CAT_OTHER);
497 break;
498
499 case IDS_CAT_SCIENCE:
500 UpdateApplicationsList(ENUM_CAT_SCIENCE);
501 break;
502
503 case IDS_CAT_TOOLS:
504 UpdateApplicationsList(ENUM_CAT_TOOLS);
505 break;
506
507 case IDS_CAT_VIDEO:
508 UpdateApplicationsList(ENUM_CAT_VIDEO);
509 break;
510 }
511 }
512 }
513 break;
514
515 case LVN_KEYDOWN:
516 {
517 LPNMLVKEYDOWN pnkd = (LPNMLVKEYDOWN) lParam;
518
519 if (pnkd->hdr.hwndFrom == hListView)
520 {
521 INT ItemIndex = (INT) SendMessage(hListView, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
522
523 if (pnkd->wVKey == VK_UP) ItemIndex -= 1;
524 if (pnkd->wVKey == VK_DOWN) ItemIndex += 1;
525
526 if (IS_INSTALLED_ENUM(SelectedEnumType))
527 ShowInstalledAppInfo(ItemIndex);
528 if (IS_AVAILABLE_ENUM(SelectedEnumType))
529 ShowAvailableAppInfo(ItemIndex);
530 }
531 }
532 break;
533
534 case LVN_COLUMNCLICK:
535 {
536 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
537
538 (VOID) ListView_SortItems(hListView, ListViewCompareFunc, pnmv->iSubItem);
539 bAscending = !bAscending;
540 }
541 break;
542
543 case NM_CLICK:
544 if (data->hwndFrom == hListView)
545 {
546 if (IS_INSTALLED_ENUM(SelectedEnumType))
547 ShowInstalledAppInfo(-1);
548 if (IS_AVAILABLE_ENUM(SelectedEnumType))
549 ShowAvailableAppInfo(-1);
550 }
551 break;
552
553 case NM_RCLICK:
554 if (data->hwndFrom == hListView)
555 ShowPopupMenu(hListView, IDR_APPLICATIONMENU);
556 break;
557
558 case EN_LINK:
559 RichEditOnLink(hwnd, (ENLINK*)lParam);
560 break;
561
562 case TTN_GETDISPINFO:
563 ToolBarOnGetDispInfo((LPTOOLTIPTEXT)lParam);
564 break;
565 }
566 }
567 break;
568
569 case WM_PAINT:
570 break;
571
572 case WM_SIZE:
573 {
574 if ((GetClientWindowHeight(hMainWnd) - GetWindowHeight(hStatusBar) - SPLIT_WIDTH) < GetHSplitterPos())
575 {
576 INT NewSplitPos = GetClientWindowHeight(hwnd) - 100 - GetWindowHeight(hStatusBar) - SPLIT_WIDTH;
577 if (NewSplitPos > GetWindowHeight(hToolBar) + SPLIT_WIDTH)
578 SetHSplitterPos(NewSplitPos);
579 }
580
581 MainWndOnSize(hwnd, wParam, lParam);
582 }
583 break;
584
585 case WM_SIZING:
586 {
587 int RichEditHeight = GetWindowHeight(hRichEdit);
588 LPRECT pRect = (LPRECT)lParam;
589
590 while (RichEditHeight <= 100)
591 {
592 if (GetHSplitterPos() - 1 < GetWindowHeight(hToolBar) + GetWindowHeight(hListView) + SPLIT_WIDTH)
593 break;
594 SetHSplitterPos(GetHSplitterPos() - 1);
595 RichEditHeight++;
596 }
597
598 if (pRect->right-pRect->left < 565)
599 pRect->right = pRect->left + 565;
600
601 if (pRect->bottom-pRect->top < 300)
602 pRect->bottom = pRect->top + 300;
603 return TRUE;
604 }
605
606 case WM_DESTROY:
607 {
608 if (IS_AVAILABLE_ENUM(SelectedEnumType))
609 FreeAvailableAppList();
610 if (hImageListView) ImageList_Destroy(hImageListView);
611 if (hImageTreeView) ImageList_Destroy(hImageTreeView);
612 PostQuitMessage(0);
613 return 0;
614 }
615 break;
616 }
617
618 return DefWindowProc(hwnd, Msg, wParam, lParam);
619 }
620
621 int WINAPI
622 wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
623 {
624 WNDCLASSEXW WndClass = {0};
625 WCHAR szWindowClass[] = L"ROSAPPMGR";
626 WCHAR szWindowName[MAX_STR_LEN];
627 HANDLE hMutex = NULL;
628 MSG Msg;
629
630 hMutex = CreateMutexW(NULL, FALSE, szWindowClass);
631 if ((!hMutex) || (GetLastError() == ERROR_ALREADY_EXISTS))
632 {
633 /* If already started, it is found its window */
634 HWND hWindow = FindWindowW(szWindowClass, NULL);
635
636 /* Activate window */
637 ShowWindow(hWindow, SW_SHOWNORMAL);
638 SetForegroundWindow(hWindow);
639 return 1;
640 }
641
642 hInst = hInstance;
643
644 InitCommonControls();
645
646 /* Create the window */
647 WndClass.cbSize = sizeof(WNDCLASSEXW);
648 WndClass.lpszClassName = szWindowClass;
649 WndClass.lpfnWndProc = MainWindowProc;
650 WndClass.hInstance = hInstance;
651 WndClass.style = CS_HREDRAW | CS_VREDRAW;
652 WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN));
653 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
654 WndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
655 WndClass.lpszMenuName = MAKEINTRESOURCEW(IDR_MAINMENU);
656
657 if (RegisterClassExW(&WndClass) == (ATOM)0) goto Exit;
658
659 LoadStringW(hInst, IDS_APPTITLE, szWindowName, sizeof(szWindowName) / sizeof(WCHAR));
660
661 hMainWnd = CreateWindowExW(WS_EX_WINDOWEDGE,
662 szWindowClass,
663 szWindowName,
664 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
665 CW_USEDEFAULT,
666 CW_USEDEFAULT,
667 680,
668 450,
669 NULL,
670 NULL,
671 hInstance,
672 NULL);
673
674 if (!hMainWnd) goto Exit;
675
676 /* Show it */
677 ShowWindow(hMainWnd, SW_SHOW);
678 UpdateWindow(hMainWnd);
679
680 /* Message Loop */
681 while (GetMessage(&Msg, NULL, 0, 0))
682 {
683 TranslateMessage(&Msg);
684 DispatchMessage(&Msg);
685 }
686
687 Exit:
688 if (hMutex) CloseHandle(hMutex);
689
690 return 0;
691 }