Jay Yang : explorer: Add dropdown entries to explorer's combobox.

Alexandre Julliard julliard at winehq.org
Mon Jul 4 13:46:08 CDT 2011


Module: wine
Branch: master
Commit: c1b6d91c5bc42b60f8be582977c34b4c1ec485df
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c1b6d91c5bc42b60f8be582977c34b4c1ec485df

Author: Jay Yang <jkelleyy at gmail.com>
Date:   Sun Jul  3 21:36:05 2011 -0400

explorer: Add dropdown entries to explorer's combobox.

---

 programs/explorer/explorer.c |  185 +++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 182 insertions(+), 3 deletions(-)

diff --git a/programs/explorer/explorer.c b/programs/explorer/explorer.c
index 0cb00a4..e42065f 100644
--- a/programs/explorer/explorer.c
+++ b/programs/explorer/explorer.c
@@ -62,6 +62,7 @@ typedef struct
     HWND main_window,path_box;
     INT rebar_height;
     LPCITEMIDLIST pidl;
+    IImageList *icon_list;
 } explorer_info;
 
 enum
@@ -101,11 +102,153 @@ static ULONG WINAPI IExplorerBrowserEventsImpl_fnRelease(IExplorerBrowserEvents
     return ref;
 }
 
+static BOOL create_combobox_item(IShellFolder *folder, LPCITEMIDLIST pidl, IImageList *icon_list, COMBOBOXEXITEMW *item)
+{
+    STRRET strret;
+    HRESULT hres;
+    IExtractIconW *extract_icon;
+    UINT reserved;
+    WCHAR icon_file[MAX_PATH];
+    INT icon_index;
+    UINT icon_flags;
+    HICON icon;
+    strret.uType=STRRET_WSTR;
+    hres = IShellFolder_GetDisplayNameOf(folder,pidl,SHGDN_FORADDRESSBAR,&strret);
+    if(FAILED(hres))
+    {
+        WINE_WARN("Could not get name for pidl\n");
+        return FALSE;
+    }
+    switch(strret.uType)
+    {
+    case STRRET_WSTR:
+        item->pszText = strret.pOleStr;
+        break;
+    default:
+        WINE_FIXME("Unimplemented STRRET type:%u\n",strret.uType);
+        break;
+    }
+    hres = IShellFolder_GetUIObjectOf(folder,NULL,1,&pidl,&IID_IExtractIconW,
+                                      &reserved,(void**)&extract_icon);
+    if(SUCCEEDED(hres))
+    {
+        item->mask |= CBEIF_IMAGE;
+        IExtractIconW_GetIconLocation(extract_icon,GIL_FORSHELL,icon_file,
+                                      sizeof(icon_file)/sizeof(WCHAR),
+                                      &icon_index,&icon_flags);
+        IExtractIconW_Extract(extract_icon,icon_file,icon_index,NULL,&icon,20);
+        item->iImage = ImageList_AddIcon((HIMAGELIST)icon_list,icon);
+    }
+    else
+    {
+        item->mask &= ~CBEIF_IMAGE;
+        WINE_WARN("Could not get an icon for %s\n",wine_dbgstr_w(item->pszText));
+    }
+    return TRUE;
+}
+
 static void update_path_box(explorer_info *info)
 {
-    WCHAR path[MAX_PATH];
-    SHGetPathFromIDListW(info->pidl,path);
-    SetWindowTextW(info->path_box,path);
+    COMBOBOXEXITEMW item;
+    COMBOBOXEXITEMW main_item;
+    IShellFolder *desktop;
+    IPersistFolder2 *persist;
+    LPITEMIDLIST desktop_pidl;
+    IEnumIDList *ids;
+
+    ImageList_Remove((HIMAGELIST)info->icon_list,-1);
+    SendMessageW(info->path_box,CB_RESETCONTENT,0,0);
+    SHGetDesktopFolder(&desktop);
+    IShellFolder_QueryInterface(desktop,&IID_IPersistFolder2,(void**)&persist);
+    IPersistFolder2_GetCurFolder(persist,&desktop_pidl);
+    IPersistFolder2_Release(persist);
+    persist = NULL;
+    /*Add Desktop*/
+    item.iItem = -1;
+    item.mask = CBEIF_TEXT | CBEIF_INDENT | CBEIF_LPARAM;
+    item.iIndent = 0;
+    create_combobox_item(desktop,desktop_pidl,info->icon_list,&item);
+    item.lParam = (LPARAM)desktop_pidl;
+    SendMessageW(info->path_box,CBEM_INSERTITEMW,0,(LPARAM)&item);
+    if(ILIsEqual(info->pidl,desktop_pidl))
+        main_item = item;
+    else
+        CoTaskMemFree(item.pszText);
+    /*Add all direct subfolders of Desktop*/
+    if(SUCCEEDED(IShellFolder_EnumObjects(desktop,NULL,SHCONTF_FOLDERS,&ids))
+       && ids!=NULL)
+    {
+        LPITEMIDLIST curr_pidl;
+        HRESULT hres;
+
+        item.iIndent = 1;
+        while(1)
+        {
+            hres = IEnumIDList_Next(ids,1,&curr_pidl,NULL);
+            if(FAILED(hres) || hres == S_FALSE)
+                break;
+            if(!create_combobox_item(desktop,curr_pidl,info->icon_list,&item))
+                WINE_WARN("Could not create a combobox item\n");
+            else
+            {
+                LPITEMIDLIST full_pidl = ILCombine(desktop_pidl,curr_pidl);
+                item.lParam = (LPARAM)full_pidl;
+                SendMessageW(info->path_box,CBEM_INSERTITEMW,0,(LPARAM)&item);
+                if(ILIsEqual(full_pidl,info->pidl))
+                    main_item = item;
+                else if(ILIsParent(full_pidl,info->pidl,FALSE))
+                {
+                    /*add all parents of the pidl passed in*/
+                    LPITEMIDLIST next_pidl = ILFindChild(full_pidl,info->pidl);
+                    IShellFolder *curr_folder = NULL, *temp;
+                    hres = IShellFolder_BindToObject(desktop,curr_pidl,NULL,
+                                                     &IID_IShellFolder,
+                                                     (void**)&curr_folder);
+                    if(FAILED(hres))
+                        WINE_WARN("Could not get an IShellFolder\n");
+                    while(!ILIsEmpty(next_pidl))
+                    {
+                        LPITEMIDLIST first = ILCloneFirst(next_pidl);
+                        CoTaskMemFree(item.pszText);
+                        if(!create_combobox_item(curr_folder,first,
+                                                 info->icon_list,&item))
+                        {
+                            WINE_WARN("Could not create a combobox item\n");
+                            break;
+                        }
+                        ++item.iIndent;
+                        full_pidl = ILCombine(full_pidl,first);
+                        item.lParam = (LPARAM)full_pidl;
+                        SendMessageW(info->path_box,CBEM_INSERTITEMW,0,(LPARAM)&item);
+                        temp=NULL;
+                        hres = IShellFolder_BindToObject(curr_folder,first,NULL,
+                                                         &IID_IShellFolder,
+                                                         (void**)&temp);
+                        if(FAILED(hres))
+                        {
+                            WINE_WARN("Could not get an IShellFolder\n");
+                            break;
+                        }
+                        IShellFolder_Release(curr_folder);
+                        curr_folder = temp;
+
+                        ILFree(first);
+                        next_pidl = ILGetNext(next_pidl);
+                    }
+                    memcpy(&main_item,&item,sizeof(item));
+                    if(curr_folder)
+                        IShellFolder_Release(curr_folder);
+                    item.iIndent = 1;
+                }
+                else
+                    CoTaskMemFree(item.pszText);
+            }
+        }
+    }
+    else
+        WINE_WARN("Could not enumerate the desktop\n");
+    SendMessageW(info->path_box,CBEM_SETITEMW,0,(LPARAM)&main_item);
+    CoTaskMemFree(main_item.pszText);
 }
 
 static HRESULT WINAPI IExplorerBrowserEventsImpl_fnOnNavigationComplete(IExplorerBrowserEvents *iface, PCIDLIST_ABSOLUTE pidl)
