Log in

View Full Version : monitoring an app for minimized/maximized events


Doom9
31st January 2006, 12:46
I've been asked if it were possible to write a small app (something that runs hidde, no window and no output at all), which monitors a GUI app, and when the app is being brought to the screen (from minimized state), it should bring another app to the screen as well. And then probably the reverse.. if one is minimized, the other should also be minimized. I suspect it's doable but I have no clue as to where to start looking... any ideas?

Inventive Software
31st January 2006, 13:47
I don't think such an app exists. The only way I can see something like that working is if the app you are trying to monitor sends a signal to the monitoring program when it is maximised or minimised. For that to work, the app needs to be modified slightly, and the monitoring program tailored for that program.

stax76
31st January 2006, 14:31
Maybe advanced stuff like hooks are gonna be needed. If you can't get a solution in the platform sdk docs or here maybe you've more luck in the Win32 group.

comp.os.ms-windows.programmer.win32

Ebobtron
31st January 2006, 15:27
I believe that the application that you what to track has to issues the command to close the other window.

At least I think that is the easiest way.

Let us say I want FilmCutter to minimize QuEnc, which FilmCutter has launched.

FilmCutter could "EnumWindows()" looking for QuEnc. Once I have identified QuEnc's handle I think I can send it a message to min or restore. There is other stuff to do with that "EnumWindows()", looks like a pain.

I see reference in the sdk all the time about sending windows in other aps messages or some remark like “this can not be sent to a window in another process” or something like that.

Hope this helps.

Doom9
31st January 2006, 18:10
Once I have identified QuEnc's handle I think I can send it a message to min or restore. But that's just one part of the equation. I also need to monitor an app I'm starting for minimized/maximized events.

Ebobtron
31st January 2006, 19:32
There is this in the SDK:
WinEventProc Callback Function

If you look at the event constants:
EVENT_SYSTEM_MINIMIZEEND

If you wish to minimize all open windows. Explorer has a command "Show Desktop" (right clicking the task bar), which I believe hides them and "Show Open Windows" (right clicking the task bar), shows then again. Any pior minimized window stays that way.

If you only wish to track a known group of applications, then this little aplication will need to know which they are.

I've been asked if it were possible to write a small app
Possible? Simple answer, Yes. I doubt writting it would be very simple, not for me at least.

Amnon82
5th February 2006, 12:17
@Doom9: As Ebobtron told you already. It is possible to write your needed app. The only thing I or he must know is should it maximize all running minimized tasks or only a few programs you use most. If the last one we need the titles of the windows to search for it (for example 'foobar2000 v.0.8.3'). But there is also a way to write it for only a few programs using a ini where the titles are stored. So you have three options now:

#1 for all minimized programs
#2 for a few programs (fixed)
#3 for a few programs (flexible)

If you want it can also track reverse ...

Write a pm if you don't want to post it public.

stax76
5th February 2006, 12:34
@Ebobtron

Never heard of WinEvents (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msaa/msaaccgd_3mgj.asp), it appears to be thing we was looking for.

Doom9
5th February 2006, 15:10
well.. if you want to take a bit at it, here's the scenario:
Our custom app starts app A and app B. It registers a callback that catches the minimized event of app A and minimizes app B upon reception of such an event.
When it catches an "app A maximized" event, it maximizes app B.

Amnon82
5th February 2006, 15:58
So you go for #2. In that case I need the window titles of both apps. Or I do #3 and you can write the titles into the ini.

Doom9
5th February 2006, 16:18
I don't know these titles by heart.. but iirc they can change (version number in the title).

Amnon82
5th February 2006, 16:52
Here is some Delphi code:
function FindWindowByTitle(WindowTitle: string): Hwnd;
var
NextHandle: Hwnd;
NextTitle: array[0..260] of char;
begin
// Get the first window
NextHandle := GetWindow(Application.Handle, GW_HWNDFIRST);
while NextHandle > 0 do
begin
// retrieve its text
GetWindowText(NextHandle, NextTitle, 255);
if Pos(WindowTitle, StrPas(NextTitle)) <> 0 then
begin
Result := NextHandle;
Exit;
end
else
// Get the next window
NextHandle := GetWindow(NextHandle, GW_HWNDNEXT);
end;
Result := 0;
end;

And here the code to click the 'Encode'-Button in any CCE to fix the 'Encode'-Bug in some CCE 2.70 versions:
procedure TForm1.Timer1Timer(Sender: TObject);
var
wnd2: hWnd;
pfad:string;
begin
timer1.enabled:=false;
Pfad := ExtractFilePath(ParamStr(0)) ;
wnd2 := FindWindowByTitle('.ecl');
wnd2 := FindWindowEx(wnd2, 0, 'Button', 'Encode');

if wnd2 <> 0 then
begin
SendMessage(wnd2,BM_CLICK,0,0);
Application.terminate;
end;

end;

So I only search for '.ecl'. The CCE Version changes. Some user don't have the same version I'm running, but '.ecl' is still in the title. So I don't see a problem to do your little app.

