tagging release
[dasher.git] / Src / Win32 / DasherWindow.cpp
blob2b49884283650dcf049cd0128d85222da46adf0c
1 // DasherWindow.cpp
2 //
3 /////////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (c) 2002 Iain Murray, Inference Group, Cavendish, Cambridge.
6 //
7 /////////////////////////////////////////////////////////////////////////////
9 #include "WinCommon.h"
10 #include <guiddef.h>
11 #include <Oleacc.h>
12 // Don't seem to be needed and not in VC8 platform SDK, kdv
13 //#include <Textstor.h>
14 //#include <Msctf.h>
15 //#include <Msaatext.h>
16 #include <Htmlhelp.h>
18 #include "DasherWindow.h"
20 #include "Common/WinMenus.h"
22 #include "../DasherCore/DasherTypes.h"
23 #include "../DasherCore/ControlManager.h"
24 #include "Widgets/AboutBox.h"
25 #include "Widgets/AlphabetBox.h"
26 #include "Widgets/ColourBox.h"
27 #include "Widgets/KeyControl.h"
28 #include "Widgets/SplashScreen.h"
29 #include "Widgets/Prefs.h"
30 #include "Widgets/Toolbar.h"
31 #include "Widgets/Slidebar.h"
33 #include "DasherMouseInput.h"
34 #include "Dasher.h"
36 using namespace Dasher;
37 using namespace std;
40 #define IDT_TIMER1 200
42 #ifdef PJC_EXPERIMENTAL
44 // Bits an pieces from pjc playing with text service framework stuff
46 bool g_bInCallback(false);
47 HWND g_hWnd;
48 IAccClientDocMgr *g_pMgr;
49 VOID CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime);
51 #endif
53 CDasherWindow::CDasherWindow()
54 :Splash(0), m_pToolbar(0), m_pEdit(0), m_pSlidebar(0), m_pSplitter(0), m_pDasher(0), m_pCanvas(0)
57 m_hIconSm = (HICON) LoadImage(WinHelper::hInstApp, (LPCTSTR) IDI_DASHER, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
59 ATL::CWndClassInfo& wc = CDasherWindow::GetWndClassInfo();
60 wc.m_wc.hIcon = LoadIcon(WinHelper::hInstApp, (LPCTSTR) IDI_DASHER);
61 wc.m_wc.hCursor = LoadCursor(NULL, IDC_ARROW);
62 wc.m_wc.hbrBackground = (HBRUSH) (COLOR_ACTIVEBORDER + 1); // Must add one to the value we want for some unknown reason
63 wc.m_wc.lpszMenuName = (LPCTSTR) IDC_DASHER;
64 // wc.m_wc.lpszClassName = WndClassName; // Not in a resource - does not require translation
65 wc.m_wc.hIconSm = m_hIconSm;
67 #ifdef PJC_EXPERIMENTAL
69 // Create an acc manager foobar
71 CLSID MyClsid;
73 MyClsid.Data1 = 0xFC48CC30;
74 MyClsid.Data2 = 0x4F3E;
75 MyClsid.Data3 = 0x4fa1;
76 MyClsid.Data4[0] = 0x80;
77 MyClsid.Data4[1] = 0x3B;
78 MyClsid.Data4[2] = 0xAD;
79 MyClsid.Data4[3] = 0x0E;
80 MyClsid.Data4[4] = 0x19;
81 MyClsid.Data4[5] = 0x6A;
82 MyClsid.Data4[6] = 0x83;
83 MyClsid.Data4[7] = 0xB1;
85 IID MyIid;
87 MyIid.Data1 = 0x4C896039;
88 MyIid.Data2 = 0x7B6D;
89 MyIid.Data3 = 0x49e6;
90 MyIid.Data4[0] = 0xA8;
91 MyIid.Data4[1] = 0xC1;
92 MyIid.Data4[2] = 0x45;
93 MyIid.Data4[3] = 0x11;
94 MyIid.Data4[4] = 0x6A;
95 MyIid.Data4[5] = 0x98;
96 MyIid.Data4[6] = 0x29;
97 MyIid.Data4[7] = 0x2B;
100 HRESULT Foo = CoCreateInstance(MyClsid, 0, CLSCTX_ALL, MyIid, (void**)&g_pMgr);
101 g_pMgr->AddRef();
102 // Set up callback for WinEvents
104 HWINEVENTHOOK hEventHook;
106 hEventHook = SetWinEventHook(EVENT_OBJECT_FOCUS, // Get all events.
107 EVENT_OBJECT_FOCUS,
108 GetModuleHandle(NULL), // Use this module
109 WinEventProc,
110 0, // All processes
111 0, // All threads
112 WINEVENT_OUTOFCONTEXT);
113 if(!hEventHook) {
114 MessageBox(NULL, L"Initialisation of WinEvent hook failed");
116 #endif
120 HWND CDasherWindow::Create()
122 hAccelTable = LoadAccelerators(WinHelper::hInstApp, (LPCTSTR) IDC_DASHER);
124 // Get window title from resource script
125 Tstring WindowTitle;
126 WinLocalisation::GetResourceString(IDS_APP_TITLE, &WindowTitle);
128 m_pAppSettings = new CAppSettings(0, 0);
129 int iStyle(m_pAppSettings->GetLongParameter(APP_LP_STYLE));
131 HWND hWnd;
132 if((iStyle == 1) || (iStyle == 2))
133 hWnd = CWindowImpl<CDasherWindow >::Create(NULL, NULL, WindowTitle.c_str(), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, WS_EX_NOACTIVATE | WS_EX_APPWINDOW | WS_EX_TOPMOST);
134 else
135 hWnd = CWindowImpl<CDasherWindow >::Create(NULL, NULL, WindowTitle.c_str(), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN);
137 // Create Widgets
138 m_pDasher = new CDasher(hWnd);
140 // Create a CAppSettings
141 m_pAppSettings->SetHwnd(hWnd);
142 m_pAppSettings->SetDasher(m_pDasher);
144 m_pEdit = new CEdit(m_pAppSettings);
145 m_pEdit->Create(hWnd, m_pAppSettings->GetBoolParameter(APP_BP_TIME_STAMP));
146 m_pEdit->SetFont(m_pAppSettings->GetStringParameter(APP_SP_EDIT_FONT), m_pAppSettings->GetLongParameter(APP_LP_EDIT_FONT_SIZE));
148 #ifdef PJC_EXPERIMENTAL
149 g_hWnd = m_pEdit->GetHwnd();
150 #endif
152 m_pToolbar = new CToolbar(hWnd, m_pAppSettings->GetBoolParameter(APP_BP_SHOW_TOOLBAR));
154 // FIXME - the edit box really shouldn't need access to the interface,
155 // but at the moment it does, for training, blanking the display etc
157 m_pEdit->SetInterface(m_pDasher);
159 // FIXME - we shouldn't need to know about these outside of CDasher
161 m_pCanvas = m_pDasher->GetCanvas();
163 m_pSlidebar = new CSlidebar(hWnd, m_pDasher);
166 m_pSplitter = new CSplitter(this,100);
168 HWND hSplitter = m_pSplitter->Create(hWnd);
170 if (!hSplitter)
171 return 0;
173 // Add extra control nodes
175 m_pDasher->RegisterNode( Dasher::CControlManager::CTL_USER, "Speak", -1 );
176 m_pDasher->RegisterNode( Dasher::CControlManager::CTL_USER+1, "All", -1 );
177 m_pDasher->RegisterNode( Dasher::CControlManager::CTL_USER+2, "New", -1 );
178 m_pDasher->RegisterNode( Dasher::CControlManager::CTL_USER+3, "Repeat", -1 );
180 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_USER, Dasher::CControlManager::CTL_ROOT, -2);
182 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_USER+1, Dasher::CControlManager::CTL_USER, -2);
183 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_USER+2, Dasher::CControlManager::CTL_USER, -2);
184 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_USER+3, Dasher::CControlManager::CTL_USER, -2);
186 m_pDasher->ConnectNode(-1, Dasher::CControlManager::CTL_USER+1, -2);
187 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_ROOT, Dasher::CControlManager::CTL_USER+1, -2);
189 m_pDasher->ConnectNode(-1, Dasher::CControlManager::CTL_USER+2, -2);
190 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_ROOT, Dasher::CControlManager::CTL_USER+2, -2);
192 m_pDasher->ConnectNode(-1, Dasher::CControlManager::CTL_USER+3, -2);
193 m_pDasher->ConnectNode(Dasher::CControlManager::CTL_ROOT, Dasher::CControlManager::CTL_USER+3, -2);
195 m_pGameModeHelper = 0;
197 return hWnd;
200 CDasherWindow::~CDasherWindow() {
201 delete Splash; // In case Show() was never called.
202 delete m_pToolbar;
203 delete m_pEdit;
204 delete m_pSplitter;
205 delete m_pDasher;
206 delete m_pAppSettings;
207 DestroyIcon(m_hIconSm);
212 void CDasherWindow::Main()
214 DASHER_ASSERT_VALIDPTR_RW(m_pDasher);
215 m_pDasher->Main();
216 Sleep(50); // limits framerate to 50fps
219 int CDasherWindow::MessageLoop()
221 MSG msg;
223 while(GetMessage(&msg, NULL, 0, 0)) {
224 if(!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
225 TranslateMessage(&msg);
226 DispatchMessage(&msg);
230 m_pDasher->StartShutdown();
232 return msg.wParam;
235 /////////////////////////////////////////////////////////////////////////////
237 void CDasherWindow::Show(int nCmdShow)
239 // Make sure Dasher has started up.
240 // m_pDasher->Start();
242 // Clear SplashScreen
243 delete Splash;
244 Splash = 0;
246 // Show Window
247 InvalidateRect( NULL, FALSE);
248 if(!LoadWindowState())
249 ShowWindow(nCmdShow); // Now set up. Kill splash screen and display main window
253 void CDasherWindow::SaveWindowState() const
255 #ifndef DASHER_WINCE
256 WINDOWPLACEMENT wp;
257 wp.length = sizeof(WINDOWPLACEMENT);
259 if(GetWindowPlacement( &wp)) {//function call succeeds
260 m_pAppSettings->SaveSetting("WindowState", &wp);
262 #endif
265 bool CDasherWindow::LoadWindowState() {
266 #ifndef DASHER_WINCE
267 WINDOWPLACEMENT wp;
269 if(m_pAppSettings->LoadSetting("WindowState", &wp))
271 if(SetWindowPlacement(&wp))
272 return true;
274 #endif
275 return false;
278 void CDasherWindow::HandleParameterChange(int iParameter) {
279 switch(iParameter) {
280 case APP_BP_SHOW_TOOLBAR:
281 m_pToolbar->ShowToolbar(m_pAppSettings->GetBoolParameter(APP_BP_SHOW_TOOLBAR));
282 break;
283 case APP_LP_STYLE:
284 Layout();
285 break;
286 case APP_BP_TIME_STAMP:
287 // TODO: reimplement
288 // m_pEdit->TimeStampNewFiles(m_pAppSettings->GetBoolParameter(APP_BP_TIME_STAMP));
289 break;
290 case LP_MAX_BITRATE:
291 // TODO: reimplement
292 break;
293 case APP_SP_EDIT_FONT:
294 case APP_LP_EDIT_FONT_SIZE:
295 m_pEdit->SetFont(m_pAppSettings->GetStringParameter(APP_SP_EDIT_FONT), m_pAppSettings->GetLongParameter(APP_LP_EDIT_FONT_SIZE));
296 break;
300 void CDasherWindow::HandleControlEvent(int iID) {
301 switch(iID) {
302 case Dasher::CControlManager::CTL_MOVE_FORWARD_CHAR:
303 if(m_pEdit)
304 m_pEdit->Move(EDIT_FORWARDS, EDIT_CHAR);
305 break;
306 case Dasher::CControlManager::CTL_MOVE_FORWARD_WORD:
307 if(m_pEdit)
308 m_pEdit->Move(EDIT_FORWARDS, EDIT_WORD);
309 break;
310 case Dasher::CControlManager::CTL_MOVE_FORWARD_LINE:
311 if(m_pEdit)
312 m_pEdit->Move(EDIT_FORWARDS, EDIT_LINE);
313 break;
314 case Dasher::CControlManager::CTL_MOVE_FORWARD_FILE:
315 if(m_pEdit)
316 m_pEdit->Move(EDIT_FORWARDS, EDIT_FILE);
317 break;
318 case Dasher::CControlManager::CTL_MOVE_BACKWARD_CHAR:
319 if(m_pEdit)
320 m_pEdit->Move(EDIT_BACKWARDS, EDIT_CHAR);
321 break;
322 case Dasher::CControlManager::CTL_MOVE_BACKWARD_WORD:
323 if(m_pEdit)
324 m_pEdit->Move(EDIT_BACKWARDS, EDIT_WORD);
325 break;
326 case Dasher::CControlManager::CTL_MOVE_BACKWARD_LINE:
327 if(m_pEdit)
328 m_pEdit->Move(EDIT_BACKWARDS, EDIT_LINE);
329 break;
330 case Dasher::CControlManager::CTL_MOVE_BACKWARD_FILE:
331 if(m_pEdit)
332 m_pEdit->Move(EDIT_BACKWARDS, EDIT_FILE);
333 break;
334 case Dasher::CControlManager::CTL_DELETE_FORWARD_CHAR:
335 if(m_pEdit)
336 m_pEdit->Delete(EDIT_FORWARDS, EDIT_CHAR);
337 break;
338 case Dasher::CControlManager::CTL_DELETE_FORWARD_WORD:
339 if(m_pEdit)
340 m_pEdit->Delete(EDIT_FORWARDS, EDIT_WORD);
341 break;
342 case Dasher::CControlManager::CTL_DELETE_FORWARD_LINE:
343 if(m_pEdit)
344 m_pEdit->Delete(EDIT_FORWARDS, EDIT_LINE);
345 break;
346 case Dasher::CControlManager::CTL_DELETE_FORWARD_FILE:
347 if(m_pEdit)
348 m_pEdit->Delete(EDIT_FORWARDS, EDIT_FILE);
349 break;
350 case Dasher::CControlManager::CTL_DELETE_BACKWARD_CHAR:
351 if(m_pEdit)
352 m_pEdit->Delete(EDIT_BACKWARDS, EDIT_CHAR);
353 break;
354 case Dasher::CControlManager::CTL_DELETE_BACKWARD_WORD:
355 if(m_pEdit)
356 m_pEdit->Delete(EDIT_BACKWARDS, EDIT_WORD);
357 break;
358 case Dasher::CControlManager::CTL_DELETE_BACKWARD_LINE:
359 if(m_pEdit)
360 m_pEdit->Delete(EDIT_BACKWARDS, EDIT_LINE);
361 break;
362 case Dasher::CControlManager::CTL_DELETE_BACKWARD_FILE:
363 if(m_pEdit)
364 m_pEdit->Delete(EDIT_BACKWARDS, EDIT_FILE);
365 break;
366 case Dasher::CControlManager::CTL_USER+1: // Speak all
367 if(m_pEdit)
368 m_pEdit->speak(1);
369 break;
370 case Dasher::CControlManager::CTL_USER+2: // Speak new
371 if(m_pEdit)
372 m_pEdit->speak(2);
373 break;
374 case Dasher::CControlManager::CTL_USER+3: // Repeat speech
375 if(m_pEdit)
376 m_pEdit->speak(3);
377 break;
383 LRESULT CDasherWindow::OnCommand(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
385 const int wmId = LOWORD(wParam);
386 const int wmEvent = HIWORD(wParam);
388 // Tell edit box if it has changed. It should know itself really, but this is easier
389 if( m_pEdit && ((HWND) lParam == m_pEdit->GetHwnd()) && (HIWORD(wParam) == EN_CHANGE)) {
390 m_pEdit->SetDirty();
391 return 0;
394 RECT windowsize;
396 // Parse the menu selections:
397 switch (wmId)
399 case ID_OPTIONS_FONTSIZE_NORMAL:
400 m_pDasher->SetLongParameter(LP_DASHER_FONTSIZE, Dasher::Opts::FontSize(1));
401 break;
402 case ID_OPTIONS_FONTSIZE_LARGE:
403 m_pDasher->SetLongParameter(LP_DASHER_FONTSIZE, Dasher::Opts::FontSize(2));
404 break;
405 case ID_OPTIONS_FONTSIZE_VERYLARGE:
406 m_pDasher->SetLongParameter(LP_DASHER_FONTSIZE, Dasher::Opts::FontSize(4));
407 break;
408 case ID_OPTIONS_EDITFONT:{
409 CHOOSEFONT Data;
410 LOGFONT lf;
411 HFONT Font = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
412 GetObject(Font, sizeof(LOGFONT), &lf);
413 Tstring tstrFaceName;
414 WinUTF8::UTF8string_to_wstring(m_pAppSettings->GetStringParameter(APP_SP_EDIT_FONT), tstrFaceName);
415 _tcscpy(lf.lfFaceName, tstrFaceName.c_str());
416 lf.lfHeight = m_pAppSettings->GetLongParameter(APP_LP_EDIT_FONT_SIZE);
417 Data.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
418 Data.lStructSize = sizeof(CHOOSEFONT);
419 Data.hwndOwner = m_hWnd;
420 Data.lpLogFont = &lf;
421 if(ChooseFont(&Data)) {
422 string FontName;
423 WinUTF8::wstring_to_UTF8string(lf.lfFaceName, FontName);
424 m_pAppSettings->SetStringParameter(APP_SP_EDIT_FONT, FontName);
425 m_pAppSettings->SetLongParameter(APP_LP_EDIT_FONT_SIZE, lf.lfHeight);
428 break;
429 case ID_OPTIONS_DASHERFONT:
431 CHOOSEFONT Data;
432 LOGFONT lf;
433 HFONT Font = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
434 GetObject(Font, sizeof(LOGFONT), &lf);
435 Tstring tstrFaceName;
436 WinUTF8::UTF8string_to_wstring(m_pAppSettings->GetStringParameter(SP_DASHER_FONT), tstrFaceName);
437 _tcscpy(lf.lfFaceName, tstrFaceName.c_str());
438 Data.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
439 Data.lStructSize = sizeof(CHOOSEFONT);
440 Data.hwndOwner = m_hWnd;
441 Data.lpLogFont = &lf;
442 if(ChooseFont(&Data)) {
443 string FontName;
444 WinUTF8::wstring_to_UTF8string(lf.lfFaceName, FontName);
445 m_pAppSettings->SetStringParameter(SP_DASHER_FONT, FontName);
448 return 0;
449 case ID_OPTIONS_RESETFONT:
450 m_pAppSettings->ResetParamater(SP_DASHER_FONT);
451 m_pAppSettings->ResetParamater(APP_SP_EDIT_FONT);
452 return 0;
453 case IDM_ABOUT: {
454 CAboutBox Aboutbox;
455 Aboutbox.DoModal(m_hWnd);
456 return 0;
458 case ID_OPTIONS_PREFS: {
459 CPrefs Prefs(m_hWnd, m_pDasher, m_pAppSettings);
460 return 0;
462 case ID_HELP_CONTENTS:
463 HtmlHelp(m_hWnd, L"Dasher.chm", HH_DISPLAY_INDEX, NULL);
464 return 0;
465 case ID_HELP_DASHERTUTORIAL:
466 m_pGameModeHelper = new CGameModeHelper(m_pDasher);
467 return 0;
468 case IDM_EXIT:
469 DestroyWindow();
470 return 0;
471 case ID_EDIT_SELECTALL:
472 if(m_pEdit)
473 m_pEdit->SelectAll();
474 return 0;
475 case ID_EDIT_CUT:
476 if(m_pEdit)
477 m_pEdit->Cut();
478 return 0;
479 case ID_EDIT_COPY:
480 if(m_pEdit)
481 m_pEdit->Copy();
482 return 0;
483 case ID_EDIT_COPY_ALL:
484 if(m_pEdit)
485 m_pEdit->CopyAll();
486 return 0;
487 case ID_EDIT_PASTE:
488 if(m_pEdit)
489 m_pEdit->Paste();
490 return 0;
491 case ID_FILE_NEW:
492 if(m_pEdit)
493 m_pEdit->New();
494 // Selecting file->new indicates a new trial to our user logging object
495 if (m_pDasher != NULL) {
496 CUserLogBase* pUserLog = m_pDasher->GetUserLogPtr();
497 if (pUserLog != NULL)
498 pUserLog->NewTrial();
500 return 0;
501 case ID_FILE_OPEN:
502 if(m_pEdit)
503 m_pEdit->Open();
504 return 0;
505 case ID_FILE_SAVE:
506 if(m_pEdit)
507 if(!m_pEdit->Save())
508 m_pEdit->SaveAs();
509 return 0;
510 case ID_FILE_SAVE_AS:
511 if(m_pEdit)
512 m_pEdit->SaveAs();
513 return 0;
514 case ID_IMPORT_TRAINFILE:
515 // TODO: Fix dummy arguments
516 m_pDasher->TrainFile(m_pEdit->Import(),0,0);
517 return 0;
518 default:
519 return DefWindowProc(message, wParam, lParam);
522 PopulateSettings();
523 Layout();
524 return 0;
527 LRESULT CDasherWindow::OnDasherEvent(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
528 // Apparently putting the typecast directly in the switch doesn't work
529 CEvent *pEvent( (CEvent *)lParam );
531 switch(pEvent->m_iEventType) {
532 case EV_PARAM_NOTIFY:
533 HandleParameterChange(((CParameterNotificationEvent *)pEvent)->m_iParameter);
534 break;
535 case EV_CONTROL:
536 HandleControlEvent(((CControlEvent *)pEvent)->m_iID);
537 break;
538 case EV_EDIT:
539 if(m_pGameModeHelper) {
540 Dasher::CEditEvent * pEvt(static_cast< Dasher::CEditEvent * >(pEvent));
542 switch (pEvt->m_iEditType) {
543 case 1:
544 m_pGameModeHelper->Output(pEvt->m_sText);
545 break;
546 case 2:
547 m_pGameModeHelper->Delete(pEvt->m_sText.size());
548 break;
551 break;
554 default:
555 break;
558 if(m_pEdit)
559 m_pEdit->HandleEvent(pEvent);
561 return 0;
564 LRESULT CDasherWindow::OnDasherFocus(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
565 ::SetFocus(m_pEdit->GetHwnd());
567 // TODO: Is this obsolete?
568 HWND *pHwnd((HWND *)lParam);
569 m_pEdit->SetKeyboardTarget(*pHwnd);
570 return 0;
573 LRESULT CDasherWindow::OnDestroy(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
574 if(m_pEdit != 0) {
575 m_pEdit->write_to_file();
578 PostQuitMessage(0);
579 return 0;
582 LRESULT CDasherWindow::OnGetMinMaxInfo(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
583 // not yet created
584 if (m_pToolbar == 0 || m_pSplitter == 0 || m_pSlidebar == 0)
585 return 0;
587 bHandled = TRUE;
588 LPPOINT lppt;
589 lppt = (LPPOINT) lParam; // lParam points to array of POINTs
590 lppt[3].x = 100; // Set minimum width (arbitrary)
591 // Set minimum height:
592 if(m_pAppSettings->GetBoolParameter(APP_BP_SHOW_TOOLBAR))
593 lppt[3].y = m_pToolbar->GetHeight() + m_pSplitter->GetPos()
594 + m_pSplitter->GetHeight() + m_pSlidebar->GetHeight() + GetSystemMetrics(SM_CYEDGE) * 10;
595 else
596 lppt[3].y = m_pSplitter->GetPos()
597 + m_pSplitter->GetHeight() + m_pSlidebar->GetHeight() + GetSystemMetrics(SM_CYEDGE) * 10;
599 return 0;
602 LRESULT CDasherWindow::OnInitMenuPopup(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
603 PopulateSettings();
604 WinMenu.SortOut((HMENU) wParam);
605 return 0;
608 LRESULT CDasherWindow::OnClose(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
609 // TODO: Prompt for confirmation here
610 SaveWindowState();
611 DestroyWindow();
612 return 0;
615 LRESULT CDasherWindow::OnSize(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
616 if(wParam == SIZE_MINIMIZED)
617 return 0;
619 m_pToolbar->Resize();
620 m_pSlidebar->Resize();
622 Layout();
624 return 0;
628 LRESULT CDasherWindow::OnSetFocus(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
629 ::SetFocus(m_pCanvas->getwindow());
630 return 0;
633 LRESULT CDasherWindow::OnOther(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
634 if (message == WM_DASHER_EVENT)
635 return OnDasherEvent( message, wParam, lParam, bHandled);
636 else if (message == WM_DASHER_FOCUS)
637 return OnDasherFocus(message, wParam, lParam, bHandled);
638 else if (message == DASHER_SHOW_PREFS) {
639 CPrefs Prefs(m_hWnd, m_pDasher, m_pAppSettings);
641 return 0;
644 void CDasherWindow::Layout() {
645 int iStyle(m_pAppSettings->GetLongParameter(APP_LP_STYLE));
647 // Set up the window properties
649 if((iStyle == 1) || (iStyle == 2)) {
650 SetWindowLong(GWL_EXSTYLE, GetWindowLong(GWL_EXSTYLE) | WS_EX_NOACTIVATE | WS_EX_APPWINDOW);
651 SetWindowPos(HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
653 else {
654 SetWindowLong(GWL_EXSTYLE, GetWindowLong(GWL_EXSTYLE) & !WS_EX_NOACTIVATE);
655 SetWindowPos(HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
658 // Now do the actual layout
660 bool bHorizontal(iStyle == 1);
661 bool bShowEdit(iStyle != 2);
663 RECT ClientRect;
664 GetClientRect( &ClientRect);
665 const int Width = ClientRect.right;
666 const int Height = ClientRect.bottom;
668 int ToolbarHeight;
669 if((m_pToolbar != 0) && m_pAppSettings->GetBoolParameter(APP_BP_SHOW_TOOLBAR))
670 ToolbarHeight = m_pToolbar->GetHeight() + 2;
671 else
672 ToolbarHeight = 0;
673 int CurY = ToolbarHeight;
675 int SlidebarHeight;
676 if(m_pSlidebar != 0)
677 SlidebarHeight = m_pSlidebar->GetHeight();
678 else
679 SlidebarHeight = 0;
680 int MaxCanvas = Height - SlidebarHeight;
682 if(m_pSplitter) {
683 int SplitterPos = m_pSplitter->GetPos();
684 int SplitterHeight = m_pSplitter->GetHeight();
685 SplitterPos = max(CurY + 2 * SplitterHeight, SplitterPos);
686 SplitterPos = min(SplitterPos, MaxCanvas - 3 * SplitterHeight);
687 m_pSplitter->Move(SplitterPos, Width);
689 if(bHorizontal) {
690 if(m_pCanvas)
691 m_pCanvas->Move(0, CurY, Width / 2, MaxCanvas - CurY);
693 if(m_pEdit)
694 m_pEdit->Move(Width / 2, CurY, Width / 2, MaxCanvas - CurY);
696 else {
697 if(bShowEdit) {
698 m_pEdit->ShowWindow(SW_SHOW);
699 m_pSplitter->ShowWindow(SW_SHOW);
701 if(m_pEdit)
702 m_pEdit->Move(0, CurY, Width, SplitterPos - CurY);
704 CurY = SplitterPos + SplitterHeight;
706 else {
707 m_pEdit->ShowWindow(SW_HIDE);
708 m_pSplitter->ShowWindow(SW_HIDE);
711 int CanvasHeight = Height - CurY - SlidebarHeight - GetSystemMetrics(SM_CYEDGE);
713 if(m_pCanvas)
714 m_pCanvas->Move(0, CurY, Width, CanvasHeight);
719 void CDasherWindow::PopulateSettings() {
720 if(m_pDasher) {
721 WinMenu.SetStatus(ID_OPTIONS_FONTSIZE_NORMAL, false, m_pDasher->GetLongParameter(LP_DASHER_FONTSIZE)==1);
722 WinMenu.SetStatus(ID_OPTIONS_FONTSIZE_LARGE, false, m_pDasher->GetLongParameter(LP_DASHER_FONTSIZE)==2);
723 WinMenu.SetStatus(ID_OPTIONS_FONTSIZE_VERYLARGE, false, m_pDasher->GetLongParameter(LP_DASHER_FONTSIZE)==4);
727 #ifdef PJC_EXPERIMENTAL
729 VOID CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime) {
731 if(hwnd == g_hWnd)
732 return;
734 if(!g_bInCallback) {
735 g_bInCallback = true;
736 VARIANT MyV;
737 IAccessible *pMyAccessible;
738 VariantInit(&MyV);
740 if( AccessibleObjectFromEvent( hwnd, idObject, idChild, &pMyAccessible, &MyV) != S_OK) {
741 // Do nothing
743 else {
744 VARIANT MyV2;
745 VariantInit(&MyV2);
747 pMyAccessible->get_accRole(MyV, &MyV2);
749 // if(MyV2.iVal == ROLE_SYSTEM_TEXT) {
750 ITextStoreAnchor *pAnchor(NULL);
751 HRESULT MyFoo = g_pMgr->GetFocused(IID_ITextStoreAnchor, (IUnknown **)(&pAnchor));
752 pAnchor->AddRef();
753 // pMyAccessible->QueryInterface(IID_ITextStoreAnchor, (void **)(&pAnchor));
754 // MessageBox(NULL, L"Got Text", L"Foo", MB_OK);
755 HRESULT MyBar;
757 if(pAnchor) {
758 IAnchor *pStart;
759 IAnchor *pEnd;
762 HRESULT MyLock;
763 HRESULT MyLock2;
765 IEnumUnknown *pMyEnum;
767 g_pMgr->GetDocuments(&pMyEnum);
769 if(pMyEnum) {
770 pMyEnum->AddRef();
773 MyLock = pAnchor->RequestLock(TS_LF_READWRITE, &MyLock2);
775 MyBar = pAnchor->InsertTextAtSelection(TF_IAS_NOQUERY, L"Foo", 3, &pStart, &pEnd);
776 //MessageBox(NULL, L"Got Text", L"Foo", MB_OK);
779 VariantClear(&MyV2);
782 VariantClear(&MyV);
783 g_bInCallback = false;
787 #endif