[TRANSLATIONS] Estonian for various base applications
[reactos.git] / base / applications / charmap_new / MainWindow.cpp
1 /*
2 * PROJECT: ReactOS Character Map
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/charmap/MainWindow.cpp
5 * PURPOSE: Implements the main dialog window
6 * COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
7 */
8
9
10 #include "precomp.h"
11 #include "MainWindow.h"
12
13
14 /* DATA *****************************************************/
15
16 #define ID_ABOUT 0x1
17
18 HINSTANCE g_hInstance = NULL;
19
20
21 /* PUBLIC METHODS **********************************************/
22
23 CCharMapWindow::CCharMapWindow(void) :
24 m_hMainWnd(NULL),
25 m_hStatusBar(NULL),
26 m_CmdShow(0),
27 m_hRichEd(NULL),
28 m_GridView(nullptr)
29 {
30 m_GridView = new CGridView();
31 }
32
33 CCharMapWindow::~CCharMapWindow(void)
34 {
35 }
36
37 bool
38 CCharMapWindow::Create(_In_ HINSTANCE hInst,
39 _In_ int nCmdShow)
40 {
41 INITCOMMONCONTROLSEX icex;
42 CAtlStringW szAppName;
43 int Ret = 1;
44
45 // Store the instance
46 g_hInstance = hInst;
47 m_CmdShow = nCmdShow;
48
49 // Initialize common controls
50 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
51 icex.dwICC = ICC_BAR_CLASSES | ICC_COOL_CLASSES;
52 InitCommonControlsEx(&icex);
53
54 // Load the application name
55 if (szAppName.LoadStringW(g_hInstance, IDS_TITLE))
56 {
57 // Initialize the main window
58 if (Initialize(szAppName, nCmdShow))
59 {
60 // Run the application
61 Ret = Run();
62
63 // Uninitialize the main window
64 Uninitialize();
65 }
66 }
67
68 return (Ret == 0);
69 }
70
71
72
73 /* PRIVATE METHODS **********************************************/
74
75 bool
76 CCharMapWindow::Initialize(_In_z_ LPCTSTR lpCaption,
77 _In_ int nCmdShow)
78 {
79 // The dialog has a rich edit text box
80 m_hRichEd = LoadLibraryW(L"riched20.DLL");
81 if (m_hRichEd == NULL) return false;
82
83 return !!(CreateDialogParamW(g_hInstance,
84 MAKEINTRESOURCE(IDD_CHARMAP),
85 NULL,
86 DialogProc,
87 (LPARAM)this));
88 }
89
90 void
91 CCharMapWindow::Uninitialize(void)
92 {
93 if (m_hRichEd)
94 FreeLibrary(m_hRichEd);
95 }
96
97 int
98 CCharMapWindow::Run(void)
99 {
100 MSG Msg;
101
102 // Pump the message queue
103 while (GetMessageW(&Msg, NULL, 0, 0) != 0)
104 {
105 TranslateMessage(&Msg);
106 DispatchMessageW(&Msg);
107 }
108
109 return 0;
110 }
111
112 void
113 CCharMapWindow::UpdateStatusBar(_In_ bool InMenuLoop)
114 {
115 SendMessageW(m_hStatusBar,
116 SB_SIMPLE,
117 (WPARAM)InMenuLoop,
118 0);
119 }
120
121 bool
122 CCharMapWindow::CreateStatusBar(void)
123 {
124 int StatWidths[] = { 110, -1 }; // widths of status bar
125 bool bRet = FALSE;
126
127 // Create the status bar
128 m_hStatusBar = CreateWindowExW(0,
129 STATUSCLASSNAME,
130 NULL,
131 WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
132 0, 0, 0, 0,
133 m_hMainWnd,
134 (HMENU)IDD_STATUSBAR,
135 g_hInstance,
136 NULL);
137 if (m_hStatusBar)
138 {
139 // Create the sections
140 bRet = (SendMessageW(m_hStatusBar,
141 SB_SETPARTS,
142 sizeof(StatWidths) / sizeof(int),
143 (LPARAM)StatWidths) != 0);
144
145 // Set the status bar for multiple parts output
146 SendMessage(m_hStatusBar, SB_SIMPLE, (WPARAM)FALSE, (LPARAM)0);
147 }
148
149 return bRet;
150 }
151
152 bool
153 CCharMapWindow::StatusBarLoadString(_In_ HWND hStatusBar,
154 _In_ INT PartId,
155 _In_ HINSTANCE hInstance,
156 _In_ UINT uID)
157 {
158 CAtlStringW szMessage;
159 bool bRet = false;
160
161 // Load the string from the resource
162 if (szMessage.LoadStringW(hInstance, uID))
163 {
164 // Display it on the status bar
165 bRet = (SendMessageW(hStatusBar,
166 SB_SETTEXT,
167 (WPARAM)PartId,
168 (LPARAM)szMessage.GetBuffer()) != 0);
169 }
170
171 return bRet;
172 }
173
174 BOOL
175 CCharMapWindow::OnCreate(_In_ HWND hDlg)
176 {
177 m_hMainWnd = hDlg;
178
179 if (!CreateStatusBar())
180 return FALSE;
181
182 if (!m_GridView->Create(hDlg))
183 return FALSE;
184
185 // Load an 'about' option into the system menu
186 HMENU hSysMenu;
187 hSysMenu = GetSystemMenu(m_hMainWnd, FALSE);
188 if (hSysMenu != NULL)
189 {
190 CAtlStringW AboutText;
191 if (AboutText.LoadStringW(IDS_ABOUT))
192 {
193 AppendMenuW(hSysMenu, MF_SEPARATOR, 0, NULL);
194 AppendMenuW(hSysMenu, MF_STRING, ID_ABOUT, AboutText);
195 }
196 }
197
198 // Add all the fonts to the
199 if (!CreateFontComboBox())
200 return FALSE;
201
202 ChangeMapFont();
203
204 // Configure Richedit control for sending notification changes.
205 DWORD evMask;
206 evMask = SendDlgItemMessage(hDlg, IDC_TEXTBOX, EM_GETEVENTMASK, 0, 0);
207 evMask |= ENM_CHANGE;
208 SendDlgItemMessage(hDlg, IDC_TEXTBOX, EM_SETEVENTMASK, 0, (LPARAM)evMask);
209
210 // Display the window according to the user request
211 ShowWindow(m_hMainWnd, m_CmdShow);
212
213 return TRUE;
214 }
215
216 BOOL
217 CCharMapWindow::OnSize(
218 _In_ WPARAM wParam
219 )
220 {
221 RECT rcClient, rcStatus;
222 INT lvHeight, iStatusHeight;
223
224 // Resize the status bar
225 SendMessage(m_hStatusBar, WM_SIZE, 0, 0);
226
227 // Get the statusbar rect and save the height
228 GetWindowRect(m_hStatusBar, &rcStatus);
229 iStatusHeight = rcStatus.bottom - rcStatus.top;
230
231 // Get the full client rect
232 GetClientRect(m_hMainWnd, &rcClient);
233
234 // Calculate the remaining height for the gridview
235 lvHeight = rcClient.bottom - iStatusHeight;
236
237 // Resize the grid view
238 SendMessageW(m_GridView->GetHwnd(), WM_SIZE, wParam, 0);
239
240 return TRUE;
241 }
242
243 BOOL
244 CCharMapWindow::OnNotify(_In_ LPARAM lParam)
245 {
246 LPNMHDR NmHdr = (LPNMHDR)lParam;
247 LRESULT Ret = 0;
248
249 switch (NmHdr->code)
250 {
251 case NM_RCLICK:
252 {
253 break;
254 }
255
256 case NM_DBLCLK:
257 case NM_RETURN:
258 {
259 break;
260 }
261 }
262
263 return Ret;
264 }
265
266 BOOL
267 CCharMapWindow::OnContext(_In_ LPARAM lParam)
268 {
269 return 0;// m_GridView->OnContextMenu(lParam);
270 }
271
272 BOOL
273 CCharMapWindow::OnCommand(_In_ WPARAM wParam,
274 _In_ LPARAM /*lParam*/)
275 {
276 LRESULT RetCode = 0;
277 WORD Msg;
278
279 // Get the message
280 Msg = LOWORD(wParam);
281
282 switch (Msg)
283 {
284 case IDC_CHECK_ADVANCED:
285 break;
286
287 case IDC_FONTCOMBO:
288 if (HIWORD(wParam) == CBN_SELCHANGE)
289 {
290 ChangeMapFont();
291 }
292 break;
293
294 default:
295 // We didn't handle it
296 RetCode = -1;
297 break;
298 }
299
300 return RetCode;
301 }
302
303 BOOL
304 CCharMapWindow::OnDestroy(void)
305 {
306 // Clear the user data pointer
307 SetWindowLongPtr(m_hMainWnd, GWLP_USERDATA, 0);
308
309 // Break the message loop
310 PostQuitMessage(0);
311
312 return TRUE;
313 }
314
315 INT_PTR CALLBACK
316 CCharMapWindow::DialogProc(
317 _In_ HWND hwndDlg,
318 _In_ UINT Msg,
319 _In_ WPARAM wParam,
320 _In_ LPARAM lParam
321 )
322 {
323 CCharMapWindow *This;
324 LRESULT RetCode = 0;
325
326 // Get the object pointer from window context
327 This = (CCharMapWindow *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
328 if (This == NULL)
329 {
330 // Check that this isn't a create message
331 if (Msg != WM_INITDIALOG)
332 {
333 // Don't handle null info pointer
334 return FALSE;
335 }
336 }
337
338 switch (Msg)
339 {
340 case WM_INITDIALOG:
341 {
342 // Get the object pointer from the create param
343 This = (CCharMapWindow *)lParam;
344
345 // Store the pointer in the window's global user data
346 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)This);
347
348 // Call the create handler
349 return This->OnCreate(hwndDlg);
350 }
351
352 case WM_SIZE:
353 {
354 return This->OnSize(wParam);
355 }
356
357 case WM_NOTIFY:
358 {
359 return This->OnNotify(lParam);
360 }
361
362 case WM_CONTEXTMENU:
363 {
364 return This->OnContext(lParam);
365 }
366
367 case WM_COMMAND:
368 {
369 return This->OnCommand(wParam, lParam);
370 }
371
372 case WM_SYSCOMMAND:
373 switch (wParam)
374 {
375 case ID_ABOUT:
376 // Apportion blame
377 MessageBoxW(This->m_hMainWnd,
378 L"ReactOS Character Map\r\nCopyright Ged Murphy 2015",
379 L"About",
380 MB_OK | MB_APPLMODAL);
381 break;
382 }
383 break;
384
385 case WM_ENTERMENULOOP:
386 {
387 This->UpdateStatusBar(true);
388 return TRUE;
389 }
390
391 case WM_EXITMENULOOP:
392 {
393 This->UpdateStatusBar(false);
394 return TRUE;
395 }
396
397 case WM_CLOSE:
398 {
399 // Destroy the main window
400 return DestroyWindow(hwndDlg);
401 }
402
403
404 case WM_DESTROY:
405 {
406 // Call the destroy handler
407 return This->OnDestroy();
408 }
409 }
410
411 return FALSE;
412 }
413
414 struct EnumFontParams
415 {
416 CCharMapWindow *This;
417 HWND hCombo;
418 };
419
420 int
421 CALLBACK
422 CCharMapWindow::EnumDisplayFont(ENUMLOGFONTEXW *lpelfe,
423 NEWTEXTMETRICEXW *lpntme,
424 DWORD FontType,
425 LPARAM lParam)
426 {
427 EnumFontParams *Params = (EnumFontParams *)lParam;
428 LPWSTR pszName = lpelfe->elfLogFont.lfFaceName;
429
430 /* Skip rotated font */
431 if (pszName[0] == L'@') return 1;
432
433 /* make sure font doesn't already exist in our list */
434 if (SendMessageW(Params->hCombo,
435 CB_FINDSTRINGEXACT,
436 0,
437 (LPARAM)pszName) == CB_ERR)
438 {
439 INT idx;
440 idx = (INT)SendMessageW(Params->hCombo,
441 CB_ADDSTRING,
442 0,
443 (LPARAM)pszName);
444
445 /* record the font's attributes (Fixedwidth and Truetype) */
446 BOOL fFixed = (lpelfe->elfLogFont.lfPitchAndFamily & FIXED_PITCH) ? TRUE : FALSE;
447 BOOL fTrueType = (lpelfe->elfLogFont.lfOutPrecision == OUT_STROKE_PRECIS) ? TRUE : FALSE;
448
449 /* store this information in the list-item's userdata area */
450 SendMessageW(Params->hCombo,
451 CB_SETITEMDATA,
452 idx,
453 MAKEWPARAM(fFixed, fTrueType));
454 }
455
456 return 1;
457 }
458
459
460 bool
461 CCharMapWindow::CreateFontComboBox()
462 {
463 HWND hCombo;
464 hCombo = GetDlgItem(m_hMainWnd, IDC_FONTCOMBO);
465
466 NONCLIENTMETRICSW NonClientMetrics;
467 NonClientMetrics.cbSize = sizeof(NONCLIENTMETRICSW);
468 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
469 sizeof(NONCLIENTMETRICSW),
470 &NonClientMetrics,
471 0);
472
473 // Get a handle to the font
474 HFONT GuiFont;
475 GuiFont = CreateFontIndirectW(&NonClientMetrics.lfMessageFont);
476
477 // Set the font used in the combo box
478 SendMessageW(hCombo,
479 WM_SETFONT,
480 (WPARAM)GuiFont,
481 0);
482
483 // Set the fonts which we want to enumerate
484 LOGFONTW FontsToEnum;
485 ZeroMemory(&FontsToEnum, sizeof(LOGFONTW));
486 FontsToEnum.lfCharSet = DEFAULT_CHARSET;
487
488 // Set the params we want to pass to the callback
489 EnumFontParams Params;
490 Params.This = this;
491 Params.hCombo = hCombo;
492
493 // Get a DC for combo box
494 HDC hdc;
495 hdc = GetDC(hCombo);
496
497 // Enumerate all the fonts
498 int ret;
499 ret = EnumFontFamiliesExW(hdc,
500 &FontsToEnum,
501 (FONTENUMPROCW)EnumDisplayFont,
502 (LPARAM)&Params,
503 0);
504
505 ReleaseDC(hCombo, hdc);
506 DeleteObject(GuiFont);
507
508 // Select the first item in the list
509 SendMessageW(hCombo,
510 CB_SETCURSEL,
511 0,
512 0);
513
514 return (ret == 1);
515 }
516
517 bool
518 CCharMapWindow::ChangeMapFont(
519 )
520 {
521 HWND hCombo;
522 hCombo = GetDlgItem(m_hMainWnd, IDC_FONTCOMBO);
523
524 INT Length;
525 Length = GetWindowTextLengthW(hCombo);
526 if (!Length) return false;
527
528 CAtlStringW FontName;
529 FontName.Preallocate(Length);
530
531 SendMessageW(hCombo,
532 WM_GETTEXT,
533 FontName.GetAllocLength(),
534 (LPARAM)FontName.GetBuffer());
535
536 return m_GridView->SetFont(FontName);
537 }