1 /*
2  * ReactOS Explorer
3  *
4  * Copyright 2009 Andrew Hill <ash77 at domain reactos.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 
21 /*
22 This class knows how to contain base bar site in a cabinet window.
23 */
24 
25 #include "shellbars.h"
26 
27 /*
28 Base bar that contains a vertical or horizontal explorer band. It also
29 provides resizing abilities.
30 */
31 /*
32 TODO:
33   **Make base bar support resizing -- almost done (need to support integral ?)
34     Add context menu for base bar
35     Fix base bar to correctly initialize fVertical field
36     Fix base bar to correctly reposition its base bar site when resized -- done ?
37 */
38 
39 class CBaseBar :
40     public CWindowImpl<CBaseBar, CWindow, CControlWinTraits>,
41     public CComObjectRootEx<CComMultiThreadModelNoCS>,
42     public IInputObjectSite,
43     public IOleCommandTarget,
44     public IServiceProvider,
45     public IInputObject,
46     public IDeskBar,
47     public IDockingWindow,
48     public IPersistStream,
49     public IPersistStreamInit,
50     public IPersistPropertyBag,
51     public IObjectWithSite
52 {
53 private:
54     CComPtr<IUnknown>                       fSite;
55     CComPtr<IUnknown>                       fClient;
56     HWND                                    fClientWindow;
57     bool                                    fVertical;
58     bool                                    fVisible;
59     int                                     fNeededSize;        // width or height
60 
61     // used by resize tracking loop
62     bool                                    fTracking;
63     POINT                                   fLastLocation;
64 public:
65     CBaseBar();
66     ~CBaseBar();
67     HRESULT Initialize(BOOL);
68 
69 public:
70     HRESULT ReserveBorderSpace();
71 
72     // *** IOleWindow methods ***
73     STDMETHOD(GetWindow)(HWND *lphwnd) override;
74     STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode) override;
75 
76     // *** IInputObjectSite specific methods ***
77     STDMETHOD(OnFocusChangeIS)(IUnknown *punkObj, BOOL fSetFocus) override;
78 
79     // *** IOleCommandTarget specific methods ***
80     STDMETHOD(QueryStatus)(const GUID *pguidCmdGroup, ULONG cCmds,
81         OLECMD prgCmds[  ], OLECMDTEXT *pCmdText) override;
82     STDMETHOD(Exec)(const GUID *pguidCmdGroup, DWORD nCmdID,
83         DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) override;
84 
85     // *** IServiceProvider methods ***
86     STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void **ppvObject) override;
87 
88     // *** IInputObject methods ***
89     // forward the methods to the contained active bar
90     STDMETHOD(UIActivateIO)(BOOL fActivate, LPMSG lpMsg) override;
91     STDMETHOD(HasFocusIO)() override;
92     STDMETHOD(TranslateAcceleratorIO)(LPMSG lpMsg) override;
93 
94     // *** IDeskBar methods ***
95     STDMETHOD(SetClient)(IUnknown *punkClient) override;
96     STDMETHOD(GetClient)(IUnknown **ppunkClient) override;
97     STDMETHOD(OnPosRectChangeDB)(LPRECT prc) override;
98 
99     // *** IDockingWindow methods ***
100     STDMETHOD(ShowDW)(BOOL fShow) override;
101     STDMETHOD(CloseDW)(DWORD dwReserved) override;
102     STDMETHOD(ResizeBorderDW)(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved) override;
103 
104     // *** IObjectWithSite methods ***
105     STDMETHOD(SetSite)(IUnknown *pUnkSite) override;
106     STDMETHOD(GetSite)(REFIID riid, void **ppvSite) override;
107 
108     // *** IPersist methods ***
109     STDMETHOD(GetClassID)(CLSID *pClassID) override;
110 
111     // *** IPersistStream methods ***
112     STDMETHOD(IsDirty)() override;
113     STDMETHOD(Load)(IStream *pStm) override;
114     STDMETHOD(Save)(IStream *pStm, BOOL fClearDirty) override;
115     STDMETHOD(GetSizeMax)(ULARGE_INTEGER *pcbSize) override;
116 
117     // *** IPersistStreamInit methods ***
118     STDMETHOD(InitNew)() override;
119 
120     // *** IPersistPropertyBag methods ***
121     STDMETHOD(Load)(IPropertyBag *pPropBag, IErrorLog *pErrorLog) override;
122     STDMETHOD(Save)(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties) override;
123 
124     // message handlers
125     LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
126     LRESULT OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
127     LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
128     LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
129     LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
130     LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
131     LRESULT OnCancelMode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
132     LRESULT OnCaptureChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
133 
134 DECLARE_WND_CLASS_EX(_T("BaseBar"), 0, COLOR_3DFACE)
135 
136 BEGIN_MSG_MAP(CBaseBar)
137     MESSAGE_HANDLER(WM_SIZE, OnSize)
138     MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
139     MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
140     MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
141     MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
142     MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
143     MESSAGE_HANDLER(WM_CANCELMODE, OnCancelMode)
144     MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
145 END_MSG_MAP()
146 
147 BEGIN_COM_MAP(CBaseBar)
148     COM_INTERFACE_ENTRY2_IID(IID_IOleWindow, IOleWindow, IDockingWindow)
149     COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite, IInputObjectSite)
150     COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
151     COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
152     COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
153     COM_INTERFACE_ENTRY_IID(IID_IDeskBar, IDeskBar)
154     COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)
155     COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
156     COM_INTERFACE_ENTRY2_IID(IID_IPersist, IPersist, IPersistStream)
157     COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
158     COM_INTERFACE_ENTRY_IID(IID_IPersistStreamInit, IPersistStreamInit)
159     COM_INTERFACE_ENTRY_IID(IID_IPersistPropertyBag, IPersistPropertyBag)
160 END_COM_MAP()
161 };
162 
CBaseBar()163 CBaseBar::CBaseBar()
164 {
165     fClientWindow = NULL;
166     fVertical = true;
167     fVisible = false;
168     fNeededSize = 200;
169     fTracking = false;
170 }
171 
~CBaseBar()172 CBaseBar::~CBaseBar()
173 {
174 }
175 
Initialize(BOOL vert)176 HRESULT CBaseBar::Initialize(BOOL vert)
177 {
178     fVertical = (vert == TRUE);
179     return S_OK;
180 }
181 
ReserveBorderSpace()182 HRESULT CBaseBar::ReserveBorderSpace()
183 {
184     CComPtr<IDockingWindowSite>             dockingWindowSite;
185     RECT                                    availableBorderSpace;
186     RECT                                    neededBorderSpace;
187     HRESULT                                 hResult;
188 
189     hResult = fSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &dockingWindowSite));
190     if (FAILED_UNEXPECTEDLY(hResult))
191         return hResult;
192     hResult = dockingWindowSite->GetBorderDW(static_cast<IDeskBar *>(this), &availableBorderSpace);
193     if (FAILED_UNEXPECTEDLY(hResult))
194         return hResult;
195     memset(&neededBorderSpace, 0, sizeof(neededBorderSpace));
196     if (fVisible)
197     {
198         if (fVertical)
199             neededBorderSpace.left = fNeededSize + GetSystemMetrics(SM_CXFRAME);
200         else
201             neededBorderSpace.bottom = fNeededSize + GetSystemMetrics(SM_CXFRAME);
202     }
203     hResult = dockingWindowSite->SetBorderSpaceDW(static_cast<IDeskBar *>(this), &neededBorderSpace);
204     if (FAILED_UNEXPECTEDLY(hResult))
205         return hResult;
206     return S_OK;
207 }
208 
209 // current bar size is stored in the registry under
210 // key=HKCU\Software\Microsoft\Internet Explorer\Explorer Bars
211 // value=current bar GUID
212 // result is 8 bytes of binary data, 2 longs. First is the size, second is reserved and will always be 0
213 /*HRESULT CBaseBar::StopCurrentBar()
214 {
215     CComPtr<IOleCommandTarget>              commandTarget;
216     HRESULT                                 hResult;
217 
218     if (fCurrentBar.p != NULL)
219     {
220         hResult = fCurrentBar->QueryInterface(IID_IOleCommandTarget, (void **)&commandTarget);
221         hResult = commandTarget->Exec(NULL, 0x17, 0, NULL, NULL);
222     }
223     // hide the current bar
224     memcpy(&fCurrentActiveClass, &GUID_NULL, sizeof(fCurrentActiveClass));
225     return S_OK;
226 }*/
227 
GetWindow(HWND * lphwnd)228 HRESULT STDMETHODCALLTYPE CBaseBar::GetWindow(HWND *lphwnd)
229 {
230     if (lphwnd == NULL)
231         return E_POINTER;
232     *lphwnd = m_hWnd;
233     return S_OK;
234 }
235 
ContextSensitiveHelp(BOOL fEnterMode)236 HRESULT STDMETHODCALLTYPE CBaseBar::ContextSensitiveHelp(BOOL fEnterMode)
237 {
238     return E_NOTIMPL;
239 }
240 
OnFocusChangeIS(IUnknown * punkObj,BOOL fSetFocus)241 HRESULT STDMETHODCALLTYPE CBaseBar::OnFocusChangeIS (IUnknown *punkObj, BOOL fSetFocus)
242 {
243     return IUnknown_OnFocusChangeIS(fSite, punkObj, fSetFocus);
244 }
245 
QueryStatus(const GUID * pguidCmdGroup,ULONG cCmds,OLECMD prgCmds[],OLECMDTEXT * pCmdText)246 HRESULT STDMETHODCALLTYPE CBaseBar::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds,
247     OLECMD prgCmds[  ], OLECMDTEXT *pCmdText)
248 {
249     return E_NOTIMPL;
250 }
251 
Exec(const GUID * pguidCmdGroup,DWORD nCmdID,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)252 HRESULT STDMETHODCALLTYPE CBaseBar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
253     DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
254 {
255     if (IsEqualIID(*pguidCmdGroup, CGID_Explorer))
256     {
257         // pass through to the explorer ?
258     }
259     else if (IsEqualIID(*pguidCmdGroup, IID_IDeskBarClient))
260     {
261         switch (nCmdID)
262         {
263             case 0:
264             {
265                 // hide current band
266                 ShowDW(0);
267 
268                 // Inform our site that we closed
269                 VARIANT var;
270                 V_VT(&var) = VT_UNKNOWN;
271                 V_UNKNOWN(&var) = static_cast<IDeskBar *>(this);
272                 IUnknown_Exec(fSite, CGID_Explorer, 0x22, 0, &var, NULL);
273                 break;
274             }
275             case 2:
276                 // switch bands
277                 break;
278             case 3:
279                 break;
280         }
281     }
282     return E_NOTIMPL;
283 }
284 
QueryService(REFGUID guidService,REFIID riid,void ** ppvObject)285 HRESULT STDMETHODCALLTYPE CBaseBar::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
286 {
287     CComPtr<IServiceProvider>               serviceProvider;
288     HRESULT                                 hResult;
289 
290     if (fSite == NULL)
291         return E_FAIL;
292     hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
293     if (FAILED_UNEXPECTEDLY(hResult))
294         return hResult;
295     // called for SID_STopLevelBrowser, IID_IBrowserService to find top level browser
296     // called for SID_IWebBrowserApp, IID_IConnectionPointContainer
297     // connection point called for DIID_DWebBrowserEvents2 to establish connection
298     return serviceProvider->QueryService(guidService, riid, ppvObject);
299 }
300 
UIActivateIO(BOOL fActivate,LPMSG lpMsg)301 HRESULT STDMETHODCALLTYPE CBaseBar::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
302 {
303     return IUnknown_UIActivateIO(fClient, fActivate, lpMsg);
304 }
305 
HasFocusIO()306 HRESULT STDMETHODCALLTYPE CBaseBar::HasFocusIO()
307 {
308     return IUnknown_HasFocusIO(fClient);
309 }
310 
TranslateAcceleratorIO(LPMSG lpMsg)311 HRESULT STDMETHODCALLTYPE CBaseBar::TranslateAcceleratorIO(LPMSG lpMsg)
312 {
313     return IUnknown_TranslateAcceleratorIO(fClient, lpMsg);
314 }
315 
SetClient(IUnknown * punkClient)316 HRESULT STDMETHODCALLTYPE CBaseBar::SetClient(IUnknown *punkClient)
317 {
318     CComPtr<IOleWindow>                     oleWindow;
319     HWND                                    ownerWindow;
320     HRESULT                                 hResult;
321 
322     /* Clean up old client */
323     fClient = NULL;
324 
325     if (punkClient)
326     {
327         hResult = punkClient->QueryInterface(IID_PPV_ARG(IUnknown, &fClient));
328         if (FAILED_UNEXPECTEDLY(hResult))
329             return hResult;
330         hResult = fSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
331         if (FAILED_UNEXPECTEDLY(hResult))
332             return hResult;
333         hResult = oleWindow->GetWindow(&ownerWindow);
334         if (FAILED_UNEXPECTEDLY(hResult))
335             return hResult;
336         Create(ownerWindow, 0, NULL,
337             WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_TOOLWINDOW);
338         ReserveBorderSpace();
339     }
340     else
341     {
342         DestroyWindow();
343     }
344     return S_OK;
345 }
346 
GetClient(IUnknown ** ppunkClient)347 HRESULT STDMETHODCALLTYPE CBaseBar::GetClient(IUnknown **ppunkClient)
348 {
349     if (ppunkClient == NULL)
350         return E_POINTER;
351     *ppunkClient = fClient;
352     if (fClient.p != NULL)
353         fClient.p->AddRef();
354     return S_OK;
355 }
356 
OnPosRectChangeDB(LPRECT prc)357 HRESULT STDMETHODCALLTYPE CBaseBar::OnPosRectChangeDB(LPRECT prc)
358 {
359     if (prc == NULL)
360         return E_POINTER;
361     if (fVertical)
362         fNeededSize = prc->right - prc->left;
363     else
364         fNeededSize = prc->bottom - prc->top;
365     ReserveBorderSpace();
366     return S_OK;
367 }
368 
ShowDW(BOOL fShow)369 HRESULT STDMETHODCALLTYPE CBaseBar::ShowDW(BOOL fShow)
370 {
371     fVisible = fShow ? true : false;
372     ShowWindow(fShow);
373     ReserveBorderSpace();
374     return S_OK;
375 }
376 
CloseDW(DWORD dwReserved)377 HRESULT STDMETHODCALLTYPE CBaseBar::CloseDW(DWORD dwReserved)
378 {
379     ShowDW(0);
380     // Detach from our client
381     SetClient(NULL);
382     // Destroy our site
383     SetSite(NULL);
384     return S_OK;
385 }
386 
ResizeBorderDW(LPCRECT prcBorder,IUnknown * punkToolbarSite,BOOL fReserved)387 HRESULT STDMETHODCALLTYPE CBaseBar::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
388 {
389     ReserveBorderSpace();
390     return S_OK;
391 }
392 
SetSite(IUnknown * pUnkSite)393 HRESULT STDMETHODCALLTYPE CBaseBar::SetSite(IUnknown *pUnkSite)
394 {
395     fSite = pUnkSite;
396     return S_OK;
397 }
398 
GetSite(REFIID riid,void ** ppvSite)399 HRESULT STDMETHODCALLTYPE CBaseBar::GetSite(REFIID riid, void **ppvSite)
400 {
401     if (ppvSite == NULL)
402         return E_POINTER;
403     *ppvSite = fSite;
404     if (fSite.p != NULL)
405         fSite.p->AddRef();
406     return S_OK;
407 }
408 
GetClassID(CLSID * pClassID)409 HRESULT STDMETHODCALLTYPE CBaseBar::GetClassID(CLSID *pClassID)
410 {
411     if (pClassID == NULL)
412         return E_POINTER;
413     // TODO: what class to return here?
414     return E_NOTIMPL;
415 }
416 
IsDirty()417 HRESULT STDMETHODCALLTYPE CBaseBar::IsDirty()
418 {
419     return E_NOTIMPL;
420 }
421 
Load(IStream * pStm)422 HRESULT STDMETHODCALLTYPE CBaseBar::Load(IStream *pStm)
423 {
424     return E_NOTIMPL;
425 }
426 
Save(IStream * pStm,BOOL fClearDirty)427 HRESULT STDMETHODCALLTYPE CBaseBar::Save(IStream *pStm, BOOL fClearDirty)
428 {
429     return E_NOTIMPL;
430 }
431 
GetSizeMax(ULARGE_INTEGER * pcbSize)432 HRESULT STDMETHODCALLTYPE CBaseBar::GetSizeMax(ULARGE_INTEGER *pcbSize)
433 {
434     if (pcbSize == NULL)
435         return E_POINTER;
436     return E_NOTIMPL;
437 }
438 
InitNew()439 HRESULT STDMETHODCALLTYPE CBaseBar::InitNew()
440 {
441     return E_NOTIMPL;
442 }
443 
Load(IPropertyBag * pPropBag,IErrorLog * pErrorLog)444 HRESULT STDMETHODCALLTYPE CBaseBar::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
445 {
446     return E_NOTIMPL;
447 }
448 
Save(IPropertyBag * pPropBag,BOOL fClearDirty,BOOL fSaveAllProperties)449 HRESULT STDMETHODCALLTYPE CBaseBar::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
450 {
451     return E_NOTIMPL;
452 }
453 
OnSize(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)454 LRESULT CBaseBar::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
455 {
456     DWORD                                   dwWidth;
457     DWORD                                   dwHeight;
458     CComPtr<IOleWindow>                     pClient;
459     HWND                                    clientHwnd;
460     HRESULT                                 hr;
461 
462     if (fVisible)
463     {
464         dwWidth = LOWORD(lParam);
465         dwHeight = HIWORD(lParam);
466 
467         // substract resizing grips to child's window size
468         if (fVertical)
469             dwWidth -= GetSystemMetrics(SM_CXFRAME);
470         else
471             dwHeight -= GetSystemMetrics(SM_CXFRAME);
472         hr = fClient->QueryInterface(IID_PPV_ARG(IOleWindow, &pClient));
473         if (FAILED_UNEXPECTEDLY(hr))
474             return 0;
475         hr = pClient->GetWindow(&clientHwnd);
476         if (FAILED_UNEXPECTEDLY(hr))
477             return 0;
478         ::SetWindowPos(clientHwnd, NULL, 0, (fVertical) ? 0 : GetSystemMetrics(SM_CXFRAME), dwWidth, dwHeight, NULL);
479         bHandled = TRUE;
480     }
481     return 0;
482 }
483 
OnSetCursor(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)484 LRESULT CBaseBar::OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
485 {
486     if ((short)lParam != HTCLIENT || (HWND)wParam != m_hWnd)
487     {
488         bHandled = FALSE;
489         return 0;
490     }
491     if (fVertical)
492         SetCursor(LoadCursor(NULL, IDC_SIZEWE));
493     else
494         SetCursor(LoadCursor(NULL, IDC_SIZENS));
495     return 1;
496 }
497 
OnNotify(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)498 LRESULT CBaseBar::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
499 {
500     CComPtr<IWinEventHandler>               winEventHandler;
501     LRESULT                                 result;
502     HRESULT                                 hResult;
503 
504     result = 0;
505     if (fClient.p != NULL)
506     {
507         hResult = fClient->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
508         if (SUCCEEDED(hResult) && winEventHandler.p != NULL)
509             hResult = winEventHandler->OnWinEvent(NULL, uMsg, wParam, lParam, &result);
510     }
511     return result;
512 }
513 
OnLButtonDown(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)514 LRESULT CBaseBar::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
515 {
516     SetCapture();
517     fTracking = true;
518     fLastLocation.x = (short)LOWORD(lParam);
519     fLastLocation.y = (short)HIWORD(lParam);
520     return 0;
521 }
522 
OnLButtonUp(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)523 LRESULT CBaseBar::OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
524 {
525     ReleaseCapture();
526     fTracking = false;
527     return 0;
528 }
529 
OnMouseMove(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)530 LRESULT CBaseBar::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
531 {
532     POINT                                   newLocation;
533     int                                     delta;
534 
535     if (fTracking)
536     {
537         newLocation.x = (short)LOWORD(lParam);
538         newLocation.y = (short)HIWORD(lParam);
539         if (fVertical)
540             delta = newLocation.x - fLastLocation.x;
541         else
542             delta = fLastLocation.y - newLocation.y;
543         if (fNeededSize + delta < 0)
544             return 0;
545         fNeededSize += delta;
546         fLastLocation = newLocation;
547         ReserveBorderSpace();
548     }
549     return 0;
550 }
551 
OnCancelMode(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)552 LRESULT CBaseBar::OnCancelMode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
553 {
554     fTracking = false;
555     return 0;
556 }
557 
OnCaptureChanged(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)558 LRESULT CBaseBar::OnCaptureChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
559 {
560     fTracking = false;
561     return 0;
562 }
563 
CBaseBar_CreateInstance(REFIID riid,void ** ppv,BOOL vertical)564 HRESULT CBaseBar_CreateInstance(REFIID riid, void **ppv, BOOL vertical)
565 {
566     return ShellObjectCreatorInit<CBaseBar, BOOL>(vertical, riid, ppv);
567 }
568