@@ -148,6 +291,8 @@ static IExplorerBrowserEvents *make_explorer_events(explorer_info *info)
         = HeapAlloc(GetProcessHeap(), 0, sizeof(IExplorerBrowserEventsImpl));
     ret->IExplorerBrowserEvents_iface.lpVtbl = &vt_IExplorerBrowserEvents;
     ret->info = info;
+    SHGetImageList(SHIL_SMALL,&IID_IImageList,(void**)&(ret->info->icon_list));
+    SendMessageW(info->path_box,CBEM_SETIMAGELIST,0,(LPARAM)ret->info->icon_list);
     IExplorerBrowserEvents_AddRef(&ret->IExplorerBrowserEvents_iface);
     return &ret->IExplorerBrowserEvents_iface;
 }
@@ -287,6 +432,12 @@ static LRESULT explorer_on_end_edit(explorer_info *info,NMCBEENDEDITW *edit_info
     WINE_TRACE("iWhy=%x\n",edit_info->iWhy);
     switch(edit_info->iWhy)
     {
+    case CBENF_DROPDOWN:
+        if(edit_info->iNewSelection!=CB_ERR)
+            pidl = (LPITEMIDLIST)SendMessageW(edit_info->hdr.hwndFrom,
+                                              CB_GETITEMDATA,
+                                              edit_info->iNewSelection,0);
+        break;
     case CBENF_RETURN:
         {
             WCHAR path[MAX_PATH];
@@ -330,8 +481,36 @@ static LRESULT explorer_on_notify(explorer_info* info,NMHDR* notification)
     WINE_TRACE("code=%i\n",notification->code);
     switch(notification->code)
     {
+    case CBEN_BEGINEDIT:
+        {
+            WCHAR path[MAX_PATH];
+            HWND edit_ctrl = (HWND)SendMessageW(notification->hwndFrom,
+                                                CBEM_GETEDITCONTROL,0,0);
+            SHGetPathFromIDListW(info->pidl,path);
+            SetWindowTextW(edit_ctrl,path);
+            break;
+        }
+    case CBEN_ENDEDITA:
+        {
+            NMCBEENDEDITA *edit_info_a = (NMCBEENDEDITA*)notification;
+            NMCBEENDEDITW edit_info_w;
+            edit_info_w.hdr = edit_info_a->hdr;
+            edit_info_w.fChanged = edit_info_a->fChanged;
+            edit_info_w.iNewSelection = edit_info_a->iNewSelection;
+            MultiByteToWideChar(CP_ACP,0,edit_info_a->szText,-1,
+                                edit_info_w.szText,CBEMAXSTRLEN);
+            edit_info_w.iWhy = edit_info_a->iWhy;
+            return explorer_on_end_edit(info,&edit_info_w);
+        }
     case CBEN_ENDEDITW:
         return explorer_on_end_edit(info,(NMCBEENDEDITW*)notification);
+    case CBEN_DELETEITEM:
+        {
+            NMCOMBOBOXEXW *entry = (NMCOMBOBOXEXW*)notification;
+            if(entry->ceItem.lParam)
+                ILFree((LPITEMIDLIST)entry->ceItem.lParam);
+            break;
+        }
     case RBN_AUTOSIZE:
         return update_rebar_size(info,(NMRBAUTOSIZE*)notification);
     default:




More information about the wine-cvs mailing list