xref: /reactos/dll/win32/browseui/addressband.cpp (revision 8209aa52)
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 Implements the navigation band of the cabinet window
23 */
24 
25 #include "precomp.h"
26 #include <commoncontrols.h>
27 #include <shlwapi_undoc.h>
28 #include <shellapi.h>
29 
30 /*
31 TODO:
32 ****Add tooltip notify handler
33   **Properly implement GetBandInfo
34     Implement Exec
35     Implement QueryService
36     Implement Load
37     Implement Save
38 */
39 
CAddressBand()40 CAddressBand::CAddressBand()
41 {
42     fEditControl = NULL;
43     fGoButton = NULL;
44     fComboBox = NULL;
45     fGoButtonShown = false;
46 }
47 
~CAddressBand()48 CAddressBand::~CAddressBand()
49 {
50 }
51 
FocusChange(BOOL bFocus)52 void CAddressBand::FocusChange(BOOL bFocus)
53 {
54 //    m_bFocus = bFocus;
55 
56     //Inform the input object site that the focus has changed.
57     if (fSite)
58     {
59 #if 0
60         fSite->OnFocusChangeIS((IDockingWindow *)this, bFocus);
61 #endif
62     }
63 }
64 
GetBandInfo(DWORD dwBandID,DWORD dwViewMode,DESKBANDINFO * pdbi)65 HRESULT STDMETHODCALLTYPE CAddressBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO *pdbi)
66 {
67     if (!m_hWnd || !pdbi)  return E_FAIL;  /* Verify window exists */
68     if (pdbi->dwMask & DBIM_MINSIZE)
69     {
70         if (fGoButtonShown)
71             pdbi->ptMinSize.x = 100;
72         else
73             pdbi->ptMinSize.x = 150;
74         pdbi->ptMinSize.y = 22;
75     }
76     if (pdbi->dwMask & DBIM_MAXSIZE)
77     {
78         pdbi->ptMaxSize.x = 0;
79         pdbi->ptMaxSize.y = 0;
80     }
81     if (pdbi->dwMask & DBIM_INTEGRAL)
82     {
83         pdbi->ptIntegral.x = 0;
84         pdbi->ptIntegral.y = 0;
85     }
86     if (pdbi->dwMask & DBIM_ACTUAL)
87     {
88         if (fGoButtonShown)
89             pdbi->ptActual.x = 100;
90         else
91             pdbi->ptActual.x = 150;
92         pdbi->ptActual.y = 22;
93     }
94     if (pdbi->dwMask & DBIM_TITLE)
95     {
96         if (!LoadStringW(_AtlBaseModule.GetResourceInstance(), IDS_ADDRESSBANDLABEL, pdbi->wszTitle, _countof(pdbi->wszTitle)))
97             return HRESULT_FROM_WIN32(GetLastError());
98     }
99 
100     if (pdbi->dwMask & DBIM_MODEFLAGS)
101         pdbi->dwModeFlags = DBIMF_UNDELETEABLE;
102     if (pdbi->dwMask & DBIM_BKCOLOR)
103         pdbi->crBkgnd = 0;
104     return S_OK;
105 }
106 
SetSite(IUnknown * pUnkSite)107 HRESULT STDMETHODCALLTYPE CAddressBand::SetSite(IUnknown *pUnkSite)
108 {
109     CComPtr<IShellService>                  shellService;
110     HWND                                    parentWindow;
111     HWND                                    combobox;
112     HRESULT                                 hResult;
113     IImageList                              *piml;
114 
115     if (pUnkSite == NULL)
116     {
117         fSite.Release();
118         return S_OK;
119     }
120 
121     fSite.Release();
122 
123     hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &fSite));
124     if (FAILED_UNEXPECTEDLY(hResult))
125         return hResult;
126 
127     // get window handle of parent
128     parentWindow = NULL;
129     hResult = IUnknown_GetWindow(fSite, &parentWindow);
130 
131     if (!::IsWindow(parentWindow))
132         return E_FAIL;
133 
134     // create combo box ex
135     combobox = CreateWindowEx(WS_EX_TOOLWINDOW, WC_COMBOBOXEXW, NULL, WS_CHILD | WS_VISIBLE |
136         WS_CLIPCHILDREN | WS_TABSTOP | CCS_NODIVIDER | CCS_NOMOVEY | CBS_OWNERDRAWFIXED,
137                     0, 0, 500, 250, parentWindow, (HMENU)IDM_TOOLBARS_ADDRESSBAR, _AtlBaseModule.GetModuleInstance(), 0);
138     if (combobox == NULL)
139         return E_FAIL;
140     SubclassWindow(combobox);
141 
142     HRESULT hr = SHGetImageList(SHIL_SMALL, IID_PPV_ARG(IImageList, &piml));
143     if (FAILED_UNEXPECTEDLY(hr))
144     {
145         SendMessageW(combobox, CBEM_SETIMAGELIST, 0, 0);
146     }
147     else
148     {
149         SendMessageW(combobox, CBEM_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(piml));
150     }
151 
152     SendMessage(CBEM_SETEXTENDEDSTYLE,
153         CBES_EX_CASESENSITIVE | CBES_EX_NOSIZELIMIT, CBES_EX_CASESENSITIVE | CBES_EX_NOSIZELIMIT);
154 
155     fEditControl = reinterpret_cast<HWND>(SendMessage(CBEM_GETEDITCONTROL, 0, 0));
156     fComboBox = reinterpret_cast<HWND>(SendMessage(CBEM_GETCOMBOCONTROL, 0, 0));
157     hResult = CAddressEditBox_CreateInstance(IID_PPV_ARG(IAddressEditBox, &fAddressEditBox));
158     if (FAILED_UNEXPECTEDLY(hResult))
159         return hResult;
160 
161     hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IShellService, &shellService));
162     if (FAILED_UNEXPECTEDLY(hResult))
163         return hResult;
164     hResult = fAddressEditBox->Init(combobox, fEditControl, 8, fSite /*(IAddressBand *)this*/);
165     if (FAILED_UNEXPECTEDLY(hResult))
166         return hResult;
167     hResult = shellService->SetOwner(fSite);
168     if (FAILED_UNEXPECTEDLY(hResult))
169         return hResult;
170 
171     fGoButtonShown = SHRegGetBoolUSValueW(L"Software\\Microsoft\\Internet Explorer\\Main", L"ShowGoButton", FALSE, TRUE);
172     if (fGoButtonShown)
173         CreateGoButton();
174 
175     return hResult;
176 }
177 
GetSite(REFIID riid,void ** ppvSite)178 HRESULT STDMETHODCALLTYPE CAddressBand::GetSite(REFIID riid, void **ppvSite)
179 {
180     if (fSite == NULL)
181         return E_FAIL;
182     return fSite->QueryInterface(riid, ppvSite);
183 }
184 
GetWindow(HWND * lphwnd)185 HRESULT STDMETHODCALLTYPE CAddressBand::GetWindow(HWND *lphwnd)
186 {
187     if (lphwnd == NULL)
188         return E_POINTER;
189     *lphwnd = m_hWnd;
190     return S_OK;
191 }
192 
ContextSensitiveHelp(BOOL fEnterMode)193 HRESULT STDMETHODCALLTYPE CAddressBand::ContextSensitiveHelp(BOOL fEnterMode)
194 {
195     return E_NOTIMPL;
196 }
197 
CloseDW(DWORD dwReserved)198 HRESULT STDMETHODCALLTYPE CAddressBand::CloseDW(DWORD dwReserved)
199 {
200     ShowDW(FALSE);
201 
202     if (IsWindow())
203         DestroyWindow();
204 
205     m_hWnd = NULL;
206 
207     CComPtr<IShellService> pservice;
208     HRESULT hres = fAddressEditBox->QueryInterface(IID_PPV_ARG(IShellService, &pservice));
209     if (SUCCEEDED(hres ))
210         pservice->SetOwner(NULL);
211 
212     if (fAddressEditBox) fAddressEditBox.Release();
213     if (fSite) fSite.Release();
214 
215     if (m_himlNormal)
216         ImageList_Destroy(m_himlNormal);
217 
218     if (m_himlHot)
219         ImageList_Destroy(m_himlHot);
220 
221     return S_OK;
222 }
223 
ResizeBorderDW(const RECT * prcBorder,IUnknown * punkToolbarSite,BOOL fReserved)224 HRESULT STDMETHODCALLTYPE CAddressBand::ResizeBorderDW(
225     const RECT *prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
226 {
227     return E_NOTIMPL;
228 }
229 
ShowDW(BOOL fShow)230 HRESULT STDMETHODCALLTYPE CAddressBand::ShowDW(BOOL fShow)
231 {
232     if (m_hWnd)
233     {
234         if (fShow)
235             ShowWindow(SW_SHOW);
236         else
237             ShowWindow(SW_HIDE);
238     }
239     return S_OK;
240 }
241 
QueryStatus(const GUID * pguidCmdGroup,ULONG cCmds,OLECMD prgCmds[],OLECMDTEXT * pCmdText)242 HRESULT STDMETHODCALLTYPE CAddressBand::QueryStatus(
243     const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[  ], OLECMDTEXT *pCmdText)
244 {
245     return IUnknown_QueryStatus(fAddressEditBox, *pguidCmdGroup, cCmds, prgCmds, pCmdText);
246 }
247 
Exec(const GUID * pguidCmdGroup,DWORD nCmdID,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)248 HRESULT STDMETHODCALLTYPE CAddressBand::Exec(const GUID *pguidCmdGroup,
249     DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
250 {
251     // incomplete
252     return E_NOTIMPL;
253 }
254 
HasFocusIO()255 HRESULT STDMETHODCALLTYPE CAddressBand::HasFocusIO()
256 {
257     if (GetFocus() == fEditControl || SendMessage(CB_GETDROPPEDSTATE, 0, 0))
258         return S_OK;
259     return S_FALSE;
260 }
261 
GetAccessKeyFromText(WCHAR chAccess,LPCWSTR pszText)262 static WCHAR GetAccessKeyFromText(WCHAR chAccess, LPCWSTR pszText)
263 {
264     for (const WCHAR *pch = pszText; *pch != UNICODE_NULL; ++pch)
265     {
266         if (*pch == L'&' && pch[1] == L'&')
267         {
268             /* Skip the first '&', the second is skipped by the for-loop */
269             ++pch;
270             continue;
271         }
272         if (*pch == L'&')
273         {
274             ++pch;
275             chAccess = *pch;
276             break;
277         }
278     }
279 
280     ::CharUpperBuffW(&chAccess, 1);
281     return chAccess;
282 }
283 
GetAddressBarAccessKey(WCHAR chAccess)284 static WCHAR GetAddressBarAccessKey(WCHAR chAccess)
285 {
286     static WCHAR s_chCache = 0;
287     static LANGID s_ThreadLocale = 0;
288     if (s_chCache && s_ThreadLocale == ::GetThreadLocale())
289         return s_chCache;
290 
291     WCHAR szText[80];
292     if (!LoadStringW(_AtlBaseModule.GetResourceInstance(), IDS_ADDRESSBANDLABEL,
293                      szText, _countof(szText)))
294     {
295         return chAccess;
296     }
297 
298     s_chCache = GetAccessKeyFromText(chAccess, szText);
299     s_ThreadLocale = ::GetThreadLocale();
300     return s_chCache;
301 }
302 
TranslateAcceleratorIO(LPMSG lpMsg)303 HRESULT STDMETHODCALLTYPE CAddressBand::TranslateAcceleratorIO(LPMSG lpMsg)
304 {
305     // Enable Address bar access key (Alt+D)
306     switch (lpMsg->message)
307     {
308         case WM_SYSKEYDOWN:
309         case WM_SYSCHAR:
310         {
311             WCHAR chAccess = GetAddressBarAccessKey(L'D');
312             if (lpMsg->wParam == chAccess)
313             {
314                 ::PostMessageW(fEditControl, EM_SETSEL, 0, -1);
315                 ::SetFocus(fEditControl);
316                 return S_FALSE;
317             }
318             break;
319         }
320     }
321 
322     if (lpMsg->hwnd == fEditControl)
323     {
324         switch (lpMsg->message)
325         {
326         case WM_SYSKEYDOWN:
327         case WM_SYSKEYUP:
328         case WM_SYSCOMMAND:
329         case WM_SYSDEADCHAR:
330         case WM_SYSCHAR:
331             return S_FALSE;
332         }
333 
334         TranslateMessage(lpMsg);
335         DispatchMessage(lpMsg);
336         return S_OK;
337     }
338     return S_FALSE;
339 }
340 
UIActivateIO(BOOL fActivate,LPMSG lpMsg)341 HRESULT STDMETHODCALLTYPE CAddressBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
342 {
343     if (fActivate)
344     {
345         IUnknown_OnFocusChangeIS(fSite, static_cast<IDeskBand *>(this), fActivate);
346         SetFocus();
347     }
348     return S_OK;
349 }
350 
OnWinEvent(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam,LRESULT * theResult)351 HRESULT STDMETHODCALLTYPE CAddressBand::OnWinEvent(
352     HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
353 {
354     CComPtr<IWinEventHandler>               winEventHandler;
355     HRESULT                                 hResult;
356     RECT                                    rect;
357 
358     if (theResult)
359         *theResult = 0;
360 
361     switch (uMsg)
362     {
363         case WM_WININICHANGE:
364             break;
365         case WM_COMMAND:
366             if (wParam == IDM_TOOLBARS_GOBUTTON)
367             {
368                 fGoButtonShown = !SHRegGetBoolUSValueW(L"Software\\Microsoft\\Internet Explorer\\Main", L"ShowGoButton", FALSE, TRUE);
369                 SHRegSetUSValueW(L"Software\\Microsoft\\Internet Explorer\\Main", L"ShowGoButton", REG_SZ, fGoButtonShown ? (LPVOID)L"yes" : (LPVOID)L"no", fGoButtonShown ? 8 : 6, SHREGSET_FORCE_HKCU);
370                 if (!fGoButton)
371                     CreateGoButton();
372                 ::ShowWindow(fGoButton,fGoButtonShown ? SW_HIDE : SW_SHOW);
373                 GetWindowRect(&rect);
374                 SendMessage(m_hWnd,WM_SIZE,0,MAKELPARAM(rect.right-rect.left,rect.bottom-rect.top));
375                 // broadcast change notification to all explorer windows
376             }
377             break;
378     }
379     hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
380     if (FAILED_UNEXPECTEDLY(hResult))
381         return hResult;
382     return winEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
383 }
384 
IsWindowOwner(HWND hWnd)385 HRESULT STDMETHODCALLTYPE CAddressBand::IsWindowOwner(HWND hWnd)
386 {
387     CComPtr<IWinEventHandler>               winEventHandler;
388     HRESULT                                 hResult;
389 
390     if (fAddressEditBox)
391     {
392         hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
393         if (FAILED_UNEXPECTEDLY(hResult))
394             return hResult;
395         return winEventHandler->IsWindowOwner(hWnd);
396     }
397     return S_FALSE;
398 }
399 
FileSysChange(long param8,long paramC)400 HRESULT STDMETHODCALLTYPE CAddressBand::FileSysChange(long param8, long paramC)
401 {
402     CComPtr<IAddressBand>                   addressBand;
403     HRESULT                                 hResult;
404 
405     hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IAddressBand, &addressBand));
406     if (FAILED_UNEXPECTEDLY(hResult))
407         return hResult;
408     return addressBand->FileSysChange(param8, paramC);
409 }
410 
Refresh(long param8)411 HRESULT STDMETHODCALLTYPE CAddressBand::Refresh(long param8)
412 {
413     CComPtr<IAddressBand>                   addressBand;
414     HRESULT                                 hResult;
415 
416     hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IAddressBand, &addressBand));
417     if (FAILED_UNEXPECTEDLY(hResult))
418         return hResult;
419     return addressBand->Refresh(param8);
420 }
421 
QueryService(REFGUID guidService,REFIID riid,void ** ppvObject)422 HRESULT STDMETHODCALLTYPE CAddressBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
423 {
424     return E_NOTIMPL;
425 }
426 
OnFocusChangeIS(IUnknown * punkObj,BOOL fSetFocus)427 HRESULT STDMETHODCALLTYPE CAddressBand::OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus)
428 {
429     return E_NOTIMPL;
430 }
431 
GetClassID(CLSID * pClassID)432 HRESULT STDMETHODCALLTYPE CAddressBand::GetClassID(CLSID *pClassID)
433 {
434     if (pClassID == NULL)
435         return E_POINTER;
436     *pClassID = CLSID_SH_AddressBand;
437     return S_OK;
438 }
439 
IsDirty()440 HRESULT STDMETHODCALLTYPE CAddressBand::IsDirty()
441 {
442     return E_NOTIMPL;
443 }
444 
Load(IStream * pStm)445 HRESULT STDMETHODCALLTYPE CAddressBand::Load(IStream *pStm)
446 {
447     // incomplete
448     return E_NOTIMPL;
449 }
450 
Save(IStream * pStm,BOOL fClearDirty)451 HRESULT STDMETHODCALLTYPE CAddressBand::Save(IStream *pStm, BOOL fClearDirty)
452 {
453     // incomplete
454     return E_NOTIMPL;
455 }
456 
GetSizeMax(ULARGE_INTEGER * pcbSize)457 HRESULT STDMETHODCALLTYPE CAddressBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
458 {
459     // incomplete
460     return E_NOTIMPL;
461 }
462 
OnNotifyClick(WPARAM wParam,NMHDR * notifyHeader,BOOL & bHandled)463 LRESULT CAddressBand::OnNotifyClick(WPARAM wParam, NMHDR *notifyHeader, BOOL &bHandled)
464 {
465     if (notifyHeader->hwndFrom == fGoButton)
466     {
467         fAddressEditBox->Execute(0);
468     }
469     return 0;
470 }
471 
OnTipText(UINT idControl,NMHDR * notifyHeader,BOOL & bHandled)472 LRESULT CAddressBand::OnTipText(UINT idControl, NMHDR *notifyHeader, BOOL &bHandled)
473 {
474     if (notifyHeader->hwndFrom == fGoButton)
475     {
476         WCHAR szText[MAX_PATH];
477         WCHAR szFormat[MAX_PATH];
478         LPNMTBGETINFOTIP pGIT = (LPNMTBGETINFOTIP)notifyHeader;
479 
480         if (::GetWindowTextW(fEditControl, szText, _countof(szText)))
481         {
482             LoadStringW(_AtlBaseModule.GetResourceInstance(), IDS_GOBUTTONTIPTEMPLATE, szFormat, _countof(szFormat));
483             wnsprintf(pGIT->pszText, pGIT->cchTextMax, szFormat, szText);
484         }
485         else
486             *pGIT->pszText = 0;
487     }
488     return 0;
489 }
490 
OnEraseBackground(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)491 LRESULT CAddressBand::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
492 {
493     POINT                                   pt;
494     POINT                                   ptOrig;
495     HWND                                    parentWindow;
496     LRESULT                                 result;
497 
498     if (fGoButtonShown == false)
499     {
500         bHandled = FALSE;
501         return 0;
502     }
503     pt.x = 0;
504     pt.y = 0;
505     parentWindow = GetParent();
506     ::MapWindowPoints(m_hWnd, parentWindow, &pt, 1);
507     OffsetWindowOrgEx(reinterpret_cast<HDC>(wParam), pt.x, pt.y, &ptOrig);
508     result = SendMessage(parentWindow, WM_ERASEBKGND, wParam, 0);
509     SetWindowOrgEx(reinterpret_cast<HDC>(wParam), ptOrig.x, ptOrig.y, NULL);
510     if (result == 0)
511     {
512         bHandled = FALSE;
513         return 0;
514     }
515     return result;
516 }
517 
OnSize(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)518 LRESULT CAddressBand::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
519 {
520     RECT                                    goButtonBounds;
521     RECT                                    buttonBounds;
522     long                                    buttonWidth;
523     long                                    buttonHeight;
524     RECT                                    comboBoxBounds;
525     long                                    newHeight;
526     long                                    newWidth;
527 
528     if (fGoButtonShown == false)
529     {
530         bHandled = FALSE;
531         return 0;
532     }
533 
534     newHeight = HIWORD(lParam);
535     newWidth = LOWORD(lParam);
536 
537     if (!fGoButton)
538         CreateGoButton();
539 
540     SendMessage(fGoButton, TB_GETITEMRECT, 0, reinterpret_cast<LPARAM>(&buttonBounds));
541     buttonWidth = buttonBounds.right - buttonBounds.left;
542     buttonHeight = buttonBounds.bottom - buttonBounds.top;
543 
544     DefWindowProc(WM_SIZE, wParam, MAKELONG(newWidth - buttonWidth - 2, newHeight));
545     ::GetWindowRect(fComboBox, &comboBoxBounds);
546     ::SetWindowPos(fGoButton, NULL, newWidth - buttonWidth, (comboBoxBounds.bottom - comboBoxBounds.top - buttonHeight) / 2,
547                     buttonWidth, buttonHeight, SWP_NOOWNERZORDER | SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOZORDER);
548 
549     goButtonBounds.left = newWidth - buttonWidth;
550     goButtonBounds.top = 0;
551     goButtonBounds.right = newWidth - buttonWidth;
552     goButtonBounds.bottom = newHeight;
553     InvalidateRect(&goButtonBounds, TRUE);
554 
555     SendMessage(fComboBox, CB_SETDROPPEDWIDTH, 200, 0);
556     return 0;
557 }
558 
OnWindowPosChanging(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)559 LRESULT CAddressBand::OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
560 {
561     RECT                                    goButtonBounds;
562     RECT                                    buttonBounds;
563     long                                    buttonWidth;
564     long                                    buttonHeight;
565     RECT                                    comboBoxBounds;
566     WINDOWPOS                               positionInfoCopy;
567     long                                    newHeight;
568     long                                    newWidth;
569 
570     if (!fGoButtonShown)
571     {
572         bHandled = FALSE;
573         return 0;
574     }
575 
576     if (!fGoButton)
577         CreateGoButton();
578 
579     positionInfoCopy = *reinterpret_cast<WINDOWPOS *>(lParam);
580     newHeight = positionInfoCopy.cy;
581     newWidth = positionInfoCopy.cx;
582 
583     SendMessage(fGoButton, TB_GETITEMRECT, 0, reinterpret_cast<LPARAM>(&buttonBounds));
584 
585     buttonWidth = buttonBounds.right - buttonBounds.left;
586     buttonHeight = buttonBounds.bottom - buttonBounds.top;
587     positionInfoCopy.cx = newWidth - 2 - buttonWidth;
588     DefWindowProc(WM_WINDOWPOSCHANGING, wParam, reinterpret_cast<LPARAM>(&positionInfoCopy));
589     ::GetWindowRect(fComboBox, &comboBoxBounds);
590     ::SetWindowPos(fGoButton, NULL, newWidth - buttonWidth, (comboBoxBounds.bottom - comboBoxBounds.top - buttonHeight) / 2,
591                     buttonWidth, buttonHeight, SWP_NOOWNERZORDER | SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOZORDER);
592 
593     goButtonBounds.left = newWidth - buttonWidth;
594     goButtonBounds.top = 0;
595     goButtonBounds.right = newWidth - buttonWidth;
596     goButtonBounds.bottom = newHeight;
597     InvalidateRect(&goButtonBounds, TRUE);
598 
599     SendMessage(fComboBox, CB_SETDROPPEDWIDTH, 200, 0);
600     return 0;
601 }
602 
CreateGoButton()603 void CAddressBand::CreateGoButton()
604 {
605     const TBBUTTON buttonInfo [] = { { 0, 1, TBSTATE_ENABLED, 0 } };
606     HINSTANCE             shellInstance;
607 
608     shellInstance = _AtlBaseModule.GetResourceInstance();
609     m_himlNormal = ImageList_LoadImageW(shellInstance, MAKEINTRESOURCEW(IDB_GOBUTTON_NORMAL),
610                                         20, 0, RGB(255, 0, 255), IMAGE_BITMAP, LR_CREATEDIBSECTION);
611     m_himlHot = ImageList_LoadImageW(shellInstance, MAKEINTRESOURCEW(IDB_GOBUTTON_HOT),
612                                      20, 0, RGB(255, 0, 255), IMAGE_BITMAP, LR_CREATEDIBSECTION);
613 
614     fGoButton = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAMEW, 0, WS_CHILD | WS_CLIPSIBLINGS |
615                                WS_CLIPCHILDREN | TBSTYLE_LIST | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CCS_NODIVIDER |
616                                CCS_NOPARENTALIGN | CCS_NORESIZE,
617                                0, 0, 0, 0, m_hWnd, NULL, _AtlBaseModule.GetModuleInstance(), NULL);
618     SendMessage(fGoButton, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
619     SendMessage(fGoButton, TB_SETMAXTEXTROWS, 1, 0);
620     if (m_himlNormal)
621         SendMessage(fGoButton, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(m_himlNormal));
622     if (m_himlHot)
623         SendMessage(fGoButton, TB_SETHOTIMAGELIST, 0, reinterpret_cast<LPARAM>(m_himlHot));
624     SendMessage(fGoButton, TB_ADDSTRINGW,
625                 reinterpret_cast<WPARAM>(_AtlBaseModule.GetResourceInstance()), IDS_GOBUTTONLABEL);
626     SendMessage(fGoButton, TB_ADDBUTTONSW, 1, (LPARAM) &buttonInfo);
627 }
628