[CMD] Выделение иконки на десктопе

fils

Новый пользователь
Сообщения
28
Реакции
3
Можно ли програмно выделить иконку на десктопе (не в папке Desktop, а на экране монитора) зная только её имя?
 
Последнее редактирование:
В уже открытой папке или ещё нет?

Код:
explorer /select,"путь"
 
В уже открытой папке или ещё нет?

Код:
explorer /select,"путь"
Этот скрипт откроет и выделит файл/папку в папке "Desktop",
а мне надо чтобы выделело иконку на рабочем поле монитора.
 
Последнее редактирование:
Для уже открытой папки, если знакомы с программированием на интерфейсах и Shell, то вот так можно:

C++:
IWebBrowserApp *m_pSite;
if (SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, (void**)&m_pSite)))
{
    IServiceProvider * pServiceProvider;
    if (SUCCEEDED(m_pSite->QueryInterface(IID_IServiceProvider, (LPVOID*)&pServiceProvider)))
    {
        IShellBrowser * pShellBrowser;
        if (SUCCEEDED(pServiceProvider->QueryService(SID_SShellBrowser, IID_IShellBrowser, (LPVOID*)&pShellBrowser)))
        {
            // получаем интерфейс активного окна explorer
            IShellView * pShellView;
            if (SUCCEEDED(pShellBrowser->QueryActiveShellView(&pShellView)))
            {
                IFolderView * pFolderView;
                if (SUCCEEDED(pShellView->QueryInterface(IID_IFolderView, (LPVOID*)&pFolderView)))
                {
                    int nCount = 0;
                    if (SUCCEEDED(pFolderView->ItemCount(SVGIO_ALLVIEW, &nCount)))
                    {
                        // select each entry
                        for (int i = 0; i < nCount; i++)
                        {
                            LPITEMIDLIST pidl;
                            pFolderView->Item(i, &pidl);
                            // здесь можно получить имя объекта, например через IShellFolder::GetDisplayNameOf
                        
                            // выделить объект
                            pFolderView->SelectItem(i, SVSI_SELECT);
                        }
                    }
                }
                pShellView->Release();
            }
            pShellBrowser->Release();
        }
        pServiceProvider->Release();
    }
    m_pSite->Release();
}

Или более быстро наверное так: IPersistFolder2::GetCurFolder, затем IShellView::SelectItem

Из скриптовых ЯП ничего из этого не доступно.
 
Последнее редактирование:
Вообще-то скриптовым языкам доступен объект Shell.Application и в частности Shell.Windows, но там в FolderItem нет нужного метода SelectItem.

На счёт варианта на С++, вот здесь есть более подробное объяснение кода от Реймонда Чена.

Сейчас вот поэкспериментировал, если открыта папка и там уже выделены какие-то объекты, то чтобы убрать выделение со всех них, а также прямоугольник фокуса, после чего выделить нужный объект, требуется выполнить последовательность таких действий:

Код:
pFolderView->SelectItem(i, SVSI_DESELECTOTHERS);
pFolderView->SelectItem(i, SVSI_FOCUSED);
pFolderView->SelectItem(i, SVSI_SELECT);

Здесь вот кстати, еще вариант на VB6: Раз, Два.
Для кода "Раз", пример с перечислением элементов в папке и выделения нужного на VB6:

VB.NET / VBA:
Dim k As Long
Dim nCount As Long
Dim shItem As IShellItem2

'получаем кол-во элементов
Call spfv.ItemCount(SVGIO_ALLVIEW, nCount)

For k = 0 To nCount - 1

    spfv.GetItem k, IID_IShellItem, shItem

    'получаем полный путь к файлу
    shItem.GetDisplayName SIGDN_DESKTOPABSOLUTEPARSING, lpPath
    sPath = LPWSTRtoStr(lpPath)
    
    Debug.Print sPath

    If sPath = "xxxxx" Then ' проверяем что нашли нужный нам путь
        
        'выделяем его, сняв выделение с остальных
        Call spfv.SelectItem(k, SVSI_DESELECTOTHERS)
        Call spfv.SelectItem(k, SVSI_FOCUSED)
        Call spfv.SelectItem(k, SVSI_SELECT)
        
        Exit For
    End If
Next
 
