Create this branch to work on loading of different Kernel-Debugger DLL providers...
[reactos.git] / dll / win32 / browseui / addressband.cpp
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 #include "precomp.h"
25
26 /*
27 TODO:
28 ****Add command handler for show/hide Go button to OnWinEvent
29 ****Add tooltip notify handler
30 **Properly implement GetBandInfo
31 **Add support for showing/hiding Go button
32 **Fix so Go button will be shown/hidden properly on load
33 **Add correct text to Go button
34 **Implement TranslateAcceleratorIO
35 Implement Exec
36 Implement QueryService
37 Implement Load
38 Implement Save
39 */
40
41 CAddressBand::CAddressBand()
42 {
43 fEditControl = NULL;
44 fGoButton = NULL;
45 fComboBox = NULL;
46 fGoButtonShown = false;
47 }
48
49 CAddressBand::~CAddressBand()
50 {
51 }
52
53 void CAddressBand::FocusChange(BOOL bFocus)
54 {
55 // m_bFocus = bFocus;
56
57 //Inform the input object site that the focus has changed.
58 if (fSite)
59 {
60 #if 0
61 fSite->OnFocusChangeIS((IDockingWindow *)this, bFocus);
62 #endif
63 }
64 }
65
66 HRESULT STDMETHODCALLTYPE CAddressBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO *pdbi)
67 {
68 if (pdbi->dwMask & DBIM_MINSIZE)
69 {
70 pdbi->ptMinSize.x = 400;
71 pdbi->ptMinSize.y = 22;
72 }
73 if (pdbi->dwMask & DBIM_MAXSIZE)
74 {
75 pdbi->ptMaxSize.x = 0;
76 pdbi->ptMaxSize.y = 0;
77 }
78 if (pdbi->dwMask & DBIM_INTEGRAL)
79 {
80 pdbi->ptIntegral.x = 0;
81 pdbi->ptIntegral.y = 0;
82 }
83 if (pdbi->dwMask & DBIM_ACTUAL)
84 {
85 pdbi->ptActual.x = 400;
86 pdbi->ptActual.y = 22;
87 }
88 if (pdbi->dwMask & DBIM_TITLE)
89 wcscpy(pdbi->wszTitle, L"Address");
90 if (pdbi->dwMask & DBIM_MODEFLAGS)
91 pdbi->dwModeFlags = DBIMF_UNDELETEABLE;
92 if (pdbi->dwMask & DBIM_BKCOLOR)
93 pdbi->crBkgnd = 0;
94 return S_OK;
95 }
96
97 HRESULT STDMETHODCALLTYPE CAddressBand::SetSite(IUnknown *pUnkSite)
98 {
99 CComPtr<IShellService> shellService;
100 CComPtr<IUnknown> offset34;
101 HWND parentWindow;
102 IOleWindow *oleWindow;
103 HWND toolbar;
104 static const TBBUTTON buttonInfo[] = { {0, 1, TBSTATE_ENABLED, 0} };
105 HIMAGELIST normalImagelist;
106 HIMAGELIST hotImageList;
107 HINSTANCE shellInstance;
108 HRESULT hResult;
109
110 fSite.Release();
111 if (pUnkSite == NULL)
112 return S_OK;
113
114 hResult = pUnkSite->QueryInterface(IID_IDockingWindowSite, reinterpret_cast<void **>(&fSite));
115 if (FAILED(hResult))
116 return hResult;
117
118 // get window handle of parent
119 parentWindow = NULL;
120 hResult = pUnkSite->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&oleWindow));
121 if (SUCCEEDED(hResult))
122 {
123 oleWindow->GetWindow(&parentWindow);
124 oleWindow->Release();
125 }
126 if (!::IsWindow(parentWindow))
127 return E_FAIL;
128
129 // create combo box ex
130 toolbar = CreateWindowEx(WS_EX_TOOLWINDOW, WC_COMBOBOXEXW, NULL, WS_CHILD | WS_VISIBLE |
131 WS_CLIPCHILDREN | WS_TABSTOP | CCS_NODIVIDER | CCS_NOMOVEY,
132 0, 0, 500, 250, parentWindow, (HMENU)0xa205, _AtlBaseModule.GetModuleInstance(), 0);
133 if (toolbar == NULL)
134 return E_FAIL;
135 SubclassWindow(toolbar);
136
137 SendMessage(CBEM_SETEXTENDEDSTYLE,
138 CBES_EX_CASESENSITIVE | CBES_EX_NOSIZELIMIT, CBES_EX_CASESENSITIVE | CBES_EX_NOSIZELIMIT);
139
140 fEditControl = reinterpret_cast<HWND>(SendMessage(CBEM_GETEDITCONTROL, 0, 0));
141 fComboBox = reinterpret_cast<HWND>(SendMessage(CBEM_GETCOMBOCONTROL, 0, 0));
142 #if 1
143 hResult = CoCreateInstance(CLSID_AddressEditBox, NULL, CLSCTX_INPROC_SERVER,
144 IID_IAddressEditBox, reinterpret_cast<void **>(&fAddressEditBox));
145 if (FAILED(hResult))
146 return hResult;
147 #else
148 // instantiate new version
149 #endif
150
151 hResult = fAddressEditBox->QueryInterface(IID_IShellService, reinterpret_cast<void **>(&shellService));
152 if (FAILED(hResult))
153 return hResult;
154 hResult = fAddressEditBox->Init(toolbar, fEditControl, 8, pUnkSite /*(IAddressBand *)this*/ );
155 if (FAILED(hResult))
156 return hResult;
157 hResult = shellService->SetOwner(pUnkSite);
158 if (FAILED(hResult))
159 return hResult;
160
161 // TODO: properly initialize this from registry
162 fGoButtonShown = true;
163
164 shellInstance = GetModuleHandle(_T("shell32.dll"));
165 normalImagelist = ImageList_LoadImageW(shellInstance, MAKEINTRESOURCE(IDB_GOBUTTON_NORMAL),
166 20, 0, RGB(255, 0, 255), IMAGE_BITMAP, LR_CREATEDIBSECTION);
167 hotImageList = ImageList_LoadImageW(shellInstance, MAKEINTRESOURCE(IDB_GOBUTTON_HOT),
168 20, 0, RGB(255, 0, 255), IMAGE_BITMAP, LR_CREATEDIBSECTION);
169
170 fGoButton = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAMEW, 0, WS_CHILD | WS_CLIPSIBLINGS |
171 WS_CLIPCHILDREN | TBSTYLE_LIST | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CCS_NODIVIDER |
172 CCS_NOPARENTALIGN | CCS_NORESIZE,
173 0, 0, 0, 0, m_hWnd, NULL, _AtlBaseModule.GetModuleInstance(), NULL);
174 SendMessage(fGoButton, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
175 SendMessage(fGoButton, TB_SETMAXTEXTROWS, 1, 0);
176 SendMessage(fGoButton, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(normalImagelist));
177 SendMessage(fGoButton, TB_SETHOTIMAGELIST, 0, reinterpret_cast<LPARAM>(hotImageList));
178 SendMessage(fGoButton, TB_ADDSTRINGW,
179 reinterpret_cast<WPARAM>(_AtlBaseModule.GetResourceInstance()), IDS_GOBUTTONLABEL);
180 SendMessage(fGoButton, TB_ADDBUTTONSW, 1, (LPARAM)&buttonInfo);
181
182 return hResult;
183 }
184
185 HRESULT STDMETHODCALLTYPE CAddressBand::GetSite(REFIID riid, void **ppvSite)
186 {
187 if (fSite == NULL)
188 return E_FAIL;
189 return fSite->QueryInterface(riid, ppvSite);
190 }
191
192 HRESULT STDMETHODCALLTYPE CAddressBand::GetWindow(HWND *lphwnd)
193 {
194 if (lphwnd == NULL)
195 return E_POINTER;
196 *lphwnd = m_hWnd;
197 return S_OK;
198 }
199
200 HRESULT STDMETHODCALLTYPE CAddressBand::ContextSensitiveHelp(BOOL fEnterMode)
201 {
202 return E_NOTIMPL;
203 }
204
205 HRESULT STDMETHODCALLTYPE CAddressBand::CloseDW(DWORD dwReserved)
206 {
207 ShowDW(FALSE);
208
209 if (IsWindow())
210 DestroyWindow();
211
212 m_hWnd = NULL;
213
214 return S_OK;
215 }
216
217 HRESULT STDMETHODCALLTYPE CAddressBand::ResizeBorderDW(
218 const RECT *prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
219 {
220 return E_NOTIMPL;
221 }
222
223 HRESULT STDMETHODCALLTYPE CAddressBand::ShowDW(BOOL fShow)
224 {
225 if (m_hWnd)
226 {
227 if (fShow)
228 ShowWindow(SW_SHOW);
229 else
230 ShowWindow(SW_HIDE);
231 }
232 return S_OK;
233 }
234
235 HRESULT STDMETHODCALLTYPE CAddressBand::QueryStatus(
236 const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText)
237 {
238 CComPtr<IOleCommandTarget> oleCommandTarget;
239 HRESULT hResult;
240
241 hResult = fAddressEditBox->QueryInterface(IID_IOleCommandTarget, reinterpret_cast<void **>(&oleCommandTarget));
242 if (FAILED(hResult))
243 return hResult;
244 return oleCommandTarget->QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText);
245 }
246
247 HRESULT STDMETHODCALLTYPE CAddressBand::Exec(const GUID *pguidCmdGroup,
248 DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
249 {
250 // incomplete
251 return E_NOTIMPL;
252 }
253
254 HRESULT STDMETHODCALLTYPE CAddressBand::HasFocusIO()
255 {
256 if (GetFocus() == fEditControl || SendMessage(CB_GETDROPPEDSTATE, 0, 0))
257 return S_OK;
258 return S_FALSE;
259 }
260
261 HRESULT STDMETHODCALLTYPE CAddressBand::TranslateAcceleratorIO(LPMSG lpMsg)
262 {
263 // incomplete
264 return S_FALSE;
265 }
266
267 HRESULT STDMETHODCALLTYPE CAddressBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
268 {
269 CComPtr<IInputObjectSite> inputObjectSite;
270 HRESULT hResult;
271
272 if (fActivate)
273 {
274 hResult = fSite->QueryInterface(IID_IInputObjectSite, reinterpret_cast<void **>(&inputObjectSite));
275 if (FAILED(hResult))
276 return hResult;
277 hResult = inputObjectSite->OnFocusChangeIS(static_cast<IDeskBand *>(this), fActivate);
278 SetFocus();
279 }
280 return S_OK;
281 }
282
283 HRESULT STDMETHODCALLTYPE CAddressBand::OnWinEvent(
284 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
285 {
286 CComPtr<IWinEventHandler> winEventHandler;
287 HRESULT hResult;
288
289 switch (uMsg)
290 {
291 case WM_WININICHANGE:
292 break;
293 case WM_COMMAND:
294 if (wParam == IDM_TOOLBARS_GOBUTTON)
295 {
296 // toggle whether the Go button is displayed
297 // setting is Yes or No, stored in key "Software\Microsoft\Internet Explorer\Main" in value ShowGoButton
298 // broadcast change notification to all explorer windows
299 }
300 break;
301 }
302 hResult = fAddressEditBox->QueryInterface(IID_IWinEventHandler, reinterpret_cast<void **>(&winEventHandler));
303 if (FAILED(hResult))
304 return hResult;
305 return winEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
306 }
307
308 HRESULT STDMETHODCALLTYPE CAddressBand::IsWindowOwner(HWND hWnd)
309 {
310 CComPtr<IWinEventHandler> winEventHandler;
311 HRESULT hResult;
312
313 hResult = fAddressEditBox->QueryInterface(IID_IWinEventHandler, reinterpret_cast<void **>(&winEventHandler));
314 if (FAILED(hResult))
315 return hResult;
316 return winEventHandler->IsWindowOwner(hWnd);
317 }
318
319 HRESULT STDMETHODCALLTYPE CAddressBand::FileSysChange(long param8, long paramC)
320 {
321 CComPtr<IAddressBand> addressBand;
322 HRESULT hResult;
323
324 hResult = fAddressEditBox->QueryInterface(IID_IAddressBand, reinterpret_cast<void **>(&addressBand));
325 if (FAILED(hResult))
326 return hResult;
327 return addressBand->FileSysChange(param8, paramC);
328 }
329
330 HRESULT STDMETHODCALLTYPE CAddressBand::Refresh(long param8)
331 {
332 CComPtr<IAddressBand> addressBand;
333 HRESULT hResult;
334
335 hResult = fAddressEditBox->QueryInterface(IID_IAddressBand, reinterpret_cast<void **>(&addressBand));
336 if (FAILED(hResult))
337 return hResult;
338 return addressBand->Refresh(param8);
339 }
340
341 HRESULT STDMETHODCALLTYPE CAddressBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
342 {
343 return E_NOTIMPL;
344 }
345
346 HRESULT STDMETHODCALLTYPE CAddressBand::OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus)
347 {
348 return E_NOTIMPL;
349 }
350
351 HRESULT STDMETHODCALLTYPE CAddressBand::GetClassID(CLSID *pClassID)
352 {
353 if (pClassID == NULL)
354 return E_POINTER;
355 *pClassID = CLSID_SH_AddressBand;
356 return S_OK;
357 }
358
359 HRESULT STDMETHODCALLTYPE CAddressBand::IsDirty()
360 {
361 return E_NOTIMPL;
362 }
363
364 HRESULT STDMETHODCALLTYPE CAddressBand::Load(IStream *pStm)
365 {
366 // incomplete
367 return E_NOTIMPL;
368 }
369
370 HRESULT STDMETHODCALLTYPE CAddressBand::Save(IStream *pStm, BOOL fClearDirty)
371 {
372 // incomplete
373 return E_NOTIMPL;
374 }
375
376 HRESULT STDMETHODCALLTYPE CAddressBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
377 {
378 // incomplete
379 return E_NOTIMPL;
380 }
381
382 LRESULT CAddressBand::OnNotifyClick(WPARAM wParam, NMHDR *notifyHeader, BOOL &bHandled)
383 {
384 if (notifyHeader->hwndFrom == fGoButton)
385 {
386 SendMessage(fEditControl, WM_KEYDOWN, 13, 0);
387 SendMessage(fEditControl, WM_KEYUP, 13, 0);
388 }
389 return 0;
390 }
391
392 LRESULT CAddressBand::OnTipText(UINT idControl, NMHDR *notifyHeader, BOOL &bHandled)
393 {
394 if (notifyHeader->hwndFrom == fGoButton)
395 {
396 // TODO
397 // Go to "destination path"
398 }
399 return 0;
400 }
401
402 LRESULT CAddressBand::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
403 {
404 POINT pt;
405 POINT ptOrig;
406 HWND parentWindow;
407 LRESULT result;
408
409 if (fGoButtonShown == false)
410 {
411 bHandled = FALSE;
412 return 0;
413 }
414 pt.x = 0;
415 pt.y = 0;
416 parentWindow = GetParent();
417 ::MapWindowPoints(m_hWnd, parentWindow, &pt, 1);
418 OffsetWindowOrgEx(reinterpret_cast<HDC>(wParam), pt.x, pt.y, &ptOrig);
419 result = SendMessage(parentWindow, WM_ERASEBKGND, wParam, 0);
420 SetWindowOrgEx(reinterpret_cast<HDC>(wParam), ptOrig.x, ptOrig.y, NULL);
421 if (result == 0)
422 {
423 bHandled = FALSE;
424 return 0;
425 }
426 return result;
427 }
428
429 LRESULT CAddressBand::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
430 {
431 RECT goButtonBounds;
432 RECT buttonBounds;
433 long buttonWidth;
434 long buttonHeight;
435 RECT comboBoxBounds;
436 long newHeight;
437 long newWidth;
438
439 if (fGoButtonShown == false)
440 {
441 bHandled = FALSE;
442 return 0;
443 }
444
445 newHeight = HIWORD(lParam);
446 newWidth = LOWORD(lParam);
447
448 SendMessage(fGoButton, TB_GETITEMRECT, 0, reinterpret_cast<LPARAM>(&buttonBounds));
449 buttonWidth = buttonBounds.right - buttonBounds.left;
450 buttonHeight = buttonBounds.bottom - buttonBounds.top;
451
452 DefWindowProc(WM_SIZE, wParam, MAKELONG(newWidth - buttonWidth - 2, newHeight));
453 ::GetWindowRect(fComboBox, &comboBoxBounds);
454 ::SetWindowPos(fGoButton, NULL, newWidth - buttonWidth, (comboBoxBounds.bottom - comboBoxBounds.top - buttonHeight) / 2,
455 buttonWidth, buttonHeight, SWP_NOOWNERZORDER | SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOZORDER);
456
457 goButtonBounds.left = newWidth - buttonWidth;
458 goButtonBounds.top = 0;
459 goButtonBounds.right = newWidth - buttonWidth;
460 goButtonBounds.bottom = newHeight;
461 InvalidateRect(&goButtonBounds, TRUE);
462
463 SendMessage(fComboBox, CB_SETDROPPEDWIDTH, 200, 0);
464 return 0;
465 }
466
467 LRESULT CAddressBand::OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
468 {
469 RECT goButtonBounds;
470 RECT buttonBounds;
471 long buttonWidth;
472 long buttonHeight;
473 RECT comboBoxBounds;
474 WINDOWPOS positionInfoCopy;
475 long newHeight;
476 long newWidth;
477
478 if (!fGoButtonShown)
479 {
480 bHandled = FALSE;
481 return 0;
482 }
483
484 positionInfoCopy = *reinterpret_cast<WINDOWPOS *>(lParam);
485 newHeight = positionInfoCopy.cy;
486 newWidth = positionInfoCopy.cx;
487 SendMessage(fGoButton, TB_GETITEMRECT, 0, reinterpret_cast<LPARAM>(&buttonBounds));
488
489 buttonWidth = buttonBounds.right - buttonBounds.left;
490 buttonHeight = buttonBounds.bottom - buttonBounds.top;
491 positionInfoCopy.cx = newWidth - 2 - buttonWidth;
492 DefWindowProc(WM_WINDOWPOSCHANGING, wParam, reinterpret_cast<LPARAM>(&positionInfoCopy));
493 ::GetWindowRect(fComboBox, &comboBoxBounds);
494 ::SetWindowPos(fGoButton, NULL, newWidth - buttonWidth, (comboBoxBounds.bottom - comboBoxBounds.top - buttonHeight) / 2,
495 buttonWidth, buttonHeight, SWP_NOOWNERZORDER | SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOZORDER);
496
497 goButtonBounds.left = newWidth - buttonWidth;
498 goButtonBounds.top = 0;
499 goButtonBounds.right = newWidth - buttonWidth;
500 goButtonBounds.bottom = newHeight;
501 InvalidateRect(&goButtonBounds, TRUE);
502
503 SendMessage(fComboBox, CB_SETDROPPEDWIDTH, 200, 0);
504 return 0;
505 }
506
507 HRESULT CreateAddressBand(REFIID riid, void **ppv)
508 {
509 CComObject<CAddressBand> *theMenuBar;
510 HRESULT hResult;
511
512 if (ppv == NULL)
513 return E_POINTER;
514 *ppv = NULL;
515 ATLTRY (theMenuBar = new CComObject<CAddressBand>);
516 if (theMenuBar == NULL)
517 return E_OUTOFMEMORY;
518 hResult = theMenuBar->QueryInterface(riid, reinterpret_cast<void **>(ppv));
519 if (FAILED(hResult))
520 {
521 delete theMenuBar;
522 return hResult;
523 }
524 return S_OK;
525 }