00001
00002
00003
00004
00005
00012 #ifndef HWIDGET_H
00013 #define HWIDGET_H
00014
00015 #ifndef HGUI_H
00016 # include "HGUI.h"
00017 #endif
00018
00019 #ifndef HMAP_H
00020 # include "HMap.h"
00021 #endif
00022
00023
00024
00028
00030 #define BEGIN_MSG_MAP(x) \
00031 public: \
00032 virtual bool \
00033 HandleMessage(HANDLE hWnd, s_gi_msg * pMsg, HRESULT & hr) \
00034 { \
00035 if (NULL_PTR(pMsg)) return false;
00036
00037
00039 #define MAP_CMD(id, fn) \
00040 if (pMsg->type == MSG_COMMAND && pMsg->para1 == (id) && \
00041 fn(pMsg->para1, hr)) return true;
00042
00044 #define MAP_CMD_ALL(fn) \
00045 if (pMsg->type == MSG_COMMAND && \
00046 fn(pMsg->para1, hr)) return true;
00047
00049 #define MAP_CMD_RANGE(idLo, idHi, fn) \
00050 if (pMsg->type == MSG_COMMAND && \
00051 pMsg->para1 >= (idLo) && pMsg->para1 <= (idHi) && \
00052 fn(pMsg->para1, hr)) return true;
00053
00055 #define MAP_MSG(id, fn) \
00056 if (pMsg->type == (id) && \
00057 fn(*pMsg, hr)) return true;
00058
00060 #define MAP_MSG_RANGE(idLo, idHi, fn) \
00061 if (pMsg->type >= (idLo) && pMsg->type <= (idHi) && \
00062 fn(*pMsg, hr)) return true;
00063
00065 #define CHAIN_MAP(x) \
00066 if (x::HandleMessage(hWnd, pMsg, hr)) return true;
00067
00069 #define END_MSG_MAP \
00070 return false; \
00071 }
00072
00073
00104 class HWidget : public HObjNoCopy
00105 {
00106 typedef HObjNoCopy base_class;
00107 static StringPtr ClassName(void) { return "HWidget"; }
00108
00109
00110
00111 protected:
00112 static HMap<HANDLE, HWidget *> s_map;
00113
00114 bool m_bAutoDestruct;
00115 HANDLE m_hMe;
00116 tWindowFunction m_pfnWndProc;
00117
00118
00119
00120 public:
00121 HWidget(void) : m_bAutoDestruct(true), m_hMe(NULL), m_pfnWndProc(NULL)
00122 { }
00123
00124 virtual
00125 ~HWidget(void)
00126 { }
00127
00128
00129
00130 public:
00145 virtual bool
00146 HandleMessage(HANDLE hWnd, s_gi_msg * pMsg, HRESULT & hr)
00147 {
00148 bool bHandled = false;
00149
00150 ASSERT( GOOD_HND(hWnd) );
00151
00152 if (GOOD_PTR(pMsg))
00153 {
00154 switch (pMsg->type)
00155 {
00156 case MSG_COMMAND:
00157 bHandled = onCommand(pMsg->para1, hr);
00158 break;
00159 case MSG_GUI_REDRAW:
00160 bHandled = onRedraw(*pMsg, hr);
00161 break;
00162 case MSG_GUI_CREATE_WINDOW:
00163 bHandled = onCreateWindow(*pMsg, hr);
00164 break;
00165 case MSG_WINDOW_DESTROY:
00166 bHandled = onWindowDestroy(*pMsg, hr);
00167 break;
00168 case MSG_WINDOW_SIZED:
00169 bHandled = onWindowSized(*pMsg, hr);
00170 break;
00171 default:
00172 break;
00173 }
00174 }
00175
00176
00177
00178
00179 if (!bHandled && GOOD_PTR(m_pfnWndProc))
00180 {
00181 hr = (m_pfnWndProc)(hWnd, pMsg);
00182 bHandled = true;
00183 }
00184
00185 return bHandled;
00186 }
00187
00188 protected:
00198 bool
00199 onCommand(uint32 uCmd, HRESULT & hr)
00200 {
00201 bool bHandled = true;
00202 HANDLE hParent = getParentFromHandle(m_hMe);
00203
00204 if (GOOD_HND(hParent))
00205 hr = GI_post_command(hParent, uCmd);
00206 else
00207 {
00208 DEBUG_LOG( "HWidget[%p]::onCommand() => command %lu ignored\n",
00209 this, uCmd);
00210 bHandled = false;
00211 }
00212
00213 return bHandled;
00214 }
00224 bool
00225 onMouseBut1Released(const s_gi_msg & msg, HRESULT & hr)
00226 {
00227 ASSERT(msg.type == MSG_MOUSE_BUT1_RELEASED);
00228 DEBUG_LOG( "HWidget[%p]::onMouseBut1Released() => (%d, %d)\n",
00229 this, msg.para1, msg.para2);
00230
00231 return false;
00232 }
00242 bool
00243 onMouseBut2Released(const s_gi_msg & msg, HRESULT & hr)
00244 {
00245 ASSERT(msg.type == MSG_MOUSE_BUT2_RELEASED);
00246 DEBUG_LOG( "HWidget[%p]::onMouseBut2Released() => (%d, %d)\n",
00247 this, msg.para1, msg.para2);
00248
00249 return false;
00250 }
00258 bool
00259 onMouseEnter(const s_gi_msg & msg, HRESULT & hr)
00260 {
00261 ASSERT(msg.type == MSG_MOUSE_ENTER);
00262 return false;
00263 }
00271 bool
00272 onMouseLeave(const s_gi_msg & msg, HRESULT & hr)
00273 {
00274 ASSERT(msg.type == MSG_MOUSE_LEAVE);
00275 return false;
00276 }
00284 bool
00285 onMouseMove(const s_gi_msg & msg, HRESULT & hr)
00286 {
00287 ASSERT(msg.type == MSG_MOUSE_MOVE);
00288 return false;
00289 }
00297 virtual bool
00298 onPreDestroy(const s_gi_msg & msg, HRESULT & hr)
00299 {
00300 ASSERT(msg.type == MSG_PRE_DESTROY);
00301 return false;
00302 }
00313 virtual bool
00314 onRedraw(const s_gi_msg & msg, HRESULT & hr)
00315 {
00316 ASSERT(msg.type == MSG_GUI_REDRAW);
00317 return false;
00318 }
00326 virtual bool
00327 onCreateWindow(const s_gi_msg & msg, HRESULT & hr)
00328 {
00329 ASSERT(msg.type == MSG_GUI_CREATE_WINDOW);
00330 return false;
00331 }
00342 virtual bool
00343 onWindowDestroy(const s_gi_msg & msg, HRESULT & hr)
00344 {
00345 ASSERT(msg.type == MSG_WINDOW_DESTROY);
00346
00347 if (IsValid())
00348 {
00349 disableMessages();
00350 m_hMe = NULL;
00351 DEBUG_LOG("HWidget[%p]::onWindowDestroy() => m_hMe set to NULL.\n", this);
00352 }
00353
00354 return false;
00355 }
00363 virtual bool
00364 onWindowSized(const s_gi_msg & msg, HRESULT & hr)
00365 {
00366 ASSERT(msg.type == MSG_WINDOW_SIZED);
00367 return false;
00368 }
00369
00370
00371
00372 public:
00379 ErrCode
00380 Adopt(HANDLE hWnd)
00381 {
00382 ErrCode ec = HError::NoError();
00383
00384 ASSERT( NULL_HND(m_hMe) );
00385 ASSERT( !s_map.Contains(hWnd) );
00386
00387 if (GOOD_HND(hWnd))
00388 {
00389 m_hMe = hWnd;
00390 m_bAutoDestruct = true;
00391 ec = enableMessages();
00392 }
00393 else
00394 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00395
00396 return ec;
00397 }
00407 virtual ErrCode
00408 Destroy(void)
00409 {
00410 ErrCode ec = HError::NoError();
00411
00412 if (IsValid())
00413 {
00414 DEBUG_LOG( "HWidget[%p]::Destroy() => %s\n",
00415 this, (m_bAutoDestruct ? "auto-destruct" : "manual"));
00416
00417
00418
00419
00420
00421 if (m_bAutoDestruct)
00422 {
00423 disableMessages();
00424 m_hMe = NULL;
00425 DEBUG_LOG("HWidget[%p]::Destroy() => m_hMe set to NULL.\n", this);
00426 }
00427 else if (GI_destroy_window( GetWindow() ) != S_OK)
00428 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00429 }
00430
00431 return ec;
00432 }
00441 virtual ErrCode
00442 Draw(HRect & rDirty)
00443 { return HError::Set(ERR_NOT_IMPLEMENTED, __FILE__, __LINE__); }
00451 virtual ErrCode
00452 Show(void) const
00453 {
00454 ErrCode ec = HError::NoError();
00455
00456 if (IsValid())
00457 {
00458 if (GI_show(m_hMe) != S_OK)
00459 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00460 }
00461 else
00462 ec = HError::Set(ERR_BAD_WINDOW, __FILE__, __LINE__);
00463
00464 return ec;
00465 }
00472 virtual ErrCode
00473 Smudge(HRect const * prDirty = NULL)
00474 {
00475 ErrCode ec = HError::NoError();
00476
00477 if (IsValid())
00478 {
00479 s_window * pwMe = GetWindow();
00480
00481 if (GOOD_PTR(prDirty) && prDirty->IsNotEmpty())
00482 {
00483 s_region rDirty = *prDirty;
00484
00485 if (GI_redraw_region(pwMe, &rDirty) != S_OK)
00486 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00487 }
00488 else if (GI_redraw_window(pwMe) != S_OK)
00489 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00490 }
00491 else
00492 ec = HError::Set(ERR_BAD_WINDOW, __FILE__, __LINE__);
00493
00494 return ec;
00495 }
00503 static HRESULT
00504 WidgetProc(HANDLE hWnd, s_gi_msg * pMsg)
00505 {
00506 HRESULT hr = S_OK;
00507 HWidget * pWidget = NULL;
00508
00509 DEBUG_MSG("WidgetProc", hWnd, pMsg);
00510
00511 if (s_map.Get(hWnd, pWidget) != NO_ERROR ||
00512 !(GOOD_PTR(pWidget) && pWidget->HandleMessage(hWnd, pMsg, hr)))
00513 {
00514 hr = DefaultWindowFunc(hWnd, pMsg);
00515 }
00516
00517 return hr;
00518 }
00519
00520 protected:
00525 ErrCode
00526 disableMessages(void)
00527 {
00528 ErrCode ec = HError::NoError();
00529
00530 if (IsValid())
00531 {
00532 if (GOOD_PTR(m_pfnWndProc) &&
00533 GI_set_window_func(m_hMe, m_pfnWndProc) != S_OK)
00534 {
00535 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00536 }
00537
00538 ec = s_map.Remove(m_hMe);
00539 DEBUG_LOG("HWidget::disableMessages() => removed 0x%08lX\n", int32(m_hMe));
00540 }
00541 else
00542 ec = HError::Set(ERR_BAD_WINDOW, __FILE__, __LINE__);
00543
00544 return ec;
00545 }
00550 ErrCode
00551 enableMessages(void)
00552 {
00553 ErrCode ec = HError::NoError();
00554
00555 if (IsValid())
00556 {
00557 HWidget * pwMe = this;
00558
00559 m_pfnWndProc = GI_overload_winfunc(m_hMe, tWindowFunction(WidgetProc));
00560 ec = s_map.Set(m_hMe, pwMe);
00561 DEBUG_LOG("HWidget::enableMessages() => added 0x%08lX\n", int32(m_hMe));
00562 }
00563 else
00564 ec = HError::Set(ERR_BAD_WINDOW, __FILE__, __LINE__);
00565
00566 return ec;
00567 }
00568
00569
00570
00571 public:
00578 bool
00579 GetBounds(HRect & rBounds)
00580 {
00581 if (IsValid())
00582 {
00583 rBounds.x1 = 0;
00584 rBounds.y1 = 0;
00585 rBounds.x2 = GetWidth() + 1;
00586 rBounds.y2 = GetHeight() + 1;
00587
00588
00589
00590
00591 }
00592 else
00593 rBounds.SetEmpty();
00594
00595 return rBounds.IsNotEmpty();
00596 }
00606 bool
00607 GetClientBounds(HRect & rBounds)
00608 {
00609 if (IsValid())
00610 {
00611 rBounds.x1 = GetXPos();
00612 rBounds.y1 = GetYPos();
00613 rBounds.x2 = rBounds.x1 + GetWidth() + 1;
00614 rBounds.y2 = rBounds.y1 + GetHeight() + 1;
00615
00616
00617
00618
00619 }
00620 else
00621 rBounds.SetEmpty();
00622
00623 return rBounds.IsNotEmpty();
00624 }
00634 ErrCode
00635 GetScreenBounds(HRect & rBounds)
00636 {
00637 int nXPos = 0,
00638 nYPos = 0;
00639 ErrCode ec = HError::NoError();
00640
00641 rBounds.SetEmpty();
00642
00643 if (!IsValid())
00644 ec = HError::Set(ERR_BAD_WINDOW, __FILE__, __LINE__);
00645 else if (GI_compute_screen_coordinates(m_hMe, &nXPos, &nYPos) != S_OK)
00646 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00647 else
00648 {
00649 rBounds.x1 = nXPos;
00650 rBounds.y1 = nYPos;
00651 rBounds.x2 = rBounds.x1 + GetWidth() + 1;
00652 rBounds.y2 = rBounds.y1 + GetHeight() + 1;
00653 }
00654
00655 return ec;
00656 }
00661 inline int32 GetHeight(void) const
00662 { return IsValid() ? GI_GetWindowHeight(m_hMe) : 0; }
00667 inline int32 GetWidth(void) const
00668 { return IsValid() ? GI_GetWindowWidth(m_hMe) : 0; }
00673 inline s_window * GetParentWindow(void) const
00674 { return reinterpret_cast<s_window *>( getParentFromHandle(m_hMe) ); }
00679 inline HPoint GetPosition(void) const
00680 { return HPoint(GetXPos(), GetYPos()); }
00685 inline s_window * GetWindow(void) const
00686 { return reinterpret_cast<s_window *>(m_hMe); }
00691 inline int32 GetXPos(void) const
00692 { return IsValid() ? GI_GetWindowX(m_hMe) : 0; }
00697 inline int32 GetYPos(void) const
00698 { return IsValid() ? GI_GetWindowY(m_hMe) : 0; }
00703 inline HANDLE GetHandle(void) const
00704 { return m_hMe; }
00709 inline void SetAutoDestruct(bool bAuto = true)
00710 { m_bAutoDestruct = bAuto; }
00721 ErrCode SetBounds(int32 nX, int32 nY, int32 nXDim, int32 nYDim, bool bRedraw = true)
00722 {
00723 HRect rBounds(nX, nY, nX + nXDim, nY + nYDim);
00724 return SetBounds(rBounds, bRedraw);
00725 }
00733 virtual ErrCode SetBounds(const HRect & rBounds, bool bRedraw = true)
00734 {
00735 ErrCode ec = HError::NoError();
00736
00737 ASSERT( rBounds.IsNotEmpty() );
00738
00739 if (!IsValid())
00740 ec = HError::Set(ERR_BAD_WINDOW, __FILE__, __LINE__);
00741 else if (GI_set_dimension(m_hMe, (bRedraw ? TRUE : FALSE),
00742 rBounds.x1, rBounds.y1,
00743 rBounds.GetWidth(), rBounds.GetHeight()) != S_OK)
00744 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00745 else
00746 {
00747
00748
00749
00750
00751 }
00752
00753 return ec;
00754 }
00763 ErrCode SetPosition(int32 nX, int32 nY, bool bRedraw = true)
00764 {
00765 HRect rBounds;
00766
00767 GetBounds(rBounds);
00768 rBounds.MoveTo(nX, nY);
00769 return SetBounds(rBounds, bRedraw);
00770 }
00771 protected:
00776 static inline HANDLE getParentFromHandle(HANDLE hWnd)
00777 {
00778 s_window * pw = reinterpret_cast<s_window *>(hWnd);
00779 return GOOD_PTR(pw) ? pw->parent : NULL;
00780 }
00781
00782
00783
00784
00785 public:
00788 inline bool IsValid(void) const
00789 { return GOOD_HND(m_hMe); }
00796 inline HRESULT SendCommand(uint32 uCmd) const
00797 { return IsValid() ? GI_post_command(m_hMe, uCmd) : S_FAILED; }
00807 inline HRESULT SendMessage(uint32 uType, uint32 uP1 = 0, uint32 uP2 = 0, s_region * pr = NULL) const
00808 { return IsValid() ? SkyGI_PostMessage(m_hMe, uType, uP1, uP2) : S_FAILED; }
00809 };
00810
00811 typedef HWidget * HWidgetPtr;
00812
00813 #endif // HWIDGET_H
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855