1 // DeskBand.cpp --- CDeskBand implementation
2 //
3 // Copyright (C) 2004, 2005, 2006, 2007, 2010 Raymond Penners <raymond@dotsphinx.com>
4 // All rights reserved.
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 //
19 // $Id$
20 
21 #include <windowsx.h>
22 
23 #include "DeskBand.h"
24 #include "TimeBar.h"
25 #include "TimerBox.h"
26 #include "Guid.h"
27 #include "Applet.hh"
28 #include "Debug.h"
29 #include "PaintHelper.h"
30 
CDeskBand()31 CDeskBand::CDeskBand()
32 {
33   m_pSite = NULL;
34   m_hWnd = NULL;
35   m_hwndParent = NULL;
36   m_bFocus = FALSE;
37   m_dwViewMode = 0;
38   m_dwBandID = 0;
39   m_TimerBox = NULL;
40   m_HasAppletMenu = FALSE;
41   m_LastCopyData = 0;
42   m_ObjRefCount = 1;
43 
44   g_DllRefCount++;
45 }
46 
47 
~CDeskBand()48 CDeskBand::~CDeskBand()
49 {
50   TRACE_ENTER("CDeskBand::~CDeskBand");
51   //this should have been freed in a call to SetSite(NULL), but just to be safe
52   if (m_pSite)
53     {
54       m_pSite->Release();
55       m_pSite = NULL;
56     }
57 
58   g_DllRefCount--;
59   TRACE_MSG(g_DllRefCount);
60   TRACE_EXIT();
61 }
62 
63 STDMETHODIMP
QueryInterface(REFIID riid,LPVOID * ppReturn)64 CDeskBand::QueryInterface(REFIID riid, LPVOID *ppReturn)
65 {
66   *ppReturn = NULL;
67 
68   //IUnknown
69   if (IsEqualIID(riid, IID_IUnknown))
70     {
71       *ppReturn = this;
72     }
73 
74   //IOleWindow
75   else if (IsEqualIID(riid, IID_IOleWindow))
76     {
77       *ppReturn = (IOleWindow*)this;
78     }
79 
80   //IDockingWindow
81   else if (IsEqualIID(riid, IID_IDockingWindow))
82     {
83       *ppReturn = (IDockingWindow*)this;
84     }
85 
86   //IInputObject
87   else if (IsEqualIID(riid, IID_IInputObject))
88     {
89       *ppReturn = (IInputObject*)this;
90     }
91 
92   //IObjectWithSite
93   else if (IsEqualIID(riid, IID_IObjectWithSite))
94     {
95       *ppReturn = (IObjectWithSite*)this;
96     }
97 
98   //IDeskBand
99   else if (IsEqualIID(riid, IID_IDeskBand))
100     {
101       *ppReturn = (IDeskBand*)this;
102     }
103 
104   //IDeskBand2
105   else if (IsEqualIID(riid, IID_IDeskBand2))
106     {
107       *ppReturn = (IDeskBand2*)this;
108     }
109 
110   //IPersist
111   else if (IsEqualIID(riid, IID_IPersist))
112     {
113       *ppReturn = (IPersist*)this;
114     }
115 
116   //IPersistStream
117   else if (IsEqualIID(riid, IID_IPersistStream))
118     {
119       *ppReturn = (IPersistStream*)this;
120     }
121 
122   //IContextMenu
123   else if (IsEqualIID(riid, IID_IContextMenu))
124     {
125       *ppReturn = (IContextMenu*)this;
126     }
127 
128   if (*ppReturn)
129     {
130       (*(LPUNKNOWN*)ppReturn)->AddRef();
131       return S_OK;
132     }
133 
134   return E_NOINTERFACE;
135 }
136 
STDMETHODIMP_(DWORD)137 STDMETHODIMP_(DWORD)
138 CDeskBand::AddRef()
139 {
140   return ++m_ObjRefCount;
141 }
142 
143 
STDMETHODIMP_(DWORD)144 STDMETHODIMP_(DWORD)
145 CDeskBand::Release()
146 {
147   if (--m_ObjRefCount == 0)
148     {
149       delete this;
150       return 0;
151     }
152 
153   return m_ObjRefCount;
154 }
155 
156 STDMETHODIMP
GetWindow(HWND * phWnd)157 CDeskBand::GetWindow(HWND *phWnd)
158 {
159   TRACE_ENTER("CDeskBand::GetWindow");
160   *phWnd = m_hWnd;
161 
162   TRACE_EXIT();
163   return S_OK;
164 }
165 
166 STDMETHODIMP
ContextSensitiveHelp(BOOL fEnterMode)167 CDeskBand::ContextSensitiveHelp(BOOL fEnterMode)
168 {
169   return E_NOTIMPL;
170 }
171 
172 STDMETHODIMP
ShowDW(BOOL fShow)173 CDeskBand::ShowDW(BOOL fShow)
174 {
175   TRACE_ENTER_MSG("CDeskBand::ShowDW", fShow);
176   if (m_hWnd)
177     {
178       if (fShow)
179         {
180           //show our window
181           ShowWindow(m_hWnd, SW_SHOW);
182         }
183       else
184         {
185           //hide our window
186           ShowWindow(m_hWnd, SW_HIDE);
187         }
188     }
189 
190   TRACE_EXIT();
191   return S_OK;
192 }
193 
194 STDMETHODIMP
CloseDW(DWORD dwReserved)195 CDeskBand::CloseDW(DWORD dwReserved)
196 {
197   TRACE_ENTER("CDeskBand::CloseDW");
198   ShowDW(FALSE);
199 
200   delete m_TimerBox;
201   m_TimerBox = NULL;
202 
203   if (IsWindow(m_hWnd))
204     DestroyWindow(m_hWnd);
205 
206   m_hWnd = NULL;
207 
208   TRACE_EXIT();
209   return S_OK;
210 }
211 
212 STDMETHODIMP
ResizeBorderDW(LPCRECT prcBorder,IUnknown * punkSite,BOOL fReserved)213 CDeskBand::ResizeBorderDW(LPCRECT prcBorder,
214                           IUnknown* punkSite,
215                           BOOL fReserved)
216 {
217   return E_NOTIMPL;
218 }
219 
220 STDMETHODIMP
UIActivateIO(BOOL fActivate,LPMSG pMsg)221 CDeskBand::UIActivateIO(BOOL fActivate, LPMSG pMsg)
222 {
223   if (fActivate)
224     SetFocus(m_hWnd);
225 
226   return S_OK;
227 }
228 
229 STDMETHODIMP
HasFocusIO()230 CDeskBand::HasFocusIO()
231 {
232   if (m_bFocus)
233     return S_OK;
234 
235   return S_FALSE;
236 }
237 
238 STDMETHODIMP
TranslateAcceleratorIO(LPMSG pMsg)239 CDeskBand::TranslateAcceleratorIO(LPMSG pMsg)
240 {
241   return S_FALSE;
242 }
243 
244 STDMETHODIMP
SetSite(IUnknown * punkSite)245 CDeskBand::SetSite(IUnknown* punkSite)
246 {
247   TRACE_ENTER("CDeskBand::SetSite");
248   //If a site is being held, release it.
249   if (m_pSite)
250     {
251       m_pSite->Release();
252       m_pSite = NULL;
253     }
254 
255   //If punkSite is not NULL, a new site is being set.
256   if (punkSite)
257     {
258       //Get the parent window.
259       IOleWindow  *pOleWindow;
260 
261       m_hwndParent = NULL;
262 
263       if (SUCCEEDED(punkSite->QueryInterface(IID_IOleWindow, (LPVOID*)&pOleWindow)))
264         {
265           pOleWindow->GetWindow(&m_hwndParent);
266           pOleWindow->Release();
267         }
268 
269       if (!m_hwndParent)
270         return E_FAIL;
271 
272       if (!RegisterAndCreateWindow())
273         return E_FAIL;
274 
275       //Get and keep the IInputObjectSite pointer.
276       if (SUCCEEDED(punkSite->QueryInterface(IID_IInputObjectSite, (LPVOID*)&m_pSite)))
277         {
278           return S_OK;
279         }
280 
281       return E_FAIL;
282     }
283 
284   TRACE_EXIT();
285   return S_OK;
286 }
287 
288 STDMETHODIMP
GetSite(REFIID riid,LPVOID * ppvReturn)289 CDeskBand::GetSite(REFIID riid, LPVOID *ppvReturn)
290 {
291   TRACE_ENTER("CDeskBand::GetSite");
292   *ppvReturn = NULL;
293 
294   if (m_pSite)
295     return m_pSite->QueryInterface(riid, ppvReturn);
296 
297   return E_FAIL;
298 }
299 
300 STDMETHODIMP
GetBandInfo(DWORD dwBandID,DWORD dwViewMode,DESKBANDINFO * pdbi)301 CDeskBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi)
302 {
303   TRACE_ENTER_MSG("CDeskBand::GetBandInfo", dwBandID << " " << dwViewMode);
304   if (pdbi)
305     {
306       m_dwBandID = dwBandID;
307       m_dwViewMode = dwViewMode;
308 
309       if (pdbi->dwMask & DBIM_MINSIZE)
310         {
311           if (DBIF_VIEWMODE_FLOATING & dwViewMode)
312             {
313               pdbi->ptMinSize.x = 200;
314               pdbi->ptMinSize.y = 400;
315             }
316           else
317             {
318               pdbi->ptMinSize.x = DB_MIN_SIZE_X;
319               pdbi->ptMinSize.y = DB_MIN_SIZE_Y;
320             }
321         }
322 
323       if (pdbi->dwMask & DBIM_MAXSIZE)
324         {
325           pdbi->ptMaxSize.x = -1;
326           pdbi->ptMaxSize.y = -1;
327         }
328 
329       if (pdbi->dwMask & DBIM_INTEGRAL)
330         {
331           pdbi->ptIntegral.x = 1;
332           pdbi->ptIntegral.y = 1;
333         }
334 
335       if (pdbi->dwMask & DBIM_ACTUAL)
336         {
337           pdbi->ptActual.x = 100;
338           pdbi->ptActual.y = 100;
339         }
340 
341       if (pdbi->dwMask & DBIM_TITLE)
342         {
343           if (dwViewMode & DBIF_VIEWMODE_FLOATING)
344             {
345               lstrcpyW(pdbi->wszTitle, L"Workrave");
346             }
347           else
348             {
349               pdbi->dwMask &= ~DBIM_TITLE;
350             }
351         }
352 
353       if (pdbi->dwMask & DBIM_MODEFLAGS)
354         {
355           pdbi->dwModeFlags = DBIMF_NORMAL;
356           pdbi->dwModeFlags |= DBIMF_VARIABLEHEIGHT;
357         }
358 
359       if (pdbi->dwMask & DBIM_BKCOLOR)
360         {
361           //Use the default background color by removing this flag.
362           pdbi->dwMask &= ~DBIM_BKCOLOR;
363         }
364 
365       return S_OK;
366     }
367 
368   TRACE_EXIT();
369   return E_INVALIDARG;
370 }
371 
372 STDMETHODIMP
CanRenderComposited(BOOL * pfCanRenderComposited)373 CDeskBand::CanRenderComposited(BOOL *pfCanRenderComposited)
374 {
375   TRACE_ENTER("CDeskBand::CanRenderComposited");
376 
377   if (!pfCanRenderComposited)
378     return E_INVALIDARG;
379 
380   *pfCanRenderComposited = TRUE;
381   TRACE_EXIT();
382   return S_OK;
383 }
384 
385 STDMETHODIMP
GetCompositionState(BOOL * pfCompositionEnabled)386 CDeskBand::GetCompositionState( BOOL *pfCompositionEnabled )
387 {
388   TRACE_ENTER("CDeskBand::GetCompositionState");
389   if (!pfCompositionEnabled)
390     return E_INVALIDARG;
391 
392   *pfCompositionEnabled = m_CompositionEnabled;
393   TRACE_EXIT();
394   return S_OK;
395 }
396 
397 STDMETHODIMP
SetCompositionState(BOOL fCompositionEnabled)398 CDeskBand::SetCompositionState( BOOL fCompositionEnabled )
399 {
400   TRACE_ENTER_MSG("CDeskBand::SetCompositionState", fCompositionEnabled);
401   m_CompositionEnabled = fCompositionEnabled;
402 
403   PaintHelper::SetCompositionEnabled(fCompositionEnabled != FALSE);
404   TRACE_EXIT();
405   return S_OK;
406 }
407 
408 STDMETHODIMP
GetClassID(LPCLSID pClassID)409 CDeskBand::GetClassID(LPCLSID pClassID)
410 {
411   *pClassID = CLSID_WorkraveDeskBand;
412 
413   return S_OK;
414 }
415 
416 STDMETHODIMP
IsDirty()417 CDeskBand::IsDirty()
418 {
419   return S_FALSE;
420 }
421 
422 STDMETHODIMP
Load(LPSTREAM pStream)423 CDeskBand::Load(LPSTREAM pStream)
424 {
425   return S_OK;
426 }
427 
428 STDMETHODIMP
Save(LPSTREAM pStream,BOOL fClearDirty)429 CDeskBand::Save(LPSTREAM pStream, BOOL fClearDirty)
430 {
431   return S_OK;
432 }
433 STDMETHODIMP
GetSizeMax(ULARGE_INTEGER * pul)434 CDeskBand::GetSizeMax(ULARGE_INTEGER *pul)
435 {
436   return E_NOTIMPL;
437 }
438 
439 STDMETHODIMP
QueryContextMenu(HMENU hMenu,UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags)440 CDeskBand::QueryContextMenu(HMENU hMenu,
441                             UINT indexMenu,
442                             UINT idCmdFirst,
443                             UINT idCmdLast,
444                             UINT uFlags)
445 {
446   TRACE_ENTER("CDeskBand::QueryContextMenu");
447   if ((!m_HasAppletMenu) || (CMF_DEFAULTONLY & uFlags) || !IsWindow( get_command_window() ))
448     return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
449 
450   int m = 0;
451   HMENU popup = NULL;
452   while (m < m_AppletMenu.num_items)
453     {
454       AppletMenuItemData *d = &m_AppletMenu.items[m];
455       wchar_t textw[APPLET_MENU_TEXT_MAX_LENGTH*2];
456       MultiByteToWideChar(CP_UTF8, 0, d->text, -1,
457                           textw, sizeof(textw)/sizeof(textw[0]));
458       wchar_t *abbrev = wcschr(textw, '_');
459       UINT flags = MF_STRING | MF_BYPOSITION;
460       if (d->flags & APPLET_MENU_FLAG_SELECTED)
461         {
462           flags |= MF_CHECKED;
463         }
464       if (abbrev != NULL)
465         {
466           *abbrev = '&';
467         }
468       if (d->flags & APPLET_MENU_FLAG_POPUP)
469         {
470           if (popup == NULL)
471             {
472               popup = CreatePopupMenu();
473             }
474           AppendMenuW(popup,
475                       flags,
476                       idCmdFirst + m,
477                       textw);
478         }
479       else
480         {
481           if (popup != NULL)
482             {
483               InsertMenuW(hMenu,
484                           indexMenu++,
485                           MF_POPUP | flags,
486                           (UINT) popup,
487                           textw);
488               popup = NULL;
489             }
490           else
491             {
492               InsertMenuW(hMenu,
493                           indexMenu++,
494                           flags,
495                           idCmdFirst + m,
496                           textw);
497             }
498         }
499       m++;
500     }
501 
502   TRACE_EXIT();
503   return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(m_AppletMenu.num_items + 1));
504 }
505 
506 STDMETHODIMP
InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)507 CDeskBand::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
508 {
509   TRACE_ENTER("CDeskBand::InvokeCommand");
510   int cmd = LOWORD(lpcmi->lpVerb);
511   HRESULT ret;
512 
513   if (m_HasAppletMenu && cmd >= 0 && cmd < m_AppletMenu.num_items && IsWindow( get_command_window() ))
514     {
515       SendMessage( get_command_window(), WM_USER, m_AppletMenu.items[cmd].command, NULL );
516       ret = NOERROR;
517     }
518   else
519     {
520       ret = E_INVALIDARG;
521     }
522   TRACE_EXIT();
523   return ret;
524 }
525 
526 STDMETHODIMP
GetCommandString(UINT_PTR idCommand,UINT uFlags,LPUINT lpReserved,LPSTR lpszName,UINT uMaxNameLen)527 CDeskBand::GetCommandString(UINT_PTR idCommand,
528                             UINT uFlags,
529                             LPUINT lpReserved,
530                             LPSTR lpszName,
531                             UINT uMaxNameLen)
532 {
533   HRESULT  hr = E_INVALIDARG;
534   return hr;
535 }
536 
537 LRESULT CALLBACK
WndProc(HWND hWnd,UINT uMessage,WPARAM wParam,LPARAM lParam)538 CDeskBand::WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
539 {
540   TRACE_ENTER("CDeskBand::WndProc");
541   LRESULT lResult = 0;
542   CDeskBand  *pThis = (CDeskBand*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
543 
544   switch (uMessage)
545     {
546     case WM_NCCREATE:
547       {
548         LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
549         pThis = (CDeskBand *)( lpcs->lpCreateParams );
550         SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pThis);
551         SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
552                      SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
553 
554         //set the window handle
555         pThis->m_hWnd = hWnd;
556         SetTimer(hWnd, 0xdeadf00d, 3000, NULL);
557         PaintHelper::Init();
558       }
559       break;
560 
561     case WM_ERASEBKGND:
562 	  if (pThis->m_CompositionEnabled)
563 	  {
564 		lResult = 1;
565 	  }
566       break;
567 
568     case WM_COMMAND:
569       pThis->OnCommand(wParam, lParam);
570       break;
571 
572     case WM_TIMER:
573       pThis->OnTimer(wParam, lParam);
574       break;
575 
576     case WM_COPYDATA:
577       pThis->OnCopyData((PCOPYDATASTRUCT) lParam);
578       break;
579 
580     case WM_SETFOCUS:
581       pThis->OnSetFocus();
582       break;
583 
584     case WM_KILLFOCUS:
585       pThis->OnKillFocus();
586       break;
587 
588     case WM_SIZE:
589       pThis->OnSize(lParam);
590       break;
591 
592     case WM_WINDOWPOSCHANGING:
593       pThis->OnWindowPosChanging(wParam, lParam);
594       break;
595 
596     case WM_LBUTTONUP:
597       SendMessage((HWND)LongToHandle(pThis->m_AppletMenu.command_window),
598                   WM_USER + 1, 0, NULL);
599       break;
600     }
601 
602     if (uMessage != WM_ERASEBKGND)
603     {
604         lResult = DefWindowProc(hWnd, uMessage, wParam, lParam);
605     }
606 
607     TRACE_EXIT();
608     return lResult;
609 }
610 
611 LRESULT
OnCommand(WPARAM wParam,LPARAM lParam)612 CDeskBand::OnCommand(WPARAM wParam, LPARAM lParam)
613 {
614   return 0;
615 }
616 
617 LRESULT
OnTimer(WPARAM wParam,LPARAM lParam)618 CDeskBand::OnTimer(WPARAM wParam, LPARAM lParam)
619 {
620   TRACE_ENTER_MSG("CDeskBand::OnTimer", wParam << " " << lParam);
621   if (m_TimerBox != NULL)
622     {
623       if (m_LastCopyData == 0 || difftime(time(NULL), m_LastCopyData) > 2)
624         {
625           m_TimerBox->set_enabled(false);
626           m_TimerBox->update(false);
627         }
628     }
629   TRACE_EXIT();
630   return 0;
631 }
632 
633 LRESULT
OnCopyData(PCOPYDATASTRUCT copy_data)634 CDeskBand::OnCopyData(PCOPYDATASTRUCT copy_data)
635 {
636   TRACE_ENTER("CDeskBand::OnCopyData");
637   m_LastCopyData = time(NULL);
638   if (copy_data->dwData == APPLET_MESSAGE_MENU
639       && copy_data->cbData == sizeof(AppletMenuData))
640     {
641       m_AppletMenu = *((AppletMenuData *) copy_data->lpData);
642       m_HasAppletMenu = TRUE;
643     }
644   else if (m_TimerBox != NULL
645            && copy_data->dwData == APPLET_MESSAGE_HEARTBEAT
646            && copy_data->cbData == sizeof(AppletHeartbeatData))
647     {
648       AppletHeartbeatData *data = (AppletHeartbeatData *) copy_data->lpData;
649       m_TimerBox->set_enabled(data->enabled);
650       for (int s = 0; s < BREAK_ID_SIZEOF; s++)
651         {
652           m_TimerBox->set_slot(s, (BreakId) data->slots[s]);
653         }
654       for (int b = 0; b < BREAK_ID_SIZEOF; b++)
655         {
656           TimeBar *bar = m_TimerBox->get_time_bar(BreakId(b));
657           if (bar != NULL)
658             {
659               bar->set_text(data->bar_text[b]);
660               bar->set_bar_color((ITimeBar::ColorId) data->bar_primary_color[b]);
661               bar->set_secondary_bar_color((ITimeBar::ColorId) data->bar_secondary_color[b]);
662               bar->set_progress(data->bar_primary_val[b], data->bar_primary_max[b]);
663               bar->set_secondary_progress(data->bar_secondary_val[b], data->bar_secondary_max[b]);
664             }
665         }
666 
667       m_TimerBox->update(false);
668     }
669   TRACE_EXIT();
670   return 0;
671 }
672 
673 
674 LRESULT
OnSize(LPARAM lParam)675 CDeskBand::OnSize(LPARAM lParam)
676 {
677   TRACE_ENTER_MSG("CDeskBand::OnSize",lParam);
678   int   cx, cy;
679 
680   cx = LOWORD(lParam);
681   cy = HIWORD(lParam);
682   if (m_TimerBox != NULL)
683     {
684       m_TimerBox->set_size(cx, cy);
685       m_TimerBox->update(true);
686     }
687 
688   TRACE_EXIT();
689   return 0;
690 }
691 
692 
693 void
FocusChange(BOOL bFocus)694 CDeskBand::FocusChange(BOOL bFocus)
695 {
696   TRACE_ENTER_MSG("CDeskBand::OnWindowPosChanging", bFocus);
697   m_bFocus = bFocus;
698 
699   //inform the input object site that the focus has changed
700   if (m_pSite)
701     {
702       m_pSite->OnFocusChangeIS((IDockingWindow*)this, bFocus);
703     }
704   TRACE_EXIT();
705 }
706 
707 
708 LRESULT
OnSetFocus()709 CDeskBand::OnSetFocus()
710 {
711   TRACE_ENTER("CDeskBand::OnSetFocus");
712   FocusChange(TRUE);
713   TRACE_EXIT();
714   return 0;
715 }
716 
717 
718 LRESULT
OnKillFocus()719 CDeskBand::OnKillFocus()
720 {
721   TRACE_ENTER("CDeskBand::OnKillFocus");
722   FocusChange(FALSE);
723   TRACE_EXIT();
724   return 0;
725 }
726 
727 BOOL
RegisterAndCreateWindow()728 CDeskBand::RegisterAndCreateWindow()
729 {
730   TRACE_ENTER("CDeskBand::RegisterAndCreateWindow");
731   //If the window doesn't exist yet, create it now.
732   if (!m_hWnd)
733     {
734       //Can't create a child window without a parent.
735       if (!m_hwndParent)
736         {
737           return FALSE;
738         }
739 
740       //If the window class has not been registered, then do so.
741       WNDCLASS wc;
742       if (!GetClassInfo(g_hInst, DB_CLASS_NAME, &wc))
743         {
744           ZeroMemory(&wc, sizeof(wc));
745           wc.style          = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
746           wc.lpfnWndProc    = (WNDPROC)WndProc;
747           wc.cbClsExtra     = 0;
748           wc.cbWndExtra     = 0;
749           wc.hInstance      = g_hInst;
750           wc.hIcon          = NULL;
751           wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
752           wc.hbrBackground  = NULL;//(HBRUSH)(COLOR_WINDOWFRAME+1);
753           wc.lpszMenuName   = NULL;
754           wc.lpszClassName  = DB_CLASS_NAME;
755 
756           if (!RegisterClass(&wc))
757             {
758               //If RegisterClass fails, CreateWindow below will fail.
759             }
760         }
761 
762       RECT  rc;
763 
764       GetClientRect(m_hwndParent, &rc);
765 
766       //Create the window. The WndProc will set m_hWnd.
767       HWND h = CreateWindowEx(WS_EX_TRANSPARENT,
768                               DB_CLASS_NAME,
769                               NULL,
770                               WS_CHILD | WS_CLIPSIBLINGS,
771                               rc.left,
772                               rc.top,
773                               rc.right - rc.left,
774                               rc.bottom - rc.top,
775                               m_hwndParent,
776                               NULL,
777                               g_hInst,
778                               (LPVOID)this);
779 
780       m_TimerBox = new TimerBox(h, g_hInst, this);
781     }
782 
783   return (NULL != m_hWnd);
784   TRACE_EXIT();
785 }
786 
787 
788 LRESULT
OnWindowPosChanging(WPARAM wParam,LPARAM lParam)789 CDeskBand::OnWindowPosChanging(WPARAM wParam, LPARAM lParam)
790 {
791   TRACE_ENTER_MSG("CDeskBand::OnWindowPosChanging", wParam << " " << lParam);
792   if (m_TimerBox != NULL)
793     {
794       m_TimerBox->update(true);
795     }
796   TRACE_EXIT();
797   return 0;
798 }
799