Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Кординаты ярлыков на рабочем столе


Автор: Riddik 11.10.2009, 21:25
Приветствую.

Нужно узнать координаты ярлыков.
Сначала получаю дескриптор рабочего стола, затем дочерних элементов:
Код

HWND desc = FindWindow("ProgMan", NULL);
 desc = GetWindow(desc, GW_CHILD);
 desc = GetWindow(desc, GW_CHILD);


Узнаю количество ярлыков:

Код

int n = SendMessage(desc, LVM_GETITEMCOUNT, 0, 0);


И надо записать их координаты:

Код

POINT p;
for(int i=0; i<n; i++) 
{
       SendMessage(desc, LVM_GETITEMPOSITION, i , (LPARAM)&p);
       file<<p.x<<" "<<p.y<<'\n';
}



Все числа в файле одинаковые, нифига не записываются в p координаты значков.

Что не так делаю?


И второй вопрос: как происходит нумерация значков - просте слева направо и сверху вниз? Или если перемешать значки (переместить), то нумерация за ними сохраниться?


Автор: uxoos 11.10.2009, 23:04
Ты наверно тоже это тестовое задание выполняешь...
Я остановился на том что при вызове в программе GetItemPosition(hWndw,1,(LPARAM)&pt) проводник windows7 перезапускается. Дескриптор рабочего стола находится верно.
Код
HWND hWndw=GetWindow(GetWindow(FindWindow("ProgMan",NULL),GW_CHILD),GW_CHILD);
POINT pt;
 ListView_GetItemPosition(hWndw,1,(LPARAM)&pt);
 //или эта функция SendMessage(hWndw,LVM_GETITEMPOSITION,1,pt);

Не знаю в чём дело:(
1 - хочется узнать что за окно такое "ProgMan" которому судя по функциям рабочий стол является внуком.
2 - почему проводник windows7 перезапускается?
3 - как правильно получить координаты иконы с рабочего стола.
4 - где можно почитать про подобные вещи.
кстати
Код
int nIconCount=SendMessage(hWndw,LVM_GETITEMCOUNT,0,0);

выполняется правильно.

Автор: smoke_man 12.10.2009, 00:20
Вот исходник с пояснениями для сохранения позиций ярлыков. 

Автор: Riddik 12.10.2009, 00:54
uxoos, какое тест-задание smile

smoke_man, благодарю! 
Там лезут в реестр и используют MFC.

Неужто без реестра не обойтись.
И все же, ведь должно ведь работать, из MSDN'а так вроде...
SendMessage(desc, LVM_GETITEMPOSITION, i , (LPARAM)&p);

Почему не присваивает координаты значка?

Автор: smoke_man 12.10.2009, 08:30
Реестр они используют для сохранения расположения ярлыков. С использованием выше приведнного исходника накидал пример, который  выводит координаты ярлыков.

Автор: Riddik 12.10.2009, 10:39
smoke_man, большое спасибо!

Автор: uxoos 12.10.2009, 21:14
Да. Наверно это правильно.. Вот содержательная часть исходника. Чтобы гугл нашёл и если файл удалят. Я просто так иногда ищу подобные решения и если, нахожу их в ссылках на удалённый файл исходника. А, ладно, не читайте это если не понравилось что прочитали. smile 
Код
#include <Windows.h>
#include <commctrl.h>
#include <iostream>


HWND FindListView() throw(...)
{
    HWND progman_wnd = 0;
    HWND desktopview_wnd = NULL;
    HWND listview_wnd = NULL;

    // First find the main window of program that houses the desktop.
    progman_wnd = FindWindowA(NULL, "Program Manager");
    if(progman_wnd == NULL) throw(GetLastError());

    // Then get the desktop window
    desktopview_wnd = FindWindowExA(progman_wnd, NULL, "SHELLDLL_DefView", NULL);
    if(desktopview_wnd == NULL) throw(GetLastError());

    // Finally get the handle to the listview on the desktop.
    // Thanks [email protected] for pointing out this works in NT 4 and not the way I did it originally.
    listview_wnd = FindWindowExA(desktopview_wnd, NULL,"SysListView32", NULL);
    if(listview_wnd == NULL) throw(GetLastError());

    return listview_wnd;
}

HANDLE FindExlorerProcess(HWND slave_wnd) throw(...)

    // Thanks to [email protected] who pointed me to GetWindowThreadProcessId(), that makes this function waaaaaaaaaaaaay shorter.
    HANDLE proc;
    DWORD explorer_pid;

    // Get the PID based on a HWND. This is the good stuff. You wouldn't believe the long and difficult function I had to write before I heard of this simple API call.
    GetWindowThreadProcessId(slave_wnd, &explorer_pid);
    // Get a process handle which we need for the shared memory functions.
    proc = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, explorer_pid);
    if(proc == NULL) throw(GetLastError());
    else return proc;
}

void* AllocMemInForeignProcess(HANDLE process, unsigned long size) throw(...)
{
    void *ptr = VirtualAllocEx(process, NULL, size, MEM_COMMIT, PAGE_READWRITE);
    if(ptr == NULL) throw(GetLastError());
    else return ptr;
}


void ReadFromForeignProcessMemory(HANDLE process, void* ptr, void* target, unsigned long size) throw(...)
{
    if(ReadProcessMemory(process, ptr, target, size, NULL) == 0) throw(GetLastError());
}

void FreeMemInForeignProcess(HANDLE process, void* ptr) throw(...)
{
    if(VirtualFreeEx(process, ptr, 0, MEM_RELEASE) == 0) throw(GetLastError());
}

int main()
{
    void* ipc_iconpos = 0;
    LRESULT msg_result = 0;
    HANDLE explorer = 0;
    POINT iconpos;
    HWND listview_wnd = FindListView();
    unsigned long iconcount = static_cast<unsigned long>(SendMessage(listview_wnd, LVM_GETITEMCOUNT, 0, 0));
    // Get the PID of the process that houses the listview, i.e.: Explorer.exe
    explorer = FindExlorerProcess(listview_wnd);
    // Here we allocate the shared memory buffers to use in our little IPC.
    ipc_iconpos = AllocMemInForeignProcess(explorer, sizeof(POINT));
    for(int i = 0; i < iconcount ; ++i)
    {
        msg_result = SendMessage(listview_wnd, LVM_GETITEMPOSITION, i, reinterpret_cast<LPARAM>(ipc_iconpos));
        ReadFromForeignProcessMemory(explorer, ipc_iconpos, &iconpos, sizeof(POINT));
        std::cout<<"x = "<<iconpos.x<<" y = "<<iconpos.y<<std::endl;
    }
    FreeMemInForeignProcess(explorer, ipc_iconpos);
    CloseHandle(explorer);
    system("PAUSE");
    return EXIT_SUCCESS;
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)