|
Hi,
I am writing a small program that launches a third party application (a game). It extracts a few temporary, sensitive files to the hard disk, and makes sure that the user can't access them. This is the method it uses, and after trying most other avenues, I am pretty happy with it:
1) My program starts and extracts the files needed for the game to a temporary folder (and tells the system to delete these files if the system is rebooted)
2) My program then launches the game using ShellExecuteEx()
3) My program then finds the HWND handle to the game using FindWindow()
4) My program then monitors the game, checking to make sure it is the foreground window.
5) If the game (or one of its children - eg. an error box) is no longer the foreground window, my program deletes any sensitive files.
6) When the game is restored to the foreground window, my program re-extracts the necessary files. To ensure that the game doesn't try to access them before they are back on the disk, it takes these steps:
a) When the game is restored by the user, my program minimizes it again immediately.
b) My program will then show a dialog box saying "Restoring data, please wait..." with a progress bar.
c) Once the data is reloaded, my program restores the game window to the main window.
(If this sounds like an odd process, believe me that it is the best solution for what I am doing. Not necessarily the most ideal, but the best given the time I have and the little skill I have. )
So far, so good. However, because I am a relative novice, my code is far from perfect, and I am hoping someone here can show me a better way of writing the code that I am posting below, that deals with checking whether the game is in the foreground and with minimizing/restoring it accordingly. At the moment I am using a variable, int not_foreground, with GetForeGroundWindow() to check whether the game is the active window or not. However, although this works mostly, I have noticed that it doesn't work 100% of the time, which must be due to something seriously wobbly in my code (and is obviously not acceptable). Very occasionally (about 1 in 10) the game window isn't minimized by my program when the user tries to return to it, though I can't understand why. If someone could give me some pointers on how to improve this code, I would be really grateful.
Also, as I don't have access to my WinXP system for a few days and can only test this on WinMe, is there any reason the method I use for minimizing and restoring the game window wouldn't work on XP/2000 systems?
The code:
[code]
//ThirdPartyApp_hWnd = the application (game) that my program launched with ShellExecuteEx:
HWND ThirdPartyApp_hWnd = FindWindow(NULL,"Game window");
...
int not_foreground = 0;
//in main message loop:
//while the game window is active, test that it remains so:
if(not_foreground == 0)
{
if(ThirdPartyApp_hWnd != GetForegroundWindow())
{
//if the game window loses focus, make sure it's not just to a child window:
HWND checkwnd = GetForegroundWindow();
if(GetParent(checkwnd)!=ThirdPartyApp_hWnd)
{
/* My file deletion code would go here */
not_foreground = 1; //no longer foreground window
}
}
}
//while the game window is not active, check for it being restored:
if(not_foreground == 1) //not foreground
{
if(ThirdPartyApp_hWnd == GetForegroundWindow()) //game is back in foreground
{
//Minimize the program again:
SendMessage(ThirdPartyApp_hWnd,WM_SYSCOMMAND,SC_MINIMIZE,0);
/* My file restore code would go here */
Sleep(5000); //For testing purposes, just wait 5 secs
//And now restore the game as the active window:
SetWindowPos(ThirdPartyApp_hWnd,HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
ShowWindow(ThirdPartyApp_hWnd,SW_RESTORE);
not_foreground = 0; //we are foreground again, so don't do this again
}
}
//message processing:
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message == WM_QUIT)
{
//If user destroys the launcher, close the game too:
SendMessage(ThirdPartyApp_hWnd,WM_CLOSE,0,0);
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
[/code]
As you can see, I'm using the straight WinAPI SDK with _no_ MFC. Any suggestions for improvements or tips as to why my code might be failing on occasion would be greatly appreciated.
May thanks,
KB
|
|
|
|
|
You could try using GetAncestor with the GA_PARENT flag instead of GetParent() because it sometimes returns an owner handle instead of a parent one (which means your foreground check would be in the wrong loop). Also, since the foreground check is only ever a 1 or 0 you should use
if(not_foreground == 1)
{
//do stuff
}
else
{
//Do stuff
}
Personally I would use SetWindowsHookEx with WH_CALLWNDPROC and a CallWndProc() CALLBACK to process the messages sent to the app for the loss of keyboard focus, window activation etc. This is event driven, much more efficient than polling the foreground window every time.
|
|
|
|
|
Thanks for the reply, this is really useful. The only problem with using SetWindowsHookEx - wouldn't that have to go in a separate DLL seeing as I am trying to get the messages that are being passed to a different application?
Many thanks,
KB
|
|
|
|
|
Kayembi wrote:
The only problem with using SetWindowsHookEx - wouldn't that have to go in a separate DLL seeing as I am trying to get the messages that are being passed to a different application?
Yes.
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
Correct, I'm not sure as to why this is *necessary* particularly if your not sharing any data, but the CALLBACK will need to be in the dll, perhaps you could have an initialise function that sets up the hook in the dll?
|
|
|
|
|
Dangleberry wrote:
I'm not sure as to why this is *necessary* particularly if your not sharing any data
The hook function is called in the context of the process that causes the callback, not the one that installs the hook. This means that the function must be loaded into the other process' address space. The only way this can happen is if it's in a DLL - an EXE cannot be loaded into another process' address space.
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
Gotcha Ryan, it makes a lot more sense now, thanks for that.
|
|
|
|
|
Thanks. Is there another way of doing this that is not so intensive as keep checking GetForegroundWindow()? Or do I definitely have to take the Windows hook DLL route?
Many thanks,
KB
|
|
|
|
|
Kayembi wrote:
Is there another way of doing this that is not so intensive as keep checking GetForegroundWindow()? Or do I definitely have to take the Windows hook DLL route?
A hook would probably be the best way to do it. You could do what you are doing - just don't do it constantly - wait for 10ms or so between checks. But I would recommend using a hook.
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
Hi !
I have an enumerated type with for instance 8 enumerations.
I would like to do a for() loop to go through each of the enumerations.
Is there a way to do it easily in C++, or do I have to use a for(int i=... ;... ;...) and cast the int into the enumerated type ?
Thanks !
Jerome
|
|
|
|
|
|
Jerome Conus wrote:
I would like to do a for() loop to go through each of the enumerations.
Unfortunately, a for loop like
enum day {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
for ( day d = Sun; d <= Sat; d++)
...
will not work as you can't add 1 to d . Have you looked at Neville's suggestion.
|
|
|
|
|
I'm currently working on a videosurveillance software.
I have to display, as fast as possible, sequences of bitmaps, with
streching possibility.
I'm using VisualC++ 6.0, and I'm looking for someone who tried
different ways to display such images :
- drawdibdraw family functions
- strechdibits functions
- opengl texture mapping
- directx
- ... others ?
My goal is to find the FASTEST way to do it, whatever method.
Thanks
Mickey
|
|
|
|
|
Anyone knows how to work with 24bit pictures?
For negative it's not a problem, I just subtract every RGB value from 0xFF and it will be fine. But let's say we want to do a gray calculation like so: (3*red + 4*green + 2*blue)/9 for each RGB pixel. Since I have to use 8bytes in calculations, I get in 2pixels and 2 extra bytes which will just be there.
mm0: RR GG BB RR GG BB RR GG
and the next sequance will be:
mm0: BB RR GG BB RR GG BB RR
You see my problem?
How can I still use MMX to do this in 24bit pics?
thanks
|
|
|
|
|
Hi I am using a drag and drop to install a license file. How can I take the dropped file and save it to the install directory of the software?
I used an environmental variable to get the directory path where the file needs to be saved eg:
char *ptr;
ptr = getenv("LM_LICENSE_FILE");
I can do it using dialogs, but I need an alternative way, please help urgently!!!
|
|
|
|
|
Hi, how to do it properly?
I tried following:
TCHAR tch[20];
CString str;
.....
str = tch;
but Have an error, do not what kind of, know that because of the assignment.
Thanx.
|
|
|
|
|
Exceter wrote:
TCHAR tch[20];
CString str;
str = tch;
I just tried the code you posted and it works just fine...
The error must be something other in your code. Can you perhaps post the compiler/linker output?
-Dominik
_outp(0x64, 0xAD);
and
__asm mov al, 0xAD __asm out 0x64, al
do the same... but what do they do??
|
|
|
|
|
Yes, it worked fine for me too, at least for last 2 months.
but yesterday it stopped working. I checked that in DEBUG.
Unbelievable, now it is working, I changed nothing in the code, NOTHING,
it works
What is going on!!!
|
|
|
|
|
Exceter wrote:
I changed nothing in the code, NOTHING,
Ha,Ha.
I've had my share of random compiler errors in my early programming years as well.
But as I later find out, 9/10 times it was my fault, or there was an explanation (however obscure it may be).
"..Even my comments have bugs!"
Inspired by Toni78
|
|
|
|
|
But 1/10 errors of your code was because of the compiler.
but as I said, my program was working, and I got that error.
and later, it started working again. I do not think that was my fault.
thatnx.
|
|
|
|
|
But 1/10 errors of your code was because of the compiler.
but as I said, my program was working, and I got that error.
and later, it started working again. I do not think that was my fault.
thanx.
|
|
|
|
|
Hello, what is the correct way to enumerate MCI devices?
I've found the following ways:
1) In System.ini, the [mci] key
2) In registry the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\MediaResources\mci key
3) I'm not sure, but can one use the wDeviceID like an index?
Which is the correct way? Or even another way to do it? Do you know a sample?
-Dominik
_outp(0x64, 0xAD);
and
__asm mov al, 0xAD __asm out 0x64, al
do the same... but what do they do??
|
|
|
|
|
Hi!
I have two ATL objects, A and B. object A can be create from a method of object B. the user of this COM, should not directly create A in its code, but get one from object B.
I don't know how to stop the user from creating A directly.
Any idea?
|
|
|
|
|
1. Don't supply a coclass for A in the IDL
2. Remove A from your object map in the main CPP file for the project
However, you will need to make sure that the interfaces that object A provides are declared in the library block of your IDL file, or it won't 'publish' the interfaces in the TLB/DLL.
Steve S
|
|
|
|
|
Hi,
I have a SDI application and dont want to show it on the task bar. What is the best way in doing this?
|
|
|
|
|