![]() |
![]() |
|||||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
|
Q: Minimize all open applicationsAnswer:Windows contains a system wide hotkey that allows the user to minimize all programs with one keystroke. The hotkey is the windows key plus M. One way to minimize all programs from code is to artificially emulate this hotkey. You could accomplish this by broadcasting a WM_HOTKEY message. However, I decided to seek a different approach for several reasons. For starters, the hotkey might vary from language to language, and it may be customizable by the user. Another reason to avoid the WINDOWS + M keystroke is that some machines don't have that wonderful windows key on the keyboard. Does the operating system still create a system wide hotkey even if the key isn't present? Who knows. Not to mention the fact that the WM_HOTKEY approach probably won't work on windows NT 3.5. Lastly, who knows how long the WINDOWS + M hotkey will be around. If the hotkey ever goes away, your code would malfunction. I decided to implement a hard-core technique using plain API calls. The process is broken into two steps. The first step is to tell windows to enumerate the windows on the desktop. The second step is to write the enumeration callback and design it to minimize each program. Step 1: Enumerating the desktop windows.The code for the enumeration step is shown below. The EnumWindows API function allows us to enumerate the windows on the desktop. EnumWindows takes a function as an argument. The operating system will call the function that you pass to EnumWindows once for each window on desktop. The EnumWindows statement does not return until the callback has executed for each window. void __fastcall TForm1::Button1Click(TObject *Sender) { // determine if minimization animation was originally on ANIMATIONINFO info; info.cbSize = sizeof(info); SystemParametersInfo(SPI_GETANIMATION,sizeof(info),&info,0); bool bAnimationWasOn = info.iMinAnimate; // if animation was on, then turn it off to speed things up if(bAnimationWasOn) { info.iMinAnimate = false; SystemParametersInfo(SPI_SETANIMATION, sizeof(info), &info, 0); } // disable painting of the desktop until we are finished LockWindowUpdate(GetDesktopWindow()); // enumerate the desktop windows EnumWindows((WNDENUMPROC)MinimizeAllWindows, 0); // enable desktop painting LockWindowUpdate(NULL); // turn the animation back on if it was originally on if(bAnimationWasOn) { info.iMinAnimate = true; SystemParametersInfo(SPI_SETANIMATION, sizeof(info), &info,0); } }Many users configure their system to animate the frame of a window when it minimizes. This animation can bog down the system when the code minimizes several windows. The code segment above deactivates the animation before EnumWindows executes. The animization setting is restored after all of the windows have been minimized to the taskbar. The desktop will repaint itself after each window minimizes to the taskbar. This can cause a lot of flashing. To reduce the amount of flashing, the code uses LockWindowUpdate to prevent the desktop from repainting. Once all of the programs have been minimized, the desktop is allowed to paint itself again. Step 2: Minimizing each windowThe callback function is shown below. This function is responsible for minimizing each program. You can minimize a program by calling the ShowWindow API function and passing it the SW_MINIMIZE parameter. Notice that the callback will only call ShowWindow if the window is not owned by another window and if the window is currently visible. Checking for ownership ensures that we don't minimize dialog boxes and tool windows. These windows don't minimize to the taskbar, they minimize to the desktop. Restoring these windows can be a pain. Windows will automatically hide owned windows when we minimize their owner, so it's best to leave owned windows alone. We must also be careful not to minimize a hidden window. Minimizing a hidden window makes it visible. Since there is no way for the user to re-hide the window, minimizing a hidden window can royally screw up the system (remove the IsWindowVisible check to see what I mean). BOOL CALLBACK MinimizeAllWindows(HWND hwnd,LPARAM lParam) { // determine if the window is owned by anyone HWND hParent = GetWindow(hwnd, GW_OWNER); // if the window is ownerless, and if it is visible, // then minimize it to the desktop if((hParent == NULL) && IsWindowVisible(hwnd)) ShowWindow(hwnd, SW_MINIMIZE); // return true to continue the enumeration return TRUE; } Note: Since the EnumWindows call references the MinimizeAllWindows callback function, you should insert the body of the callback function above EnumWindows statement to avoid a compiler error. Alternatively, you could add a protoype for the callback function at the top of the source file or in a header file. Note: Notice that the callback function is not a member of any class. It just hangs out in space all by itself. The callback function cannot be a regular method of a class because the function is being called by Windows. Remember that all instances of a C++ class share the same code. Objects contain unique data, but the functions are shared across all objects. To identify which object is being acted on by a member function, C++ passes a hidden this pointer to the member function. You can see the this pointer if you view the assembly code of a function call. Unfortunately, Windows has no concept of this pointers. Windows will execute the callback function like it is a regular C style function that uses the __stdcall calling convention. It will not pass a parameter where the this pointer would normally go. You could make the callback function a static method of a class, since static methods don't take a this pointer. But why bother. The function works fine on its own. | ||||||
All rights reserved. |