Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Iterate over open apps/documents 1

Status
Not open for further replies.

csteinhilber

Programmer
Aug 2, 2002
1,291
US
I'm trying to write an app that can take a snapshot at any given time and provide a list of documents (preferably using the Window Title text) I currently have open.

Part of the trick seems to be that some of the documents are going to be parent windows, and some are going to be in MDI applications. For those that are MDI, I'd like to get the text of the parent window as well, so I know what app is actually running the document.

ex:
May 01, 2009 9:15pm
- Photoshop - Image 1.psd
- Photoshop - Image 2.psd
- Firefox - CodeGear (Borland): Delphi Forum - Tek Tips
- Notepad - Client notes.txt


Anybody have any ideas?
Thanks in advance!
-Carl
 
Code:
procedure TForm1.Button1Click(Sender: TObject);
var
  Winaddr: HWND;
  WinNamea, ClassNamea: array[0..255] of char;
  ListItem: TListItem;
begin
  ListView1.Items.Clear;
  WinAddr := GetActiveWindow;
  repeat
    case RadioGroup1.ItemIndex of
      0: begin
           GetClassName(WinAddr, ClassNamea, 256);
           GetWindowText(WinAddr, WinNamea, 256);
           with ListView1 do
             begin
               ListItem := Items.Add;
               ListItem.Caption := IntToStr(WinAddr);
               ListItem.SubItems.Add(ClassNameA);
               ListItem.SubItems.Add(WinNamea);
             end;
         end;
      1: if IsWindowVisible(WinAddr) then
           begin
             GetClassName(WinAddr, ClassNamea, 256);
             GetWindowText(WinAddr, WinNamea, 256);
             with ListView1 do
                begin
                 ListItem := Items.Add;
                 ListItem.Caption := IntToStr(WinAddr);
                 ListItem.SubItems.Add(ClassNameA);
                 ListItem.SubItems.Add(WinNamea);
                end;
           end;
    end;
    WinAddr := GetNextWindow(WinAddr, GW_HWNDNEXT);
  until WinAddr = 0;
end;

This loads into a ListView of course. The RadioGroup determines whether the user wants to see all windows or just visible ones. The only thing not demonstrated is how to find the parent window. This will do it (0 means there isn't one).

Code:
if GetParent(starthandle) = 0 then // this is main window

With how the window browsing works, though, you'll just want to use this as a litmus test before you even show the list.

Measurement is not management.
 
Probably a bit above and beyond your question, but here's some more useful information. Here's how to find out the ProcessID (this is different than the process handle) and ThreadID from the Window Handle.

Code:
var
  WinAddr: HWND; // the window handle
  ThreadID, ProcessID: DWord;

ThreadID := GetWindowThreadProcessID(WinAddr, @processid);

Measurement is not management.
 
Thanks Glenn...
That works nicely for most apps, except the two that I really need ;-)
- Photoshop
and
- Dreamweaver

Dreamweaver might be a lost cause. I'd love to be able to get a list of all the files I have open... but since it's a custom IDE with a tabbed control for files, I might have to give up on that.

Photoshop, though, is more of a traditional MDI app. And the Window list code above, all I get is the text of the parent window title (ie - "Adobe Photoshop CS3 Extended") and nothing about the titles of the child windows (which, in the case of Photoshop, is simply the filename).

The above code also finds all of Photoshop's palette windows, which I would expect, but I can't figure out a way to filter them out based on any sort of attribute.
:-(
 
I'm not sure you're going to get exactly what you're looking for (I'm not even sure what the goal is for what you're doing). As far as Windows go, you can move down to the control level using code like what you were shown (which will show those tabbed controls) starting with GW_CHILD and the handle in question. The example was meant to iterate top-level window handles, and not anything else.

The problem is going to be translating that to "what files I have open" - the only thing I can think of is to look at the Window text you get for each item that appears. Of course, the question becomes whether you will get that or not. For example, I can load IE up and parse every single control it uses and even pick up website titles, but I can't pick up a lot, either.

I'm not sure if that helps, but hopefully it'll be a start.

Measurement is not management.
 
I work at an agency, and I find I'm really bad about keeping track of my time... even with time tracker utilities. So I'm trying to write an app that automatically tracks how long I spend in a given file so I can begin to build an initial picture of how I spent my day and what I was working on at any given point.

So having filenames is pretty essential, since tracking window text of "Photoshop" doesn't give me enough information (I could open 15 different Photoshop documents throughout the day, having to do with 9 different projects... so knowing that I was in Photoshop for 7 hours doesn't get me any closer to knowing that I worked on Project X for 2 hours, Project Y for 3 hours, etc).

I'm wondering if I'm going about this from the wrong angle, though. Is there perhaps a way to track file handles that Windows has open... and not have to deal with application processes? Just a collection of file handles at any particular time, regardless of which application may have them open?
 
Could you make your own application to open the photoshop files, timestamp the "open" state and the process spawned? If you always used your app to open them it could then compute the time diff between its timestamp and that of the last write to that file when you hit "calculate usage" at end of day.

So you open 3 files at * AM, it checks for a record for today for file A,B,C --creates as needed. If you close A with a save it is timestamped itself. A timer function in your opener app checks any of the files that it has "open" to see if they are locked, if not it calculates the diff between the open and the file timestamp, adds that to the time used field in the record for that file that day and marks it as closed.

What you end up with is a database of records of usage for files, with a new record for each file in a given day holding a field which has the total time for that day on that file. This makes for an easy query/report.

Personally I would make the database itself Access, but that is just a matter of taste really.

So far this assumes you only want to track time in files that you modify during the day. If you want to also notate files that were opened but not changed you may have some difficulty --unless you don't mind clicking them in the opener app (say another tab showing files already opened) and marking them closed manually.

YMMV
Scotto the Unwise
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top