Он имеет ввиду иконки на рабочем столе, там где стоит фоновая картинка, когда все окна свернутые.
Иконка проорамно выделится, если по ней сделать клик (нужно знать ее координаты), или сделать клик по первой иконке (Мой компьютер) и кдавишей Таб дойти до нужной (нужно знать ее номер).
Хотя... если сделать переименование иконки (ярлыка), то она получает фокус
(не утверждаю, а предполагаю, так как проверить не могу - у меня нет иконок на раб.столе - просто синий єкран).
 
На рабочем столе множество иконок:
1) иконки ярлыков и других файлов в области открытой виртуальной папки "Рабочий стол"
2) иконки закрепленных ярлыков на панели задач
3) иконки запущенных приложений на панели задач
4) иконки запущенных приложений в панели уведомления
5) иконки файлов в отдельно открытой папке
Ждём от TC скриншот, что именно он имел в виду.
 
Последнее редактирование:
нету такого понятия.

Вы имеете в виду уже открытую папку?
На рабочем столе выделена иконка 1.txt.
Я бы хотел сделать это выделение программно зная только имя файла (в данном случае 1.txt ).
 

Вложения

  • Рабочий стол.jpg
    Рабочий стол.jpg
    30.5 KB · Просмотры: 51
Последнее редактирование:
Он имеет ввиду иконки на рабочем столе, там где стоит фоновая картинка, когда все окна свернутые.
Иконка проорамно выделится, если по ней сделать клик (нужно знать ее координаты), или сделать клик по первой иконке (Мой компьютер) и кдавишей Таб дойти до нужной (нужно знать ее номер).
Хотя... если сделать переименование иконки (ярлыка), то она получает фокус
(не утверждаю, а предполагаю, так как проверить не могу - у меня нет иконок на раб.столе - просто синий єкран).
Вы всё поняли абсолютно правильно.
Я подумаю над Вашей идеей "сделать клик (программно) по первой иконке (Мой компьютер) и клавишей Таб дойти до нужной (программно)".
Спасибо за подсказку!
 
@fils,

C++:
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <shlobj.h>
#include <exdisp.h>
#include <shlwapi.h>
#include <atlbase.h>
#include <atlalloc.h>
#include <stdio.h>

void FindDesktopFolderView(REFIID riid, void** ppv)
{
    CComPtr<IShellWindows> spShellWindows;
    spShellWindows.CoCreateInstance(CLSID_ShellWindows);

    CComVariant vtLoc(CSIDL_DESKTOP);
    CComVariant vtEmpty;
    long lhwnd;
    CComPtr<IDispatch> spdisp;
    spShellWindows->FindWindowSW(
        &vtLoc, &vtEmpty,
        SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp);

    CComPtr<IShellBrowser> spBrowser;
    CComQIPtr<IServiceProvider>(spdisp)->
        QueryService(SID_STopLevelBrowser,
            IID_PPV_ARGS(&spBrowser));

    CComPtr<IShellView> spView;
    spBrowser->QueryActiveShellView(&spView);

    spView->QueryInterface(riid, ppv);
}

int __cdecl wmain(int argc, wchar_t** argv)
{
    LPVOID lpRes = NULL;
    CoInitialize(lpRes);
    CComPtr<IFolderView> spView;
    FindDesktopFolderView(IID_PPV_ARGS(&spView));
    CComPtr<IShellFolder> spFolder;
    spView->GetFolder(IID_PPV_ARGS(&spFolder));
    int nCount = 0;
    spView->ItemCount(SVGIO_ALLVIEW, &nCount);
    
    for (int i = 0; i < nCount; i++)
    {
        CComHeapPtr<ITEMID_CHILD> spidl;
        spView->Item(i, &spidl);

        STRRET str;
        spFolder->GetDisplayNameOf(spidl, SHGDN_NORMAL, &str);
        CComHeapPtr<wchar_t> spszName;
        StrRetToStr(&str, spidl, &spszName);

        wprintf(L"Name: %ls\n", static_cast<LPWSTR>(spszName));

        if (_wcsicmp(spszName, L"Reverse") == 0) // название файла на рабочем столе
        {
            spView->SelectItem(i, SVSI_DESELECTOTHERS | SVSI_FOCUSED | SVSI_SELECT);
        }
    }
    
    return 0;
}

Часть кода взята из статей Raymond Chen:
 
Он имеет ввиду иконки на рабочем столе, там где стоит фоновая картинка, когда все окна свернутые.
Иконка проорамно выделится, если по ней сделать клик (нужно знать ее координаты), или сделать клик по первой иконке (Мой компьютер) и кдавишей Таб дойти до нужной (нужно знать ее номер).
Хотя... если сделать переименование иконки (ярлыка), то она получает фокус
(не утверждаю, а предполагаю, так как проверить не могу - у меня нет иконок на раб.столе - просто синий єкран).
Попробывал Вашу вторую догатку с переименованием иконки, и вроде всё получилось.
Т.е батник работает как поисковая система. Вводишь имя с расширением файла или имя папки
и он на рабочем столе выделяет её иконку.
Спасибо за помощь.
 
Всем большое спасибо!
Вопрос решён.
Прилагаю скрипт батника, может быть кому-нибудь будет интересно.
CMD/BATCH:
@echo off >nul
Chcp 1251 >nul

set /p i= ВВЕДИ ИМЯ файла/папки -
for %%a in ("%i%") do set x=%%~xa

cmdow @ /min
ren "%i%" ъ%x%
nircmd wait 500
nircmd win activate class progman
nircmd wait 500
nircmd sendkeypress ctrl+1 shift+221
nircmd wait 500
ren ъ%x% "%i%"
exit
 
Последнее редактирование:
@fils,

C++:
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <shlobj.h>
#include <exdisp.h>
#include <shlwapi.h>
#include <atlbase.h>
#include <atlalloc.h>
#include <stdio.h>

void FindDesktopFolderView(REFIID riid, void** ppv)
{
    CComPtr<IShellWindows> spShellWindows;
    spShellWindows.CoCreateInstance(CLSID_ShellWindows);

    CComVariant vtLoc(CSIDL_DESKTOP);
    CComVariant vtEmpty;
    long lhwnd;
    CComPtr<IDispatch> spdisp;
    spShellWindows->FindWindowSW(
        &vtLoc, &vtEmpty,
        SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp);

    CComPtr<IShellBrowser> spBrowser;
    CComQIPtr<IServiceProvider>(spdisp)->
        QueryService(SID_STopLevelBrowser,
            IID_PPV_ARGS(&spBrowser));

    CComPtr<IShellView> spView;
    spBrowser->QueryActiveShellView(&spView);

    spView->QueryInterface(riid, ppv);
}

int __cdecl wmain(int argc, wchar_t** argv)
{
    LPVOID lpRes = NULL;
    CoInitialize(lpRes);
    CComPtr<IFolderView> spView;
    FindDesktopFolderView(IID_PPV_ARGS(&spView));
    CComPtr<IShellFolder> spFolder;
    spView->GetFolder(IID_PPV_ARGS(&spFolder));
    int nCount = 0;
    spView->ItemCount(SVGIO_ALLVIEW, &nCount);
   
    for (int i = 0; i < nCount; i++)
    {
        CComHeapPtr<ITEMID_CHILD> spidl;
        spView->Item(i, &spidl);

        STRRET str;
        spFolder->GetDisplayNameOf(spidl, SHGDN_NORMAL, &str);
        CComHeapPtr<wchar_t> spszName;
        StrRetToStr(&str, spidl, &spszName);

        wprintf(L"Name: %ls\n", static_cast<LPWSTR>(spszName));

        if (_wcsicmp(spszName, L"Reverse") == 0) // название файла на рабочем столе
        {
            spView->SelectItem(i, SVSI_DESELECTOTHERS | SVSI_FOCUSED | SVSI_SELECT);
        }
    }
   
    return 0;
}

Часть кода взята из статей Raymond Chen:
Где это можно скомпилировать on-line?
Или ещё что-нибудь посоветуете для разового применения.
 
Где это можно скомпилировать on-line?
не в курсе, но могу скомпилировать вам, сделав название файла как первый аргумент запуска программы

Или ещё что-нибудь посоветуете для разового применения.
не понимаю вопроса
 
И в чём прикол?
В Win10 можно поставить такой же компилятор, как и на Линукс (mingw), если лень заморачиваться со скачиванием огромного дистрибутива MS Visual Studio.
Вот только не факт, что в нём найдутся все нужные хидеры. Приведённый выше код требует ATL.
 
Последнее редактирование:
Попробывал Вашу вторую догатку с переименованием иконки, и вроде всё получилось.
Т.е батник работает как поисковая система. Вводишь имя с расширением файла или имя папки
и он на рабочем столе выделяет её иконку.
Спасибо за помощь.
Там учтите, что иконки - иногда ярлыки (папок) с расширением lnk или даже url
 
Хоть что угодно.
Если брать из числа Visual Studio, то наиболее легковесная версия 2013, где более-менее есть поддержка основных фич и код выше должен собраться.
 
Назад
Сверху Снизу