I think the best is we go for #3 ...

First version:

http://img153.imageshack.us/img153/7250/mima019sz.png

MiMa v.01 (http://scifi.pages.at/amsoft/files/MiMa_01.7z) - Mirror (http://www.megaupload.com/?d=W57N4XBB)

Second version:

http://img152.imageshack.us/img152/3407/mima026wz.png

Changes:

* INI added
* all apps in the INI do the same as the master app
* Only the states minimized|maximized

ToDo:

* Make all apps master apps
* Start all apps in the INI with start values form the INI
* Start MiMa minimized
* find a way to do normalize
* find time to code

MiMa v.02 (http://scifi.pages.at/amsoft/files/MiMa_02.7z) - Mirror (http://www.megaupload.com/?d=S7GE9VK6) - Delphi source (http://www.megaupload.com/?d=I1GG1KVF)

tateu
8th February 2006, 12:04
WinEvents looks similar to something I have played around with before: SetWindowsHookEx (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/usinghooks.asp). The hook procedure needs to be in a separate dll and you call SetWindowsHookEx with WH_CBT, CBTProc and the dwThreadID of the program you want to monitor. The dll will then get HCBT_MINMAX messages whenever the app is minimized, maximized, restored, etc. I then usually send messages back to my main app with PostMessage to let it know which event has occurred.

Doom9
15th February 2006, 11:04
@Amnon82: I'm not familiar with delphi but it looks to me as if you're using timers, then get the handle to the desired window(s), check their status and do the minimize/maximize blues depending on the state and configuration. Polling is a rather ineffective way though, wouldn't you agree?

tateu
15th February 2006, 11:47
I played around with this a little. I wrote a dll the gets called by the MainApp. The MainApp launches MasterApp and SlaveApp and does an enum window search based on dwThreadId to get an HWND to each of those apps.

The MainApp then calls SetMsghook from the dll, passing in it's own HWND and the HWND's of the MasterApp and SlaveApp. The dll calls SetWindowsHookEx to hook into the MasterApp's CBTProc. Whenever the MasterApp gets minimized, etc., the dll recognizes an HCBT_MINMAX message and can do...something. The idea I had was to use the HWND of the SlaveApp and have the dll send it a min/max message via PostMessage.

The PostMessage part is not working. The dll receives the HWND's from the MainApp when it is initialized but somehow loses them by the time a min/max event takes place. Right now, I just have the dll poping up a messagebox showing that it does receive the min/max notifications.

Here's the dll and a quick sample MFC app showing how it is supposed to be used. Maybe it will be of some use to you. The code is C++.

SetEventHook_Test (http://www.tateu.net/software/dl.php?f=SetEventHook_Test)

Amnon82
16th February 2006, 21:53
@Doom9. It was only a try. I didn't have/had the time to do it professional. Still don't have the time to come up with something new.

Title string|Starthandle value|?Master app?

I used a timer to search for the title string. After that I check the status of the window. If it changes I do the same with all other windows in the list.

Normaly I wanted to do the same to all listed apps, but it won't work as I planed. I'll ask in a delphi board (http://www.delphipraxis.net/topic75595_minimierenmaximieren+von+mehreren+programmen.html) if somebody has a better idea for this.

@tateu: I took a short look on your sources and also tried your sample app. It doesn't work on my german xp sp2. But it is good that you worte the dll.

Darksoul71
17th February 2006, 21:39
@all:
Has someone thought about AutoIt ?
AutoIt is perfectly for monitoring Window Events and you can run it "hidden" (= without trayicon).

Here´s some sample code:

Opt("TrayIconHide", 1)

Func WinCheck ()
; If MainWindow minimized and "OtherWindow" not minimized, minimize it
If BitAnd(WinGetState("MainWindow", ""), 16) And Not BitAnd(WinGetState("OtherWindow", ""),16) Then WinSetState ( "OtherWindow", "", @SW_MINIMIZE )

; If MainWindow restored and "OtherWindow" stil minimized, restore it
If BitAnd(WinGetState("MainWindow", ""), 2) And Not BitAnd(WinGetState("OtherWindow", ""),2) Then WinSetState ( "OtherWindow", "", @SW_SHOW )
EndFunc


AdlibEnable("WinCheck")

While 1
Sleep(1000)
WEnd


This is only an example and not tested but at work I have a pretty similiar script running in the back which monitors for error messages, captures the error message, saves the context into a text file and closes the error message.

With some testing and may be adjusting the BitAnd Settings and or WinStates this should work fine.

AutoIt is very handy for this kind of things !

@doom9:
If you need help just drop me a PM and we can discuss the details. I´m pretty skilled with AutoIt and could code a small "Hide you, hide me" app with only a few kB in size.

-D$

Amnon82
19th February 2006, 12:04
@Darksoul71: AutoIt will do it. I'm not so skilled with it. I think it is best for Doom9s problem ;)

Darksoul71
19th February 2006, 13:26
@Amnon82:
I hope Doom9 agrees with you. AutoIt does also "only" polling but who cares if the additional cpu load is below 0.2% :)