[ROSAPPS][VGAFONTEDIT] String/Memory check
[reactos.git] / modules / rosapps / applications / devutils / vgafontedit / mainwnd.c
1 /*
2 * PROJECT: ReactOS VGA Font Editor
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Implements the main window of the application
5 * COPYRIGHT: Copyright 2008 Colin Finck (colin@reactos.org)
6 * Copyright 2018 Katayama Hirofui MZ (katayama.hirofumi.mz@gmail.com)
7 */
8
9 #include "precomp.h"
10
11 static const WCHAR szMainWndClass[] = L"VGAFontEditMainWndClass";
12
13 static VOID
14 InitResources(IN PMAIN_WND_INFO Info)
15 {
16 HDC hMemDC;
17 HDC hMainDC;
18 HPEN hPen, hPenOld;
19 RECT rect;
20 HBITMAP hBitmapOld;
21
22 hMemDC = CreateCompatibleDC(NULL);
23 hMainDC = GetDC(Info->hMainWnd);
24
25 // Create the "Box" bitmap
26 Info->hBoxBmp = CreateCompatibleBitmap(hMainDC, CHARACTER_BOX_WIDTH, CHARACTER_BOX_HEIGHT);
27 hBitmapOld = SelectObject(hMemDC, Info->hBoxBmp);
28
29 rect.left = 0;
30 rect.top = 0;
31 rect.right = CHARACTER_INFO_BOX_WIDTH;
32 rect.bottom = CHARACTER_INFO_BOX_HEIGHT;
33 FillRect( hMemDC, &rect, (HBRUSH)(COLOR_BTNFACE + 1) );
34
35 hPenOld = SelectObject( hMemDC, GetStockObject(WHITE_PEN) );
36 Rectangle(hMemDC, 0, 0, CHARACTER_INFO_BOX_WIDTH - 1, 2);
37 Rectangle(hMemDC, 0, 2, 2, CHARACTER_INFO_BOX_HEIGHT - 1);
38 hPen = SelectObject(hMemDC, hPenOld);
39
40 hPen = CreatePen( PS_SOLID, 1, RGB(128, 128, 128) );
41 hPenOld = SelectObject(hMemDC, hPen);
42 Rectangle(hMemDC, 1, CHARACTER_INFO_BOX_HEIGHT - 2, CHARACTER_INFO_BOX_WIDTH, CHARACTER_INFO_BOX_HEIGHT);
43 Rectangle(hMemDC, CHARACTER_INFO_BOX_WIDTH - 2, 1, CHARACTER_INFO_BOX_WIDTH, CHARACTER_INFO_BOX_HEIGHT - 2);
44
45 SetPixel( hMemDC, CHARACTER_INFO_BOX_WIDTH - 1, 0, RGB(128, 128, 128) );
46 SetPixel( hMemDC, 0, CHARACTER_INFO_BOX_HEIGHT - 1, RGB(128, 128, 128) );
47 SelectObject(hMemDC, hBitmapOld);
48
49 hPen = SelectObject(hMemDC, hPenOld);
50 DeleteObject(hPen);
51 DeleteDC(hMemDC);
52 ReleaseDC(Info->hMainWnd, hMainDC);
53 }
54
55 static VOID
56 UnInitResources(IN PMAIN_WND_INFO Info)
57 {
58 DeleteObject(Info->hBoxBmp);
59 }
60
61 static VOID
62 AddToolbarButton(IN PMAIN_WND_INFO Info, IN INT iBitmap, IN INT idCommand, IN UINT uID)
63 {
64 PWSTR pszTooltip;
65 TBBUTTON tbb = {0,};
66
67 if( AllocAndLoadString(&pszTooltip, uID) )
68 {
69 tbb.fsState = TBSTATE_ENABLED;
70 tbb.iBitmap = iBitmap;
71 tbb.idCommand = idCommand;
72 tbb.iString = (INT_PTR)pszTooltip;
73
74 SendMessageW( Info->hToolbar, TB_ADDBUTTONSW, 1, (LPARAM)&tbb );
75 HeapFree(hProcessHeap, 0, pszTooltip);
76 }
77 }
78
79 static VOID
80 SetToolbarButtonState(IN PMAIN_WND_INFO Info, INT idCommand, BOOL bEnabled)
81 {
82 TBBUTTONINFOW tbbi = {0,};
83
84 tbbi.cbSize = sizeof(tbbi);
85 tbbi.dwMask = TBIF_STATE;
86 tbbi.fsState = (bEnabled ? TBSTATE_ENABLED : 0);
87
88 SendMessageW(Info->hToolbar, TB_SETBUTTONINFOW, idCommand, (LPARAM)&tbbi);
89 }
90
91 VOID
92 SetToolbarFileButtonState(IN PMAIN_WND_INFO Info, BOOL bEnabled)
93 {
94 SetToolbarButtonState(Info, ID_FILE_SAVE, bEnabled);
95 SetToolbarButtonState(Info, ID_EDIT_GLYPH, bEnabled);
96 SetToolbarButtonState(Info, ID_EDIT_COPY, bEnabled);
97 }
98
99 static VOID
100 AddToolbarSeparator(IN PMAIN_WND_INFO Info)
101 {
102 TBBUTTON tbb = {0,};
103
104 tbb.fsStyle = BTNS_SEP;
105
106 SendMessageW( Info->hToolbar, TB_ADDBUTTONSW, 1, (LPARAM)&tbb );
107 }
108
109 static VOID
110 InitMainWnd(IN PMAIN_WND_INFO Info)
111 {
112 CLIENTCREATESTRUCT ccs;
113 INT iCustomBitmaps;
114 INT iStandardBitmaps;
115 TBADDBITMAP tbab;
116
117 // Add the toolbar
118 Info->hToolbar = CreateWindowExW(0,
119 TOOLBARCLASSNAMEW,
120 NULL,
121 WS_VISIBLE | WS_CHILD | TBSTYLE_TOOLTIPS,
122 0,
123 0,
124 0,
125 0,
126 Info->hMainWnd,
127 NULL,
128 hInstance,
129 NULL);
130
131 // Identify the used Common Controls version
132 SendMessageW(Info->hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
133
134 // Enable Tooltips
135 SendMessageW(Info->hToolbar, TB_SETMAXTEXTROWS, 0, 0);
136
137 // Add the toolbar bitmaps
138 tbab.hInst = HINST_COMMCTRL;
139 tbab.nID = IDB_STD_SMALL_COLOR;
140 iStandardBitmaps = (INT)SendMessageW(Info->hToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab);
141
142 tbab.hInst = hInstance;
143 tbab.nID = IDB_MAIN_TOOLBAR;
144 iCustomBitmaps = (INT)SendMessageW(Info->hToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab);
145
146 // Add the toolbar buttons
147 AddToolbarButton(Info, iStandardBitmaps + STD_FILENEW, ID_FILE_NEW, IDS_TOOLTIP_NEW);
148 AddToolbarButton(Info, iStandardBitmaps + STD_FILEOPEN, ID_FILE_OPEN, IDS_TOOLTIP_OPEN);
149 AddToolbarButton(Info, iStandardBitmaps + STD_FILESAVE, ID_FILE_SAVE, IDS_TOOLTIP_SAVE);
150 AddToolbarSeparator(Info);
151 AddToolbarButton(Info, iCustomBitmaps + TOOLBAR_EDIT_GLYPH, ID_EDIT_GLYPH, IDS_TOOLTIP_EDIT_GLYPH);
152 AddToolbarSeparator(Info);
153 AddToolbarButton(Info, iStandardBitmaps + STD_COPY, ID_EDIT_COPY, IDS_TOOLTIP_COPY);
154 AddToolbarButton(Info, iStandardBitmaps + STD_PASTE, ID_EDIT_PASTE, IDS_TOOLTIP_PASTE);
155
156 SetToolbarFileButtonState(Info, FALSE);
157 SetPasteButtonState(Info);
158
159 // Add the MDI client area
160 ccs.hWindowMenu = GetSubMenu(Info->hMenu, 2);
161 ccs.idFirstChild = ID_MDI_FIRSTCHILD;
162
163 Info->hMdiClient = CreateWindowExW(WS_EX_CLIENTEDGE,
164 L"MDICLIENT",
165 NULL,
166 WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL,
167 0,
168 0,
169 0,
170 0,
171 Info->hMainWnd,
172 NULL,
173 hInstance,
174 &ccs);
175
176 // Initialize the file handling
177 FileInitialize(Info->hMainWnd);
178 }
179
180 static VOID
181 InitMenuPopup(IN PMAIN_WND_INFO Info)
182 {
183 UINT uState;
184
185 uState = MF_BYCOMMAND | !(Info->CurrentFontWnd);
186
187 EnableMenuItem(Info->hMenu, ID_FILE_CLOSE, uState);
188 EnableMenuItem(Info->hMenu, ID_FILE_SAVE, uState);
189 EnableMenuItem(Info->hMenu, ID_FILE_SAVE_AS, uState);
190
191 EnableMenuItem(Info->hMenu, ID_EDIT_COPY, uState);
192 EnableMenuItem(Info->hMenu, ID_EDIT_GLYPH, uState);
193
194 uState = MF_BYCOMMAND | !(Info->CurrentFontWnd && IsClipboardFormatAvailable(uCharacterClipboardFormat));
195 EnableMenuItem(Info->hMenu, ID_EDIT_PASTE, uState);
196 }
197
198 static VOID
199 DoFileNew(IN PMAIN_WND_INFO Info)
200 {
201 PFONT_OPEN_INFO OpenInfo;
202
203 OpenInfo = (PFONT_OPEN_INFO) HeapAlloc( hProcessHeap, HEAP_ZERO_MEMORY, sizeof(FONT_OPEN_INFO) );
204 OpenInfo->bCreateNew = TRUE;
205
206 CreateFontWindow(Info, OpenInfo);
207 }
208
209 static VOID
210 DoFileOpen(IN PMAIN_WND_INFO Info)
211 {
212 PFONT_OPEN_INFO OpenInfo;
213
214 OpenInfo = (PFONT_OPEN_INFO) HeapAlloc( hProcessHeap, HEAP_ZERO_MEMORY, sizeof(FONT_OPEN_INFO) );
215 OpenInfo->pszFileName = HeapAlloc(hProcessHeap, 0, MAX_PATH);
216 if (OpenInfo->pszFileName)
217 {
218 OpenInfo->pszFileName[0] = 0;
219
220 if (DoOpenFile(OpenInfo->pszFileName))
221 {
222 OpenInfo->bCreateNew = FALSE;
223 CreateFontWindow(Info, OpenInfo);
224 }
225 }
226 else
227 {
228 MessageBoxW(Info->hMainWnd, L"Out of memory!", NULL, MB_ICONERROR);
229 }
230 }
231
232 static VOID
233 MainWndOpenFile(IN PMAIN_WND_INFO Info, LPCWSTR File)
234 {
235 PFONT_OPEN_INFO OpenInfo;
236
237 OpenInfo = HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, sizeof(FONT_OPEN_INFO));
238 OpenInfo->pszFileName = HeapAlloc(hProcessHeap, 0, MAX_PATH);
239 if (OpenInfo->pszFileName)
240 {
241 if (StringCchCopyW(OpenInfo->pszFileName, MAX_PATH, File) == S_OK)
242 {
243 OpenInfo->bCreateNew = FALSE;
244 CreateFontWindow(Info, OpenInfo);
245 }
246 else
247 {
248 MessageBoxW(Info->hMainWnd, L"Pathname is too long!", NULL, MB_ICONERROR);
249 }
250 }
251 else
252 {
253 MessageBoxW(Info->hMainWnd, L"Out of memory!", NULL, MB_ICONERROR);
254 }
255 }
256
257 static VOID
258 MainWndDropFiles(IN PMAIN_WND_INFO Info, HDROP hDrop)
259 {
260 WCHAR Path[MAX_PATH];
261 INT i, Count = DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0);
262
263 for (i = 0; i < Count; ++i)
264 {
265 DragQueryFileW(hDrop, i, Path, MAX_PATH);
266 MainWndOpenFile(Info, Path);
267 }
268
269 DragFinish(hDrop);
270 }
271
272 VOID
273 DoFileSave(IN PMAIN_WND_INFO Info, IN BOOL bSaveAs)
274 {
275 DWORD dwBytesWritten;
276 HANDLE hFile;
277
278 // Show the "Save" dialog
279 // - if "Save As" was clicked
280 // - if the file was not yet saved
281 // - if another format than the binary format was opened
282 if(bSaveAs || !Info->CurrentFontWnd->OpenInfo->bBinaryFileOpened)
283 {
284 if(!Info->CurrentFontWnd->OpenInfo->pszFileName)
285 {
286 Info->CurrentFontWnd->OpenInfo->pszFileName = (PWSTR) HeapAlloc(hProcessHeap, 0, MAX_PATH);
287 Info->CurrentFontWnd->OpenInfo->pszFileName[0] = 0;
288 }
289 else if(!Info->CurrentFontWnd->OpenInfo->bBinaryFileOpened)
290 {
291 // For a file in another format, the user has to enter a new file name as well
292 Info->CurrentFontWnd->OpenInfo->pszFileName[0] = 0;
293 }
294
295 if( !DoSaveFile(Info->CurrentFontWnd->OpenInfo->pszFileName) )
296 return;
297 }
298
299 // Save the binary font
300 hFile = CreateFileW(Info->CurrentFontWnd->OpenInfo->pszFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
301
302 if(hFile == INVALID_HANDLE_VALUE)
303 {
304 LocalizedError( IDS_OPENERROR, GetLastError() );
305 return;
306 }
307
308 if( !WriteFile(hFile, Info->CurrentFontWnd->Font, sizeof(BITMAP_FONT), &dwBytesWritten, NULL) )
309 LocalizedError( IDS_WRITEERROR, GetLastError() );
310
311 CloseHandle(hFile);
312 }
313
314 static VOID
315 CopyCurrentGlyph(IN PFONT_WND_INFO FontWndInfo)
316 {
317 HGLOBAL hMem;
318 PUCHAR pCharacterBits;
319
320 if(!OpenClipboard(NULL))
321 return;
322
323 EmptyClipboard();
324
325 hMem = GlobalAlloc(GMEM_MOVEABLE, 8);
326 pCharacterBits = GlobalLock(hMem);
327 RtlCopyMemory(pCharacterBits, FontWndInfo->Font->Bits + FontWndInfo->uSelectedCharacter * 8, 8);
328 GlobalUnlock(hMem);
329
330 SetClipboardData(uCharacterClipboardFormat, hMem);
331
332 CloseClipboard();
333 }
334
335 static VOID
336 PasteIntoCurrentGlyph(IN PFONT_WND_INFO FontWndInfo)
337 {
338 HGLOBAL hMem;
339
340 if(!IsClipboardFormatAvailable(uCharacterClipboardFormat))
341 return;
342
343 if(!OpenClipboard(NULL))
344 return;
345
346 hMem = GetClipboardData(uCharacterClipboardFormat);
347 if(hMem)
348 {
349 PUCHAR pCharacterBits;
350
351 pCharacterBits = GlobalLock(hMem);
352 if(pCharacterBits)
353 {
354 RECT CharacterRect;
355 UINT uFontRow;
356 UINT uFontColumn;
357
358 RtlCopyMemory(FontWndInfo->Font->Bits + FontWndInfo->uSelectedCharacter * 8, pCharacterBits, 8);
359 GlobalUnlock(hMem);
360
361 FontWndInfo->OpenInfo->bModified = TRUE;
362
363 GetCharacterPosition(FontWndInfo->uSelectedCharacter, &uFontRow, &uFontColumn);
364 GetCharacterRect(uFontRow, uFontColumn, &CharacterRect);
365 InvalidateRect(FontWndInfo->hFontBoxesWnd, &CharacterRect, FALSE);
366 }
367 }
368
369 CloseClipboard();
370 }
371
372 VOID
373 SetPasteButtonState(IN PMAIN_WND_INFO Info)
374 {
375 SetToolbarButtonState(Info,
376 ID_EDIT_PASTE,
377 (Info->CurrentFontWnd && IsClipboardFormatAvailable(uCharacterClipboardFormat)));
378 }
379
380 static BOOL
381 MenuCommand(IN INT nMenuItemID, IN PMAIN_WND_INFO Info)
382 {
383 switch(nMenuItemID)
384 {
385 // File Menu
386 case ID_FILE_NEW:
387 DoFileNew(Info);
388 return TRUE;
389
390 case ID_FILE_OPEN:
391 DoFileOpen(Info);
392 return TRUE;
393
394 case ID_FILE_CLOSE:
395 SendMessageW(Info->CurrentFontWnd->hSelf, WM_CLOSE, 0, 0);
396 return TRUE;
397
398 case ID_FILE_SAVE:
399 DoFileSave(Info, FALSE);
400 return TRUE;
401
402 case ID_FILE_SAVE_AS:
403 DoFileSave(Info, TRUE);
404 return TRUE;
405
406 case ID_FILE_EXIT:
407 PostMessage(Info->hMainWnd, WM_CLOSE, 0, 0);
408 return TRUE;
409
410 // Edit Menu
411 case ID_EDIT_GLYPH:
412 EditCurrentGlyph(Info->CurrentFontWnd);
413 return TRUE;
414
415 case ID_EDIT_COPY:
416 CopyCurrentGlyph(Info->CurrentFontWnd);
417 return TRUE;
418
419 case ID_EDIT_PASTE:
420 PasteIntoCurrentGlyph(Info->CurrentFontWnd);
421 return TRUE;
422
423 // Window Menu
424 case ID_WINDOW_TILE_HORZ:
425 SendMessageW(Info->hMdiClient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
426 return TRUE;
427
428 case ID_WINDOW_TILE_VERT:
429 SendMessageW(Info->hMdiClient, WM_MDITILE, MDITILE_VERTICAL, 0);
430 return TRUE;
431
432 case ID_WINDOW_CASCADE:
433 SendMessageW(Info->hMdiClient, WM_MDICASCADE, 0, 0);
434 return TRUE;
435
436 case ID_WINDOW_ARRANGE:
437 SendMessageW(Info->hMdiClient, WM_MDIICONARRANGE, 0, 0);
438 return TRUE;
439
440 case ID_WINDOW_NEXT:
441 SendMessageW(Info->hMdiClient, WM_MDINEXT, 0, 0);
442 return TRUE;
443
444 // Help Menu
445 case ID_HELP_ABOUT:
446 DialogBoxW( hInstance, MAKEINTRESOURCEW(IDD_ABOUT), Info->hMainWnd, AboutDlgProc );
447 return TRUE;
448 }
449
450 return FALSE;
451 }
452
453 static VOID
454 MainWndSize(PMAIN_WND_INFO Info, INT cx, INT cy)
455 {
456 HDWP dwp;
457 INT iMdiTop;
458 RECT ToolbarRect;
459
460 iMdiTop = 0;
461
462 dwp = BeginDeferWindowPos(2);
463 if(!dwp)
464 return;
465
466 if(Info->hToolbar)
467 {
468 GetWindowRect(Info->hToolbar, &ToolbarRect);
469 iMdiTop += ToolbarRect.bottom - ToolbarRect.top;
470
471 dwp = DeferWindowPos(dwp, Info->hToolbar, NULL, 0, 0, cx, ToolbarRect.bottom - ToolbarRect.top, SWP_NOZORDER);
472 if(!dwp)
473 return;
474 }
475
476 if(Info->hMdiClient)
477 {
478 dwp = DeferWindowPos(dwp, Info->hMdiClient, NULL, 0, iMdiTop, cx, cy - iMdiTop, SWP_NOZORDER);
479 if(!dwp)
480 return;
481 }
482
483 EndDeferWindowPos(dwp);
484 }
485
486 static LRESULT CALLBACK
487 MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
488 {
489 static HWND hNextClipboardViewer;
490 INT i;
491 PMAIN_WND_INFO Info;
492
493 Info = (PMAIN_WND_INFO) GetWindowLongPtrW(hwnd, GWLP_USERDATA);
494
495 if(Info || uMsg == WM_CREATE)
496 {
497 switch(uMsg)
498 {
499 case WM_COMMAND:
500 if( MenuCommand( LOWORD(wParam), Info ) )
501 return 0;
502
503 break;
504
505 case WM_CHANGECBCHAIN:
506 if((HWND)wParam == hNextClipboardViewer)
507 hNextClipboardViewer = (HWND)lParam;
508 else
509 SendMessage(hNextClipboardViewer, uMsg, wParam, lParam);
510
511 return 0;
512
513 case WM_CLOSE:
514 if(Info->FirstFontWnd)
515 {
516 // Send WM_CLOSE to all subwindows, so they can prompt for saving unsaved files
517 PFONT_WND_INFO pNextWnd;
518 PFONT_WND_INFO pWnd;
519
520 pWnd = Info->FirstFontWnd;
521
522 do
523 {
524 // The pWnd structure might already be destroyed after the WM_CLOSE, so we have to preserve the address of the next window here
525 pNextWnd = pWnd->NextFontWnd;
526
527 // Send WM_USER_APPCLOSE, so we can check for a custom return value
528 // In this case, we check if the user clicked the "Cancel" button in one of the prompts and if so, we don't close the app
529 if( !SendMessage(pWnd->hSelf, WM_USER_APPCLOSE, 0, 0) )
530 return 0;
531 }
532 while( (pWnd = pNextWnd) );
533 }
534 break;
535
536 case WM_CREATE:
537 Info = (PMAIN_WND_INFO)( ( (LPCREATESTRUCT)lParam )->lpCreateParams );
538 Info->hMainWnd = hwnd;
539 Info->hMenu = GetMenu(hwnd);
540 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)Info);
541
542 hNextClipboardViewer = SetClipboardViewer(hwnd);
543
544 InitMainWnd(Info);
545 InitResources(Info);
546
547 ShowWindow(hwnd, Info->nCmdShow);
548
549 for (i = 1; i < __argc; ++i)
550 {
551 MainWndOpenFile(Info, __wargv[i]);
552 }
553 DragAcceptFiles(hwnd, TRUE);
554 return 0;
555
556 case WM_DESTROY:
557 UnInitResources(Info);
558
559 HeapFree(hProcessHeap, 0, Info);
560 SetWindowLongPtrW(hwnd, GWLP_USERDATA, 0);
561 PostQuitMessage(0);
562 return 0;
563
564 case WM_DRAWCLIPBOARD:
565 SetPasteButtonState(Info);
566
567 // Pass the message to the next clipboard window in the chain
568 SendMessage(hNextClipboardViewer, uMsg, wParam, lParam);
569 return 0;
570
571 case WM_INITMENUPOPUP:
572 InitMenuPopup(Info);
573 break;
574
575 case WM_SIZE:
576 MainWndSize( Info, LOWORD(lParam), HIWORD(lParam) );
577 return 0;
578
579 case WM_DROPFILES:
580 MainWndDropFiles(Info, (HDROP)wParam);
581 return 0;
582 }
583 }
584
585 if(Info && Info->hMdiClient)
586 return DefFrameProcW(hwnd, Info->hMdiClient, uMsg, wParam, lParam);
587 else
588 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
589 }
590
591 BOOL
592 CreateMainWindow(IN INT nCmdShow, OUT PMAIN_WND_INFO* Info)
593 {
594 HWND hMainWnd;
595
596 *Info = (PMAIN_WND_INFO) HeapAlloc( hProcessHeap, HEAP_ZERO_MEMORY, sizeof(MAIN_WND_INFO) );
597
598 if(*Info)
599 {
600 (*Info)->nCmdShow = nCmdShow;
601
602 hMainWnd = CreateWindowExW(0,
603 szMainWndClass,
604 szAppName,
605 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
606 CW_USEDEFAULT,
607 CW_USEDEFAULT,
608 CW_USEDEFAULT,
609 CW_USEDEFAULT,
610 NULL,
611 LoadMenuW(hInstance, MAKEINTRESOURCEW(IDM_MAINMENU)),
612 hInstance,
613 *Info);
614
615 if(hMainWnd)
616 return TRUE;
617 else
618 HeapFree(hProcessHeap, 0, *Info);
619 }
620
621 return FALSE;
622 }
623
624 BOOL
625 InitMainWndClass(VOID)
626 {
627 WNDCLASSW wc = {0,};
628
629 wc.lpfnWndProc = MainWndProc;
630 wc.hInstance = hInstance;
631 wc.hCursor = LoadCursor( NULL, IDC_ARROW );
632 wc.hIcon = LoadIconW( hInstance, MAKEINTRESOURCEW(IDI_MAIN) );
633 wc.hbrBackground = (HBRUSH)( COLOR_BTNFACE + 1 );
634 wc.lpszClassName = szMainWndClass;
635
636 return RegisterClassW(&wc) != 0;
637 }
638
639 VOID
640 UnInitMainWndClass(VOID)
641 {
642 UnregisterClassW(szMainWndClass, hInstance);
643 }