Lars Martin Hambro <lars_martin4 AT hotmail DOT com>
[reactos.git] / reactos / base / applications / notepad / main.c
1 /*
2 * Notepad
3 *
4 * Copyright 2000 Mike McCormack <Mike_McCormack@looksmart.com.au>
5 * Copyright 1997,98 Marcel Baur <mbaur@g26.ethz.ch>
6 * Copyright 2002 Sylvain Petreolle <spetreolle@yahoo.fr>
7 * Copyright 2002 Andriy Palamarchuk
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
25 #include <notepad.h>
26
27 NOTEPAD_GLOBALS Globals;
28 static ATOM aFINDMSGSTRING;
29
30 VOID NOTEPAD_EnableSearchMenu()
31 {
32 EnableMenuItem(GetMenu(Globals.hMainWnd), CMD_SEARCH,
33 MF_BYCOMMAND | ((GetWindowTextLength(Globals.hEdit) == 0) ? MF_DISABLED | MF_GRAYED : MF_ENABLED));
34 EnableMenuItem(GetMenu(Globals.hMainWnd), CMD_SEARCH_NEXT,
35 MF_BYCOMMAND | ((GetWindowTextLength(Globals.hEdit) == 0) ? MF_DISABLED | MF_GRAYED : MF_ENABLED));
36 }
37
38 /***********************************************************************
39 *
40 * SetFileName
41 *
42 * Sets Global File Name.
43 */
44 VOID SetFileName(LPCTSTR szFileName)
45 {
46 _tcscpy(Globals.szFileName, szFileName);
47 Globals.szFileTitle[0] = 0;
48 GetFileTitle(szFileName, Globals.szFileTitle, SIZEOF(Globals.szFileTitle));
49 }
50
51 /***********************************************************************
52 *
53 * NOTEPAD_MenuCommand
54 *
55 * All handling of main menu events
56 */
57 static int NOTEPAD_MenuCommand(WPARAM wParam)
58 {
59 switch (wParam)
60 {
61 case CMD_NEW: DIALOG_FileNew(); break;
62 case CMD_OPEN: DIALOG_FileOpen(); break;
63 case CMD_SAVE: DIALOG_FileSave(); break;
64 case CMD_SAVE_AS: DIALOG_FileSaveAs(); break;
65 case CMD_PRINT: DIALOG_FilePrint(); break;
66 case CMD_PAGE_SETUP: DIALOG_FilePageSetup(); break;
67 case CMD_PRINTER_SETUP: DIALOG_FilePrinterSetup();break;
68 case CMD_EXIT: DIALOG_FileExit(); break;
69
70 case CMD_UNDO: DIALOG_EditUndo(); break;
71 case CMD_CUT: DIALOG_EditCut(); break;
72 case CMD_COPY: DIALOG_EditCopy(); break;
73 case CMD_PASTE: DIALOG_EditPaste(); break;
74 case CMD_DELETE: DIALOG_EditDelete(); break;
75 case CMD_SELECT_ALL: DIALOG_EditSelectAll(); break;
76 case CMD_TIME_DATE: DIALOG_EditTimeDate();break;
77
78 case CMD_SEARCH: DIALOG_Search(); break;
79 case CMD_SEARCH_NEXT: DIALOG_SearchNext(); break;
80 case CMD_REPLACE: DIALOG_Replace(); break;
81 case CMD_GOTO: DIALOG_GoTo(); break;
82
83 case CMD_WRAP: DIALOG_EditWrap(); break;
84 case CMD_FONT: DIALOG_SelectFont(); break;
85
86 case CMD_STATUSBAR: DIALOG_ViewStatusBar(); break;
87
88 case CMD_HELP_CONTENTS: DIALOG_HelpContents(); break;
89 case CMD_HELP_SEARCH: DIALOG_HelpSearch(); break;
90 case CMD_HELP_ON_HELP: DIALOG_HelpHelp(); break;
91 case CMD_ABOUT: DialogBox(GetModuleHandle(NULL),
92 MAKEINTRESOURCE(IDD_ABOUTBOX),
93 Globals.hMainWnd,
94 (DLGPROC) AboutDialogProc);
95 break;
96 case CMD_ABOUT_WINE: DIALOG_HelpAboutWine(); break;
97
98 default:
99 break;
100 }
101 return 0;
102 }
103
104 /***********************************************************************
105 *
106 * NOTEPAD_FindTextAt
107 */
108
109 static BOOL NOTEPAD_FindTextAt(FINDREPLACE *pFindReplace, LPCTSTR pszText, int iTextLength, DWORD dwPosition)
110 {
111 BOOL bMatches;
112 size_t iTargetLength;
113
114 iTargetLength = _tcslen(pFindReplace->lpstrFindWhat);
115
116 /* Make proper comparison */
117 if (pFindReplace->Flags & FR_MATCHCASE)
118 bMatches = !_tcsncmp(&pszText[dwPosition], pFindReplace->lpstrFindWhat, iTargetLength);
119 else
120 bMatches = !_tcsnicmp(&pszText[dwPosition], pFindReplace->lpstrFindWhat, iTargetLength);
121
122 if (bMatches && pFindReplace->Flags & FR_WHOLEWORD)
123 {
124 if ((dwPosition > 0) && !_istspace(pszText[dwPosition-1]))
125 bMatches = FALSE;
126 if ((dwPosition < (DWORD) iTextLength - 1) && !_istspace(pszText[dwPosition+1]))
127 bMatches = FALSE;
128 }
129
130 return bMatches;
131 }
132
133 /***********************************************************************
134 *
135 * NOTEPAD_FindNext
136 */
137
138 BOOL NOTEPAD_FindNext(FINDREPLACE *pFindReplace, BOOL bReplace, BOOL bShowAlert)
139 {
140 int iTextLength, iTargetLength;
141 size_t iAdjustment = 0;
142 LPTSTR pszText = NULL;
143 DWORD dwPosition, dwBegin, dwEnd;
144 BOOL bMatches = FALSE;
145 TCHAR szResource[128], szText[128];
146 BOOL bSuccess;
147
148 iTargetLength = (int) _tcslen(pFindReplace->lpstrFindWhat);
149
150 /* Retrieve the window text */
151 iTextLength = GetWindowTextLength(Globals.hEdit);
152 if (iTextLength > 0)
153 {
154 pszText = (LPTSTR) HeapAlloc(GetProcessHeap(), 0, (iTextLength + 1) * sizeof(TCHAR));
155 if (!pszText)
156 return FALSE;
157
158 GetWindowText(Globals.hEdit, pszText, iTextLength + 1);
159 }
160
161 SendMessage(Globals.hEdit, EM_GETSEL, (WPARAM) &dwBegin, (LPARAM) &dwEnd);
162 if (bReplace && ((dwEnd - dwBegin) == (DWORD) iTargetLength))
163 {
164 if (NOTEPAD_FindTextAt(pFindReplace, pszText, iTextLength, dwBegin))
165 {
166 SendMessage(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM) pFindReplace->lpstrReplaceWith);
167 iAdjustment = _tcslen(pFindReplace->lpstrReplaceWith) - (dwEnd - dwBegin);
168 }
169 }
170
171 if (pFindReplace->Flags & FR_DOWN)
172 {
173 /* Find Down */
174 dwPosition = dwEnd;
175 while(dwPosition < (DWORD) iTextLength)
176 {
177 bMatches = NOTEPAD_FindTextAt(pFindReplace, pszText, iTextLength, dwPosition);
178 if (bMatches)
179 break;
180 dwPosition++;
181 }
182 }
183 else
184 {
185 /* Find Up */
186 dwPosition = dwBegin;
187 while(dwPosition > 0)
188 {
189 dwPosition--;
190 bMatches = NOTEPAD_FindTextAt(pFindReplace, pszText, iTextLength, dwPosition);
191 if (bMatches)
192 break;
193 }
194 }
195
196 if (bMatches)
197 {
198 /* Found target */
199 if (dwPosition > dwBegin)
200 dwPosition += (DWORD) iAdjustment;
201 SendMessage(Globals.hEdit, EM_SETSEL, dwPosition, dwPosition + iTargetLength);
202 SendMessage(Globals.hEdit, EM_SCROLLCARET, 0, 0);
203 bSuccess = TRUE;
204 }
205 else
206 {
207 /* Can't find target */
208 if (bShowAlert)
209 {
210 LoadString(Globals.hInstance, STRING_CANNOTFIND, szResource, SIZEOF(szResource));
211 _sntprintf(szText, SIZEOF(szText), szResource, pFindReplace->lpstrFindWhat);
212 LoadString(Globals.hInstance, STRING_NOTEPAD, szResource, SIZEOF(szResource));
213 MessageBox(Globals.hFindReplaceDlg, szText, szResource, MB_OK);
214 }
215 bSuccess = FALSE;
216 }
217
218 if (pszText)
219 HeapFree(GetProcessHeap(), 0, pszText);
220 return bSuccess;
221 }
222
223 /***********************************************************************
224 *
225 * NOTEPAD_ReplaceAll
226 */
227
228 static VOID NOTEPAD_ReplaceAll(FINDREPLACE *pFindReplace)
229 {
230 BOOL bShowAlert = TRUE;
231
232 SendMessage(Globals.hEdit, EM_SETSEL, 0, 0);
233
234 while (NOTEPAD_FindNext(pFindReplace, TRUE, bShowAlert))
235 {
236 bShowAlert = FALSE;
237 }
238 }
239
240 /***********************************************************************
241 *
242 * NOTEPAD_FindTerm
243 */
244
245 static VOID NOTEPAD_FindTerm(VOID)
246 {
247 Globals.hFindReplaceDlg = NULL;
248 }
249
250 /***********************************************************************
251 * Data Initialization
252 */
253 static VOID NOTEPAD_InitData(VOID)
254 {
255 LPTSTR p = Globals.szFilter;
256 static const TCHAR txt_files[] = _T("*.txt");
257 static const TCHAR all_files[] = _T("*.*");
258
259 p += LoadString(Globals.hInstance, STRING_TEXT_FILES_TXT, p, MAX_STRING_LEN)+1;
260 _tcscpy(p, txt_files);
261 p += SIZEOF(txt_files);
262
263 p += LoadString(Globals.hInstance, STRING_ALL_FILES, p, MAX_STRING_LEN)+1;
264 _tcscpy(p, all_files);
265 p += SIZEOF(all_files);
266 *p = '\0';
267 Globals.find.lpstrFindWhat = NULL;
268 }
269
270 /***********************************************************************
271 * Enable/disable items on the menu based on control state
272 */
273 static VOID NOTEPAD_InitMenuPopup(HMENU menu, LPARAM index)
274 {
275 int enable;
276
277 UNREFERENCED_PARAMETER(index);
278
279 CheckMenuItem(GetMenu(Globals.hMainWnd), CMD_WRAP,
280 MF_BYCOMMAND | (Globals.bWrapLongLines ? MF_CHECKED : MF_UNCHECKED));
281 if ( !Globals.bWrapLongLines )
282 {
283 CheckMenuItem(GetMenu(Globals.hMainWnd), CMD_STATUSBAR,
284 MF_BYCOMMAND | (Globals.bShowStatusBar ? MF_CHECKED : MF_UNCHECKED));
285 }
286 EnableMenuItem(menu, CMD_UNDO,
287 SendMessage(Globals.hEdit, EM_CANUNDO, 0, 0) ? MF_ENABLED : MF_GRAYED);
288 EnableMenuItem(menu, CMD_PASTE,
289 IsClipboardFormatAvailable(CF_TEXT) ? MF_ENABLED : MF_GRAYED);
290 enable = (int) SendMessage(Globals.hEdit, EM_GETSEL, 0, 0);
291 enable = (HIWORD(enable) == LOWORD(enable)) ? MF_GRAYED : MF_ENABLED;
292 EnableMenuItem(menu, CMD_CUT, enable);
293 EnableMenuItem(menu, CMD_COPY, enable);
294 EnableMenuItem(menu, CMD_DELETE, enable);
295
296 EnableMenuItem(menu, CMD_SELECT_ALL,
297 GetWindowTextLength(Globals.hEdit) ? MF_ENABLED : MF_GRAYED);
298 DrawMenuBar(Globals.hMainWnd);
299 }
300
301 LRESULT CALLBACK EDIT_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
302 {
303 switch (msg)
304 {
305 case WM_KEYUP:
306 {
307 switch (wParam)
308 {
309 case VK_UP:
310 case VK_DOWN:
311 case VK_LEFT:
312 case VK_RIGHT:
313 DIALOG_StatusBarUpdateCaretPos();
314 break;
315 }
316 }
317 case WM_LBUTTONUP:
318 {
319 DIALOG_StatusBarUpdateCaretPos();
320 break;
321 }
322 }
323 return CallWindowProc( (WNDPROC)Globals.EditProc, hWnd, msg, wParam, lParam);
324 }
325
326 /***********************************************************************
327 *
328 * NOTEPAD_WndProc
329 */
330 static LRESULT WINAPI NOTEPAD_WndProc(HWND hWnd, UINT msg, WPARAM wParam,
331 LPARAM lParam)
332 {
333 switch (msg) {
334
335 case WM_CREATE:
336 {
337 static const TCHAR edit[] = _T("edit");
338 RECT rc;
339 GetClientRect(hWnd, &rc);
340 Globals.hEdit = CreateWindowEx(EDIT_EXSTYLE, edit, NULL, Globals.bWrapLongLines ? EDIT_STYLE_WRAP : EDIT_STYLE,
341 0, 0, rc.right, rc.bottom, hWnd,
342 NULL, Globals.hInstance, NULL);
343 if (!Globals.hEdit)
344 return -1;
345 SendMessage(Globals.hEdit, EM_LIMITTEXT, 0, 0);
346 if (Globals.hFont)
347 SendMessage(Globals.hEdit, WM_SETFONT, (WPARAM)Globals.hFont, (LPARAM)TRUE);
348
349 Globals.EditProc = (WNDPROC) SetWindowLongPtr(Globals.hEdit, GWLP_WNDPROC, (LONG_PTR)EDIT_WndProc);
350
351 break;
352 }
353
354 case WM_COMMAND:
355 if (HIWORD(wParam) == EN_CHANGE || HIWORD(wParam) == EN_HSCROLL || HIWORD(wParam) == EN_VSCROLL)
356 DIALOG_StatusBarUpdateCaretPos();
357 if ((HIWORD(wParam) == EN_CHANGE))
358 NOTEPAD_EnableSearchMenu();
359 NOTEPAD_MenuCommand(LOWORD(wParam));
360 break;
361
362 case WM_DESTROYCLIPBOARD:
363 /*MessageBox(Globals.hMainWnd, "Empty clipboard", "Debug", MB_ICONEXCLAMATION);*/
364 break;
365
366 case WM_CLOSE:
367 if (DoCloseFile()) {
368 if (Globals.hFont)
369 DeleteObject(Globals.hFont);
370 DestroyWindow(hWnd);
371 }
372 break;
373
374 case WM_QUERYENDSESSION:
375 if (DoCloseFile()) {
376 return 1;
377 }
378 break;
379
380 case WM_DESTROY:
381 SetWindowLongPtr(Globals.hEdit, GWLP_WNDPROC, (LONG_PTR)Globals.EditProc);
382 SaveSettings();
383 PostQuitMessage(0);
384 break;
385
386 case WM_SIZE:
387 {
388 if (Globals.bShowStatusBar)
389 {
390 RECT rcStatusBar;
391 HDWP hdwp;
392
393 if (!GetWindowRect(Globals.hStatusBar, &rcStatusBar))
394 break;
395
396 hdwp = BeginDeferWindowPos(2);
397 if (hdwp == NULL)
398 break;
399
400 hdwp = DeferWindowPos(hdwp, Globals.hEdit, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam) - (rcStatusBar.bottom - rcStatusBar.top), SWP_NOZORDER | SWP_NOMOVE);
401 if (hdwp == NULL)
402 break;
403
404 hdwp = DeferWindowPos(hdwp, Globals.hStatusBar, NULL, 0, 0, LOWORD(lParam), LOWORD(wParam), SWP_NOZORDER);
405
406 if (hdwp != NULL)
407 EndDeferWindowPos(hdwp);
408 }
409 else
410 SetWindowPos(Globals.hEdit, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER | SWP_NOMOVE);
411
412 break;
413 }
414
415 case WM_SETFOCUS:
416 SetFocus(Globals.hEdit);
417 break;
418
419 case WM_DROPFILES:
420 {
421 TCHAR szFileName[MAX_PATH];
422 HDROP hDrop = (HDROP) wParam;
423
424 DragQueryFile(hDrop, 0, szFileName, SIZEOF(szFileName));
425 DragFinish(hDrop);
426 DoOpenFile(szFileName);
427 break;
428 }
429 case WM_CHAR:
430 case WM_INITMENUPOPUP:
431 NOTEPAD_InitMenuPopup((HMENU)wParam, lParam);
432 break;
433 default:
434 if (msg == aFINDMSGSTRING)
435 {
436 FINDREPLACE *pFindReplace = (FINDREPLACE *) lParam;
437 Globals.find = *(FINDREPLACE *) lParam;
438
439 if (pFindReplace->Flags & FR_FINDNEXT)
440 NOTEPAD_FindNext(pFindReplace, FALSE, TRUE);
441 else if (pFindReplace->Flags & FR_REPLACE)
442 NOTEPAD_FindNext(pFindReplace, TRUE, TRUE);
443 else if (pFindReplace->Flags & FR_REPLACEALL)
444 NOTEPAD_ReplaceAll(pFindReplace);
445 else if (pFindReplace->Flags & FR_DIALOGTERM)
446 NOTEPAD_FindTerm();
447 break;
448 }
449
450 return DefWindowProc(hWnd, msg, wParam, lParam);
451 }
452 return 0;
453 }
454
455 static int AlertFileDoesNotExist(LPCTSTR szFileName)
456 {
457 int nResult;
458 TCHAR szMessage[MAX_STRING_LEN];
459 TCHAR szResource[MAX_STRING_LEN];
460
461 LoadString(Globals.hInstance, STRING_DOESNOTEXIST, szResource, SIZEOF(szResource));
462 wsprintf(szMessage, szResource, szFileName);
463
464 LoadString(Globals.hInstance, STRING_NOTEPAD, szResource, SIZEOF(szResource));
465
466 nResult = MessageBox(Globals.hMainWnd, szMessage, szResource,
467 MB_ICONEXCLAMATION | MB_YESNO);
468
469 return(nResult);
470 }
471
472 static void HandleCommandLine(LPTSTR cmdline)
473 {
474 int opt_print=0;
475
476 while (*cmdline == _T(' ') || *cmdline == _T('-') || *cmdline == _T('/'))
477 {
478 TCHAR option;
479
480 if (*cmdline++ == _T(' ')) continue;
481
482 option = *cmdline;
483 if (option) cmdline++;
484 while (*cmdline == _T(' ')) cmdline++;
485
486 switch(option)
487 {
488 case 'p':
489 case 'P':
490 opt_print=1;
491 break;
492 }
493 }
494
495 if (*cmdline)
496 {
497 /* file name is passed in the command line */
498 LPCTSTR file_name = NULL;
499 BOOL file_exists = FALSE;
500 TCHAR buf[MAX_PATH];
501
502 if (cmdline[0] == _T('"'))
503 {
504 cmdline++;
505 cmdline[lstrlen(cmdline) - 1] = 0;
506 }
507
508 file_name = cmdline;
509 if (FileExists(file_name))
510 {
511 file_exists = TRUE;
512 }
513 else if (!HasFileExtension(cmdline))
514 {
515 static const TCHAR txt[] = _T(".txt");
516
517 /* try to find file with ".txt" extension */
518 if (!_tcscmp(txt, cmdline + _tcslen(cmdline) - _tcslen(txt)))
519 {
520 file_exists = FALSE;
521 }
522 else
523 {
524 _tcsncpy(buf, cmdline, MAX_PATH - _tcslen(txt) - 1);
525 _tcscat(buf, txt);
526 file_name = buf;
527 file_exists = FileExists(file_name);
528 }
529 }
530
531 if (file_exists)
532 {
533 DoOpenFile(file_name);
534 InvalidateRect(Globals.hMainWnd, NULL, FALSE);
535 if (opt_print)
536 DIALOG_FilePrint();
537 }
538 else
539 {
540 switch (AlertFileDoesNotExist(file_name)) {
541 case IDYES:
542 DoOpenFile(file_name);
543 break;
544
545 case IDNO:
546 break;
547 }
548 }
549 }
550 }
551
552 /***********************************************************************
553 *
554 * WinMain
555 */
556 int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE prev, LPTSTR cmdline, int show)
557 {
558 MSG msg;
559 HACCEL hAccel;
560 WNDCLASSEX wndclass;
561 HMONITOR monitor;
562 MONITORINFO info;
563 INT x, y;
564
565 static const TCHAR className[] = _T("NPClass");
566 static const TCHAR winName[] = _T("Notepad");
567
568 UNREFERENCED_PARAMETER(prev);
569
570 aFINDMSGSTRING = (ATOM) RegisterWindowMessage(FINDMSGSTRING);
571
572 ZeroMemory(&Globals, sizeof(Globals));
573 Globals.hInstance = hInstance;
574 LoadSettings();
575
576 ZeroMemory(&wndclass, sizeof(wndclass));
577 wndclass.cbSize = sizeof(wndclass);
578 wndclass.lpfnWndProc = NOTEPAD_WndProc;
579 wndclass.hInstance = Globals.hInstance;
580 wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_NPICON));
581 wndclass.hCursor = LoadCursor(0, IDC_ARROW);
582 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
583 wndclass.lpszMenuName = MAKEINTRESOURCE(MAIN_MENU);
584 wndclass.lpszClassName = className;
585 wndclass.hIconSm = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_NPICON),
586 IMAGE_ICON, 16, 16, 0);
587
588 if (!RegisterClassEx(&wndclass)) return FALSE;
589
590 /* Setup windows */
591
592 monitor = MonitorFromRect( &Globals.main_rect, MONITOR_DEFAULTTOPRIMARY );
593 info.cbSize = sizeof(info);
594 GetMonitorInfoW( monitor, &info );
595
596 x = Globals.main_rect.left;
597 y = Globals.main_rect.top;
598 if (Globals.main_rect.left >= info.rcWork.right ||
599 Globals.main_rect.top >= info.rcWork.bottom ||
600 Globals.main_rect.right < info.rcWork.left ||
601 Globals.main_rect.bottom < info.rcWork.top)
602 x = y = CW_USEDEFAULT;
603
604 Globals.hMainWnd =
605 CreateWindow(className, winName, WS_OVERLAPPEDWINDOW,
606 x, y, Globals.main_rect.right - Globals.main_rect.left,
607 Globals.main_rect.bottom - Globals.main_rect.top,
608 NULL, NULL, Globals.hInstance, NULL);
609 if (!Globals.hMainWnd)
610 {
611 ShowLastError();
612 ExitProcess(1);
613 }
614
615 NOTEPAD_InitData();
616 DIALOG_FileNew();
617
618 ShowWindow(Globals.hMainWnd, show);
619 UpdateWindow(Globals.hMainWnd);
620 DragAcceptFiles(Globals.hMainWnd, TRUE);
621
622 DIALOG_ViewStatusBar();
623
624 HandleCommandLine(cmdline);
625
626 hAccel = LoadAccelerators( hInstance, MAKEINTRESOURCE(ID_ACCEL) );
627
628 while (GetMessage(&msg, 0, 0, 0))
629 {
630 if (!IsDialogMessage(Globals.hFindReplaceDlg, &msg) &&
631 !TranslateAccelerator(Globals.hMainWnd, hAccel, &msg))
632 {
633 TranslateMessage(&msg);
634 DispatchMessage(&msg);
635 }
636 }
637 return (int) msg.wParam;
638 }