1 /* 2 * ReactOS Explorer 3 * 4 * Copyright 2009 Andrew Hill <ash77 at domain reactos.org> 5 * Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22 /* 23 This class handles the combo box of the address band. 24 */ 25 26 #include "precomp.h" 27 28 /* 29 TODO: 30 Add drag and drop of icon in edit box 31 Handle change notifies to update appropriately 32 */ 33 34 CAddressEditBox::CAddressEditBox() : 35 fCombobox(WC_COMBOBOXEXW, this), 36 fEditWindow(WC_EDITW, this), 37 fSite(NULL), 38 pidlLastParsed(NULL) 39 { 40 } 41 42 CAddressEditBox::~CAddressEditBox() 43 { 44 if (pidlLastParsed) 45 ILFree(pidlLastParsed); 46 } 47 48 HRESULT STDMETHODCALLTYPE CAddressEditBox::SetOwner(IUnknown *pOwner) 49 { 50 if (!pOwner) 51 { 52 CComPtr<IBrowserService> browserService; 53 HRESULT hResult = IUnknown_QueryService(fSite, SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService)); 54 if (SUCCEEDED(hResult)) 55 AtlUnadvise(browserService, DIID_DWebBrowserEvents, fAdviseCookie); 56 fSite = NULL; 57 } 58 // connect to browser connection point 59 return 0; 60 } 61 62 HRESULT STDMETHODCALLTYPE CAddressEditBox::FileSysChange(long param8, long paramC) 63 { 64 return E_NOTIMPL; 65 } 66 67 HRESULT STDMETHODCALLTYPE CAddressEditBox::Refresh(long param8) 68 { 69 return E_NOTIMPL; 70 } 71 72 HRESULT STDMETHODCALLTYPE CAddressEditBox::Init(HWND comboboxEx, HWND editControl, long param14, IUnknown *param18) 73 { 74 CComPtr<IBrowserService> browserService; 75 76 fCombobox.SubclassWindow(comboboxEx); 77 fEditWindow.SubclassWindow(editControl); 78 fSite = param18; 79 hComboBoxEx = comboboxEx; 80 81 SHAutoComplete(fEditWindow.m_hWnd, SHACF_FILESYSTEM | SHACF_URLALL | SHACF_USETAB); 82 83 // take advice to watch events 84 HRESULT hResult = IUnknown_QueryService(param18, SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService)); 85 if (SUCCEEDED(hResult)) 86 { 87 hResult = AtlAdvise(browserService, static_cast<IDispatch *>(this), DIID_DWebBrowserEvents, &fAdviseCookie); 88 } 89 90 return hResult; 91 } 92 93 HRESULT STDMETHODCALLTYPE CAddressEditBox::SetCurrentDir(long paramC) 94 { 95 return E_NOTIMPL; 96 } 97 98 BOOL CAddressEditBox::GetComboBoxText(CComHeapPtr<WCHAR>& pszText) 99 { 100 pszText.Free(); 101 INT cchMax = fCombobox.GetWindowTextLength() + sizeof(UNICODE_NULL); 102 if (!pszText.Allocate(cchMax)) 103 return FALSE; 104 return fCombobox.GetWindowText(pszText, cchMax); 105 } 106 107 HRESULT CAddressEditBox::RefreshAddress() 108 { 109 /* Get the current pidl of the browser */ 110 CComHeapPtr<ITEMIDLIST> absolutePIDL; 111 HRESULT hr = GetAbsolutePidl(&absolutePIDL); 112 if (FAILED_UNEXPECTEDLY(hr)) 113 return hr; 114 115 /* Fill the combobox */ 116 ATLASSERT(absolutePIDL != NULL); 117 PopulateComboBox(absolutePIDL); 118 119 /* Get pShellFolder and pidlChild */ 120 CComPtr<IShellFolder> pShellFolder; 121 PCITEMID_CHILD pidlChild; 122 hr = SHBindToParent(absolutePIDL, IID_PPV_ARG(IShellFolder, &pShellFolder), &pidlChild); 123 if (FAILED_UNEXPECTEDLY(hr)) 124 return hr; 125 126 /* Get ready to set the displayed item */ 127 COMBOBOXEXITEMW item = { CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_TEXT | CBEIF_LPARAM }; 128 item.iItem = -1; /* -1 to specify the displayed item */ 129 item.iImage = SHMapPIDLToSystemImageListIndex(pShellFolder, pidlChild, &item.iSelectedImage); 130 131 /* Set the path if filesystem; otherwise use the name */ 132 WCHAR szPathOrName[MAX_PATH]; 133 SHGDNF flags = SHGDN_FORADDRESSBAR; 134 if (gCabinetState.fFullPathAddress) 135 flags |= SHGDN_FORPARSING; 136 137 if (SUCCEEDED(IEGetNameAndFlags(absolutePIDL, flags, szPathOrName, _countof(szPathOrName), NULL))) 138 item.pszText = szPathOrName; 139 140 /* Ownership of absolutePIDL will be moved to fCombobox. See CBEN_DELETEITEM */ 141 item.lParam = reinterpret_cast<LPARAM>(absolutePIDL.Detach()); 142 143 fCombobox.SendMessage(CBEM_SETITEM, 0, reinterpret_cast<LPARAM>(&item)); /* Set it! */ 144 return S_OK; 145 } 146 147 HRESULT CAddressEditBox::GetAbsolutePidl(PIDLIST_ABSOLUTE *pAbsolutePIDL) 148 { 149 CComPtr<IBrowserService> isb; 150 HRESULT hr = IUnknown_QueryService(fSite, SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService, &isb)); 151 if (FAILED_UNEXPECTEDLY(hr)) 152 return hr; 153 154 hr = isb->GetPidl(pAbsolutePIDL); 155 if (FAILED_UNEXPECTEDLY(hr)) 156 return hr; 157 158 return S_OK; 159 } 160 161 /* Execute command line from address bar */ 162 BOOL CAddressEditBox::ExecuteCommandLine() 163 { 164 /* Get command line */ 165 CComHeapPtr<WCHAR> pszCmdLine; 166 if (!GetComboBoxText(pszCmdLine)) 167 return FALSE; 168 169 /* Split 1st parameter from trailing arguments */ 170 PWCHAR args = PathGetArgsW(pszCmdLine); 171 PathRemoveArgsW(pszCmdLine); 172 173 PathUnquoteSpacesW(pszCmdLine); /* Unquote the 1st parameter */ 174 175 /* Get ready for execution */ 176 SHELLEXECUTEINFOW info = { sizeof(info), SEE_MASK_FLAG_NO_UI, m_hWnd }; 177 info.lpFile = pszCmdLine; 178 info.lpParameters = args; 179 info.nShow = SW_SHOWNORMAL; 180 181 /* Set current directory */ 182 WCHAR dir[MAX_PATH] = L""; 183 CComHeapPtr<ITEMIDLIST> pidl; 184 if (SUCCEEDED(GetAbsolutePidl(&pidl))) 185 { 186 if (SHGetPathFromIDListW(pidl, dir) && PathIsDirectoryW(dir)) 187 info.lpDirectory = dir; 188 } 189 190 if (!::ShellExecuteExW(&info)) /* Execute! */ 191 return FALSE; 192 193 RefreshAddress(); 194 return TRUE; 195 } 196 197 HRESULT STDMETHODCALLTYPE CAddressEditBox::ParseNow(long paramC) 198 { 199 ULONG eaten; 200 ULONG attributes; 201 HRESULT hr; 202 HWND topLevelWindow; 203 PIDLIST_ABSOLUTE pidlCurrent= NULL; 204 PIDLIST_RELATIVE pidlRelative = NULL; 205 CComPtr<IShellFolder> psfCurrent; 206 207 CComPtr<IBrowserService> pbs; 208 hr = IUnknown_QueryService(fSite, SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &pbs)); 209 if (FAILED_UNEXPECTEDLY(hr)) 210 return hr; 211 212 hr = IUnknown_GetWindow(pbs, &topLevelWindow); 213 if (FAILED_UNEXPECTEDLY(hr)) 214 return hr; 215 216 /* Get the path to browse and expand it if needed */ 217 CComHeapPtr<WCHAR> input, address; 218 if (!GetComboBoxText(input)) 219 return E_FAIL; 220 221 INT addressLength = (wcschr(input, L'%') ? ::SHExpandEnvironmentStringsW(input, NULL, 0) : 0); 222 if (addressLength <= 0 || 223 !address.Allocate(addressLength + 1) || 224 !::SHExpandEnvironmentStringsW(input, address, addressLength)) 225 { 226 address.Free(); 227 address.Attach(input.Detach()); 228 } 229 230 /* Try to parse a relative path and if it fails, try to browse an absolute path */ 231 CComPtr<IShellFolder> psfDesktop; 232 hr = SHGetDesktopFolder(&psfDesktop); 233 if (FAILED_UNEXPECTEDLY(hr)) 234 goto cleanup; 235 236 hr = pbs->GetPidl(&pidlCurrent); 237 if (FAILED_UNEXPECTEDLY(hr)) 238 goto parseabsolute; 239 240 hr = psfDesktop->BindToObject(pidlCurrent, NULL, IID_PPV_ARG(IShellFolder, &psfCurrent)); 241 if (FAILED_UNEXPECTEDLY(hr)) 242 goto parseabsolute; 243 244 hr = psfCurrent->ParseDisplayName(topLevelWindow, NULL, address, &eaten, &pidlRelative, &attributes); 245 if (SUCCEEDED(hr)) 246 { 247 pidlLastParsed = ILCombine(pidlCurrent, pidlRelative); 248 ILFree(pidlRelative); 249 goto cleanup; 250 } 251 252 parseabsolute: 253 /* We couldn't parse a relative path, attempt to parse an absolute path */ 254 hr = psfDesktop->ParseDisplayName(topLevelWindow, NULL, address, &eaten, &pidlLastParsed, &attributes); 255 256 cleanup: 257 if (pidlCurrent) 258 ILFree(pidlCurrent); 259 return hr; 260 } 261 262 HRESULT STDMETHODCALLTYPE CAddressEditBox::ShowFileNotFoundError(HRESULT hRet) 263 { 264 CComHeapPtr<WCHAR> input; 265 if (!GetComboBoxText(input)) 266 return E_FAIL; 267 268 ShellMessageBoxW(_AtlBaseModule.GetResourceInstance(), fCombobox.m_hWnd, MAKEINTRESOURCEW(IDS_PARSE_ADDR_ERR_TEXT), MAKEINTRESOURCEW(IDS_PARSE_ADDR_ERR_TITLE), MB_OK | MB_ICONERROR, input.m_pData); 269 270 return hRet; 271 } 272 273 HRESULT STDMETHODCALLTYPE CAddressEditBox::Execute(long paramC) 274 { 275 HRESULT hr; 276 277 /* 278 * Parse the path if it wasn't parsed 279 */ 280 if (!pidlLastParsed) 281 { 282 hr = ParseNow(0); 283 284 /* If the destination path doesn't exist then display an error message */ 285 if (hr == HRESULT_FROM_WIN32(ERROR_INVALID_DRIVE) || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) 286 { 287 if (ExecuteCommandLine()) 288 return S_OK; 289 290 return ShowFileNotFoundError(hr); 291 } 292 293 if (!pidlLastParsed) 294 return E_FAIL; 295 } 296 297 /* 298 * Get the IShellBrowser and IBrowserService interfaces of the shell browser 299 */ 300 CComPtr<IShellBrowser> pisb; 301 hr = IUnknown_QueryService(fSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &pisb)); 302 if (FAILED(hr)) 303 return hr; 304 305 /* 306 * Get the current pidl of the shellbrowser and check if it is the same with the parsed one 307 */ 308 PIDLIST_ABSOLUTE pidl; 309 hr = GetAbsolutePidl(&pidl); 310 if (FAILED(hr)) 311 return hr; 312 313 CComPtr<IShellFolder> psf; 314 hr = SHGetDesktopFolder(&psf); 315 if (FAILED(hr)) 316 return hr; 317 318 hr = psf->CompareIDs(0, pidl, pidlLastParsed); 319 320 SHFree(pidl); 321 322 if (hr == 0) 323 { 324 if (pidlLastParsed) 325 { 326 ILFree(pidlLastParsed); 327 pidlLastParsed = NULL; 328 } 329 return S_OK; 330 } 331 332 /* 333 * Attempt to browse to the parsed pidl 334 */ 335 hr = pisb->BrowseObject(pidlLastParsed, 0); 336 if (SUCCEEDED(hr)) 337 return hr; 338 339 /* 340 * Browsing to the pidl failed so it's not a folder. So invoke its defaule command. 341 */ 342 HWND topLevelWindow; 343 hr = IUnknown_GetWindow(pisb, &topLevelWindow); 344 if (FAILED(hr)) 345 return hr; 346 347 LPCITEMIDLIST pidlChild; 348 CComPtr<IShellFolder> sf; 349 hr = SHBindToParent(pidlLastParsed, IID_PPV_ARG(IShellFolder, &sf), &pidlChild); 350 if (FAILED(hr)) 351 return hr; 352 353 hr = SHInvokeDefaultCommand(topLevelWindow, sf, pidlChild); 354 if (FAILED(hr)) 355 return hr; 356 357 return hr; 358 } 359 360 HRESULT STDMETHODCALLTYPE CAddressEditBox::Save(long paramC) 361 { 362 return E_NOTIMPL; 363 } 364 365 HRESULT STDMETHODCALLTYPE CAddressEditBox::OnWinEvent( 366 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) 367 { 368 LPNMHDR hdr; 369 370 if (theResult) 371 *theResult = 0; 372 373 switch (uMsg) 374 { 375 case WM_COMMAND: 376 { 377 if (HIWORD(wParam) == CBN_SELCHANGE) 378 { 379 UINT selectedIndex = SendMessageW((HWND)lParam, CB_GETCURSEL, 0, 0); 380 pidlLastParsed = ILClone((LPITEMIDLIST)SendMessageW((HWND)lParam, CB_GETITEMDATA, selectedIndex, 0)); 381 Execute(0); 382 } 383 break; 384 } 385 case WM_NOTIFY: 386 { 387 hdr = (LPNMHDR) lParam; 388 if (hdr->code == CBEN_ENDEDIT) 389 { 390 NMCBEENDEDITW *endEdit = (NMCBEENDEDITW*) lParam; 391 if (endEdit->iWhy == CBENF_RETURN) 392 { 393 Execute(0); 394 } 395 else if (endEdit->iWhy == CBENF_ESCAPE) 396 { 397 /* Reset the contents of the combo box */ 398 RefreshAddress(); 399 } 400 } 401 else if (hdr->code == CBEN_DELETEITEM) 402 { 403 PNMCOMBOBOXEX pCBEx = (PNMCOMBOBOXEX) lParam; 404 LPITEMIDLIST itemPidl = (LPITEMIDLIST)pCBEx->ceItem.lParam; 405 if (itemPidl) 406 { 407 ILFree(itemPidl); 408 } 409 } 410 break; 411 } 412 } 413 return S_OK; 414 } 415 416 HRESULT STDMETHODCALLTYPE CAddressEditBox::IsWindowOwner(HWND hWnd) 417 { 418 if (fCombobox.m_hWnd == hWnd) 419 return S_OK; 420 if (fEditWindow.m_hWnd == hWnd) 421 return S_OK; 422 return S_FALSE; 423 } 424 425 HRESULT STDMETHODCALLTYPE CAddressEditBox::QueryStatus( 426 const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText) 427 { 428 return E_NOTIMPL; 429 } 430 431 HRESULT STDMETHODCALLTYPE CAddressEditBox::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, 432 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 433 { 434 return E_NOTIMPL; 435 } 436 437 HRESULT STDMETHODCALLTYPE CAddressEditBox::GetTypeInfoCount(UINT *pctinfo) 438 { 439 return E_NOTIMPL; 440 } 441 442 HRESULT STDMETHODCALLTYPE CAddressEditBox::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) 443 { 444 return E_NOTIMPL; 445 } 446 447 HRESULT STDMETHODCALLTYPE CAddressEditBox::GetIDsOfNames( 448 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) 449 { 450 return E_NOTIMPL; 451 } 452 453 HRESULT STDMETHODCALLTYPE CAddressEditBox::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, 454 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) 455 { 456 if (pDispParams == NULL) 457 return E_INVALIDARG; 458 459 switch (dispIdMember) 460 { 461 case DISPID_NAVIGATECOMPLETE2: 462 case DISPID_DOCUMENTCOMPLETE: 463 if (pidlLastParsed) 464 { 465 ILFree(pidlLastParsed); 466 pidlLastParsed = NULL; 467 } 468 469 RefreshAddress(); 470 break; 471 } 472 return S_OK; 473 } 474 475 HRESULT STDMETHODCALLTYPE CAddressEditBox::GetClassID(CLSID *pClassID) 476 { 477 if (pClassID == NULL) 478 return E_POINTER; 479 *pClassID = CLSID_AddressEditBox; 480 return S_OK; 481 } 482 483 HRESULT STDMETHODCALLTYPE CAddressEditBox::IsDirty() 484 { 485 return E_NOTIMPL; 486 } 487 488 HRESULT STDMETHODCALLTYPE CAddressEditBox::Load(IStream *pStm) 489 { 490 return E_NOTIMPL; 491 } 492 493 HRESULT STDMETHODCALLTYPE CAddressEditBox::Save(IStream *pStm, BOOL fClearDirty) 494 { 495 return E_NOTIMPL; 496 } 497 498 HRESULT STDMETHODCALLTYPE CAddressEditBox::GetSizeMax(ULARGE_INTEGER *pcbSize) 499 { 500 return E_NOTIMPL; 501 } 502 503 void CAddressEditBox::PopulateComboBox(LPITEMIDLIST pidlCurrent) 504 { 505 HRESULT hr; 506 LPITEMIDLIST pidl; 507 int indent = 0; 508 int index; 509 510 index = SendMessageW(hComboBoxEx, CB_GETCOUNT, 0, 0); 511 for (int i = 0; i < index; i++) 512 SendMessageW(hComboBoxEx, CBEM_DELETEITEM, i, 0); 513 SendMessageW(hComboBoxEx, CB_RESETCONTENT, 0, 0); 514 515 /* Calculate the indent level. No need to clone the pidl */ 516 pidl = pidlCurrent; 517 do 518 { 519 if(!pidl->mkid.cb) 520 break; 521 pidl = ILGetNext(pidl); 522 indent++; 523 } while (pidl); 524 index = indent; 525 526 /* Add every id from the pidl in the combo box */ 527 pidl = ILClone(pidlCurrent); 528 do 529 { 530 AddComboBoxItem(pidl, 0, index); 531 ILRemoveLastID(pidl); 532 index--; 533 } while (index >= 0); 534 ILFree(pidl); 535 536 /* Add the items of the desktop */ 537 FillOneLevel(0, 1, indent); 538 539 /* Add the items of My Computer */ 540 hr = SHGetSpecialFolderLocation(0, CSIDL_DRIVES, &pidl); 541 if (FAILED_UNEXPECTEDLY(hr)) 542 return; 543 544 for(LPITEMIDLIST i = GetItemData(0); i; i = GetItemData(index)) 545 { 546 if (ILIsEqual(i, pidl)) 547 { 548 FillOneLevel(index, 2, indent); 549 break; 550 } 551 index++; 552 } 553 ILFree(pidl); 554 } 555 556 void CAddressEditBox::AddComboBoxItem(LPITEMIDLIST pidl, int index, int indent) 557 { 558 HRESULT hr; 559 WCHAR buf[4096]; 560 561 LPCITEMIDLIST pidlChild; 562 CComPtr<IShellFolder> sf; 563 hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &sf), &pidlChild); 564 if (FAILED_UNEXPECTEDLY(hr)) 565 return; 566 567 STRRET strret; 568 hr = sf->GetDisplayNameOf(pidlChild, SHGDN_FORADDRESSBAR, &strret); 569 if (FAILED_UNEXPECTEDLY(hr)) 570 return; 571 572 hr = StrRetToBufW(&strret, pidlChild, buf, 4095); 573 if (FAILED_UNEXPECTEDLY(hr)) 574 return; 575 576 COMBOBOXEXITEMW item = {0}; 577 item.mask = CBEIF_LPARAM | CBEIF_INDENT | CBEIF_SELECTEDIMAGE | CBEIF_IMAGE | CBEIF_TEXT; 578 item.iImage = SHMapPIDLToSystemImageListIndex(sf, pidlChild, &item.iSelectedImage); 579 item.pszText = buf; 580 item.lParam = (LPARAM)(ILClone(pidl)); 581 item.iIndent = indent; 582 item.iItem = index; 583 SendMessageW(hComboBoxEx, CBEM_INSERTITEMW, 0, (LPARAM)&item); 584 } 585 586 void CAddressEditBox::FillOneLevel(int index, int levelIndent, int indent) 587 { 588 HRESULT hr; 589 ULONG numObj; 590 int count; 591 LPITEMIDLIST pidl, pidl2, pidl3, pidl4; 592 593 count = index + 1; 594 pidl = GetItemData(index); 595 pidl2 = GetItemData(count); 596 if(pidl) 597 { 598 CComPtr<IShellFolder> psfDesktop; 599 CComPtr<IShellFolder> psfItem; 600 601 hr = SHGetDesktopFolder(&psfDesktop); 602 if (FAILED_UNEXPECTEDLY(hr)) 603 return; 604 605 if (!pidl->mkid.cb) 606 { 607 psfItem = psfDesktop; 608 } 609 else 610 { 611 hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfItem)); 612 if (FAILED_UNEXPECTEDLY(hr)) 613 return; 614 } 615 616 CComPtr<IEnumIDList> pEnumIDList; 617 hr = psfItem->EnumObjects(0, SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN, &pEnumIDList); 618 if (FAILED_UNEXPECTEDLY(hr)) 619 return; 620 621 do 622 { 623 hr = pEnumIDList->Next(1, &pidl3, &numObj); 624 if(hr != S_OK || !numObj) 625 break; 626 627 pidl4 = ILCombine(pidl, pidl3); 628 if (pidl2 && ILIsEqual(pidl4, pidl2)) 629 count += (indent - levelIndent); 630 else 631 AddComboBoxItem(pidl4, count, levelIndent); 632 count++; 633 ILFree(pidl3); 634 ILFree(pidl4); 635 } while (true); 636 } 637 } 638 639 LPITEMIDLIST CAddressEditBox::GetItemData(int index) 640 { 641 COMBOBOXEXITEMW item; 642 643 memset(&item, 0, sizeof(COMBOBOXEXITEMW)); 644 item.mask = CBEIF_LPARAM; 645 item.iItem = index; 646 SendMessageW(hComboBoxEx, CBEM_GETITEMW, 0, (LPARAM)&item); 647 return (LPITEMIDLIST)item.lParam; 648 } 649 650 LRESULT CAddressEditBox::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 651 { 652 RefreshAddress(); 653 return NO_ERROR; 654 } 655