PageRenderTime 64ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/src/win32/Lgi/GView.cpp

#
C++ | 2196 lines | 1899 code | 216 blank | 81 comment | 329 complexity | 894e8da90d51873ca6bf0ad0806e8526 MD5 | raw file
Possible License(s): LGPL-2.1, Unlicense
  1. /*hdr
  2. ** FILE: GView.cpp
  3. ** AUTHOR: Matthew Allen
  4. ** DATE: 23/4/98
  5. ** DESCRIPTION: Win32 GView Implementation
  6. **
  7. ** Copyright (C) 1998-2003, Matthew Allen
  8. ** fret@memecode.com
  9. */
  10. #include <stdio.h>
  11. #include <time.h>
  12. #include "Lgi.h"
  13. #include "Base64.h"
  14. #include "GCom.h"
  15. #include "GDragAndDrop.h"
  16. #include "GDropFiles.h"
  17. #include "GdiLeak.h"
  18. #include "GViewPriv.h"
  19. #define DEBUG_OVER 0
  20. #define OLD_WM_CHAR_MODE 1
  21. #define GWL_LGI_MAGIC 8
  22. #define GWL_EXTRA_BYTES 12
  23. ////////////////////////////////////////////////////////////////////////////////////////////////////
  24. bool In_SetWindowPos = false;
  25. HWND GViewPrivate::hPrevCapture = 0;
  26. GViewPrivate::GViewPrivate()
  27. {
  28. Font = 0;
  29. FontOwn = false;
  30. CtrlId = -1;
  31. WndStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN;
  32. WndExStyle = 0;
  33. WndClass = 0;
  34. WndDlgCode = 0;
  35. TimerId = 0;
  36. DropTarget = 0;
  37. Parent = 0;
  38. ParentI = 0;
  39. Notify = 0;
  40. }
  41. GViewPrivate::~GViewPrivate()
  42. {
  43. if (FontOwn)
  44. {
  45. DeleteObj(Font);
  46. }
  47. }
  48. ////////////////////////////////////////////////////////////////////////////////////////////////////
  49. // Helper Stuff
  50. #include "zmouse.h"
  51. int MouseRollMsg = 0;
  52. #ifdef __GNUC__
  53. #define MSH_WHEELMODULE_CLASS "MouseZ"
  54. #define MSH_WHEELMODULE_TITLE "Magellan MSWHEEL"
  55. #define MSH_SCROLL_LINES "MSH_SCROLL_LINES_MSG"
  56. #endif
  57. int _lgi_mouse_wheel_lines()
  58. {
  59. OSVERSIONINFO Info;
  60. ZeroObj(Info);
  61. Info.dwOSVersionInfoSize = sizeof(Info);
  62. if (GetVersionEx(&Info) &&
  63. Info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
  64. Info.dwMajorVersion == 4 &&
  65. Info.dwMinorVersion == 0)
  66. {
  67. HWND hdlMSHWheel=NULL;
  68. UINT msgMSHWheelGetScrollLines=NULL;
  69. UINT uiMsh_WheelScrollLines;
  70. msgMSHWheelGetScrollLines =
  71. RegisterWindowMessage(MSH_SCROLL_LINES);
  72. hdlMSHWheel = FindWindow(MSH_WHEELMODULE_CLASS,
  73. MSH_WHEELMODULE_TITLE);
  74. if (hdlMSHWheel && msgMSHWheelGetScrollLines)
  75. {
  76. return SendMessage(hdlMSHWheel, msgMSHWheelGetScrollLines, 0, 0);
  77. }
  78. }
  79. else
  80. {
  81. UINT nScrollLines;
  82. if (SystemParametersInfo( SPI_GETWHEELSCROLLLINES,
  83. 0,
  84. (PVOID) &nScrollLines,
  85. 0))
  86. {
  87. return nScrollLines;
  88. }
  89. }
  90. return 3;
  91. }
  92. #define SetKeyFlag(v, k, f) if (GetKeyState(k)&0xFF00) { v |= f; }
  93. int _lgi_get_key_flags()
  94. {
  95. int Flags = 0;
  96. if (LgiGetOs() == LGI_OS_WIN9X)
  97. {
  98. SetKeyFlag(Flags, VK_MENU, LGI_EF_ALT);
  99. SetKeyFlag(Flags, VK_SHIFT, LGI_EF_SHIFT);
  100. SetKeyFlag(Flags, VK_CONTROL, LGI_EF_CTRL);
  101. }
  102. else // is NT/2K/XP
  103. {
  104. SetKeyFlag(Flags, VK_LMENU, LGI_EF_LALT);
  105. SetKeyFlag(Flags, VK_RMENU, LGI_EF_RALT);
  106. SetKeyFlag(Flags, VK_LSHIFT, LGI_EF_LSHIFT);
  107. SetKeyFlag(Flags, VK_RSHIFT, LGI_EF_RSHIFT);
  108. SetKeyFlag(Flags, VK_LCONTROL, LGI_EF_LCTRL);
  109. SetKeyFlag(Flags, VK_RCONTROL, LGI_EF_RCTRL);
  110. }
  111. if (GetKeyState(VK_CAPITAL))
  112. SetFlag(Flags, LGI_EF_CAPS_LOCK);
  113. return Flags;
  114. }
  115. ////////////////////////////////////////////////////////////////////////////////////////////////////
  116. int GetInputACP()
  117. {
  118. char Str[16];
  119. LCID Lcid = (NativeInt)GetKeyboardLayout(LgiGetCurrentThread()) & 0xffff;
  120. GetLocaleInfo(Lcid, LOCALE_IDEFAULTANSICODEPAGE , Str, sizeof(Str));
  121. return atoi(Str);
  122. }
  123. GKey::GKey(int v, int flags)
  124. {
  125. const char *Cp = 0;
  126. vkey = v;
  127. c16 = 0;
  128. if (IsWin9x)
  129. {
  130. uchar c = (uchar)vkey;
  131. const void *In = &c;
  132. int Len = 1;
  133. Cp = LgiAnsiToLgiCp(GetInputACP());
  134. LgiBufConvertCp(&c16, "ucs-2", sizeof(c16), In, Cp, Len);
  135. }
  136. else
  137. {
  138. #if OLD_WM_CHAR_MODE
  139. c16 = vkey;
  140. #else
  141. typedef int (WINAPI *p_ToUnicode)(UINT, UINT, PBYTE, LPWSTR, int, UINT);
  142. static bool First = true;
  143. static p_ToUnicode ToUnicode = 0;
  144. if (First)
  145. {
  146. ToUnicode = (p_ToUnicode) GetProcAddress(LoadLibrary("User32.dll"), "ToUnicode");
  147. First = false;
  148. }
  149. if (ToUnicode)
  150. {
  151. BYTE state[256];
  152. GetKeyboardState(state);
  153. char16 w[4];
  154. int r = ToUnicode(vkey, flags & 0x7f, state, w, CountOf(w), 0);
  155. if (r == 1)
  156. {
  157. c16 = w[0];
  158. }
  159. }
  160. #endif
  161. }
  162. }
  163. ////////////////////////////////////////////////////////////////////////////////////////////////////
  164. LRESULT CALLBACK GWin32Class::Redir(HWND hWnd, UINT m, WPARAM a, LPARAM b)
  165. {
  166. if (m == WM_NCCREATE)
  167. {
  168. LPCREATESTRUCT Info = (LPCREATESTRUCT) b;
  169. GViewI *ViewI = (GViewI*) Info->lpCreateParams;
  170. if (ViewI)
  171. {
  172. GView *View = ViewI->GetGView();
  173. if (View) View->_View = hWnd;
  174. #if _MSC_VER >= 1400
  175. SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)ViewI);
  176. #else
  177. SetWindowLong(hWnd, GWL_USERDATA, (LONG)ViewI);
  178. #endif
  179. SetWindowLong(hWnd, GWL_LGI_MAGIC, LGI_GViewMagic);
  180. }
  181. }
  182. GViewI *Wnd = (GViewI*)
  183. #if _MSC_VER >= 1400
  184. GetWindowLongPtr(hWnd, GWLP_USERDATA);
  185. #else
  186. GetWindowLong(hWnd, GWL_USERDATA);
  187. #endif
  188. if (Wnd)
  189. {
  190. GMessage Msg(m, a, b);
  191. return Wnd->OnEvent(&Msg);
  192. }
  193. if (IsWin9x)
  194. {
  195. return DefWindowProcA(hWnd, m, a, b);
  196. }
  197. else
  198. {
  199. return DefWindowProcW(hWnd, m, a, b);
  200. }
  201. }
  202. LRESULT CALLBACK GWin32Class::SubClassRedir(HWND hWnd, UINT m, WPARAM a, LPARAM b)
  203. {
  204. if (m == WM_NCCREATE)
  205. {
  206. LPCREATESTRUCT Info = (LPCREATESTRUCT) b;
  207. GViewI *ViewI = 0;
  208. if (Info->lpCreateParams)
  209. {
  210. if (ViewI = (GViewI*) Info->lpCreateParams)
  211. {
  212. GView *View = ViewI->GetGView();
  213. if (View)
  214. View->_View = hWnd;
  215. }
  216. }
  217. #if _MSC_VER >= 1400
  218. SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) ViewI);
  219. #else
  220. SetWindowLong(hWnd, GWL_USERDATA, (LONG) ViewI);
  221. #endif
  222. SetLastError(0);
  223. SetWindowLong(hWnd, GWL_LGI_MAGIC, LGI_GViewMagic);
  224. DWORD err = GetLastError();
  225. LgiAssert(!err);
  226. }
  227. GViewI *Wnd = (GViewI*)
  228. #if _MSC_VER >= 1400
  229. GetWindowLongPtr(hWnd, GWLP_USERDATA);
  230. #else
  231. GetWindowLong(hWnd, GWL_USERDATA);
  232. #endif
  233. if (Wnd)
  234. {
  235. GMessage Msg(m, a, b);
  236. GMessage::Result Status = Wnd->OnEvent(&Msg);
  237. return Status;
  238. }
  239. if (IsWin9x)
  240. {
  241. return DefWindowProcA(hWnd, m, a, b);
  242. }
  243. else
  244. {
  245. return DefWindowProcW(hWnd, m, a, b);
  246. }
  247. }
  248. GWin32Class::GWin32Class(const char *name)
  249. {
  250. Name(name);
  251. ZeroObj(Class);
  252. if (IsWin9x)
  253. {
  254. Class.a.lpfnWndProc = (WNDPROC) Redir;
  255. Class.a.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  256. Class.a.cbWndExtra = GWL_EXTRA_BYTES;
  257. Class.a.cbSize = sizeof(Class.a);
  258. }
  259. else
  260. {
  261. Class.w.lpfnWndProc = (WNDPROC) Redir;
  262. Class.w.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  263. Class.w.cbWndExtra = GWL_EXTRA_BYTES;
  264. Class.w.cbSize = sizeof(Class.w);
  265. }
  266. ParentProc = 0;
  267. }
  268. GWin32Class::~GWin32Class()
  269. {
  270. if (IsWin9x)
  271. {
  272. UnregisterClassA(Name(), LgiProcessInst());
  273. }
  274. else
  275. {
  276. UnregisterClassW(NameW(), LgiProcessInst());
  277. }
  278. Class.a.lpszClassName = NULL;
  279. }
  280. GWin32Class *GWin32Class::Create(const char *ClassName)
  281. {
  282. GWin32Class *c = 0;
  283. if (LgiApp)
  284. {
  285. List<GWin32Class> *Classes = LgiApp->GetClasses();
  286. if (Classes)
  287. {
  288. for (c = Classes->First(); c; c = Classes->Next())
  289. {
  290. if (c->Name() &&
  291. ClassName &&
  292. stricmp(c->Name(), ClassName) == 0)
  293. {
  294. break;
  295. }
  296. }
  297. if (!c)
  298. {
  299. c = new GWin32Class(ClassName);
  300. if (c)
  301. {
  302. Classes->Insert(c);
  303. }
  304. }
  305. }
  306. }
  307. return c;
  308. }
  309. bool GWin32Class::Register()
  310. {
  311. bool Status = false;
  312. if (!Class.a.lpszClassName)
  313. {
  314. Class.a.hInstance = LgiProcessInst();
  315. if (IsWin9x)
  316. {
  317. Class.a.lpszClassName = Name();
  318. Status = RegisterClassExA(&Class.a) != 0;
  319. LgiAssert(Status);
  320. }
  321. else
  322. {
  323. Class.w.lpszClassName = NameW();
  324. Status = RegisterClassExW(&Class.w) != 0;
  325. LgiAssert(Status);
  326. }
  327. }
  328. return Status;
  329. }
  330. bool GWin32Class::SubClass(char *Parent)
  331. {
  332. bool Status = false;
  333. if (IsWin9x)
  334. {
  335. if (!Class.a.lpszClassName)
  336. {
  337. HBRUSH hBr = Class.a.hbrBackground;
  338. if (GetClassInfoExA(LgiProcessInst(), Parent, &Class.a))
  339. {
  340. ParentProc = Class.a.lpfnWndProc;
  341. if (hBr)
  342. {
  343. Class.a.hbrBackground = hBr;
  344. }
  345. Class.a.cbWndExtra = max(Class.a.cbWndExtra, GWL_EXTRA_BYTES);
  346. Class.a.hInstance = LgiProcessInst();
  347. Class.a.lpfnWndProc = (WNDPROC) SubClassRedir;
  348. Class.a.lpszClassName = Name();
  349. Status = RegisterClassExA(&Class.a) != 0;
  350. LgiAssert(Status);
  351. }
  352. }
  353. else Status = true;
  354. }
  355. else
  356. {
  357. if (!Class.w.lpszClassName)
  358. {
  359. HBRUSH hBr = Class.w.hbrBackground;
  360. GAutoWString p(LgiNewUtf8To16(Parent));
  361. if (p)
  362. {
  363. if (GetClassInfoExW(LgiProcessInst(), p, &Class.w))
  364. {
  365. ParentProc = Class.w.lpfnWndProc;
  366. if (hBr)
  367. {
  368. Class.w.hbrBackground = hBr;
  369. }
  370. Class.w.cbWndExtra = max(Class.w.cbWndExtra, GWL_EXTRA_BYTES);
  371. Class.w.hInstance = LgiProcessInst();
  372. Class.w.lpfnWndProc = (WNDPROC) SubClassRedir;
  373. Class.w.lpszClassName = NameW();
  374. Status = RegisterClassExW(&Class.w) != 0;
  375. LgiAssert(Status);
  376. }
  377. }
  378. }
  379. else Status = true;
  380. }
  381. return Status;
  382. }
  383. LRESULT CALLBACK GWin32Class::CallParent(HWND hWnd, UINT m, WPARAM a, LPARAM b)
  384. {
  385. if (!ParentProc) return 0;
  386. if (IsWindowUnicode(hWnd))
  387. {
  388. return CallWindowProcW(ParentProc, hWnd, m, a, b);
  389. }
  390. else
  391. {
  392. #if _MSC_VER == 1100
  393. return CallWindowProcA((FARPROC) ParentProc, hWnd, m, a, b);
  394. #else
  395. return CallWindowProcA(ParentProc, hWnd, m, a, b);
  396. #endif
  397. }
  398. }
  399. //////////////////////////////////////////////////////////////////////////////
  400. GViewI *GWindowFromHandle(HWND hWnd)
  401. {
  402. if (hWnd)
  403. {
  404. SetLastError(0);
  405. int32 m = GetWindowLong(hWnd, GWL_LGI_MAGIC);
  406. #if 0 //def _DEBUG
  407. DWORD err = GetLastError();
  408. if (err == 1413)
  409. {
  410. TCHAR name[256];
  411. if (GetClassName(hWnd, name, sizeof(name)))
  412. {
  413. WNDCLASSEX cls;
  414. ZeroObj(cls);
  415. cls.cbSize = sizeof(WNDCLASSEX);
  416. if (GetClassInfoEx(LgiApp->GetInstance(), name, &cls))
  417. {
  418. if (cls.cbWndExtra >= 8)
  419. {
  420. LgiAssert(!"Really?");
  421. }
  422. }
  423. }
  424. }
  425. #endif
  426. if (m == LGI_GViewMagic)
  427. {
  428. return (GViewI*)
  429. #if _MSC_VER >= 1400
  430. GetWindowLongPtr(hWnd, GWLP_USERDATA);
  431. #else
  432. GetWindowLong(hWnd, GWL_USERDATA);
  433. #endif
  434. }
  435. }
  436. return 0;
  437. }
  438. //////////////////////////////////////////////////////////////////////////////
  439. void GView::_Delete()
  440. {
  441. if (_View && d->DropTarget)
  442. {
  443. RevokeDragDrop(_View);
  444. }
  445. GViewI *c;
  446. #ifdef _DEBUG
  447. // Sanity check..
  448. // GArray<GViewI*> HasView;
  449. for (c = Children.First(); c; c = Children.Next())
  450. {
  451. // LgiAssert(!HasView.HasItem(c));
  452. // HasView.Add(c);
  453. LgiAssert(((GViewI*)c->GetParent()) == this || c->GetParent() == 0);
  454. }
  455. #endif
  456. // Delete myself out of my parent's list
  457. if (d->Parent)
  458. {
  459. d->Parent->OnChildrenChanged(this, false);
  460. d->Parent->DelView(this);
  461. d->Parent = 0;
  462. d->ParentI = 0;
  463. }
  464. // Delete all children
  465. while (c = Children.First())
  466. {
  467. // If it has no parent, remove the pointer from the child list
  468. if (c->GetParent() == 0)
  469. Children.Delete(c);
  470. // Delete the child view
  471. DeleteObj(c);
  472. }
  473. // Delete the OS representation of myself
  474. if (_View && IsWindow(_View))
  475. {
  476. WndFlags |= GWF_DESTRUCTOR;
  477. DestroyWindow(_View);
  478. }
  479. // NULL my handles and flags
  480. _View = 0;
  481. WndFlags = 0;
  482. // Remove static references to myself
  483. if (_Over == this) _Over = 0;
  484. if (_Capturing == this) _Capturing = 0;
  485. if (LgiApp && LgiApp->AppWnd == this)
  486. {
  487. LgiApp->AppWnd = 0;
  488. }
  489. // this should only exist in an ex-GWindow, due to the way
  490. // C++ deletes objects it needs to be here.
  491. DeleteObj(_Lock);
  492. }
  493. void GView::Quit(bool DontDelete)
  494. {
  495. if (_View)
  496. {
  497. if (!DontDelete)
  498. {
  499. WndFlags |= GWF_QUIT_WND;
  500. }
  501. DestroyWindow(_View);
  502. }
  503. }
  504. uint32 GView::GetDlgCode()
  505. {
  506. return d->WndDlgCode;
  507. }
  508. void GView::SetDlgCode(uint32 i)
  509. {
  510. d->WndDlgCode = i;
  511. }
  512. uint32 GView::GetStyle()
  513. {
  514. return d->WndStyle;
  515. }
  516. void GView::SetStyle(uint32 i)
  517. {
  518. d->WndStyle = i;
  519. }
  520. uint32 GView::GetExStyle()
  521. {
  522. return d->WndExStyle;
  523. }
  524. void GView::SetExStyle(uint32 i)
  525. {
  526. d->WndExStyle = i;
  527. }
  528. const char *GView::GetClassW32()
  529. {
  530. return d->WndClass;
  531. }
  532. void GView::SetClassW32(const char *c)
  533. {
  534. d->WndClass = c;
  535. }
  536. GWin32Class *GView::CreateClassW32(const char *Class, HICON Icon, int AddStyles)
  537. {
  538. if (Class)
  539. {
  540. SetClassW32(Class);
  541. }
  542. if (GetClassW32())
  543. {
  544. GWin32Class *c = GWin32Class::Create(GetClassW32());
  545. if (c)
  546. {
  547. if (Icon)
  548. {
  549. c->Class.a.hIcon = Icon;
  550. }
  551. if (AddStyles)
  552. {
  553. c->Class.a.style |= AddStyles;
  554. }
  555. c->Register();
  556. return c;
  557. }
  558. }
  559. return 0;
  560. }
  561. bool GView::IsAttached()
  562. {
  563. return _View && IsWindow(_View);
  564. }
  565. bool GView::Attach(GViewI *p)
  566. {
  567. bool Status = false;
  568. SetParent(p);
  569. GView *Parent = d->GetParent();
  570. _Window = Parent ? Parent->_Window : this;
  571. const char *ClsName = GetClassW32();
  572. if (!ClsName)
  573. ClsName = GetClass();
  574. if (ClsName)
  575. {
  576. // Real window with HWND
  577. uint Style = GetStyle();
  578. bool Enab = Enabled();
  579. // Check the class is created
  580. GWin32Class *Cls = GWin32Class::Create(ClsName);
  581. if (Cls)
  582. Cls->Register();
  583. else
  584. return false;
  585. LgiAssert(!Parent || Parent->Handle() != 0);
  586. if (IsWin9x)
  587. {
  588. char *Text = LgiToNativeCp(GBase::Name());
  589. _View = CreateWindowEx( GetExStyle() & ~WS_EX_CONTROLPARENT,
  590. Cls->Name(),
  591. Text,
  592. Style,
  593. Pos.x1, Pos.y1,
  594. Pos.X(), Pos.Y(),
  595. Parent ? Parent->Handle() : 0,
  596. NULL,
  597. LgiProcessInst(),
  598. (GViewI*) this);
  599. DeleteArray(Text);
  600. }
  601. else
  602. {
  603. char16 *Text = GBase::NameW();
  604. _View = CreateWindowExW(GetExStyle() & ~WS_EX_CONTROLPARENT,
  605. Cls->NameW(),
  606. Text,
  607. Style,
  608. Pos.x1, Pos.y1,
  609. Pos.X(), Pos.Y(),
  610. Parent ? Parent->Handle() : 0,
  611. NULL,
  612. LgiProcessInst(),
  613. (GViewI*) this);
  614. }
  615. #ifdef _DEBUG
  616. if (!_View)
  617. {
  618. DWORD e = GetLastError();
  619. LgiAssert(!"CreateWindowEx failed");
  620. }
  621. #endif
  622. if (_View)
  623. {
  624. Status = (_View != 0);
  625. if (d->Font)
  626. {
  627. SendMessage(_View, WM_SETFONT, (WPARAM) d->Font->Handle(), 0);
  628. }
  629. if (d->DropTarget)
  630. {
  631. RegisterDragDrop(_View, d->DropTarget);
  632. }
  633. }
  634. OnAttach();
  635. }
  636. else
  637. {
  638. // Virtual window (no HWND)
  639. Status = true;
  640. }
  641. if (Status && d->Parent)
  642. {
  643. if (!d->Parent->HasView(this))
  644. {
  645. d->Parent->AddView(this);
  646. }
  647. d->Parent->OnChildrenChanged(this, true);
  648. }
  649. return Status;
  650. }
  651. bool GView::Detach()
  652. {
  653. bool Status = false;
  654. if (d->Parent)
  655. {
  656. Visible(false);
  657. d->Parent->DelView(this);
  658. d->Parent->OnChildrenChanged(this, false);
  659. d->Parent = 0;
  660. d->ParentI = 0;
  661. Status = true;
  662. WndFlags &= ~GWF_FOCUS;
  663. if (_Capturing == this)
  664. {
  665. if (_View)
  666. {
  667. ReleaseCapture();
  668. }
  669. _Capturing = 0;
  670. }
  671. if (_View)
  672. {
  673. WndFlags &= ~GWF_QUIT_WND;
  674. DestroyWindow(_View);
  675. }
  676. }
  677. return Status;
  678. }
  679. GRect &GView::GetClient(bool InClientSpace)
  680. {
  681. static GRect Client;
  682. if (_View)
  683. {
  684. RECT rc;
  685. GetClientRect(_View, &rc);
  686. Client = rc;
  687. }
  688. else
  689. {
  690. Client.Set(0, 0, Pos.X()-1, Pos.Y()-1);
  691. if (dynamic_cast<GWindow*>(this) ||
  692. dynamic_cast<GDialog*>(this))
  693. {
  694. Client.x1 += GetSystemMetrics(SM_CXFRAME);
  695. Client.x2 -= GetSystemMetrics(SM_CXFRAME);
  696. Client.y1 += GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
  697. Client.y2 -= GetSystemMetrics(SM_CYFRAME);
  698. }
  699. else if (Sunken() || Raised())
  700. {
  701. Client.Size(_BorderSize, _BorderSize);
  702. }
  703. }
  704. if (InClientSpace)
  705. Client.Offset(-Client.x1, -Client.y1);
  706. return Client;
  707. }
  708. bool GView::SetCursor(int Cursor)
  709. {
  710. char *Set = 0;
  711. switch (Cursor)
  712. {
  713. case LCUR_UpArrow:
  714. Set = IDC_UPARROW;
  715. break;
  716. case LCUR_Cross:
  717. Set = IDC_CROSS;
  718. break;
  719. case LCUR_Wait:
  720. Set = IDC_WAIT;
  721. break;
  722. case LCUR_Ibeam:
  723. Set = IDC_IBEAM;
  724. break;
  725. case LCUR_SizeVer:
  726. Set = IDC_SIZENS;
  727. break;
  728. case LCUR_SizeHor:
  729. Set = IDC_SIZEWE;
  730. break;
  731. case LCUR_SizeBDiag:
  732. Set = IDC_SIZENESW;
  733. break;
  734. case LCUR_SizeFDiag:
  735. Set = IDC_SIZENWSE;
  736. break;
  737. case LCUR_SizeAll:
  738. Set = IDC_SIZEALL;
  739. break;
  740. case LCUR_PointingHand:
  741. {
  742. GArray<int> Ver;
  743. if (LgiGetOs(&Ver) == LGI_OS_WINNT &&
  744. Ver[0] >= 5)
  745. {
  746. #ifndef IDC_HAND
  747. #define IDC_HAND MAKEINTRESOURCE(32649)
  748. #endif
  749. Set = IDC_HAND;
  750. }
  751. // else not supported
  752. break;
  753. }
  754. case LCUR_Forbidden:
  755. Set = IDC_NO;
  756. break;
  757. // Not impl
  758. case LCUR_SplitV:
  759. break;
  760. case LCUR_SplitH:
  761. break;
  762. case LCUR_Blank:
  763. break;
  764. }
  765. ::SetCursor(LoadCursor(0, MAKEINTRESOURCE(Set?Set:IDC_ARROW)));
  766. return true;
  767. }
  768. void GView::PointToScreen(GdcPt2 &p)
  769. {
  770. POINT pt = {p.x, p.y};
  771. GViewI *t = this;
  772. while ( t &&
  773. t->GetParent() &&
  774. !t->Handle())
  775. {
  776. pt.x += t->GetPos().x1;
  777. pt.y += t->GetPos().y1;
  778. t = t->GetParent();
  779. }
  780. ClientToScreen(t->Handle(), &pt);
  781. p.x = pt.x;
  782. p.y = pt.y;
  783. }
  784. void GView::PointToView(GdcPt2 &p)
  785. {
  786. POINT pt = {p.x, p.y};
  787. GViewI *t = this;
  788. while ( t &&
  789. t->GetParent() &&
  790. !t->Handle())
  791. {
  792. pt.x -= t->GetPos().x1;
  793. pt.y -= t->GetPos().y1;
  794. t = t->GetParent();
  795. }
  796. ScreenToClient(t->Handle(), &pt);
  797. p.x = pt.x;
  798. p.y = pt.y;
  799. }
  800. bool GView::GetMouse(GMouse &m, bool ScreenCoords)
  801. {
  802. // position
  803. POINT p;
  804. GetCursorPos(&p);
  805. if (!ScreenCoords)
  806. {
  807. ScreenToClient(_View, &p);
  808. }
  809. m.x = p.x;
  810. m.y = p.y;
  811. m.Target = this;
  812. // buttons
  813. m.Flags = ((GetAsyncKeyState(VK_LBUTTON)&0x8000) ? LGI_EF_LEFT : 0) |
  814. ((GetAsyncKeyState(VK_MBUTTON)&0x8000) ? LGI_EF_MIDDLE : 0) |
  815. ((GetAsyncKeyState(VK_RBUTTON)&0x8000) ? LGI_EF_RIGHT : 0) |
  816. ((GetAsyncKeyState(VK_CONTROL)&0x8000) ? LGI_EF_CTRL : 0) |
  817. ((GetAsyncKeyState(VK_MENU)&0x8000) ? LGI_EF_ALT : 0) |
  818. ((GetAsyncKeyState(VK_SHIFT)&0x8000) ? LGI_EF_SHIFT : 0);
  819. if (m.Flags & (LGI_EF_LEFT | LGI_EF_MIDDLE | LGI_EF_RIGHT))
  820. {
  821. m.Flags |= LGI_EF_DOWN;
  822. }
  823. return true;
  824. }
  825. bool GView::SetPos(GRect &p, bool Repaint)
  826. {
  827. bool Status = true;
  828. GRect OldPos = Pos;
  829. if (Pos != p)
  830. {
  831. Pos = p;
  832. if (_View)
  833. {
  834. HWND hOld = GetFocus();
  835. bool WasVis = IsWindowVisible(_View);
  836. In_SetWindowPos = true;
  837. Status = SetWindowPos( _View,
  838. NULL,
  839. Pos.x1,
  840. Pos.y1,
  841. Pos.X(),
  842. Pos.Y(),
  843. // ((Repaint) ? 0 : SWP_NOREDRAW) |
  844. SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER);
  845. In_SetWindowPos = false;
  846. HWND hNew = GetFocus();
  847. if (hNew != hOld)
  848. {
  849. bool IsVis = IsWindowVisible(_View);
  850. LgiTrace("%s:%i - SetWindowPos changed the focus!!!!!! Old=%p New=%p Vis=%i->%i _View=%s %s->%s\n",
  851. _FL, hOld, hNew, WasVis, IsVis, GetClass(), OldPos.GetStr(), Pos.GetStr());
  852. // Oh f#$% off windows.
  853. // SetFocus(hOld);
  854. }
  855. }
  856. else if (GetParent())
  857. {
  858. OnPosChange();
  859. }
  860. if (Repaint)
  861. {
  862. Invalidate();
  863. }
  864. }
  865. return Status;
  866. }
  867. bool GView::Invalidate(GRect *r, bool Repaint, bool Frame)
  868. {
  869. if (_View)
  870. {
  871. bool Status = false;
  872. if (Frame)
  873. {
  874. RedrawWindow( _View,
  875. NULL,
  876. NULL,
  877. RDW_FRAME |
  878. RDW_INVALIDATE |
  879. RDW_ALLCHILDREN |
  880. ((Repaint) ? RDW_UPDATENOW : 0));
  881. }
  882. else
  883. {
  884. if (r)
  885. {
  886. Status = InvalidateRect(_View, &((RECT)*r), false);
  887. }
  888. else
  889. {
  890. RECT c = GetClient();
  891. Status = InvalidateRect(_View, &c, false);
  892. }
  893. }
  894. if (Repaint)
  895. {
  896. UpdateWindow(_View);
  897. }
  898. return Status;
  899. }
  900. else
  901. {
  902. GRect Up;
  903. GViewI *p = this;
  904. if (r)
  905. {
  906. Up = *r;
  907. }
  908. else
  909. {
  910. Up.Set(0, 0, Pos.X()-1, Pos.Y()-1);
  911. }
  912. if (dynamic_cast<GWindow*>(this))
  913. return true;
  914. while (p && !p->Handle())
  915. {
  916. GViewI *Par = p->GetParent();
  917. GView *VPar = Par?Par->GetGView():0;
  918. GRect w = p->GetPos();
  919. GRect c = p->GetClient(false);
  920. if (Frame && p == this)
  921. Up.Offset(w.x1, w.y1);
  922. else
  923. Up.Offset(w.x1 + c.x1, w.y1 + c.y1);
  924. p = Par;
  925. }
  926. if (p && p->Handle())
  927. {
  928. return p->Invalidate(&Up, Repaint);
  929. }
  930. }
  931. return false;
  932. }
  933. void
  934. CALLBACK
  935. GView::TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, uint32 dwTime)
  936. {
  937. GView *View = (GView*) idEvent;
  938. if (View)
  939. {
  940. View->OnPulse();
  941. }
  942. }
  943. void GView::SetPulse(int Length)
  944. {
  945. if (_View)
  946. {
  947. if (Length > 0)
  948. {
  949. d->TimerId = SetTimer(_View, (UINT_PTR) this, Length, (TIMERPROC) TimerProc);
  950. }
  951. else
  952. {
  953. KillTimer(_View, d->TimerId);
  954. d->TimerId = 0;
  955. }
  956. }
  957. }
  958. bool SysOnKey(GView *w, GMessage *m)
  959. {
  960. if (m->a == VK_TAB &&
  961. (m->Msg == WM_KEYDOWN ||
  962. m->Msg == WM_SYSKEYDOWN) )
  963. {
  964. if (!TestFlag(w->d->WndDlgCode, DLGC_WANTTAB) &&
  965. !TestFlag(w->d->WndDlgCode, DLGC_WANTALLKEYS))
  966. {
  967. // push the focus to the next control
  968. bool Shifted = (GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0;
  969. GViewI *Wnd = GetNextTabStop(w, Shifted);
  970. if (Wnd)
  971. {
  972. if (In_SetWindowPos)
  973. {
  974. assert(0);
  975. LgiTrace("%s:%i - SetFocus(%p)\n", __FILE__, __LINE__, Wnd->Handle());
  976. }
  977. ::SetFocus(Wnd->Handle());
  978. return true;
  979. }
  980. }
  981. }
  982. return false;
  983. }
  984. bool IsKeyChar(GKey &k, int vk)
  985. {
  986. if (k.Ctrl() || k.Alt() || k.System())
  987. return false;
  988. switch (vk)
  989. {
  990. case VK_BACK:
  991. case VK_TAB:
  992. case VK_RETURN:
  993. case VK_SPACE:
  994. case 0xba: // ;
  995. case 0xbb: // =
  996. case 0xbc: // ,
  997. case 0xbd: // -
  998. case 0xbe: // .
  999. case 0xbf: // /
  1000. case 0xc0: // `
  1001. case 0xdb: // [
  1002. case 0xdc: // |
  1003. case 0xdd: // ]
  1004. case 0xde: // '
  1005. return true;
  1006. }
  1007. if (vk >= VK_NUMPAD0 && vk <= VK_DIVIDE)
  1008. return true;
  1009. if (vk >= '0' && vk <= '9')
  1010. return true;
  1011. if (vk >= 'A' && vk <= 'Z')
  1012. return true;
  1013. return false;
  1014. }
  1015. #define KEY_FLAGS (~(MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))
  1016. GMessage::Result GView::OnEvent(GMessage *Msg)
  1017. {
  1018. int Status = 0;
  1019. if (MsgCode(Msg) == MouseRollMsg)
  1020. {
  1021. HWND hFocus = GetFocus();
  1022. if (_View)
  1023. {
  1024. int Flags = ((GetKeyState(VK_SHIFT)&0xF000) ? VK_SHIFT : 0) |
  1025. ((GetKeyState(VK_CONTROL)&0xF000) ? VK_CONTROL : 0);
  1026. PostMessage(hFocus, WM_MOUSEWHEEL, MAKELONG(Flags, (short)Msg->a), Msg->b);
  1027. }
  1028. return 0;
  1029. }
  1030. if (_View)
  1031. {
  1032. switch (Msg->Msg)
  1033. {
  1034. case WM_CTLCOLOREDIT:
  1035. case WM_CTLCOLORSTATIC:
  1036. {
  1037. HDC hDC = (HDC)MsgA(Msg);
  1038. HWND hCtrl = (HWND)MsgB(Msg);
  1039. GViewI *v = FindControl(hCtrl);
  1040. if (v)
  1041. {
  1042. GViewFill *b = v->GetBackgroundFill();
  1043. if (b)
  1044. {
  1045. return (GMessage::Result)b->GetBrush();
  1046. }
  1047. }
  1048. goto ReturnDefaultProc;
  1049. return 0;
  1050. }
  1051. case 5700:
  1052. {
  1053. // I forget what this is for...
  1054. break;
  1055. }
  1056. case WM_ERASEBKGND:
  1057. {
  1058. return 1;
  1059. }
  1060. case WM_GETFONT:
  1061. {
  1062. GFont *f = GetFont();
  1063. return (GMessage::Result) (f ? f->Handle() : SysFont->Handle());
  1064. break;
  1065. }
  1066. case WM_MENUCHAR:
  1067. case WM_MEASUREITEM:
  1068. case WM_DRAWITEM:
  1069. {
  1070. return GMenu::_OnEvent(Msg);
  1071. break;
  1072. }
  1073. case WM_ENABLE:
  1074. {
  1075. Invalidate(&Pos);
  1076. break;
  1077. }
  1078. case WM_HSCROLL:
  1079. case WM_VSCROLL:
  1080. {
  1081. GViewI *Wnd = FindControl((HWND) Msg->b);
  1082. if (Wnd)
  1083. {
  1084. Wnd->OnEvent(Msg);
  1085. }
  1086. break;
  1087. }
  1088. case WM_GETDLGCODE:
  1089. {
  1090. // we handle all tab control stuff
  1091. return DLGC_WANTALLKEYS; // d->WndDlgCode | DLGC_WANTTAB;
  1092. }
  1093. case WM_MOUSEWHEEL:
  1094. {
  1095. short fwKeys = LOWORD(Msg->a); // key flags
  1096. short zDelta = (short) HIWORD(Msg->a); // wheel rotation
  1097. short xPos = (short) LOWORD(Msg->b); // horizontal position of pointer
  1098. short yPos = (short) HIWORD(Msg->b); // vertical position of pointer
  1099. int nScrollLines = - _lgi_mouse_wheel_lines();
  1100. OnMouseWheel( ((int) zDelta / WHEEL_DELTA) * (int) nScrollLines );
  1101. return 0;
  1102. }
  1103. case M_CHANGE:
  1104. {
  1105. GViewI *Ctrl = dynamic_cast<GViewI*>((GViewI*) Msg->a);
  1106. if (Ctrl)
  1107. {
  1108. return OnNotify(Ctrl, Msg->b);
  1109. }
  1110. break;
  1111. }
  1112. case WM_NOTIFY:
  1113. {
  1114. LPNMHDR Hdr = (LPNMHDR) Msg->b;
  1115. GViewI *Ctrl = FindControl(Hdr->hwndFrom);
  1116. int i1 = LVN_GETDISPINFO;
  1117. if (Ctrl)
  1118. {
  1119. switch (Hdr->code)
  1120. {
  1121. #ifdef __GLIST_H
  1122. // List View Stuff
  1123. //
  1124. // this is only required when using the Win32 ListView control
  1125. // in GList.h/GList.cpp
  1126. // for xp compatibility use the owner draw list control in
  1127. // GList2.h/GList2.cpp
  1128. case LVN_GETDISPINFOW:
  1129. case LVN_GETDISPINFOA:
  1130. {
  1131. bool Unicode = Hdr->code == LVN_GETDISPINFOW;
  1132. LV_DISPINFO *Info = (LV_DISPINFO*) Msg->b;
  1133. GListItem *Item = (GListItem*) Info->item.lParam;
  1134. if (Item)
  1135. {
  1136. if (Info->item.mask & LVIF_TEXT)
  1137. {
  1138. if (Info->item.pszText)
  1139. {
  1140. char *Text = Item->GetText(Info->item.iSubItem);
  1141. if (Text)
  1142. {
  1143. if (Unicode)
  1144. {
  1145. short *d = (short*) Info->item.pszText;
  1146. char *s = Text;
  1147. int Size = Info->item.cchTextMax - 2;
  1148. while (*s && Size > 1)
  1149. {
  1150. *d++ = *s++;
  1151. Size -= 2;
  1152. }
  1153. *d++ = 0;
  1154. }
  1155. else
  1156. {
  1157. strcpy(Info->item.pszText, Text);
  1158. }
  1159. }
  1160. else
  1161. {
  1162. Info->item.pszText[0] = 0;
  1163. }
  1164. }
  1165. else
  1166. {
  1167. if (Unicode)
  1168. {
  1169. static short Error[] = { 'E', 'r', 'r', 'o', 'r', 0 };
  1170. Info->item.pszText = (char*) Error;
  1171. }
  1172. else
  1173. {
  1174. // what the?
  1175. // don't know what causes windows to call using a NULL
  1176. // pointer. Any ideas ppl?
  1177. Info->item.pszText = Item->GetText(Info->item.iSubItem);
  1178. }
  1179. }
  1180. }
  1181. if (Info->item.mask & LVIF_IMAGE)
  1182. {
  1183. Info->item.iImage = Item->GetImage();
  1184. }
  1185. }
  1186. break;
  1187. }
  1188. case LVN_ENDLABELEDIT:
  1189. {
  1190. LV_DISPINFO *Info = (LV_DISPINFO*) Msg->b;
  1191. GListItem *Item = (GListItem*) Info->item.lParam;
  1192. if (Info && Item)
  1193. {
  1194. if (Info->item.mask & LVIF_TEXT)
  1195. {
  1196. return Item->SetText(Info->item.pszText);
  1197. }
  1198. }
  1199. break;
  1200. }
  1201. case LVN_BEGINDRAG:
  1202. case LVN_BEGINRDRAG:
  1203. {
  1204. NM_LISTVIEW *Info = (NM_LISTVIEW*) Msg->b;
  1205. LV_ITEM Item;
  1206. ZeroObj(Item);
  1207. Item.mask = LVIF_PARAM;
  1208. Item.iItem = Info->iItem;
  1209. if (ListView_GetItem(Ctrl->Handle(), &Item))
  1210. {
  1211. GMouse m;
  1212. m.Target = this;
  1213. m.Flags = (Hdr->code == LVN_BEGINDRAG) ? MK_LBUTTON : MK_RBUTTON;
  1214. ((GList*) Ctrl)->OnItemBeginDrag((GListItem*) Item.lParam, m);
  1215. }
  1216. break;
  1217. }
  1218. case LVN_COLUMNCLICK:
  1219. {
  1220. NM_LISTVIEW *Info = (NM_LISTVIEW*) Msg->b;
  1221. ((GList*) Ctrl)->OnColumnClick(Info->iSubItem);
  1222. break;
  1223. }
  1224. case LVN_ITEMCHANGED:
  1225. {
  1226. LPNMLISTVIEW Info = (LPNMLISTVIEW) Msg->b;
  1227. if ((Info->uNewState | Info->uOldState) & LVIS_SELECTED)
  1228. {
  1229. GList *Lst = (GList*) Ctrl;
  1230. if (Info->uNewState & LVIS_SELECTED)
  1231. {
  1232. Lst->OnItemSelect((GListItem*) Info->lParam);
  1233. }
  1234. else
  1235. {
  1236. Lst->OnItemSelect(0);
  1237. }
  1238. }
  1239. break;
  1240. }
  1241. #endif
  1242. #if 0
  1243. // Tab Control Stuff
  1244. case TCN_SELCHANGING:
  1245. {
  1246. Status = Ctrl->SysOnNotify(Hdr->code);
  1247. break;
  1248. }
  1249. case TCN_SELCHANGE:
  1250. {
  1251. Ctrl->SysOnNotify(Hdr->code);
  1252. OnNotify(Ctrl, 0);
  1253. break;
  1254. }
  1255. #endif
  1256. #ifdef __GTREE_H
  1257. // Tree View Control
  1258. //
  1259. // this is only relevent when using the Win32 Tree control
  1260. // which resides in GTree.h and GTree.cpp
  1261. // for xp compatibility use the owner draw tree control
  1262. // in GTree2.h and GTree2.cpp
  1263. case TVN_BEGINRDRAG:
  1264. case TVN_BEGINDRAG:
  1265. {
  1266. NM_TREEVIEW *Item = (NM_TREEVIEW*) Msg->b;
  1267. ((GTree*) Ctrl)->OnItemBeginDrag((GTreeItem*) Item->itemNew.lParam, (Hdr->code == TVN_BEGINDRAG) ? MK_LBUTTON : MK_RBUTTON);
  1268. break;
  1269. }
  1270. case TVN_SELCHANGED:
  1271. {
  1272. NM_TREEVIEW *Item = (NM_TREEVIEW*) Msg->b;
  1273. ((GTree*) Ctrl)->OnItemSelect((GTreeItem*) Item->itemNew.lParam);
  1274. break;
  1275. }
  1276. case TVN_ITEMEXPANDED:
  1277. {
  1278. NM_TREEVIEW *Item = (NM_TREEVIEW*) Msg->b;
  1279. ((GTree*) Ctrl)->OnItemExpand((GTreeItem*) Item->itemNew.lParam,
  1280. (Item->itemNew.state & TVIS_EXPANDED) != 0);
  1281. break;
  1282. }
  1283. case TVN_GETDISPINFO:
  1284. {
  1285. TV_DISPINFO *Info = (TV_DISPINFO*) Msg->b;
  1286. GTreeItem *Item = (GTreeItem*) Info->item.lParam;
  1287. if (Item)
  1288. {
  1289. if (Info->item.mask & TVIF_TEXT)
  1290. {
  1291. char *Text = Item->GetText();
  1292. if (!Text) Text = "";
  1293. if (Info->item.pszText)
  1294. {
  1295. strcpy(Info->item.pszText, Text);
  1296. }
  1297. else
  1298. {
  1299. Info->item.pszText = Text;
  1300. }
  1301. }
  1302. if (Info->item.mask & TVIF_IMAGE)
  1303. {
  1304. Info->item.iImage = Item->GetImage();
  1305. }
  1306. if (Info->item.mask & TVIF_SELECTEDIMAGE)
  1307. {
  1308. Info->item.iSelectedImage = Item->GetImage(1);
  1309. }
  1310. }
  1311. break;
  1312. }
  1313. case TVN_DELETEITEM:
  1314. {
  1315. NM_TREEVIEW *pnmtv = (NM_TREEVIEW*) Msg->b;
  1316. if (pnmtv)
  1317. {
  1318. GTreeItem *Item = (GTreeItem*) pnmtv->itemOld.lParam;
  1319. if (Item)
  1320. {
  1321. Item->hTreeItem = 0;
  1322. }
  1323. }
  1324. break;
  1325. }
  1326. #endif
  1327. }
  1328. }
  1329. break;
  1330. }
  1331. case M_COMMAND:
  1332. {
  1333. GViewI *Ci = FindControl((HWND) Msg->b);
  1334. GView *Ctrl = Ci ? Ci->GetGView() : 0;
  1335. if (Ctrl)
  1336. {
  1337. short Code = HIWORD(Msg->a);
  1338. switch (Code)
  1339. {
  1340. /*
  1341. case BN_CLICKED: // BUTTON
  1342. {
  1343. OnNotify(Ctrl, 0);
  1344. break;
  1345. }
  1346. */
  1347. case EN_CHANGE: // EDIT
  1348. {
  1349. Ctrl->SysOnNotify(Code);
  1350. break;
  1351. }
  1352. case CBN_CLOSEUP:
  1353. {
  1354. PostMessage(_View, WM_COMMAND, MAKELONG(Ctrl->GetId(), CBN_EDITCHANGE), Msg->b);
  1355. break;
  1356. }
  1357. case CBN_EDITCHANGE: // COMBO
  1358. {
  1359. Ctrl->SysOnNotify(Code);
  1360. OnNotify(Ctrl, 0);
  1361. break;
  1362. }
  1363. }
  1364. }
  1365. break;
  1366. }
  1367. case WM_NCDESTROY:
  1368. {
  1369. #if _MSC_VER >= 1400
  1370. SetWindowLongPtr(_View, GWLP_USERDATA, 0);
  1371. #else
  1372. SetWindowLong(_View, GWL_USERDATA, 0);
  1373. #endif
  1374. _View = 0;
  1375. if (WndFlags & GWF_QUIT_WND)
  1376. {
  1377. delete this;
  1378. }
  1379. break;
  1380. }
  1381. case WM_CLOSE:
  1382. {
  1383. if (OnRequestClose(false))
  1384. {
  1385. Quit();
  1386. }
  1387. break;
  1388. }
  1389. case WM_DESTROY:
  1390. {
  1391. OnDestroy();
  1392. break;
  1393. }
  1394. case WM_CREATE:
  1395. {
  1396. SetId(d->CtrlId);
  1397. OnCreate();
  1398. if (TestFlag(WndFlags, GWF_FOCUS))
  1399. {
  1400. HWND hCur = GetFocus();
  1401. if (hCur != _View)
  1402. {
  1403. if (In_SetWindowPos)
  1404. {
  1405. assert(0);
  1406. LgiTrace("%s:%i - SetFocus(%p) (%s)\n", __FILE__, __LINE__, Handle(), GetClass());
  1407. }
  1408. SetFocus(_View);
  1409. }
  1410. }
  1411. break;
  1412. }
  1413. case WM_SETFOCUS:
  1414. {
  1415. OnFocus(true);
  1416. break;
  1417. }
  1418. case WM_KILLFOCUS:
  1419. {
  1420. OnFocus(false);
  1421. break;
  1422. }
  1423. case WM_WINDOWPOSCHANGED:
  1424. {
  1425. if (!IsIconic(_View))
  1426. {
  1427. WINDOWPOS *Info = (LPWINDOWPOS) Msg->b;
  1428. if (Info)
  1429. {
  1430. if (Info->x == -32000 &&
  1431. Info->y == -32000)
  1432. {
  1433. #if 0
  1434. LgiTrace("WM_WINDOWPOSCHANGED %i,%i,%i,%i (icon=%i)\n",
  1435. Info->x,
  1436. Info->y,
  1437. Info->cx,
  1438. Info->cy,
  1439. IsIconic(Handle()));
  1440. #endif
  1441. }
  1442. else
  1443. {
  1444. GRect r;
  1445. r.ZOff(Info->cx-1, Info->cy-1);
  1446. r.Offset(Info->x, Info->y);
  1447. if (r.Valid() && r != Pos)
  1448. {
  1449. Pos = r;
  1450. }
  1451. }
  1452. }
  1453. OnPosChange();
  1454. }
  1455. if (!(WndFlags & GWF_DIALOG))
  1456. {
  1457. goto ReturnDefaultProc;
  1458. }
  1459. break;
  1460. }
  1461. case WM_CAPTURECHANGED:
  1462. {
  1463. _Capturing = 0;
  1464. break;
  1465. }
  1466. case M_MOUSEENTER:
  1467. {
  1468. GMouse Ms;
  1469. Ms.Target = this;
  1470. Ms.x = (short) (Msg->b&0xFFFF);
  1471. Ms.y = (short) (Msg->b>>16);
  1472. Ms.Flags = 0;
  1473. GViewI *MouseOver = WindowFromPoint(Ms.x, Ms.y);
  1474. if (MouseOver &&
  1475. _Over != MouseOver &&
  1476. !(MouseOver == this || MouseOver->Handle() == 0))
  1477. {
  1478. if (_Capturing)
  1479. {
  1480. if (MouseOver == _Capturing)
  1481. {
  1482. Ms = lgi_adjust_click(Ms, _Capturing);
  1483. _Capturing->OnMouseEnter(Ms);
  1484. }
  1485. }
  1486. else
  1487. {
  1488. if (_Over)
  1489. {
  1490. GMouse m = lgi_adjust_click(Ms, _Over);
  1491. _Over->OnMouseExit(m);
  1492. #if DEBUG_OVER
  1493. LgiTrace("LoseOver=%p '%-20s'\n", _Over, _Over->Name());
  1494. #endif
  1495. }
  1496. _Over = MouseOver;
  1497. if (_Over)
  1498. {
  1499. #if DEBUG_OVER
  1500. LgiTrace("GetOver=%p '%-20s'\n", _Over, _Over->Name());
  1501. #endif
  1502. GMouse m = lgi_adjust_click(Ms, _Over);
  1503. _Over->OnMouseEnter(m);
  1504. }
  1505. }
  1506. }
  1507. break;
  1508. }
  1509. case M_MOUSEEXIT:
  1510. {
  1511. if (_Over)
  1512. {
  1513. GMouse Ms;
  1514. Ms.Target = this;
  1515. Ms.x = (short) (Msg->b&0xFFFF);
  1516. Ms.y = (short) (Msg->b>>16);
  1517. Ms.Flags = 0;
  1518. bool Mine = false;
  1519. if (_Over->Handle())
  1520. {
  1521. Mine = _Over == this;
  1522. }
  1523. else
  1524. {
  1525. for (GViewI *o = _Capturing ? _Capturing : _Over; o; o = o->GetParent())
  1526. {
  1527. if (o == this)
  1528. {
  1529. Mine = true;
  1530. break;
  1531. }
  1532. }
  1533. }
  1534. if (Mine)
  1535. {
  1536. if (_Capturing)
  1537. {
  1538. GMouse m = lgi_adjust_click(Ms, _Capturing);
  1539. _Capturing->OnMouseExit(m);
  1540. }
  1541. else
  1542. {
  1543. #if DEBUG_OVER
  1544. LgiTrace("LoseOver=%p '%-20s'\n", _Over, _Over->Name());
  1545. #endif
  1546. _Over->OnMouseExit(Ms);
  1547. _Over = 0;
  1548. }
  1549. }
  1550. }
  1551. break;
  1552. }
  1553. case WM_MOUSEMOVE:
  1554. {
  1555. GMouse Ms;
  1556. Ms.Target = this;
  1557. Ms.x = (short) (Msg->b&0xFFFF);
  1558. Ms.y = (short) (Msg->b>>16);
  1559. Ms.Flags = _lgi_get_key_flags();
  1560. if (TestFlag(Msg->a, MK_LBUTTON)) SetFlag(Ms.Flags, LGI_EF_LEFT);
  1561. if (TestFlag(Msg->a, MK_RBUTTON)) SetFlag(Ms.Flags, LGI_EF_RIGHT);
  1562. if (TestFlag(Msg->a, MK_MBUTTON)) SetFlag(Ms.Flags, LGI_EF_MIDDLE);
  1563. SetKeyFlag(Ms.Flags, VK_MENU, MK_ALT);
  1564. Ms.Down((Msg->a & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON)) != 0);
  1565. int Hit = OnHitTest(Ms.x, Ms.y);
  1566. if (Hit < 0)
  1567. {
  1568. SetCursor(LCUR_Normal);
  1569. }
  1570. GViewI *MouseOver = WindowFromPoint(Ms.x, Ms.y);
  1571. if (_Over != MouseOver)
  1572. {
  1573. if (_Over)
  1574. {
  1575. #if DEBUG_OVER
  1576. LgiTrace("LoseOver=%p '%-20s'\n", _Over, _Over->Name());
  1577. #endif
  1578. GMouse m = lgi_adjust_click(Ms, _Over);
  1579. _Over->OnMouseExit(m);
  1580. }
  1581. _Over = MouseOver;
  1582. if (_Over)
  1583. {
  1584. GMouse m = lgi_adjust_click(Ms, _Over);
  1585. _Over->OnMouseEnter(m);
  1586. #if DEBUG_OVER
  1587. LgiTrace("GetOver=%p '%-20s'\n", _Over, _Over->Name());
  1588. #endif
  1589. }
  1590. }
  1591. if (_Capturing)
  1592. {
  1593. Ms = lgi_adjust_click(Ms, _Capturing);
  1594. }
  1595. else if (_Over)
  1596. {
  1597. Ms = lgi_adjust_click(Ms, _Over);
  1598. }
  1599. else return 0;
  1600. GWindow *Wnd = GetWindow();
  1601. if (!Wnd || Wnd->HandleViewMouse(dynamic_cast<GView*>(Ms.Target), Ms))
  1602. {
  1603. Ms.Target->OnMouseMove(Ms);
  1604. }
  1605. break;
  1606. }
  1607. case WM_NCHITTEST:
  1608. {
  1609. POINT Pt = { LOWORD(Msg->b), HIWORD(Msg->b) };
  1610. ScreenToClient(_View, &Pt);
  1611. int Hit = OnHitTest(Pt.x, Pt.y);
  1612. if (Hit >= 0)
  1613. {
  1614. return Hit;
  1615. }
  1616. if (!(WndFlags & GWF_DIALOG))
  1617. {
  1618. goto ReturnDefaultProc;
  1619. }
  1620. break;
  1621. }
  1622. case WM_LBUTTONDBLCLK:
  1623. case WM_LBUTTONDOWN:
  1624. case WM_LBUTTONUP:
  1625. {
  1626. GMouse Ms;
  1627. Ms.x = (short) (Msg->b&0xFFFF);
  1628. Ms.y = (short) (Msg->b>>16);
  1629. Ms.Flags = _lgi_get_key_flags() | LGI_EF_LEFT;
  1630. Ms.Down(Msg->Msg != WM_LBUTTONUP);
  1631. Ms.Double(Msg->Msg == WM_LBUTTONDBLCLK);
  1632. if (_Capturing)
  1633. {
  1634. Ms = lgi_adjust_click(Ms, _Capturing);
  1635. }
  1636. else if (_Over)
  1637. {
  1638. Ms = lgi_adjust_click(Ms, _Over);
  1639. }
  1640. else
  1641. {
  1642. Ms.Target = this;
  1643. }
  1644. GWindow *Wnd = GetWindow();
  1645. if (!Wnd || Wnd->HandleViewMouse(dynamic_cast<GView*>(Ms.Target), Ms))
  1646. {
  1647. Ms.Target->OnMouseClick(Ms);
  1648. }
  1649. break;
  1650. }
  1651. case WM_RBUTTONDBLCLK:
  1652. case WM_RBUTTONDOWN:
  1653. case WM_RBUTTONUP:
  1654. {
  1655. GMouse Ms;
  1656. Ms.x = (short) (Msg->b&0xFFFF);
  1657. Ms.y = (short) (Msg->b>>16);
  1658. Ms.Flags = _lgi_get_key_flags() | LGI_EF_RIGHT;
  1659. Ms.Down(Msg->Msg != WM_RBUTTONUP);
  1660. Ms.Double(Msg->Msg == WM_RBUTTONDBLCLK);
  1661. if (_Capturing)
  1662. {
  1663. Ms = lgi_adjust_click(Ms, _Capturing);
  1664. _Capturing->OnMouseClick(Ms);
  1665. }
  1666. else if (_Over)
  1667. {
  1668. Ms = lgi_adjust_click(Ms, _Over);
  1669. _Over->OnMouseClick(Ms);
  1670. }
  1671. else
  1672. {
  1673. Ms.Target = this;
  1674. OnMouseClick(Ms);
  1675. }
  1676. break;
  1677. }
  1678. case WM_MBUTTONDBLCLK:
  1679. case WM_MBUTTONDOWN:
  1680. case WM_MBUTTONUP:
  1681. {
  1682. GMouse Ms;
  1683. Ms.x = (short) (Msg->b&0xFFFF);
  1684. Ms.y = (short) (Msg->b>>16);
  1685. Ms.Flags = _lgi_get_key_flags() | LGI_EF_MIDDLE;
  1686. Ms.Down(Msg->Msg != WM_MBUTTONUP);
  1687. Ms.Double(Msg->Msg == WM_MBUTTONDBLCLK);
  1688. if (_Capturing)
  1689. {
  1690. Ms = lgi_adjust_click(Ms, _Capturing);
  1691. _Capturing->OnMouseClick(Ms);
  1692. }
  1693. else if (_Over)
  1694. {
  1695. Ms = lgi_adjust_click(Ms, _Over);
  1696. _Over->OnMouseClick(Ms);
  1697. }
  1698. else
  1699. {
  1700. Ms.Target = this;
  1701. OnMouseClick(Ms);
  1702. }
  1703. break;
  1704. }
  1705. case WM_SYSKEYUP:
  1706. case WM_SYSKEYDOWN:
  1707. case WM_KEYDOWN:
  1708. case WM_KEYUP:
  1709. {
  1710. static char AltCode[32];
  1711. bool IsDialog = TestFlag(WndFlags, GWF_DIALOG);
  1712. bool IsDown = Msg->Msg == WM_KEYDOWN || Msg->Msg == WM_SYSKEYDOWN;
  1713. int KeyFlags = _lgi_get_key_flags();
  1714. HWND hwnd = _View;
  1715. #if !OLD_WM_CHAR_MODE
  1716. if (Msg->a == VK_MENU)
  1717. {
  1718. int Code = (Msg->b & 0xc0000000) >> 29;
  1719. if (Code != 2)
  1720. {
  1721. if (Code)
  1722. {
  1723. // Up
  1724. int Code = atoi(AltCode);
  1725. if (Code)
  1726. {
  1727. char *Cs;
  1728. if (AltCode[0] == '0')
  1729. Cs = "windows-1252";
  1730. else
  1731. Cs = "us-ascii";
  1732. char16 u = 0;
  1733. if (Code < 256)
  1734. {
  1735. uchar c = Code;
  1736. int Len = 1;
  1737. uchar *Ch = &c;
  1738. LgiBufConvertCp(&u, LGI_WideCharset, sizeof(u), (void*&)Ch, Cs, Len);
  1739. }
  1740. else u = Code;
  1741. if (u)
  1742. {
  1743. GKey Key(0, 0);
  1744. Key.c16 = u;
  1745. Key.Flags = KeyFlags;
  1746. Key.Data = Msg->b;
  1747. Key.Down(true);
  1748. Key.IsChar = true;
  1749. GWindow *Wnd = GetWindow();
  1750. if (Wnd)
  1751. {
  1752. Wnd->HandleViewKey(this, Key);
  1753. }
  1754. else
  1755. {
  1756. OnKey(Key);
  1757. }
  1758. }
  1759. }
  1760. }
  1761. else
  1762. {
  1763. // Down
  1764. AltCode[0] = 0;
  1765. }
  1766. }
  1767. }
  1768. else if (IsDown && (KeyFlags & LGI_EF_ALT) != 0)
  1769. {
  1770. int Num = -1;
  1771. if (Msg->a >= VK_NUMPAD0 && Msg->a <= VK_NUMPAD9)
  1772. Num = Msg->a - VK_NUMPAD0;
  1773. else if (Msg->a >= '0' && Msg->a <= '9')
  1774. Num = Msg->a - '0';
  1775. if (Num >= 0)
  1776. {
  1777. int e = strlen(AltCode);
  1778. if (e < sizeof(AltCode) - 1)
  1779. {
  1780. AltCode[e++] = Num + '0';
  1781. AltCode[e] = 0;
  1782. }
  1783. }
  1784. }
  1785. #endif
  1786. if (!SysOnKey(this, Msg))
  1787. {
  1788. // Key
  1789. GKey Key(Msg->a, Msg->b);
  1790. Key.Flags = KeyFlags;
  1791. Key.Data = Msg->b;
  1792. Key.Down(IsDown);
  1793. Key.IsChar = false;
  1794. if (Key.Ctrl())
  1795. {
  1796. Key.c16 = Msg->a;
  1797. }
  1798. #if 0
  1799. LgiTrace("KEYDOWN 0x%x(%c) v=0x%x cas=%i:%i:%i\n",
  1800. Key.c16, Key.c16>=' '?Key.c16:'.',
  1801. Msg->a,
  1802. Key.Ctrl(), Key.Alt(), Key.Shift());
  1803. #endif
  1804. GWindow *Wnd = GetWindow();
  1805. if (Wnd)
  1806. {
  1807. if (Key.Alt() ||
  1808. Key.Ctrl() ||
  1809. (Key.c16 < 'A' || Key.c16 > 'Z'))
  1810. {
  1811. Wnd->HandleViewKey(this, Key);
  1812. }
  1813. }
  1814. else
  1815. {
  1816. OnKey(Key);
  1817. }
  1818. #if !OLD_WM_CHAR_MODE
  1819. // Keydown -> Char, because TranslateMessage is broken
  1820. if (Key.c16 &&
  1821. (Key.IsChar = IsKeyChar(Key, Msg->a)) != 0)
  1822. {
  1823. #if 0
  1824. LgiTrace("CHAR 0x%x(%c) v=0x%x cas=%i:%i:%i\n",
  1825. Key.c16, Key.c16>=' '?Key.c16:'.',
  1826. Msg->a,
  1827. Key.Ctrl(), Key.Alt(), Key.Shift());
  1828. #endif
  1829. GWindow *Wnd = GetWindow();
  1830. if (Wnd)
  1831. {
  1832. Wnd->HandleViewKey(this, Key);
  1833. }
  1834. else
  1835. {
  1836. OnKey(Key);
  1837. }
  1838. }
  1839. #endif
  1840. }
  1841. if (!IsDialog)
  1842. {
  1843. // required for Alt-Key function (eg Alt-F4 closes window)
  1844. goto ReturnDefaultProc;
  1845. }
  1846. break;
  1847. }
  1848. #if OLD_WM_CHAR_MODE
  1849. case WM_CHAR:
  1850. {
  1851. GKey Key(Msg->a, Msg->b);
  1852. Key.Flags = _lgi_get_key_flags();
  1853. Key.Data = Msg->b;
  1854. Key.Down(true);
  1855. Key.IsChar = true;
  1856. bool Shift = Key.Shift();
  1857. bool Caps = TestFlag(Key.Flags, LGI_EF_CAPS_LOCK);
  1858. if (!(Shift ^ Caps))
  1859. {
  1860. Key.c16 = ToLower(Key.c16);
  1861. }
  1862. else
  1863. {
  1864. Key.c16 = ToUpper(Key.c16);
  1865. }
  1866. GWindow *Wnd = GetWindow();
  1867. if (Wnd)
  1868. {
  1869. Wnd->HandleViewKey(this, Key);
  1870. }
  1871. else
  1872. {
  1873. OnKey(Key);
  1874. }
  1875. break;
  1876. }
  1877. #endif
  1878. case M_SET_WND_STYLE:
  1879. {
  1880. SetWindowLong(Handle(), GWL_STYLE, Msg->b);
  1881. SetWindowPos( Handle(),
  1882. 0, 0, 0, 0, 0,
  1883. SWP_NOMOVE | SWP_NOZORDER | SWP_NOSIZE | SWP_FRAMECHANGED);
  1884. break;
  1885. }
  1886. case WM_PAINT:
  1887. {
  1888. _Paint();
  1889. break;
  1890. }
  1891. case WM_NCPAINT:
  1892. {
  1893. bool Thin = (Sunken() || Raised()) && (_BorderSize == 1);
  1894. if (Thin)
  1895. {
  1896. HDC hDC = GetWindowDC(_View);
  1897. GScreenDC Dc(hDC, _View, true);
  1898. GRect p(0, 0, Dc.X()-1, Dc.Y()-1);
  1899. if (p.Valid())
  1900. {
  1901. LgiThinBorder(&Dc, p, Sunken()?SUNKEN:RAISED);
  1902. }
  1903. }
  1904. else
  1905. {
  1906. goto ReturnDefaultProc;
  1907. }
  1908. break;
  1909. }
  1910. /*
  1911. case M_GTHREADWORK_COMPELTE:
  1912. {
  1913. GThreadOwner *Owner = (GThreadOwner *) Msg->a;
  1914. GThreadWork *WorkUnit = (GThreadWork *) Msg->b;
  1915. Owner->OnComplete(WorkUnit);
  1916. DeleteObj(WorkUnit);
  1917. break;
  1918. }
  1919. */
  1920. case WM_NCCALCSIZE:
  1921. {
  1922. bool Thin = (Sunken() || Raised()) && _BorderSize == 1;
  1923. if (Msg->a)
  1924. {
  1925. if (Thin)
  1926. {
  1927. NCCALCSIZE_PARAMS *p = (NCCALCSIZE_PARAMS*) Msg->b;
  1928. p->rgrc[0].left++;
  1929. p->rgrc[0].top++;
  1930. p->rgrc[0].right--;
  1931. p->rgrc[0].bottom--;
  1932. return 0;
  1933. }
  1934. }
  1935. else
  1936. {
  1937. if (Thin)
  1938. {
  1939. RECT *r = (RECT*)Msg->b;
  1940. r->left++;
  1941. r->top++;
  1942. r->right--;
  1943. r->bottom--;
  1944. return 0;
  1945. }
  1946. }
  1947. // Fall through
  1948. }
  1949. default:
  1950. {
  1951. if (!(WndFlags & GWF_DIALOG))
  1952. goto ReturnDefaultProc;
  1953. break;
  1954. }
  1955. }
  1956. }
  1957. return 0;
  1958. ReturnDefaultProc:
  1959. if (IsWin9x)
  1960. return DefWindowProcA(_View, Msg->Msg, Msg->a, Msg->b);
  1961. else
  1962. return DefWindowProcW(_View, Msg->Msg, Msg->a, Msg->b);
  1963. }
  1964. GViewI *GView::FindControl(OsView hCtrl)
  1965. {
  1966. if (_View == hCtrl)
  1967. {
  1968. return this;
  1969. }
  1970. ;
  1971. for (List<GViewI>::I i = Children.Start(); i.In(); i++)
  1972. {
  1973. GViewI *Ctrl = (*i)->FindControl(hCtrl);
  1974. if (Ctrl)
  1975. {
  1976. return Ctrl;
  1977. }
  1978. }
  1979. return 0;
  1980. }