Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Win32 C API for redirecting minimize animation

I have seen RocketDock redirect the minimize animation in Vista so windows minimize to the dock, and am just curious how this was done. Is the actual minimize animation redirected to the dock, or is something like a hook to stop Windows from minimizing the window and RocketDock has a custom animation when the window is minimized?

like image 920
AniDev Avatar asked Feb 15 '11 00:02

AniDev


3 Answers

I am working on an open source multi-monitor taskbar project called "OpenMMT." I've recently discovered (through many headaches) how to accomplish this.

The following explanation assumes that you know how to go about using RegisterShellHookWindow.

On the window procedure that will receive the shell hooks, look for HSHELL_GETMINRECT.

Now, from here on out is where I had problems. According to MSDN, the lparam member passed contains a pointer to a "SHELLHOOK" object. Which is true, however, I could not get it to work for the simple fact that the "rc" member of that structure, is a RECT that differs from the actual RECT structure in the Windows header files. The RECT in the header files uses LONG for its members, were as on here, we want SHORT.

Anyways, here's a snippet on how I accomplished this.

Structures to define:

typedef struct {
  SHORT left;
  SHORT top;
  SHORT right;
  SHORT bottom;
} REALRECT, *LPREALRECT;

typedef struct {
  HWND hWnd; 
  REALRECT rc;
} DOCUMENT_ME_RIGHT_MICROSOFT, *LPDOCUMENT_ME_RIGHT_MICROSOFT;

Then on the Window Procedure:

case HSHELL_GETMINRECT:
{
  LPDOCUMENT_ME_RIGHT_MICROSOFT lpShellHook = (LPDOCUMENT_ME_RIGHT_MICROSOFT)lParam;
  // lpShellHook now contains all the info. If you want to change the location
  // of the animation, simply change the lpShellHook->rc members to point
  // to the right coordinates and then return TRUE;
  return TRUE;
}

When minimizing programs from my application I encountered some instances where the animation would default back to the original one. I resolved this by minimizing them like so:

void MinimizeApp(HWND hWnd) {
  SetForegroundWindow(hWnd);
  ShowWindowAsync(hWnd, SW_MINIMIZE);
}

If you want more info regarding my project or you just want to peek at the source, feel free to do so at https://github.com/Fafson/OpenMMT

like image 56
Fafson Avatar answered Nov 19 '22 02:11

Fafson


The ptMinPosition member of the WINDOWPLACEMENT structure specifies the coordinates of the window when it is minimized, so SetWindowPlacement function can be used to that effect. But some testing shows the window should not have a task bar button for that to work (i.e. no WS_EX_APPWINDOW).

I don't know how RocketDock works, but I guess this could be achieved by installing a global WH_CBT hook, and acting upon (setting the ex_style and then setting minimized coordinates) HCBT_MINMAX notification.

like image 21
Sertac Akyuz Avatar answered Nov 19 '22 04:11

Sertac Akyuz


You can use the AnimateWindow API function, and pass it e.g. AW_HOR_POSITIVE | AW_VER_POSITIVE to get a diagonal animation.

I'd start with a global hook catching WM_SYSCOMMAND/SC_MINIMIZE, and use AnimateWindow to target the top right corner.

If this doesn't provide the desired effect, the next step would be to use WM_PRINT/WM_PRINTCLIENT to get a copy of the window into a bitmap (I believe this is what AnimateWindow does internally), then hiding the window and doing my own animation.

like image 42
Erik Avatar answered Nov 19 '22 04:11

Erik