Make it build on Windows again (don't expect it to actually work sensibly
[dasher.git] / Src / Win32 / Widgets / Canvas.cpp
blobdfa83872356068dbbfdf94619a895c78273da7a5
1 // Canvas.cpp
2 //
3 /////////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (c) 2002 Iain Murray, Inference Group, Cavendish, Cambridge.
6 //
7 /////////////////////////////////////////////////////////////////////////////
9 #include "..\Common\WinCommon.h"
11 #include "Canvas.h"
12 //#include "Edit.h"
13 #include "../Dasher.h"
14 #include "../DasherInterface.h"
18 #define PRESSED 0x8000
19 #define REPEAT 0x40000000
20 using namespace Dasher;
22 #include "../TabletPC/SystemInfo.h"
23 #include "Screen.h"
25 /////////////////////////////////////////////////////////////////////////////
27 CCanvas::CCanvas(CDasherInterface *DI, Dasher::CEventHandler *pEventHandler, CSettingsStore *pSettingsStore)
28 :m_pDasherInterface(DI), imousex(0), imousey(0), buttonnum(0), mousepostime(0) ,
29 m_dwTicksLastEvent(0), m_bButtonDown(false), m_pScreen(0),
30 CDasherComponent(pEventHandler, pSettingsStore)
34 #ifndef _WIN32_WCE
36 #else
37 WNDCLASS canvasclass;
38 GetClassInfo(NULL, TEXT("STATIC"), &canvasclass);
39 canvasclass.lpszClassName = TEXT("CANVAS");
41 #endif
44 /////////////////////////////////////////////////////////////////////////////
46 HWND CCanvas::Create(HWND hParent)
48 HWND hWnd = CWindowImpl<CCanvas>::Create(hParent, NULL, NULL, WS_CHILD | WS_VISIBLE ,WS_EX_CLIENTEDGE);
50 m_hdc = GetDC();
51 HDC hdc2 = GetDC();
52 HDC hdc3 = GetDC();
54 // Create input device objects
55 // NB We create the SocketInput object now, even if socket input is not enabled, because
56 // we can't safely create it later in response to a parameter change event (because it itself
57 // needs to register an event listener when it constructs itself).
59 // CreateSettingsStore only creates a new one if there isn't one there already
62 // TODO: Reimplement?
64 // m_pSocketInput = (CSocketInput *)m_pDasherInterface->GetModule(1);
65 // m_pSocketInput->Ref();
67 //m_pMouseInput = (CDasherMouseInput *)m_pDasherInterface->GetModule(0);
68 // m_pMouseInput->Ref();
70 /*if(m_pDasherInterface->GetBoolParameter(BP_SOCKET_INPUT_ENABLE))
72 m_pSocketInput->StartListening();
73 m_pDasherInterface->SetInput(1);
75 else {
76 m_pDasherInterface->SetInput(0);
77 }*/
80 m_pKeyboardHelper = new CKeyboardHelper;
82 m_pScreen = new CScreen(m_hdc, 300, 300);
83 m_pScreen->SetFont(m_pDasherInterface->GetStringParameter(SP_DASHER_FONT));
84 //ReleaseDC(m_hwnd,m_hDC);
85 m_pDasherInterface->ChangeScreen(m_pScreen);
87 for(int i = 0; i < 18; i++)
89 keycoords[i] = 0;
91 running = 0;
92 previoustime = GetTickCount();
93 direction = 0;
95 return hWnd;
98 /////////////////////////////////////////////////////////////////////////////
100 void CCanvas::SetScreenInterface(CDasherInterface * dasherinterface)
102 m_pScreen->SetInterface(dasherinterface);
105 /////////////////////////////////////////////////////////////////////////////
107 LRESULT CCanvas::OnCreate(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
109 bHandled = TRUE;
111 // If we're a tablet, initialize the event-generator
112 if (IsTabletPC())
114 HRESULT h = m_CursorInRange.Initialize(m_hWnd);
115 if (! SUCCEEDED(h))
117 // detected tablet, but cant initialize the event-generator
118 return -1;
121 return 0;
124 /////////////////////////////////////////////////////////////////////////////
126 LRESULT CCanvas::OnDestroy(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
128 int iRC = ReleaseDC(m_hdc);
129 if(!iRC) {
130 LPVOID lpMsgBuf;
131 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
132 (LPTSTR) & lpMsgBuf, 0, NULL);
133 // Process any inserts in lpMsgBuf.
134 // ...
135 // Display the string.
136 ::MessageBox(NULL, (LPCTSTR) lpMsgBuf, TEXT("Error"), MB_OK | MB_ICONINFORMATION);
137 // Free the buffer.
138 LocalFree(lpMsgBuf);
141 bHandled = true;
142 return 0;
145 /////////////////////////////////////////////////////////////////////////////
147 CCanvas::~CCanvas() {
148 delete m_pScreen;
149 //if(m_pMouseInput != NULL) {
150 // delete m_pMouseInput;
152 //if(m_pSocketInput != NULL) {
153 // delete m_pSocketInput;
156 if(m_pKeyboardHelper)
157 delete m_pKeyboardHelper;
160 void CCanvas::Move(int x, int y, int Width, int Height)
162 MoveWindow(x, y, Width, Height, TRUE);
165 void CCanvas::Paint()
167 InvalidateRect(NULL, FALSE);
168 UpdateWindow();
172 LRESULT CCanvas::OnCommand(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
174 bHandled = TRUE;
175 SendMessage(GetParent(), message, wParam, lParam);
176 return 0;
179 LRESULT CCanvas::OnSetFocus(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
181 bHandled = TRUE;
182 SendMessage(GetParent(), WM_DASHER_FOCUS, 0, (LPARAM)&m_hWnd);
183 return 0;
186 LRESULT CCanvas::OnPaint(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
188 PAINTSTRUCT ps;
189 BeginPaint(&ps);
191 m_pScreen->Display();
193 EndPaint(&ps);
195 bHandled = TRUE;
196 return 0;
199 LRESULT CCanvas::OnKeyUp(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
201 bHandled = TRUE;
203 int iKeyVal(-1);
205 if(m_pKeyboardHelper)
206 iKeyVal = m_pKeyboardHelper->ConvertKeyCode(wParam);
208 if(iKeyVal != -1) {
209 m_pDasherInterface->KeyUp(GetTickCount(), iKeyVal);
210 return 0;
213 switch(wParam)
215 case VK_SHIFT:
216 if(GetKeyState(VK_CONTROL) & PRESSED)
217 m_pDasherInterface->SetLongParameter(LP_BOOSTFACTOR, 25);
218 else
219 m_pDasherInterface->SetLongParameter(LP_BOOSTFACTOR, 100);
220 return 0;
221 case VK_CONTROL:
222 if(GetKeyState(VK_SHIFT) & PRESSED)
223 m_pDasherInterface->SetLongParameter(LP_BOOSTFACTOR, 175);
224 else
225 m_pDasherInterface->SetLongParameter(LP_BOOSTFACTOR, 100);
227 return 0;
228 default:
229 return 0;
234 LRESULT CCanvas::OnKeyDown(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
236 #ifdef _DEBUG
237 TCHAR tmpAutoOffset[128];
238 #endif
240 bHandled = TRUE;
242 int iKeyVal(-1);
244 if(m_pKeyboardHelper)
245 iKeyVal = m_pKeyboardHelper->ConvertKeyCode(wParam);
247 if(iKeyVal != -1) {
248 m_pDasherInterface->KeyDown(GetTickCount(), iKeyVal);
249 return 0;
252 switch (wParam) {
253 // Space, for start/stop events etc.
254 case VK_SPACE:
255 m_pDasherInterface->KeyDown(GetTickCount(), 0);
256 return 0;
258 #ifdef _DEBUG
259 case VK_F11:
260 wsprintf(tmpAutoOffset, TEXT("yAutoValue: %d"), m_pDasherInterface->GetAutoOffset());
261 MessageBox(tmpAutoOffset, TEXT("Auto-offset Value"), MB_OK);
262 return 0;
263 #endif
265 case VK_F12:
266 centrecursor();
267 return 0;
269 // Boost keys
270 case VK_SHIFT:
271 if(lParam ^ REPEAT) // ignore auto-repeat
272 m_pDasherInterface->SetLongParameter(LP_BOOSTFACTOR, 175);
273 return 0;
274 case VK_CONTROL:
275 if(lParam ^ REPEAT) // ignore auto-repeat
276 m_pDasherInterface->SetLongParameter(LP_BOOSTFACTOR, 25);
277 return 0;
279 // Button mode keys
280 case 0x41:
281 m_pDasherInterface->KeyDown(GetTickCount(), 1);
282 return 0;
283 case 0x53:
284 m_pDasherInterface->KeyDown(GetTickCount(), 2);
285 return 0;
286 case 0x57:
287 m_pDasherInterface->KeyDown(GetTickCount(), 3);
288 return 0;
289 case 0x58:
290 m_pDasherInterface->KeyDown(GetTickCount(), 4);
291 return 0;
292 default:
293 return 0;
297 LRESULT CCanvas::OnLButtonDblClk(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
299 // bHandled = TRUE;
300 // if( m_pDasherInterface->GetBoolParameter(BP_START_STYLUS) )
301 // {
302 // m_pDasherInterface->PauseAt(0, 0);
303 // }
304 return 0;
307 LRESULT CCanvas::OnLButtonDown(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
309 bHandled = TRUE;
311 OutputDebugString(TEXT("Canvas::LButtonDown\n"));
313 // FIXME - what does this do - please document
314 LPARAM lp = GetMessageExtraInfo();
315 if (lp == 0xFF515702)
316 return 0;
317 // ---
319 m_pDasherInterface->KeyDown(GetTickCount(), 100);
321 // else if ( m_pDasherInterface->GetBoolParameter(BP_START_STYLUS) )
322 // {
323 // // DJW - for the time being we only do stylus mode if not BP_START_MOUSE
325 // if ( m_pDasherInterface->GetBoolParameter(BP_DASHER_PAUSED) )
326 // m_pDasherInterface->Unpause(GetTickCount());
327 // }
329 m_bButtonDown = true;
330 return 0;
333 LRESULT CCanvas::OnLButtonUp(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
335 bHandled = TRUE;
337 endturbo = GetTickCount();
339 if(endturbo - startturbo > 1)
341 TCHAR deb[80];
342 wsprintf(deb, TEXT("start: %d\nend: %d\nduration: %d"), startturbo, endturbo, endturbo - startturbo);
343 OutputDebugString(deb);
345 lbuttonheld = 0;
347 m_bButtonDown = false;
349 return 0;
353 LRESULT CCanvas::OnCursorInRange(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
355 OutputDebugString(TEXT("CursorInRange\n"));
357 bHandled = TRUE;
359 //SetFocus();
361 if ( m_pDasherInterface->GetBoolParameter(BP_START_MOUSE) )
363 if (m_pDasherInterface->GetBoolParameter(BP_DASHER_PAUSED))
364 m_pDasherInterface->Unpause(GetTickCount());
367 return 0;
371 LRESULT CCanvas::OnCursorOutOfRange(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
373 OutputDebugString(TEXT("CursorOutOfRange\n"));
375 bHandled = TRUE;
376 if ( m_pDasherInterface->GetBoolParameter(BP_START_MOUSE) )
378 if (!m_pDasherInterface->GetBoolParameter(BP_DASHER_PAUSED))
379 m_pDasherInterface->PauseAt(0, 0);
382 return 0;
385 LRESULT CCanvas::OnRButtonDown(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
387 // bHandled = TRUE;
388 // if( m_pDasherInterface->GetBoolParameter(BP_START_STYLUS) )
389 // {
390 // if( m_pDasherInterface->GetBoolParameter(BP_DASHER_PAUSED) )
391 // m_pDasherInterface->Unpause(GetTickCount());
392 // }
393 // m_bButtonDown = true;
394 return 0;
398 LRESULT CCanvas::OnRButtonUp(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
400 bHandled = TRUE;
401 m_bButtonDown = false;
402 return 0;
405 LRESULT CCanvas::OnMouseMove(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
407 bHandled = true;
409 imousex = LOWORD(lParam);
410 imousey = HIWORD(lParam);
411 m_dwTicksLastEvent = GetTickCount();
412 // if( m_pDasherInterface->GetBoolParameter(BP_START_STYLUS) )
413 // {
414 // if( m_pDasherInterface->GetBoolParameter(BP_DASHER_PAUSED) )
415 // m_pDasherInterface->Unpause(GetTickCount());
416 // }
418 return 0;
421 LRESULT CCanvas::OnSize(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
423 bHandled = TRUE;
424 if(m_pScreen != 0)
426 delete m_pScreen;
427 m_pScreen = 0;
429 if (LOWORD(lParam)>0 && HIWORD(lParam) >0)
431 m_pScreen = new CScreen(m_hdc, LOWORD(lParam), HIWORD(lParam));
432 m_pScreen->SetFont(m_pDasherInterface->GetStringParameter(SP_DASHER_FONT));
433 m_pDasherInterface->ChangeScreen(m_pScreen);
434 InvalidateRect( NULL, FALSE);
436 return 0;
439 /*LRESULT CCanvas::OnTimer(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) */
441 void CCanvas::DoFrame()
443 POINT mousepos2;
444 GetCursorPos(&mousepos2);
446 ScreenToClient(&mousepos2);
448 POINT mousepos;
449 GetCursorPos(&mousepos);
451 // if(running == 0) {
452 // ScreenToClient(m_hwnd, &mousepos);
453 // if(m_pDasherInterface->GetBoolParameter(BP_MOUSEPOS_MODE) == true) // configuration option
454 // {
455 // // DASHER_TRACEOUTPUT("first:%d second:%d %d\n",firstwindow,secondwindow,m_iMousePosDist);
456 // if(firstwindow != true && secondwindow != true) {
457 // m_pDasherInterface->SetLongParameter(LP_MOUSE_POS_BOX, 1);
458 // firstwindow = true;
459 // }
460 // int mouseDist = m_pDasherInterface->GetLongParameter(LP_MOUSEPOSDIST);
461 // if(mousepos.y > m_pScreen->GetHeight() / 2 - mouseDist - 50 && mousepos.y < m_pScreen->GetHeight() / 2 - mouseDist + 50 && firstwindow == true) {
462 // // Mouse is in the top box
463 // if(mousepostime == 0) {
464 // mousepostime = GetTickCount();
465 // }
466 // else if((GetTickCount() - mousepostime) > 2000) {
467 // firstwindow = false;
468 // secondwindow = true;
469 // mousepostime = 0;
470 // m_pDasherInterface->SetLongParameter(LP_MOUSE_POS_BOX, 2);
471 // }
472 // }
473 // else if(firstwindow == true) {
474 // mousepostime = 0;
475 // }
476 // if(secondwindow == true) {
477 // if(mousepos.y < m_pScreen->GetHeight() / 2 + mouseDist + 50 && mousepos.y > (m_pScreen->GetHeight() / 2 + mouseDist - 50)) {
478 // // In second window
479 // if(mousepostime == 0) {
480 // mousepostime = GetTickCount();
481 // }
482 // else if((GetTickCount() - mousepostime) > 2000) {
483 // m_pDasherInterface->SetLongParameter(LP_MOUSE_POS_BOX, -1);
484 // StartStop();
485 // }
486 // }
487 // else if(mousepostime > 0) {
488 // secondwindow = false;
489 // firstwindow = true;
490 // m_pDasherInterface->SetLongParameter(LP_MOUSE_POS_BOX, 1);
491 // mousepostime = 0;
492 // }
493 // }
494 // }
495 // imousey = mousepos.y;
497 // imousex = mousepos.x;
499 // if(m_pDasherInterface->GetBoolParameter(BP_NUMBER_DIMENSIONS) == true) {
500 // double scalefactor;
501 // if(yscaling == 0) {
502 // scalefactor = 2.0;
503 // }
504 // else {
505 // scalefactor = m_pScreen->GetHeight() / yscaling;
506 // }
507 // imousey -= m_pScreen->GetHeight() / 2;
508 // imousey *= scalefactor;
509 // imousey += m_pScreen->GetHeight() / 2;
510 // }
512 // if((GetTickCount() - previoustime) > 200) {
513 // if(firstwindow == true) {
514 // m_pDasherInterface->SetLongParameter(LP_MOUSE_POS_BOX, 1);
515 // }
516 // else if(secondwindow == true) {
517 // m_pDasherInterface->SetLongParameter(LP_MOUSE_POS_BOX, 2);
518 // }
520 // previoustime = GetTickCount();
521 // }
523 // return 0;
524 // }
526 //// if(m_pDasherInterface->GetBoolParameter(BP_WINDOW_PAUSE) == true) {
527 // // RECT windowrect;
529 //// GetWindowRect(m_hwnd, &windowrect);
530 // // if(mousepos.y > windowrect.bottom || mousepos.y < windowrect.top || mousepos.x > windowrect.right || mousepos.x < windowrect.left)
531 //// return 0;
532 // // }
534 // ScreenToClient(m_hwnd, &mousepos);
535 // imousey = mousepos.y;
536 // imousex = mousepos.x;
538 // if(m_pDasherInterface->GetBoolParameter(BP_NUMBER_DIMENSIONS) == true) {
539 // double scalefactor;
540 // if(yscaling == 0) {
541 // scalefactor = 2;
542 // }
543 // else {
544 // scalefactor = m_pScreen->GetHeight() / yscaling;
545 // }
546 // imousey -= m_pScreen->GetHeight() / 2;
547 // imousey *= scalefactor;
548 // imousey += m_pScreen->GetHeight() / 2;
549 // }
551 DWORD dwTicks = GetTickCount();
553 // If not paused need to consider stop on idle
554 if( !m_pDasherInterface->GetBoolParameter(BP_DASHER_PAUSED) )
556 // only pause if button is not down
557 if( !m_bButtonDown && m_pDasherInterface->GetBoolParameter(BP_STOP_IDLE) )
559 if (dwTicks - m_dwTicksLastEvent > m_pDasherInterface->GetLongParameter(LP_STOP_IDLETIME) )
561 // idle time exceeded
562 m_pDasherInterface->PauseAt(0, 0);
567 m_pDasherInterface->NewFrame(dwTicks, false);//TapOn(imousex, imousey, GetTickCount());
570 void CCanvas::centrecursor() {
571 POINT mousepos;
572 mousepos.x = m_pScreen->GetWidth() / 2;
574 mousepos.y = m_pScreen->GetHeight() / 2;
576 ClientToScreen( &mousepos);
578 SetCursorPos(mousepos.x, mousepos.y);
582 void CCanvas::MousePosStart(bool Value) {
583 if(Value == false) {
584 firstwindow = false;
585 secondwindow = false;
589 /////////////////////////////////////////////////////////////////////////////
591 void CCanvas::StartStop() {
593 if(running == 0) {
594 SetCapture();
595 running = 1;
596 m_pDasherInterface->Unpause(GetTickCount());
597 firstwindow = false;
598 secondwindow = false;
599 mousepostime = 0;
602 else {
603 m_pDasherInterface->PauseAt(0, 0);
604 running = 0;
605 // if (speakonstop==true) { // FIXME - reimplement this
606 // m_DasherEditBox->speak(2);
607 // }
608 ReleaseCapture();
612 /////////////////////////////////////////////////////////////////////////////
614 // Gets the size of the canvas in screen coordinates. Need if we
615 // want to log mouse positions normalized by the size of the
616 // canvas.
617 bool CCanvas::GetCanvasSize(int& iTop, int& iLeft, int& iBottom, int& iRight)
620 RECT sWindowRect;
622 if (GetWindowRect( &sWindowRect))
624 iTop = sWindowRect.top;
625 iLeft = sWindowRect.left;
626 iBottom = sWindowRect.bottom;
627 iRight = sWindowRect.right;
628 return true;
630 else
631 return false;
635 void CCanvas::HandleEvent(Dasher::CEvent *pEvent) {
637 if(pEvent->m_iEventType == 1) {
638 Dasher::CParameterNotificationEvent * pEvt(static_cast < Dasher::CParameterNotificationEvent * >(pEvent));
639 switch (pEvt->m_iParameter) {
640 case SP_DASHER_FONT:
641 m_pScreen->SetFont(m_pDasherInterface->GetStringParameter(SP_DASHER_FONT));
642 break;
643 /* case BP_SOCKET_INPUT_ENABLE:
644 OutputDebugString(TEXT("Processing BP_SOCKET_INPUT_ENABLE change\n"));
645 if(GetBoolParameter(BP_SOCKET_INPUT_ENABLE)) {
646 if(!m_pSocketInput->isListening()) {
647 m_pSocketInput->StartListening();
649 m_pDasherInterface->SetInput(1);
651 else {
652 if(m_pSocketInput != NULL) {
653 m_pSocketInput->StopListening();
655 m_pDasherInterface->SetInput(0);
657 break;*/
658 default:
659 break;