Obtaining Icon Positions

Obtaining the position of icons on your (WinNT-based) desktop

.

Environment: Windows XP Pro, Visual C++.NET 2002

I have a huge monitor at home, 22". And I also have an ADSL-connection. So, when I'm at work, I'd like to connect to my home PC using Remote Desktop and do some stuff remotely. However, for some reason, the computers I connect from to my own computer never have a monitor that's the same size as mine and, thus, never the same desktop resolution. Remote Desktop then just displays my home desktop at a lower resolution when connected.

Having aligned my icons around the edges of my desktop, this causes them to be 'reorganized' so they're all messed up. Now, this isn't a problem per se, but when I get home, the icons remain at their messed-up positions, requiring me to reposition them every time I connected with Remote Desktop. Which, in my case, is daily.

Time to fire up the old development tools and write a tool that finds out the position of each icon on my desktop and save it somewhere so they can be restored at their positions at the click of a button.

This has proven to be more difficult then it seemed. Below it a step-by-step walkthrough of what I did (roughly), what problems I encountered, and how I overcame the problems. All in all, this little project took two to three hours out of my life.

The first step in getting the positions of the icons is to be able to ask something for them. And whadya know? The desktop, as you see it, is just a big ListView. So, we can use the FindWindow() and FindWindowEx() APIs to get the handle of the ListView. First, we use FindWindow() to find the window with the title "Program Manager;" then, we use FindWindowEx() to find the child window (of the program manager) with the class name "SHELLDLL_DefView" (it doesn't have a window title). Then we use FindWindowEx() again to find the child window of the SHELLDLL_DefView, with the name "FolderView." This is the ListView. So, now we have a HWND to the ListView that shows you the icons.

Next up is to ask the ListView for the icons and their positions.

We can get the number of icons pretty simply. Just SendMessage() it the LVM_GETITEMCOUNT message and it will return you the number of icons. So far, so good. Now, we can get the position of each icon by using the message LVM_GETITEMPOSITION. We need to send this message for every icon on the desktop. The WPARAM of the message is the index (which icon do we want to query?) and the LPARAM is a pointer to a POINT structure, that will receive the X and Y positions.

I did all of this, but the POINT structure never got filled. A very strange problem, indeed. The function returns TRUE, indicating success, but I get no info. After some thinking about the problem, it occurred to me. I'm sending the pointer to a place in the memory of my process, to another process. That pointer is not valid because each process has its own memory space. In other words, the pointer I send to the ListView isn't valid in its address space. So, now I need to have a pointer that is valid in the process space of the ListView, but I need to read it as well. So it's gonna need to be valid in both processes. To do this, you need to create shared memory. This seemed horribly complex to me, it was late (2:00 AM), and I wanted this small tool finished before I could go to bed. So, why not do something completely different? Why not allocate memory in the address space of the ListView and read from that? I know how to do that.

Allocating memory in the process space of another process is very easy. Just use VirtualAllocEx(). And, reading from and writing and to it is easy, as well; we have ReadProcessMemory() and WriteProcessMemory() for that. The problem I faced, however, was getting the process handle to the process that is hosting the ListView. In this case, Windows Explorer.

So, how do we find the process handle of explorer? As it turns out, there's a very simple API call for this; it's simple because we already know the handle of a window that belongs to the process we need: GetWindowThreadProcessId(). With this API, we can get the PID of the process and then use OpenProcess() to get a handle to the process.

So, now we have a process handle, we have the window handle to the ListView and we can use VirtualAllocEx(), ReadProcessMemory(), WriteProcessMemory() and VirtualFeeEx() to deal with the out-of-process-pointer issue. Combine these things, and you can get the positions of each icon on your desktop.

One final note: Because I use VirtualAllocEx() and VirtualFreeEx(), this program only works in NT-based systems (Windows NT/2000/XP), which isn't a problem for me. If you want to make this work for Win9x-based systems, you can easily do so by altering two functions in VirtualMem.cpp; I kept them nicely abstracted.

Update Info

  • Rewrote the entire program to be totally independent of MFC.
  • Used the comments made by mr_williams@rave.ch and ef_ef_ef@yahoo.com to improve the program.

Downloads

Download demo project - 86 Kb
Download source - 52 Kb


Comments

  • Short review discloses the indeniable details about gucci and ways in which it can effect you.

    Posted by emeseesip on 05/07/2013 06:29am

    The Biggest And Most Complete nike Guide book You Ever Read Otherwise Your Money Back [url=http://www.guccija.biz/]グッチ 財布[/url] Wow, remarkable solution. Your organization got to check out nike today when it is still available for sale ! ! ! [url=http://www.guccija.biz/]グッチ 財布 メンズ[/url] gucci can help everybody by simply including several exceptional functions and functions. This is a unvaluable item for every supporter of nike. [url=http://www.guccija.biz/]グッチ トートバッグ[/url] Independent editorial displays 2 fresh stuff around adidas that none is mentioning. [url=http://www.chanelja.biz/]シャネル 財布[/url] The key reason why not a single person is dealing with adidas and the thing you ought to execute right now. [url=http://www.chanelja.biz/]シャネル チェーンウォレット[/url] Hot queries about adidas clarified and consequently the reasons why you really should read through each message within this documentation. [url=http://www.chanelja.biz/]chanel 財布[/url] Concepts of the nike available to make money from getting started today.[url=http://www.nikeja.biz/]ナイキスニーカー[/url] Specifically how to understand pretty much everything there is to learn relating to nike in Some easy steps.

    Reply
  • Unconventional site will give you the facts over nike which experts claim just some buyers know of.

    Posted by icoppyapedcap on 04/25/2013 05:11pm

    VhbFqaBsyQme [url=http://www.nikeyasuijp.com/]ナイキスニーカー[/url]MtzBnlKevCua [url=http://www.nikeyasuijp.com/nike-air-force1エアフォース1-c-14.html]nike air force[/url]NdvKyrJqjLtz [url=http://www.nikeyasuijp.com/nike-air-maxエアマックス-c-12.html]ナイキランニング[/url]ZhhCoxLfvWxr [url=http://www.nikeyasuijp.com/nike-air-jordanエア-ジョーダン-c-13.html]nike air jordan[/url]BmoZitJgwUaq

    Reply
  • Obtaining Icon Positions

    Posted by Legacy on 10/01/2002 12:00am

    Originally posted by: Michael Lynn

    Hi,

    You may wish to check out my follow up. I wrote mine using Visual C++ 6, no MFC required and I save to and restore from text files. I also have a version for Windows 9x.

    http://www.lynn3686.freeserve.co.uk/desktoprestore.html
    http://www.lynn3686.freeserve.co.uk/

    Cheers,
    Michael.

    Reply
  • faster way to get explorer process

    Posted by Legacy on 02/21/2002 12:00am

    Originally posted by: mr_williams

    theres a faster way to get the processid of the explorer process. since the "progman" window is in the same address space u can use GetWindowThreadProcessId to get PID.
    i can't talk C++ only asm, but im sure u get the point:

    .DATA

    szProgman db "progman",0

    .DATA?

    hDesk dd ?
    dwPID dd ?

    .CODE

    call FindWindow, offset szProgman, NULL
    mov hDesk, eax
    call GetWindowThreadProcessId, hDesk, offset dwPID

    afterwards u can use OpenProcess with the dwPID to open explorers address space...

    Reply
  • 2-3 hours with Jeffrey Richter's book

    Posted by Legacy on 12/18/2001 12:00am

    Originally posted by: Alex Farber

    It doesn't look as 2-3 hours project, but if you have "Programming Applications for Microsoft Windows", maybe...

    Reply
  • Waooo! Greate Idea!! But probleme to work on WinNT 4.0

    Posted by Legacy on 12/17/2001 12:00am

    Originally posted by: EF

    It's sound like a greate ID ...

    But the following line of code return NULL:

    hFolderView = ::FindWindowEx(hDesktopView, NULL, NULL, "FolderView");

    On NT 4.0 the listControl does not seems to be named "FolderView" or... I' don't know!!

    Any way ... Great Idea!

    Reply
  • For 9x Devs - An Example

    Posted by Legacy on 12/17/2001 12:00am

    Originally posted by: redllar

    Nice article :) I thought I'd add to it by indicating that
    
    memory-mapped files are a good way to "share" memory
    between processes on 9x boxes.

    Here's a quick example of a function related to the
    article, which removes the desktop icon's text, so that
    they're left with just the icons themselves:

    void HideDTopIconText()
    {
    HWND hWnd = FindDTopLView();
    if( hWnd ) {
    int nItems = ListView_GetItemCount(hWnd);
    if( nItems > 0 ) {
    char szText[40];
    HANDLE hFileMap =
    CreateFileMapping((HANDLE)0xFFFFFFFF, NULL,
    PAGE_READWRITE, 0, max(sizeof(szText), sizeof
    (LVITEM)), "MyMapping");
    if( hFileMap ) {
    LPVOID pFileMap = MapViewOfFile(hFileMap,
    FILE_MAP_WRITE, 0, 0, 0);
    if( pFileMap ) {
    for( int i = 0; i < nItems; i++ ) {
    LVITEM *plvItem = (LVITEM *)pFileMap;
    ZeroMemory(plvItem, sizeof(LVITEM));
    plvItem->mask = LVIF_TEXT;
    plvItem->iItem = i;
    plvItem->pszText = (char *)pFileMap;
    plvItem->cchTextMax = sizeof(szText);
    int nChars = SendMessage(hWnd, LVM_GETITEMTEXT,
    (WPARAM)i, (LPARAM)pFileMap);
    if( nChars ) {
    CopyMemory(szText, pFileMap, nChars+1);
    ZeroMemory(plvItem, sizeof(LVITEM));
    plvItem->mask = LVIF_TEXT;
    plvItem->iItem = i;
    SendMessage(hWnd, LVM_SETITEMTEXT, (WPARAM)i,
    (LPARAM)pFileMap);
    }
    }
    UnmapViewOfFile(pFileMap);
    }
    CloseHandle(hFileMap);
    }
    }
    }
    }

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • The explosion in mobile devices and applications has generated a great deal of interest in APIs. Today's businesses are under increased pressure to make it easy to build apps, supply tools to help developers work more quickly, and deploy operational analytics so they can track users, developers, application performance, and more. Apigee Edge provides comprehensive API delivery tools and both operational and business-level analytics in an integrated platform. It is available as on-premise software or through …

  • Live Event Date: September 10, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild". This loop of continuous delivery and continuous feedback is …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds