Visual studio 2005 thinks that long long int is 64 bit. The difference between
[dasher.git] / Src / Win32 / DasherWindow.cpp
blobc70ba0de07f51d3784d5152afa56ccc7e1873698
1 // DasherWindow.cpp
2 //
3 // Copyright (c) 2007 The Dasher Team
4 //
5 // This file is part of Dasher.
6 //
7 // Dasher is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
12 // Dasher is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with Dasher; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "Common/WinMenus.h"
22 #include "Dasher.h"
23 // TODO: Put this in DasherInterfaceBase header?
24 #include "../DasherCore/ControlManager.h"
25 #include "DasherWindow.h"
26 #include "Widgets/AboutBox.h"
27 #ifndef _WIN32_WCE
28 #include "Widgets/Prefs.h"
29 #endif
31 #include "Widgets/Slidebar.h"
32 #include "Widgets/Toolbar.h"
33 #include "Widgets/GameGroup.h"
34 #include "WinCommon.h"
36 #ifndef _WIN32_WCE
37 #include <Htmlhelp.h>
38 #include <Oleacc.h>
39 //#include <guiddef.h>
40 #endif
42 using namespace Dasher;
43 using namespace std;
45 #define IDT_TIMER1 200
47 // NOTE: There were previously various bits and pieces in this class from
48 // text services framework stuff, which were never really finished. If
49 // required, look in version control history (prior to May 2007).
51 CDasherWindow::CDasherWindow() {
52 m_pToolbar = 0;
53 m_pEdit = 0;
54 m_pSpeedAlphabetBar = 0;
55 m_pSplitter = 0;
56 m_pDasher = 0;
57 m_pGameGroup = 0;
59 m_hIconSm = (HICON) LoadImage(WinHelper::hInstApp, (LPCTSTR) IDI_DASHER, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
61 ATL::CWndClassInfo& wc = CDasherWindow::GetWndClassInfo();
62 wc.m_wc.hIcon = LoadIcon(WinHelper::hInstApp, (LPCTSTR) IDI_DASHER);
63 wc.m_wc.hCursor = LoadCursor(NULL, IDC_ARROW);
64 wc.m_wc.hbrBackground = (HBRUSH) (COLOR_WINDOW);
65 #ifndef _WIN32_WCE
66 // wc.m_wc.lpszMenuName = (LPCTSTR) IDC_DASHER;
67 wc.m_wc.hIconSm = m_hIconSm;
68 #endif
70 m_hMenu = LoadMenu(WinHelper::hInstApp, (LPCTSTR) IDC_DASHER);
73 HWND CDasherWindow::Create() {
74 hAccelTable = LoadAccelerators(WinHelper::hInstApp, (LPCTSTR) IDC_DASHER);
76 // Get window title from resource script
77 Tstring WindowTitle;
78 WinLocalisation::GetResourceString(IDS_APP_TITLE, &WindowTitle);
80 m_pAppSettings = new CAppSettings(0, 0);
81 int iStyle(m_pAppSettings->GetLongParameter(APP_LP_STYLE));
83 HWND hWnd;
85 #ifndef _WIN32_WCE
86 if((iStyle == APP_STYLE_COMPOSE) || (iStyle == APP_STYLE_DIRECT)) {
87 hWnd = CWindowImpl<CDasherWindow >::Create(NULL, NULL, WindowTitle.c_str(), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, WS_EX_NOACTIVATE | WS_EX_APPWINDOW | WS_EX_TOPMOST);
88 ::SetMenu(hWnd, NULL);
90 else {
91 hWnd = CWindowImpl<CDasherWindow >::Create(NULL, NULL, WindowTitle.c_str(), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN);
92 ::SetMenu(hWnd, m_hMenu);
94 #else
95 hWnd = CWindowImpl<CDasherWindow, CWindow, CWinTraits<WS_CLIPCHILDREN | WS_CLIPSIBLINGS> >::Create(NULL);
96 #endif
100 // Create Widgets
101 m_pDasher = new CDasher(hWnd);
103 // Create a CAppSettings
104 m_pAppSettings->SetHwnd(hWnd);
105 m_pAppSettings->SetDasher(m_pDasher);
107 m_pEdit = new CEdit(m_pAppSettings);
108 m_pEdit->Create(hWnd, m_pAppSettings->GetBoolParameter(APP_BP_TIME_STAMP));
109 m_pEdit->SetFont(m_pAppSettings->GetStringParameter(APP_SP_EDIT_FONT), m_pAppSettings->GetLongParameter(APP_LP_EDIT_FONT_SIZE));
111 #ifdef PJC_EXPERIMENTAL
112 g_hWnd = m_pEdit->GetHwnd();
113 #endif
115 m_pToolbar = new CToolbar(hWnd, m_pAppSettings->GetBoolParameter(APP_BP_SHOW_TOOLBAR));
117 #ifdef _WIN32_WCE
118 m_pToolbar->ShowToolbar(false);
119 #endif
121 // FIXME - the edit box really shouldn't need access to the interface,
122 // but at the moment it does, for training, blanking the display etc
124 m_pEdit->SetInterface(m_pDasher);
126 m_pSpeedAlphabetBar = new CStatusControl(m_pDasher);
127 m_pSpeedAlphabetBar->Create(hWnd);
129 m_pGameGroup = new CGameGroup(m_pDasher, m_pEdit);
130 m_pGameGroup->Create(hWnd);
131 m_pGameGroup->ShowWindow(SW_HIDE);
132 m_pGameGroup->SetEditFont(m_pAppSettings->GetStringParameter(APP_SP_EDIT_FONT), m_pAppSettings->GetLongParameter(APP_LP_EDIT_FONT_SIZE));
134 m_pSplitter = new CSplitter(this,100);
135 HWND hSplitter = m_pSplitter->Create(hWnd);
137 if (!hSplitter)
138 return 0;
140 // Add extra control nodes
142 m_pDasher->RegisterNode( Dasher::CControlManager::CTL_USER, "Speak", -1 );
143 m_pDasher->RegisterNode( Dasher::CControlManager::CTL_USER+1, "All", -1 );
144 m_pDasher->RegisterNode( Dasher::CControlManager::CTL_USER+2, "New", -1 );
145 m_pDasher->RegisterNode( Dasher::CControlManager::CTL_USER+3, "Repeat", -1 );
147 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_USER, Dasher::CControlManager::CTL_ROOT, -2);
149 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_USER+1, Dasher::CControlManager::CTL_USER, -2);
150 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_USER+2, Dasher::CControlManager::CTL_USER, -2);
151 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_USER+3, Dasher::CControlManager::CTL_USER, -2);
153 m_pDasher->ConnectNode(-1, Dasher::CControlManager::CTL_USER+1, -2);
154 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_ROOT, Dasher::CControlManager::CTL_USER+1, -2);
156 m_pDasher->ConnectNode(-1, Dasher::CControlManager::CTL_USER+2, -2);
157 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_ROOT, Dasher::CControlManager::CTL_USER+2, -2);
159 m_pDasher->ConnectNode(-1, Dasher::CControlManager::CTL_USER+3, -2);
160 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_ROOT, Dasher::CControlManager::CTL_USER+3, -2);
162 m_pGameModeHelper = 0;
164 return hWnd;
167 CDasherWindow::~CDasherWindow() {
168 delete m_pToolbar;
169 delete m_pEdit;
170 delete m_pSplitter;
171 delete m_pDasher;
172 delete m_pAppSettings;
174 DestroyIcon(m_hIconSm);
179 void CDasherWindow::Main() {
180 // TODO: Sort this sort ofthing out, figure out how it fits into ATL etc.
181 // This function is not called by anybody...
182 #ifndef _WIN32_WCE
183 DASHER_ASSERT_VALIDPTR_RW(m_pDasher);
184 #endif
186 m_pDasher->Main();
187 Sleep(50); // limits framerate to 20fps
190 int CDasherWindow::MessageLoop() {
191 // See previous function's comments
192 MSG msg;
194 while(GetMessage(&msg, NULL, 0, 0)) {
195 if(!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
196 TranslateMessage(&msg);
197 DispatchMessage(&msg);
201 m_pDasher->StartShutdown();
203 return msg.wParam;
206 void CDasherWindow::Show(int nCmdShow) {
207 InvalidateRect(NULL, FALSE);
209 if(!LoadWindowState())
210 ShowWindow(nCmdShow);
213 void CDasherWindow::SaveWindowState() const {
214 #ifndef DASHER_WINCE
215 WINDOWPLACEMENT wp;
216 wp.length = sizeof(WINDOWPLACEMENT);
218 if(GetWindowPlacement(&wp)) {//function call succeeds
219 m_pAppSettings->SaveSetting("WindowState", &wp);
221 #endif
224 bool CDasherWindow::LoadWindowState() {
225 #ifndef DASHER_WINCE
226 WINDOWPLACEMENT wp;
228 if(m_pAppSettings->LoadSetting("WindowState", &wp)) {
229 if(SetWindowPlacement(&wp))
230 return true;
232 #endif
233 return false;
236 void CDasherWindow::HandleParameterChange(int iParameter) {
237 switch(iParameter) {
238 #ifndef _WIN32_WCE
239 case APP_BP_SHOW_TOOLBAR:
240 m_pToolbar->ShowToolbar(m_pAppSettings->GetBoolParameter(APP_BP_SHOW_TOOLBAR));
241 break;
242 #endif
243 case APP_LP_STYLE:
244 // TODO: No longer handled after startup?
245 Layout();
246 break;
247 case APP_BP_TIME_STAMP:
248 // TODO: reimplement
249 // m_pEdit->TimeStampNewFiles(m_pAppSettings->GetBoolParameter(APP_BP_TIME_STAMP));
250 break;
251 case LP_MAX_BITRATE:
252 // TODO: reimplement
253 break;
254 default:
255 break;
259 void CDasherWindow::HandleControlEvent(int iID) {
260 // TODO: Some kind of automatic translation here? Or at least a table
262 switch(iID) {
263 case Dasher::CControlManager::CTL_MOVE_FORWARD_CHAR:
264 if(m_pEdit)
265 m_pEdit->Move(EDIT_FORWARDS, EDIT_CHAR);
266 break;
267 case Dasher::CControlManager::CTL_MOVE_FORWARD_WORD:
268 if(m_pEdit)
269 m_pEdit->Move(EDIT_FORWARDS, EDIT_WORD);
270 break;
271 case Dasher::CControlManager::CTL_MOVE_FORWARD_LINE:
272 if(m_pEdit)
273 m_pEdit->Move(EDIT_FORWARDS, EDIT_LINE);
274 break;
275 case Dasher::CControlManager::CTL_MOVE_FORWARD_FILE:
276 if(m_pEdit)
277 m_pEdit->Move(EDIT_FORWARDS, EDIT_FILE);
278 break;
279 case Dasher::CControlManager::CTL_MOVE_BACKWARD_CHAR:
280 if(m_pEdit)
281 m_pEdit->Move(EDIT_BACKWARDS, EDIT_CHAR);
282 break;
283 case Dasher::CControlManager::CTL_MOVE_BACKWARD_WORD:
284 if(m_pEdit)
285 m_pEdit->Move(EDIT_BACKWARDS, EDIT_WORD);
286 break;
287 case Dasher::CControlManager::CTL_MOVE_BACKWARD_LINE:
288 if(m_pEdit)
289 m_pEdit->Move(EDIT_BACKWARDS, EDIT_LINE);
290 break;
291 case Dasher::CControlManager::CTL_MOVE_BACKWARD_FILE:
292 if(m_pEdit)
293 m_pEdit->Move(EDIT_BACKWARDS, EDIT_FILE);
294 break;
295 case Dasher::CControlManager::CTL_DELETE_FORWARD_CHAR:
296 if(m_pEdit)
297 m_pEdit->Delete(EDIT_FORWARDS, EDIT_CHAR);
298 break;
299 case Dasher::CControlManager::CTL_DELETE_FORWARD_WORD:
300 if(m_pEdit)
301 m_pEdit->Delete(EDIT_FORWARDS, EDIT_WORD);
302 break;
303 case Dasher::CControlManager::CTL_DELETE_FORWARD_LINE:
304 if(m_pEdit)
305 m_pEdit->Delete(EDIT_FORWARDS, EDIT_LINE);
306 break;
307 case Dasher::CControlManager::CTL_DELETE_FORWARD_FILE:
308 if(m_pEdit)
309 m_pEdit->Delete(EDIT_FORWARDS, EDIT_FILE);
310 break;
311 case Dasher::CControlManager::CTL_DELETE_BACKWARD_CHAR:
312 if(m_pEdit)
313 m_pEdit->Delete(EDIT_BACKWARDS, EDIT_CHAR);
314 break;
315 case Dasher::CControlManager::CTL_DELETE_BACKWARD_WORD:
316 if(m_pEdit)
317 m_pEdit->Delete(EDIT_BACKWARDS, EDIT_WORD);
318 break;
319 case Dasher::CControlManager::CTL_DELETE_BACKWARD_LINE:
320 if(m_pEdit)
321 m_pEdit->Delete(EDIT_BACKWARDS, EDIT_LINE);
322 break;
323 case Dasher::CControlManager::CTL_DELETE_BACKWARD_FILE:
324 if(m_pEdit)
325 m_pEdit->Delete(EDIT_BACKWARDS, EDIT_FILE);
326 break;
327 case Dasher::CControlManager::CTL_USER+1: // Speak all
328 if(m_pEdit)
329 m_pEdit->speak(1);
330 break;
331 case Dasher::CControlManager::CTL_USER+2: // Speak new
332 if(m_pEdit)
333 m_pEdit->speak(2);
334 break;
335 case Dasher::CControlManager::CTL_USER+3: // Repeat speech
336 if(m_pEdit)
337 m_pEdit->speak(3);
338 break;
342 LRESULT CDasherWindow::OnCommand(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
343 const int wmId = LOWORD(wParam);
344 const int wmEvent = HIWORD(wParam);
346 // Tell edit box if it has changed. It should know itself really, but this is easier
347 // This shouldn't be here - it should be in the edit box class
348 if( m_pEdit && ((HWND) lParam == m_pEdit->GetHwnd()) && (HIWORD(wParam) == EN_CHANGE)) {
349 m_pEdit->SetDirty();
350 return 0;
353 // Parse the menu selections:
354 // TODO: Put these into separate functions
355 switch (wmId) {
356 case IDM_ABOUT: {
357 CAboutBox Aboutbox;
358 Aboutbox.DoModal(m_hWnd);
359 return 0;
361 #ifndef _WIN32_WCE
362 case ID_OPTIONS_PREFS: {
363 CPrefs Prefs(m_hWnd, m_pDasher, m_pAppSettings);
364 return 0;
366 #endif
367 #ifndef _WIN32_WCE
368 case ID_HELP_CONTENTS:
369 HtmlHelp(m_hWnd, L"Dasher.chm", HH_DISPLAY_INDEX, NULL);
370 return 0;
371 #endif
372 case ID_HELP_DASHERTUTORIAL:
373 m_pGameModeHelper = new CGameModeHelper(m_pDasher);
374 return 0;
375 case ID_GAMEMODE:
376 m_pDasher->GameMessageIn(m_pGameGroup->IsWindowVisible()?
377 (GameMode::GAME_MESSAGE_GAME_OFF) : (GameMode::GAME_MESSAGE_GAME_ON),
378 NULL);
379 m_pGameGroup->ShowWindow(m_pGameGroup->IsWindowVisible()?SW_HIDE:SW_SHOW);
380 m_pEdit->Clear();
381 Layout();
382 return 0;
383 case IDM_EXIT:
384 DestroyWindow();
385 return 0;
386 case ID_EDIT_SELECTALL:
387 if(m_pEdit)
388 m_pEdit->SelectAll();
389 return 0;
390 case ID_EDIT_CUT:
391 if(m_pEdit)
392 m_pEdit->Cut();
393 return 0;
394 case ID_EDIT_COPY:
395 if(m_pEdit)
396 m_pEdit->Copy();
397 return 0;
398 case ID_EDIT_COPY_ALL:
399 if(m_pEdit)
400 m_pEdit->CopyAll();
401 return 0;
402 case ID_EDIT_PASTE:
403 if(m_pEdit)
404 m_pEdit->Paste();
405 return 0;
406 case ID_FILE_NEW:
407 if(m_pEdit)
408 m_pEdit->New();
409 // Selecting file->new indicates a new trial to our user logging object
410 if (m_pDasher != NULL) {
411 CUserLogBase* pUserLog = m_pDasher->GetUserLogPtr();
412 if (pUserLog != NULL)
413 pUserLog->NewTrial();
415 m_pDasher->SetBuffer(0);
417 return 0;
418 case ID_FILE_OPEN:
419 if(m_pEdit)
420 m_pEdit->Open();
421 return 0;
422 case ID_FILE_SAVE:
423 if(m_pEdit)
424 if(!m_pEdit->Save())
425 m_pEdit->SaveAs();
426 return 0;
427 case ID_FILE_SAVE_AS:
428 if(m_pEdit)
429 m_pEdit->SaveAs();
430 return 0;
431 case ID_IMPORT_TRAINFILE:
432 m_pDasher->ImportTrainingText(m_pEdit->Import());
433 return 0;
434 default:
435 return DefWindowProc(message, wParam, lParam);
438 Layout();
439 return 0;
442 LRESULT CDasherWindow::OnDasherEvent(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
443 // Apparently putting the typecast directly in the switch doesn't work
444 CEvent *pEvent( (CEvent *)lParam );
446 // TODO: return if handled?
447 switch(pEvent->m_iEventType) {
448 case EV_PARAM_NOTIFY:
449 HandleParameterChange(((CParameterNotificationEvent *)pEvent)->m_iParameter);
450 break;
451 case EV_CONTROL:
452 HandleControlEvent(((CControlEvent *)pEvent)->m_iID);
453 break;
454 case EV_EDIT:
455 if(m_pGameModeHelper) {
456 Dasher::CEditEvent * pEvt(static_cast< Dasher::CEditEvent * >(pEvent));
458 switch (pEvt->m_iEditType) {
459 case 1:
460 m_pGameModeHelper->Output(pEvt->m_sText);
461 break;
462 case 2:
463 m_pGameModeHelper->Delete(pEvt->m_sText.size());
464 break;
467 break;
468 case EV_EDIT_CONTEXT:
470 Dasher::CEditContextEvent *pEvt = static_cast< Dasher::CEditContextEvent * >(pEvent);
471 m_pDasher->SetContext(m_pEdit->get_context(pEvt->m_iOffset, pEvt->m_iLength));
473 break;
474 default:
475 break;
478 if(m_pEdit)
479 m_pEdit->HandleEvent(pEvent);
481 return 0;
484 LRESULT CDasherWindow::OnGameMessage(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
485 m_pGameGroup->Message(static_cast<int>(wParam), reinterpret_cast<const void*>(lParam));
486 bHandled=true;
487 return 0;
490 LRESULT CDasherWindow::OnDasherFocus(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
491 ::SetFocus(m_pEdit->GetHwnd());
493 // TODO: Is this obsolete?
494 HWND *pHwnd((HWND *)lParam);
495 m_pEdit->SetKeyboardTarget(*pHwnd);
496 return 0;
499 LRESULT CDasherWindow::OnDestroy(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
500 PostQuitMessage(0);
501 return 0;
504 #ifndef _WIN32_WCE
505 LRESULT CDasherWindow::OnGetMinMaxInfo(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
506 // not yet created
507 if (m_pToolbar == 0 || m_pSplitter == 0 || m_pSpeedAlphabetBar == 0)
508 return 0;
510 bHandled = TRUE;
511 LPPOINT lppt;
512 lppt = (LPPOINT) lParam; // lParam points to array of POINTs
513 lppt[3].x = 100; // Set minimum width (arbitrary)
514 // Set minimum height:
515 if(m_pAppSettings->GetBoolParameter(APP_BP_SHOW_TOOLBAR))
516 lppt[3].y = m_pToolbar->GetHeight() + m_pSplitter->GetPos()
517 + m_pSplitter->GetHeight() + m_pSpeedAlphabetBar->GetHeight() + GetSystemMetrics(SM_CYEDGE) * 10;
518 else
519 lppt[3].y = m_pSplitter->GetPos()
520 + m_pSplitter->GetHeight() + m_pSpeedAlphabetBar->GetHeight() + GetSystemMetrics(SM_CYEDGE) * 10;
522 return 0;
524 #endif
526 LRESULT CDasherWindow::OnInitMenuPopup(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
527 WinMenu.SortOut((HMENU) wParam);
528 return 0;
531 LRESULT CDasherWindow::OnClose(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
532 // TODO: Prompt for confirmation here
533 SaveWindowState();
534 DestroyWindow();
535 return 0;
538 LRESULT CDasherWindow::OnSize(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
539 if(wParam == SIZE_MINIMIZED)
540 return 0;
542 if(m_pToolbar)
543 m_pToolbar->Resize();
545 Layout();
547 return 0;
551 LRESULT CDasherWindow::OnSetFocus(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
552 m_pDasher->TakeFocus();
553 return 0;
556 LRESULT CDasherWindow::OnOther(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
557 // A switch statement would be preferable, except the message ids are
558 // not constant-expressions since they are provided by the system at
559 // runtime.
560 if (message == WM_DASHER_EVENT)
561 return OnDasherEvent( message, wParam, lParam, bHandled);
562 else if (message == WM_DASHER_FOCUS)
563 return OnDasherFocus(message, wParam, lParam, bHandled);
564 else if (message == WM_DASHER_GAME_MESSAGE)
565 return OnGameMessage(message, wParam, lParam, bHandled);
566 else if (message == DASHER_SHOW_PREFS) {
567 #ifndef _WIN32_WCE
568 CPrefs Prefs(m_hWnd, m_pDasher, m_pAppSettings);
569 #endif
572 return 0;
575 void CDasherWindow::Layout() {
576 int iStyle(m_pAppSettings->GetLongParameter(APP_LP_STYLE));
578 // Set up the window properties
579 #ifndef _WIN32_WCE
580 if((iStyle == APP_STYLE_COMPOSE) || (iStyle == APP_STYLE_DIRECT)) {
581 SetWindowLong(GWL_EXSTYLE, GetWindowLong(GWL_EXSTYLE) | WS_EX_NOACTIVATE | WS_EX_APPWINDOW);
582 SetWindowPos(HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
583 SetMenu(NULL);
585 else {
586 SetWindowLong(GWL_EXSTYLE, GetWindowLong(GWL_EXSTYLE) & !WS_EX_NOACTIVATE);
587 SetWindowPos(HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
588 SetMenu(m_hMenu);
590 #endif
592 // Now do the actual layout
594 bool bHorizontal(iStyle == APP_STYLE_COMPOSE);
595 bool bShowEdit(iStyle != APP_STYLE_DIRECT);
597 // Get the width of the window
598 RECT ClientRect;
599 GetClientRect( &ClientRect);
600 const int Width = ClientRect.right;
601 const int Height = ClientRect.bottom;
603 // Get the height of the toolbar widget
604 int ToolbarHeight;
605 if(m_pToolbar && m_pAppSettings->GetBoolParameter(APP_BP_SHOW_TOOLBAR))
606 ToolbarHeight = m_pToolbar->GetHeight();
607 else
608 ToolbarHeight = 0;
610 // Get the height of the control bar at the bottom of the screen
611 int SpeedAlphabetHeight;
612 if(m_pSpeedAlphabetBar != 0)
613 SpeedAlphabetHeight = m_pSpeedAlphabetBar->GetHeight();
614 else
615 SpeedAlphabetHeight = 0;
617 int GameGroupHeight = 0;
618 int GameGroupWidth = 0;
619 int GameLabelHeight = 0;
621 if(m_pGameGroup) {
622 GameGroupHeight = m_pGameGroup->GetHeight();
623 GameGroupWidth = m_pGameGroup->GetWidth();
624 GameLabelHeight = m_pGameGroup->GetLabelHeight();
627 int MaxCanvas = Height - SpeedAlphabetHeight*2;
628 int CurY = ToolbarHeight;
630 if(m_pSplitter) {
631 int SplitterPos = m_pSplitter->GetPos();
632 int SplitterHeight = m_pSplitter->GetHeight();
633 //SplitterPos = max(CurY + 2 * SplitterHeight, SplitterPos);
634 SplitterPos = max(CurY + GameGroupHeight, SplitterPos);
635 SplitterPos = min(SplitterPos, MaxCanvas - 3 * SplitterHeight);
636 m_pSplitter->Move(SplitterPos, Width);
638 if(bHorizontal) {
639 if(m_pDasher)
640 m_pDasher->Move(0, CurY, Width / 2, MaxCanvas - CurY);
642 if(m_pEdit)
643 m_pEdit->Move(Width / 2, CurY, Width / 2, MaxCanvas - CurY);
645 else {
646 if(bShowEdit) {
647 m_pEdit->ShowWindow(SW_SHOW);
648 m_pSplitter->ShowWindow(SW_SHOW);
649 m_pGameGroup->MoveWindow(0,CurY,Width,GameGroupHeight);
651 if(m_pEdit)
653 //m_pEdit->Move(2, CurY+2, Width, SplitterPos - CurY-2);
654 m_pEdit->Move(0, CurY+GameLabelHeight, Width-GameGroupWidth, SplitterPos - CurY-GameLabelHeight);
657 CurY = SplitterPos + SplitterHeight;
659 else {
660 m_pEdit->ShowWindow(SW_HIDE);
661 m_pSplitter->ShowWindow(SW_HIDE);
664 int CanvasHeight = Height - CurY - SpeedAlphabetHeight ;
665 //- GetSystemMetrics(SM_CYEDGE);
667 // Put the DasherControl in the correct place...
668 if(m_pDasher)
669 m_pDasher->Move(0, CurY, Width, CanvasHeight-5);
670 //m_pDasher->Move(2, CurY+2, Width-4, CanvasHeight-2);
672 // ...with the bottom bar just below it.
673 if(m_pSpeedAlphabetBar)
674 m_pSpeedAlphabetBar->MoveWindow(0, Height - SpeedAlphabetHeight, Width, SpeedAlphabetHeight);
675 // m_pSlidebar->MoveWindow(2, Height - SlidebarHeight, Width-4, SlidebarHeight);
681 #ifndef _WIN32_WCE
682 void CDasherWindow::HandleWinEvent(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime) {
683 // Ignore events if not in direct mode
684 if(m_pAppSettings && (m_pAppSettings->GetLongParameter(APP_LP_STYLE) != APP_STYLE_DIRECT))
685 return;
687 // For now assume all events are focus changes, so reset the buffer
688 if(m_pDasher)
689 m_pDasher->SetBuffer(0);
691 #endif