Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1180 lines
24 KiB

  1. //
  2. // mxToolKit (c) 1999 by Mete Ciragan
  3. //
  4. // file: mx.cpp
  5. // implementation: Win32 API
  6. // last modified: Apr 18 1999, Mete Ciragan
  7. // copyright: The programs and associated files contained in this
  8. // distribution were developed by Mete Ciragan. The programs
  9. // are not in the public domain, but they are freely
  10. // distributable without licensing fees. These programs are
  11. // provided without guarantee or warrantee expressed or
  12. // implied.
  13. //
  14. #include "mxtk/mx.h"
  15. #include "mxtk/mxWindow.h"
  16. #include "mxtk/mxEvent.h"
  17. #include "mxtk/mxLinkedList.h"
  18. #include <windows.h>
  19. #include <commctrl.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include "tier1/UtlVector.h"
  24. #define WM_MOUSEWHEEL 0x020A
  25. //#include <ostream.h"
  26. void mxTab_resizeChild (HWND hwnd);
  27. mxWindow *g_mainWindow = 0;
  28. static mxLinkedList *g_widgetList = 0;
  29. static mxWindow *g_idleWindow = 0;
  30. static MSG msg;
  31. static HWND g_hwndToolTipControl = 0;
  32. static bool isClosing = false;
  33. static HACCEL g_hAcceleratorTable = NULL;
  34. void mx::createAccleratorTable( int numentries, Accel_t *entries )
  35. {
  36. CUtlVector< ACCEL > accelentries;
  37. for ( int i = 0; i < numentries; ++i )
  38. {
  39. const Accel_t& entry = entries[ i ];
  40. ACCEL add;
  41. add.key = entry.key;
  42. add.cmd = entry.command;
  43. add.fVirt = 0;
  44. if ( entry.flags & ACCEL_ALT )
  45. {
  46. add.fVirt |= FALT;
  47. }
  48. if ( entry.flags & ACCEL_CONTROL )
  49. {
  50. add.fVirt |= FCONTROL;
  51. }
  52. if ( entry.flags & ACCEL_SHIFT )
  53. {
  54. add.fVirt |= FSHIFT;
  55. }
  56. if ( entry.flags & ACCEL_VIRTKEY )
  57. {
  58. add.fVirt |= FVIRTKEY;
  59. }
  60. accelentries.AddToTail( add );
  61. }
  62. g_hAcceleratorTable = ::CreateAcceleratorTable( accelentries.Base(), accelentries.Count() );
  63. }
  64. void
  65. mx_addWidget (mxWidget *widget)
  66. {
  67. if (g_widgetList)
  68. g_widgetList->add ((void *) widget);
  69. }
  70. void
  71. mx_removeWidget (mxWidget *widget)
  72. {
  73. if (g_widgetList)
  74. g_widgetList->remove ((void *) widget);
  75. }
  76. HWND
  77. mx_CreateToolTipControl ()
  78. {
  79. if (!g_hwndToolTipControl)
  80. {
  81. if (g_mainWindow)
  82. {
  83. g_hwndToolTipControl = CreateWindowEx (0, TOOLTIPS_CLASS, "", WS_POPUP | WS_EX_TOPMOST,
  84. 0, 0, 0, 0, (HWND) g_mainWindow->getHandle (),
  85. (HMENU) NULL, (HINSTANCE) GetModuleHandle (NULL), NULL);
  86. }
  87. }
  88. return g_hwndToolTipControl;
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Purpose:
  92. // Input : *window -
  93. // *event -
  94. // Output : static void
  95. //-----------------------------------------------------------------------------
  96. static void RecursiveHandleEvent( mxWindow *window, mxEvent *event )
  97. {
  98. while ( window )
  99. {
  100. if ( window->handleEvent ( event ) )
  101. break;
  102. window = window->getParent();
  103. }
  104. }
  105. char const *translatecode( int code )
  106. {
  107. switch ( code )
  108. {
  109. case NM_CLICK:
  110. return "NM_CLICK";
  111. case NM_CUSTOMDRAW:
  112. return "NM_CUSTOMDRAW";
  113. case NM_DBLCLK:
  114. return "NM_DBLCLK";
  115. case NM_KILLFOCUS:
  116. return "NM_KILLFOCUS";
  117. case NM_RCLICK:
  118. return "NM_RCLICK";
  119. case NM_RETURN:
  120. return "NM_RETURN";
  121. case NM_SETCURSOR:
  122. return "NM_SETCURSOR";
  123. case NM_SETFOCUS:
  124. return "NM_SETFOCUS";
  125. case TVN_BEGINDRAG:
  126. return "TVN_BEGINDRAG";
  127. case TVN_BEGINLABELEDIT:
  128. return "TVN_BEGINLABELEDIT";
  129. case TVN_BEGINRDRAG:
  130. return "TVN_BEGINRDRAG";
  131. case TVN_DELETEITEM:
  132. return "TVN_DELETEITEM";
  133. case TVN_ENDLABELEDIT:
  134. return "TVN_ENDLABELEDIT";
  135. case TVN_GETDISPINFO:
  136. return "TVN_GETDISPINFO";
  137. case TVN_GETINFOTIP:
  138. return "TVN_GETINFOTIP";
  139. case TVN_ITEMEXPANDED:
  140. return "TVN_ITEMEXPANDED";
  141. case TVN_ITEMEXPANDING:
  142. return "TVN_ITEMEXPANDING";
  143. case TVN_KEYDOWN :
  144. return "TVN_KEYDOWN";
  145. case TVN_SELCHANGED :
  146. return "TVN_SELCHANGED";
  147. case TVN_SELCHANGING :
  148. return "TVN_SELCHANGING";
  149. case TVN_SETDISPINFO :
  150. return "TVN_SETDISPINFO";
  151. case TVN_SINGLEEXPAND:
  152. return "TVN_SINGLEEXPAND";
  153. }
  154. return "Unknown!!!";
  155. }
  156. static LRESULT CALLBACK WndProc (HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
  157. {
  158. static bool bDragging = FALSE;
  159. switch (uMessage)
  160. {
  161. case WM_DROPFILES:
  162. {
  163. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  164. if (window)
  165. {
  166. SwitchToThisWindow(hwnd,1);
  167. TCHAR lpszFile[MAX_PATH] = {0};
  168. UINT uFile = 0;
  169. HDROP hDrop = (HDROP)wParam;
  170. uFile = DragQueryFile( hDrop, 0xFFFFFFFF, NULL, NULL );
  171. for ( UINT i=0; i<uFile; i++ )
  172. {
  173. if ( DragQueryFile( hDrop, i, lpszFile, MAX_PATH ) )
  174. {
  175. mxEvent event;
  176. event.event = mxEvent::DropFile;
  177. V_strcpy_safe( event.szChars, lpszFile );
  178. window->handleEvent (&event);
  179. }
  180. }
  181. DragFinish(hDrop);
  182. }
  183. }
  184. break;
  185. case WM_SETFOCUS:
  186. case WM_KILLFOCUS:
  187. {
  188. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  189. if ( window )
  190. {
  191. mxEvent event;
  192. event.event = mxEvent::Focus;
  193. event.widget = NULL;
  194. event.action = (uMessage == WM_SETFOCUS);
  195. RecursiveHandleEvent( window, &event );
  196. return 0;
  197. }
  198. }
  199. break;
  200. case WM_ACTIVATE:
  201. {
  202. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  203. if ( window )
  204. {
  205. mxEvent event;
  206. event.event = mxEvent::Activate;
  207. event.widget = NULL;
  208. event.action = (LOWORD( wParam ) != WA_INACTIVE);
  209. RecursiveHandleEvent( window, &event );
  210. return 0;
  211. }
  212. }
  213. break;
  214. case WM_COMMAND:
  215. {
  216. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  217. if (LOWORD (wParam) > 0 && window)
  218. {
  219. WORD wNotifyCode = (WORD) HIWORD (wParam);
  220. HWND hwndCtrl = (HWND) lParam;
  221. mxEvent event;
  222. CHAR className[128];
  223. GetClassName (hwndCtrl, className, 128);
  224. if (!strcmpi (className, "edit"))
  225. {
  226. if (wNotifyCode != EN_CHANGE)
  227. break;
  228. }
  229. else if (!strcmpi (className, "combobox"))
  230. {
  231. if (wNotifyCode != CBN_SELCHANGE)
  232. break;
  233. }
  234. else if (!strcmpi (className, "listbox"))
  235. {
  236. if (wNotifyCode != LBN_SELCHANGE)
  237. break;
  238. }
  239. event.event = mxEvent::Action;
  240. event.widget = (mxWidget *) GetWindowLong ((HWND) lParam, GWL_USERDATA);
  241. event.action = (int) LOWORD (wParam);
  242. RecursiveHandleEvent( window, &event );
  243. }
  244. }
  245. break;
  246. case WM_NOTIFY:
  247. {
  248. if (isClosing)
  249. break;
  250. NMHDR *nmhdr = (NMHDR *) lParam;
  251. mxEvent event;
  252. #if 0
  253. //if ( nmhdr->idFrom > 0 )
  254. {
  255. mxWidget *temp = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA);
  256. if ( temp && temp->getType() == MX_TREEVIEW )
  257. {
  258. NMTREEVIEW *nmt = ( NMTREEVIEW * )nmhdr;
  259. HTREEITEM hItem = TreeView_GetSelection (nmhdr->hwndFrom);
  260. char sz[ 256 ];
  261. sprintf( sz, "tree view receiving notify %i : %s action %i old %p new %p selection %p\n", nmhdr->code, translatecode( nmhdr->code ),
  262. nmt->action, nmt->itemOld, nmt->itemNew, hItem );
  263. OutputDebugString( sz );
  264. }
  265. }
  266. #endif
  267. if (nmhdr->code == TVN_SELCHANGED)
  268. {
  269. if (nmhdr->idFrom > 0)
  270. {
  271. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  272. event.event = mxEvent::Action;
  273. event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA);
  274. event.action = (int) nmhdr->idFrom;
  275. RECT rc;
  276. HTREEITEM hItem = TreeView_GetSelection (nmhdr->hwndFrom);
  277. TreeView_GetItemRect (nmhdr->hwndFrom, hItem, &rc, TRUE);
  278. event.x = (int) rc.left;
  279. event.y = (int) rc.bottom;
  280. RecursiveHandleEvent( window, &event );
  281. }
  282. }
  283. else if (nmhdr->code == LVN_ITEMCHANGED)
  284. {
  285. if (nmhdr->idFrom > 0)
  286. {
  287. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  288. event.event = mxEvent::Action;
  289. event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA);
  290. event.action = (int) nmhdr->idFrom;
  291. RecursiveHandleEvent( window, &event );
  292. }
  293. }
  294. else if (nmhdr->code == NM_RCLICK)
  295. {
  296. if (nmhdr->idFrom > 0)
  297. {
  298. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  299. event.event = mxEvent::Action;
  300. event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA);
  301. event.action = (int) nmhdr->idFrom;
  302. event.flags = mxEvent::RightClicked;
  303. if ( event.widget )
  304. {
  305. if ( event.widget->getType () == MX_TREEVIEW )
  306. {
  307. RECT rc;
  308. HTREEITEM hItem = TreeView_GetSelection (nmhdr->hwndFrom);
  309. TreeView_GetItemRect (nmhdr->hwndFrom, hItem, &rc, TRUE);
  310. event.x = (int) rc.left;
  311. event.y = (int) rc.bottom;
  312. }
  313. }
  314. RecursiveHandleEvent( window, &event );
  315. }
  316. }
  317. else if (nmhdr->code == NM_DBLCLK)
  318. {
  319. if (nmhdr->idFrom > 0)
  320. {
  321. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  322. event.event = mxEvent::Action;
  323. event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA);
  324. event.action = (int) nmhdr->idFrom;
  325. event.flags = mxEvent::DoubleClicked;
  326. if (event.widget )
  327. {
  328. if ( event.widget->getType () == MX_TREEVIEW )
  329. {
  330. RECT rc;
  331. HTREEITEM hItem = TreeView_GetSelection (nmhdr->hwndFrom);
  332. TreeView_GetItemRect (nmhdr->hwndFrom, hItem, &rc, TRUE);
  333. event.x = (int) rc.left;
  334. event.y = (int) rc.bottom;
  335. }
  336. }
  337. RecursiveHandleEvent( window, &event );
  338. return TRUE;
  339. }
  340. }
  341. else if (nmhdr->code == TCN_SELCHANGING)
  342. {
  343. TC_ITEM ti;
  344. int index = TabCtrl_GetCurSel (nmhdr->hwndFrom);
  345. if (index >= 0)
  346. {
  347. ti.mask = TCIF_PARAM;
  348. TabCtrl_GetItem (nmhdr->hwndFrom, index, &ti);
  349. mxWindow *window = (mxWindow *) ti.lParam;
  350. if (window)
  351. window->setVisible (false);
  352. }
  353. }
  354. else if (nmhdr->code == TCN_SELCHANGE)
  355. {
  356. mxTab_resizeChild (nmhdr->hwndFrom);
  357. if (nmhdr->idFrom > 0)
  358. {
  359. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  360. event.event = mxEvent::Action;
  361. event.widget = (mxWidget *) GetWindowLong (nmhdr->hwndFrom, GWL_USERDATA);
  362. event.action = (int) nmhdr->idFrom;
  363. RecursiveHandleEvent( window, &event );
  364. }
  365. }
  366. }
  367. break;
  368. case WM_SIZE:
  369. {
  370. mxEvent event;
  371. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  372. if (window)
  373. {
  374. event.event = mxEvent::Size;
  375. event.width = (int) LOWORD (lParam);
  376. event.height = (int) HIWORD (lParam);
  377. window->handleEvent (&event);
  378. }
  379. }
  380. break;
  381. case WM_WINDOWPOSCHANGED:
  382. {
  383. mxEvent event;
  384. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  385. if (window)
  386. {
  387. event.event = mxEvent::PosChanged;
  388. WINDOWPOS *wp = ( WINDOWPOS * )lParam;
  389. event.x = wp->x;
  390. event.y = wp->y;
  391. event.width = wp->cx;
  392. event.height = wp->cy;
  393. window->handleEvent (&event);
  394. }
  395. }
  396. break;
  397. case WM_ERASEBKGND:
  398. {
  399. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  400. if (window)
  401. {
  402. if (window->getType () == MX_GLWINDOW)
  403. return 0;
  404. if (window->getType () == MX_MATSYSWINDOW)
  405. return 0;
  406. if ( !isClosing && !window->PaintBackground() )
  407. {
  408. return 0;
  409. }
  410. }
  411. }
  412. break;
  413. case WM_HSCROLL:
  414. case WM_VSCROLL:
  415. {
  416. mxWidget *widget = (mxWidget *) GetWindowLong ((HWND) lParam, GWL_USERDATA);
  417. if (!widget)
  418. {
  419. break;
  420. }
  421. if (widget->getType() != MX_SCROLLBAR && widget->getType() != MX_SLIDER)
  422. {
  423. break;
  424. }
  425. switch (LOWORD (wParam))
  426. {
  427. case TB_LINEUP: // SB_LINEUP SB_LINELEFT
  428. break;
  429. case TB_LINEDOWN: // SB_LINEDOWN SB_LINERIGHT
  430. break;
  431. case TB_PAGEUP: // SB_PAGEUP SB_PAGELEFT
  432. break;
  433. case TB_PAGEDOWN: // SB_PAGEDOWN SB_PAGERIGHT
  434. break;
  435. case TB_THUMBPOSITION: // SB_THUMBPOSITION
  436. break;
  437. case TB_THUMBTRACK: // SB_THUMBTRACK
  438. break;
  439. case TB_TOP: // SB_TOP SB_LEFT
  440. break;
  441. case TB_BOTTOM: // SB_BOTTOM SB_RIGHT
  442. break;
  443. case TB_ENDTRACK: // SB_ENDSCROLL
  444. break;
  445. default:
  446. break;
  447. }
  448. switch (LOWORD (wParam))
  449. {
  450. case TB_LINEUP: // SB_LINEUP SB_LINELEFT
  451. case TB_LINEDOWN: // SB_LINEDOWN SB_LINERIGHT
  452. case TB_PAGEUP: // SB_PAGEUP SB_PAGELEFT
  453. case TB_PAGEDOWN: // SB_PAGEDOWN SB_PAGERIGHT
  454. case TB_THUMBPOSITION: // SB_THUMBPOSITION
  455. case TB_THUMBTRACK: // SB_THUMBTRACK
  456. case TB_TOP: // SB_TOP SB_LEFT
  457. case TB_BOTTOM: // SB_BOTTOM SB_RIGHT
  458. case TB_ENDTRACK: // SB_ENDSCROLL
  459. {
  460. mxEvent event;
  461. event.event = mxEvent::Action;
  462. event.widget = widget;
  463. event.action = widget->getId ();
  464. event.modifiers = LOWORD (wParam);
  465. event.height = HIWORD( wParam );
  466. mxWindow *window = widget->getParent ();
  467. if ( event.action > 0 )
  468. {
  469. RecursiveHandleEvent( window, &event );
  470. }
  471. }
  472. break;
  473. }
  474. }
  475. break;
  476. case WM_PAINT:
  477. {
  478. if ( !isClosing )
  479. {
  480. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  481. if (window)
  482. {
  483. window->redraw ();
  484. }
  485. }
  486. }
  487. break;
  488. case WM_PARENTNOTIFY:
  489. {
  490. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  491. if (window)
  492. {
  493. if ( wParam == WM_LBUTTONDOWN ||
  494. wParam == WM_MBUTTONDOWN ||
  495. wParam == WM_RBUTTONDOWN /*||
  496. wParam & WM_XBUTTONDOWN*/ )
  497. {
  498. mxEvent event;
  499. event.event = mxEvent::ParentNotify;
  500. event.x = (short)LOWORD (lParam);
  501. event.y = (short)HIWORD (lParam);
  502. event.buttons = 0;
  503. event.modifiers = 0;
  504. if ( wParam == WM_LBUTTONDOWN )
  505. event.buttons |= mxEvent::MouseLeftButton;
  506. if ( wParam == WM_RBUTTONDOWN )
  507. event.buttons |= mxEvent::MouseRightButton;
  508. if ( wParam == WM_MBUTTONDOWN )
  509. event.buttons |= mxEvent::MouseMiddleButton;
  510. window->handleEvent (&event);
  511. RecursiveHandleEvent( window, &event );
  512. return 0;
  513. }
  514. }
  515. }
  516. break;
  517. case WM_LBUTTONDOWN:
  518. case WM_MBUTTONDOWN:
  519. case WM_RBUTTONDOWN:
  520. {
  521. bDragging = TRUE;
  522. SetCapture (hwnd);
  523. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  524. if (window)
  525. {
  526. mxEvent event;
  527. event.event = mxEvent::MouseDown;
  528. event.x = (short)LOWORD (lParam);
  529. event.y = (short)HIWORD (lParam);
  530. event.buttons = 0;
  531. event.modifiers = 0;
  532. if (uMessage == WM_MBUTTONDOWN)
  533. event.buttons |= mxEvent::MouseMiddleButton;
  534. else if (uMessage == WM_RBUTTONDOWN)
  535. event.buttons |= mxEvent::MouseRightButton;
  536. else
  537. event.buttons |= mxEvent::MouseLeftButton;
  538. if (wParam & MK_LBUTTON)
  539. event.buttons |= mxEvent::MouseLeftButton;
  540. if (wParam & MK_RBUTTON)
  541. event.buttons |= mxEvent::MouseRightButton;
  542. if (wParam & MK_MBUTTON)
  543. event.buttons |= mxEvent::MouseMiddleButton;
  544. if (wParam & MK_CONTROL)
  545. event.modifiers |= mxEvent::KeyCtrl;
  546. if (wParam & MK_SHIFT)
  547. event.modifiers |= mxEvent::KeyShift;
  548. window->handleEvent (&event);
  549. }
  550. }
  551. break;
  552. case WM_LBUTTONUP:
  553. case WM_MBUTTONUP:
  554. case WM_RBUTTONUP:
  555. {
  556. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  557. if (window)
  558. {
  559. mxEvent event;
  560. event.event = mxEvent::MouseUp;
  561. event.x = (short) LOWORD (lParam);
  562. event.y = (short) HIWORD (lParam);
  563. event.buttons = 0;
  564. event.modifiers = 0;
  565. if (uMessage == WM_MBUTTONUP)
  566. event.buttons |= mxEvent::MouseMiddleButton;
  567. else if (uMessage == WM_RBUTTONUP)
  568. event.buttons |= mxEvent::MouseRightButton;
  569. else
  570. event.buttons |= mxEvent::MouseLeftButton;
  571. if (wParam & MK_LBUTTON)
  572. event.buttons |= mxEvent::MouseLeftButton;
  573. if (wParam & MK_RBUTTON)
  574. event.buttons |= mxEvent::MouseRightButton;
  575. if (wParam & MK_MBUTTON)
  576. event.buttons |= mxEvent::MouseMiddleButton;
  577. if (wParam & MK_CONTROL)
  578. event.modifiers |= mxEvent::KeyCtrl;
  579. if (wParam & MK_SHIFT)
  580. event.modifiers |= mxEvent::KeyShift;
  581. window->handleEvent (&event);
  582. }
  583. bDragging = FALSE;
  584. ReleaseCapture ();
  585. }
  586. break;
  587. case WM_MOUSEMOVE:
  588. {
  589. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  590. if (window)
  591. {
  592. mxEvent event;
  593. if (bDragging)
  594. event.event = mxEvent::MouseDrag;
  595. else
  596. event.event = mxEvent::MouseMove;
  597. event.x = (short) LOWORD (lParam);
  598. event.y = (short) HIWORD (lParam);
  599. event.buttons = 0;
  600. event.modifiers = 0;
  601. if (wParam & MK_LBUTTON)
  602. event.buttons |= mxEvent::MouseLeftButton;
  603. if (wParam & MK_RBUTTON)
  604. event.buttons |= mxEvent::MouseRightButton;
  605. if (wParam & MK_MBUTTON)
  606. event.buttons |= mxEvent::MouseMiddleButton;
  607. if (wParam & MK_CONTROL)
  608. event.modifiers |= mxEvent::KeyCtrl;
  609. if (wParam & MK_SHIFT)
  610. event.modifiers |= mxEvent::KeyShift;
  611. window->handleEvent (&event);
  612. }
  613. }
  614. break;
  615. case WM_NCLBUTTONDOWN:
  616. case WM_NCMBUTTONDOWN:
  617. case WM_NCRBUTTONDOWN:
  618. {
  619. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  620. if (window)
  621. {
  622. mxEvent event;
  623. event.event = mxEvent::NCMouseDown;
  624. event.x = (short) LOWORD (lParam);
  625. event.y = (short) HIWORD (lParam);
  626. event.buttons = 0;
  627. event.modifiers = 0;
  628. if (uMessage == WM_NCMBUTTONDOWN)
  629. event.buttons |= mxEvent::MouseMiddleButton;
  630. else if (uMessage == WM_NCRBUTTONDOWN)
  631. event.buttons |= mxEvent::MouseRightButton;
  632. else
  633. event.buttons |= mxEvent::MouseLeftButton;
  634. window->handleEvent (&event);
  635. }
  636. }
  637. break;
  638. case WM_NCLBUTTONUP:
  639. case WM_NCMBUTTONUP:
  640. case WM_NCRBUTTONUP:
  641. {
  642. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  643. if (window)
  644. {
  645. mxEvent event;
  646. event.event = mxEvent::NCMouseUp;
  647. event.x = (short) LOWORD (lParam);
  648. event.y = (short) HIWORD (lParam);
  649. event.buttons = 0;
  650. event.modifiers = 0;
  651. if (uMessage == WM_NCMBUTTONUP)
  652. event.buttons |= mxEvent::MouseMiddleButton;
  653. else if (uMessage == WM_NCRBUTTONUP)
  654. event.buttons |= mxEvent::MouseRightButton;
  655. else
  656. event.buttons |= mxEvent::MouseLeftButton;
  657. window->handleEvent (&event);
  658. }
  659. }
  660. break;
  661. case WM_NCMOUSEMOVE:
  662. {
  663. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  664. if (window)
  665. {
  666. mxEvent event;
  667. event.event = mxEvent::NCMouseMove;
  668. event.x = (short) LOWORD (lParam);
  669. event.y = (short) HIWORD (lParam);
  670. event.buttons = 0;
  671. event.modifiers = 0;
  672. window->handleEvent (&event);
  673. }
  674. }
  675. break;
  676. case WM_KEYDOWN:
  677. case WM_SYSKEYDOWN:
  678. {
  679. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  680. if (window)
  681. {
  682. mxEvent event;
  683. event.event = mxEvent::KeyDown;
  684. event.key = (int) wParam;
  685. if ( window->handleEvent (&event) )
  686. return 0;
  687. }
  688. }
  689. break;
  690. case WM_CHAR:
  691. {
  692. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  693. if (window)
  694. {
  695. mxEvent event;
  696. event.event = mxEvent::Char;
  697. event.key = (int) wParam;
  698. if ( window->handleEvent (&event) )
  699. return 0;
  700. }
  701. }
  702. break;
  703. case WM_SYSCHAR:
  704. return 0;
  705. break;
  706. case WM_KEYUP:
  707. case WM_SYSKEYUP:
  708. {
  709. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  710. if (window)
  711. {
  712. mxEvent event;
  713. event.event = mxEvent::KeyUp;
  714. event.key = (int) wParam;
  715. if ( window->handleEvent (&event) )
  716. return 0;
  717. }
  718. }
  719. break;
  720. case WM_MOUSEWHEEL:
  721. {
  722. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  723. if (window)
  724. {
  725. mxEvent event;
  726. memset( &event, 0, sizeof( event ) );
  727. event.event = mxEvent::MouseWheeled;
  728. event.x = (short) LOWORD (lParam);
  729. event.y = (short) HIWORD (lParam);
  730. if (wParam & MK_LBUTTON)
  731. event.buttons |= mxEvent::MouseLeftButton;
  732. if (wParam & MK_RBUTTON)
  733. event.buttons |= mxEvent::MouseRightButton;
  734. if (wParam & MK_MBUTTON)
  735. event.buttons |= mxEvent::MouseMiddleButton;
  736. if (wParam & MK_CONTROL)
  737. event.modifiers |= mxEvent::KeyCtrl;
  738. if (wParam & MK_SHIFT)
  739. event.modifiers |= mxEvent::KeyShift;
  740. event.height = (short)HIWORD( wParam );;
  741. RecursiveHandleEvent( window, &event );
  742. }
  743. }
  744. break;
  745. case WM_TIMER:
  746. {
  747. if (isClosing)
  748. break;
  749. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  750. if (window)
  751. {
  752. mxEvent event;
  753. event.event = mxEvent::Timer;
  754. window->handleEvent (&event);
  755. }
  756. }
  757. break;
  758. case WM_CLOSE:
  759. if (g_mainWindow)
  760. {
  761. if ((void *) hwnd == g_mainWindow->getHandle ())
  762. {
  763. mx::quit ();
  764. }
  765. else
  766. {
  767. ShowWindow (hwnd, SW_HIDE);
  768. mxWindow *window = (mxWindow *) GetWindowLong (hwnd, GWL_USERDATA);
  769. if (window)
  770. {
  771. mxEvent event;
  772. event.event = mxEvent::Close;
  773. window->handleEvent( &event );
  774. }
  775. }
  776. }
  777. //else // shouldn't happen
  778. //DestroyWindow (hwnd);
  779. return 0;
  780. /*
  781. case WM_DESTROY:
  782. if (g_mainWindow)
  783. {
  784. if ((void *) hwnd == g_mainWindow->getHandle ())
  785. mx::quit ();
  786. }
  787. break;
  788. */
  789. }
  790. return DefWindowProc (hwnd, uMessage, wParam, lParam);
  791. }
  792. int
  793. mx::init(int argc, char **argv)
  794. {
  795. WNDCLASS wc;
  796. wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  797. wc.lpfnWndProc = WndProc;
  798. wc.cbClsExtra = 0;
  799. wc.cbWndExtra = 0;
  800. wc.hInstance = (HINSTANCE) GetModuleHandle (NULL);
  801. wc.hIcon = LoadIcon (wc.hInstance, "MX_ICON");
  802. wc.hCursor = LoadCursor (NULL, IDC_ARROW);
  803. wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
  804. wc.lpszMenuName = NULL;
  805. wc.lpszClassName = "mx_class";
  806. if (!wc.hIcon)
  807. wc.hIcon = LoadIcon (NULL, IDI_WINLOGO);
  808. if (!RegisterClass (&wc))
  809. return 0;
  810. InitCommonControls ();
  811. g_widgetList = new mxLinkedList ();
  812. isClosing = false;
  813. return 1;
  814. }
  815. int
  816. mx::run()
  817. {
  818. int messagecount = 0;
  819. while (1)
  820. {
  821. bool doframe = false;
  822. if ( PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE) || !g_idleWindow )
  823. {
  824. if (!GetMessage (&msg, NULL, 0, 0))
  825. {
  826. doframe = false;
  827. break;
  828. }
  829. if ( !g_hAcceleratorTable ||
  830. !TranslateAccelerator( (HWND)g_mainWindow->getHandle (), g_hAcceleratorTable, &msg ))
  831. {
  832. TranslateMessage( &msg );
  833. DispatchMessage( &msg );
  834. }
  835. messagecount++;
  836. if ( messagecount > 10 )
  837. {
  838. messagecount = 0;
  839. doframe = true;
  840. }
  841. }
  842. else if (g_idleWindow)
  843. {
  844. doframe = true;
  845. messagecount = 0;
  846. }
  847. if ( doframe && g_idleWindow )
  848. {
  849. mxEvent event;
  850. event.event = mxEvent::Idle;
  851. g_idleWindow->handleEvent (&event);
  852. }
  853. }
  854. return msg.wParam;
  855. }
  856. int
  857. mx::check ()
  858. {
  859. if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
  860. {
  861. if (GetMessage (&msg, NULL, 0, 0))
  862. {
  863. TranslateMessage (&msg);
  864. DispatchMessage (&msg);
  865. }
  866. return 1;
  867. }
  868. return 0;
  869. }
  870. void
  871. mx::quit ()
  872. {
  873. isClosing = true;
  874. mxWindow *mainwnd = getMainWindow();
  875. if ( mainwnd )
  876. {
  877. if ( !mainwnd->Closing() )
  878. {
  879. isClosing = false;
  880. return;
  881. }
  882. }
  883. if (g_widgetList)
  884. {
  885. // remove from back to front
  886. mxListNode *node = g_widgetList->getLast ();
  887. // Pass 1, see if anyone objects to closing
  888. while (node)
  889. {
  890. mxWidget *widget = (mxWidget *) g_widgetList->getData (node);
  891. node = g_widgetList->getPrev (node);
  892. bool canclose = true;
  893. if ( widget )
  894. {
  895. if ( !widget->CanClose() )
  896. {
  897. canclose = false;
  898. }
  899. }
  900. if ( !canclose )
  901. {
  902. isClosing = false;
  903. return;
  904. }
  905. }
  906. node = g_widgetList->getLast ();
  907. // Pass 2, call OnDelete to allow final cleanup
  908. while (node)
  909. {
  910. mxWidget *widget = (mxWidget *) g_widgetList->getData (node);
  911. node = g_widgetList->getPrev (node);
  912. if ( widget )
  913. {
  914. widget->OnDelete();
  915. }
  916. }
  917. node = g_widgetList->getLast ();
  918. // Pass 3, delete stuff
  919. while (node)
  920. {
  921. mxWidget *widget = (mxWidget *) g_widgetList->getData (node);
  922. node = g_widgetList->getPrev (node);
  923. // remove it!
  924. if ( widget )
  925. {
  926. delete widget;
  927. }
  928. }
  929. delete g_widgetList;
  930. }
  931. if (g_hwndToolTipControl)
  932. DestroyWindow (g_hwndToolTipControl);
  933. if ( g_hAcceleratorTable )
  934. {
  935. DestroyAcceleratorTable( g_hAcceleratorTable );
  936. g_hAcceleratorTable = 0;
  937. }
  938. PostQuitMessage (0);
  939. UnregisterClass ("mx_class", (HINSTANCE) GetModuleHandle (NULL));
  940. }
  941. int
  942. mx::setDisplayMode (int w, int h, int bpp)
  943. {
  944. DEVMODE dm;
  945. dm.dmSize = sizeof (DEVMODE);
  946. dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
  947. dm.dmBitsPerPel = bpp;
  948. dm.dmPelsWidth = w;
  949. dm.dmPelsHeight = h;
  950. if (w == 0 || h == 0 || bpp == 0)
  951. ChangeDisplaySettings (0, 0);
  952. else
  953. ChangeDisplaySettings (&dm, CDS_FULLSCREEN);
  954. return 0;
  955. }
  956. void
  957. mx::setIdleWindow (mxWindow *window)
  958. {
  959. g_idleWindow = window;
  960. }
  961. int
  962. mx::getDisplayWidth ()
  963. {
  964. return (int) GetSystemMetrics (SM_CXSCREEN);
  965. }
  966. int
  967. mx::getDisplayHeight ()
  968. {
  969. return (int) GetSystemMetrics (SM_CYSCREEN);
  970. }
  971. mxWindow*
  972. mx::getMainWindow ()
  973. {
  974. return g_mainWindow;
  975. }
  976. const char *
  977. mx::getApplicationPath ()
  978. {
  979. static char path[256];
  980. GetModuleFileName (0, path, 256);
  981. char *ptr = strrchr (path, '\\');
  982. if (ptr)
  983. *ptr = '\0';
  984. return path;
  985. }
  986. int
  987. mx::getTickCount ()
  988. {
  989. return (int) GetTickCount ();
  990. }