Let me explain my question with an example. In my app, I need to provide a way to automatically close it from within "itself." (An example of such function is when an installer/updater of my app needs it to close before installing an update. Another example is when my app performs actions on schedule and needs to automatically close once it's done.)
I picture that in the simplest situation posting the WM_CLOSE message to the own window will accomplish this task, but there're the following cases that will not work with just that:
My app may be displaying an arbitrary number of child dialog windows.
My app may be displaying a common control window, such as Open File dialog:
or this one, but there could be others:
And lastly what could one do if the close button is not even available:
At the current point, I simply resort to terminating my process (either with the exit() method from within, or with TerminateProcess from outside.)
But I'm curious, if there's a more graceful way of closing my GUI app (from within)?
There is no single answer, it depends on your app's architecture and what it's doing. I don't quite understand why you would want to force close your application while it is in a common dialog, but if you do, then exit() is safe. In that case the process is actually shutdown from the operating system's perspective as opposed to a forced termination (TerminateProcess). In theory TerminateProcess might leave objects in the OS (DLL global data and such) in an inconsistent state, and exit() will be cleaner in that regard.
Generally though I'd avoid having visible UI that is up for the user just disappear and instead close the windows in reaction to some user choice.
But, exit() will work.
You can use exit() but a safer way to close the window would be:
SomewWindow->ShowWindow(SW_HIDE);
You could then destroy the window object or show the window later.
Related
So my question is targeted currently at Windows, but knowing the information for OSX would still be useful just to know later incase you have the answer for that.
How my program(s) function:
An initial EXE will run and create a window, this EXE will check and perform updates for the main program and take some user input. After the user input this EXE will start a new EXE (the main program), passing the details from the window so that this new EXE can claim the window and use it. The first program will terminate and the window should not close.
What I need help with:
I know how to create the window, and passing the required arguments through the exe is not something I know, but I dont think I will struggle to find and use that information. My main question is how do I stop the Window from closing when the first EXE terminates because likely the OS will automatically start cleaning things up.
Sidenotes:
Its not a super big deal, I can always start a new program and recreate a window, but I think it would just be a nice aesthetic touch to not have to close the window at all, staying alive and being handled by different programs(potentially at the same time).
I am under the impression that an EXE cannot update itself while running even if the needed files/information/compiled code are not being used so if this is wrong please let me know.
What you're trying to do cannot be done. You cannot transfer ownership of a window to a different thread. This can be inferred from the documentation of DestroyWindows:
A thread cannot use DestroyWindow to destroy a window created by a different thread.
Raymond Chen expands on this as he explains in his blog entry titled Thread affinity of user interface objects, part 1: Window handles:
The thread that creates a window is the one with which the window has an inseparable relationship. Informally, one says that the thread “owns” the window. Messages are dispatched to a window procedure only on the thread that owns it, and generally speaking, modifications to a window should be made only from the thread that owns it.
As far as the OS is concerned, nothing survives the end of a process. This is literally the end. If you need to keep a window around, you cannot terminate the process that owns its owning thread.
I've been working on an input event system.
I mapped all the keys on my own keyboard, the scancodes and so on, including both windows keys.
When I press them, the program successfully receives the distinct keydown events for them without any trouble.
When I release the keys, however, the Start Menu pops up, obscuring the program in windows mode, or even minimizing it in fullscreen.
So my problem lies in suppressing that.
Arma 2, a Military Simulator/Game allows commands to be mapped on those keys without any trouble.
Where do I have to catch that event?
Can I do it for my own window as long as it has focus?
Am I going to be stuck with a disabled win-key as long as it is running?
Or something else?
Googling it was mainly fruitless due to Windows key also referring to the product key, and when I did find something, it usually flat out disabled the whole button.
I just want to suppress the popup.
Edit:
I tried
case WM_SYSCOMMAND:
switch(wParam)
{
case SC_TASKLIST:
return 0;
default:
break;
}
But that gave me very odd results.
If I spammed the winkeys and only the winkeys, it seemed to work, as soon as I moved the mouse while doing so, it didn't, the start menu would pop up again.
Edit:
I also tried hooks, but on win7 they get removed if the callback takes too much time, which can happen when large data is loaded, so they suggest a dedicated thread for it, but I think that's overkill for just one key that needs handled.
I just want to know where the Start Menu gets called. My own program? The system?
This is so friggin annoying, I am contemplating trying to reach the people from Bohemia Interactive and ask them how they did it.
Just this one key, sheesh Microsoft...even with "Super key/superkey" search terms, I usually only get flat out disabling methods, from registry changes to third party background programs.
Bah!
This artcile was relating to C# but may point you in the right direction;
From MSDN:
A global hook monitors messages for all threads in the same desktop as
the calling thread. A thread-specific hook monitors messages for only
an individual thread. A global hook procedure can be called in the
context of any application in the same desktop as the calling thread,
so the procedure must be in a separate DLL module. A thread-specific
hook procedure is called only in the context of the associated thread.
This was the most helpful link in order to answer the question in the above article
The Raw Input API should solve your problem.
http://msdn.microsoft.com/en-us/library/ms645543.aspx
I want to perform some action when the user presses CTRL+S inside a modeless dialog.
Accelerators would be perfect for this, except that I don't have control over the thread's message loop (think plugin), so I can't call TranslateAccelerator.
A nested message loop is not an option because the main application does a lot of processing in between calls to PeekMessage.
Is there some way I can 'force' the existing message loop to handle my accelerator?
Is there any other way besides accelerators to catch CTRL+S?
I thought about using a Window hooks on WH_GETMESSAGE, which gets called before returning from GetMessage or PeekMessage. But I'm not sure what would happen after I successfully called TranslateAcellerator, I can't let the application know I handled it.
WH_MSGFILTER would require the app to implement a call to CallMsgFilter, which it doesn't from a quick glance with a debugger.
My last idea was subclassing the control which is what I'm trying to avoid. That would require some mechanism to signal the keypress event to the parent window, which I don't think is a great design. Also, if I add more controls I would have to subclass every single one.
Thanks for any hints.
This is a fairly infamous interop problem, it rears its ugly head also when using Winforms to implement UI in a native program. Microsoft's recommendation is a rough-and-tumble one: start your own thread to display the window so you can pump your own message loop. You'll need SetParent() to avoid Z-order problems. Scary stuff, do consider a modal dialog thrice before committing to this.
Can you use WM_GETDLGCODE? http://msdn.microsoft.com/en-us/library/ms645425(v=vs.85).aspx
I have a third party encryption library, which may create a MessageBox if key creation fails. The failure can be caused by bad random number generation or other rarities, and in most cases, trying again will result in success. My code will attempt key creation up to three times before deciding it failed.
Now, the issue is that the program may be used with automation. If a MessageBox is created during automation, it will block the process forever, because there's nobody to click the 'OK' button.
Does anyone know of a way to catch when this message box is created and automatically close it?
Anything is fair game, as long as it's not something that will make security suites angry. This means no hooking or code tunneling.
In summary, I need to catch when a MessageBox is created and close it. The MessageBox's creation is outside of my control. Modifying the code at runtime is not acceptable.
Also, I've noticed there are some other similar questions, but they don't have the same requirements.
EDIT: Additional note, I can find the message box via searching through all windows until I find one with a matching title and then send it a WM_CLOSE message, but I don't think this is a great solution. I also have no guarantee that the message box has been/will be displayed, or how long after my call it will be displayed. It could display instantly, it could display 1200 ms later, or it could not display at all.
Just before you begin the encryption process, install a WH_CBT hook, and in its callback watch for an nCode of HCBT_CREATEWND. If you get a matching class name ('#32770 (Dialog)' ?) and a matching title either return a nonzero value from the callback, or if that doesn't work post a WM_CLOSE (or a BM_CLICK to a relevant button if selecting an option is necessary). Uninstall the hook after the process for not messing with every possible dialog your application pops up.
That sounds like bad design on the part of that library. Generally any sort of utility library (like encryption) has no business invoking any kind of GUI (unless you explicitly ask it to).
Is there possibly some configuration or setting in this library that could disable its use of message boxes?
If not, I'd suggest that you might want to investigate using a different library. After all, if the designers of this library have already made this kind of poor design decision once, then there may be other unfortunate surprises lurking in there.
You can hope that it will be found by GetForegroundWindow, but this may catch other applications. The more brute force way is to iterate over all windows with EnumWindows looking for something that has a caption or text equal to this shown by the library.
I have once "remote controlled" an application by sending mouse click events to some controls. I guess you would have to do this in a separate thread that is watching for Events if a window is opened. Pretty ugly but working...
Create a new thread. If your function fails and a Message Box is opened, obtain a handle to the message box by looping through the windows (GetTopWindow, GetNextWindow) and comparing the window's process id to the one returned from GetCurrentProcessId().
Or, you can avoid all the hard work and just hook the MessageBox API with detours. It's not very hard, and if you don't want to pay for detours, you can do it manually.
Call VirtualProtect and set the memory protection at MessageBox at PAGE_EXECUTE_READWRITE
Create a naked function, and use it as a trampoline.
Create a function identical in parameters to MessageBox (this will be your hook)
Create a jump from MessageBox to your hook function.
I want to make a C++ button on Start>Run i.e but when I do it will not do signalled event?
Im sorry I have seen that you do not get the question.
Ok basically when you create a button with CreateWindowEx(); I want to do that but put on a different window with SetPArent which I have already done now the button does not work so I need my program to someone get when it is clicked from the Run window as example!
And yes you have it, but it's not making the button is the problem it's getting when it's clicked with my program since it does not belong to it anymore!
You need to apply the ancient but still-supported technique known in Windows as subclassing; it is well explained here (15-years-old article, but still quite valid;-). As this article puts it,
Subclassing is a technique that allows
an application to intercept messages
destined for another window. An
application can augment, monitor, or
modify the default behavior of a
window by intercepting messages meant
for another window.
You'll want "instance subclassing", since you're interested only in a single window (either your new button, or, the one you've SetParented your new button to); if you decide to subclass a window belonging to another process, you'll also need to use the injection techniques explained in the article, such as, injecting your DLL into system processes and watching over events with a WH_CBT hook, and the like. But I think you could keep the button in your own process even though you're SetParenting it to a window belonging to a different process, in which case you can do your instance subclassing entirely within your own process, which is much simpler if feasible.
"Superclassing" is an alternative to "subclassing", also explained in the article, but doesn't seem to offer that many advantages when compared to instance subclassing (though it may compared with global subclassing... but, that's not what you need here anyway).
You'll find other interesting articles on such topics here, here, and here (developing a big, rich C++ library for subclassing -- but, also showing a simpler approach based on hooks which you might prefer). Each article has a pretty difference stance and code examples, so I think that having many to look at may help you find the right mindset and code for your specific needs!
OK, I'll do my very best - as I understand you, you're trying to inject a button into some existing window. That meaning: Your tool creates a button in some window that does not belong to your application. Now, you want to be notified when that button is pressed. Am I correct so far?
To be notified about the button being pressed, you need to get the respective window message, which will only work if you also "inject" a different WndProc into the window. Actually I have no idea how that should work, but I faintly remember functions like GetWindowLong and SetWindowLong. Maybe they will help?
EDIT
I've searched MSDN a little: While you can get the address of a window's WndProc using GetWindowLong, you can not set the WndProc using SetWindowLong on Windows NT/2000/XP (and up I suppose). See here (MSDN).
So what you could do is install a global message hook that intercepts all window messages, filter those for the window you've injected the button into and then find your message. If you have trouble with this, however, I'm the wrong person to ask, because it's been years ago since I've done anything like that, but it would be stuff for a new question.
EDIT 2
Please see Alex Martinellis answer for how to define the hook. I think he's describing the technique I was referring to when I talked about defining global message hooks to intercept the window messages for the window you injected your button into.