10

Does anybody know how to make a 'always-on-bottom'-windows, or a window pinned to the desktop? It should receive focus and mouseclicks, but should stay at the bottom of the Z-order. It would also be great if it could stay on the desktop even when user do a minimize all or show desktop operation.

Both delphi and c# solutions (or partial solutions/hints) would be great.

Tim Post
  • 33,371
  • 15
  • 110
  • 174
Vegar
  • 12,828
  • 16
  • 85
  • 151
  • If possible you should use something else but Delphi, because the interaction between the hidden application window and the main window will make stuff even more complicated. Most of this is private stuff in forms.pas, hard to change. – mghie Feb 09 '09 at 13:33
  • It can't be possible when Show Desktop is used. It can, however be when Minimize All is used - by setting the MinimizeBox property to false you would disable minimizing of the form. – configurator Feb 09 '09 at 14:07
  • 1
    Duplicate: http://stackoverflow.com/questions/365094/window-on-desktop – Jim McKeeth Feb 09 '09 at 17:06
  • @mghie: I cant see why Delphi should be avoided. The proposed solution work fine, and include only two lines of code. I vote your comment down by -1 :-) – Vegar Feb 09 '09 at 20:59
  • Anyway, I'm glad it works for you. Maybe you could add an answer with a short example of those two lines in context? – mghie Feb 09 '09 at 21:58
  • @mghie: We may have different goals. I want a gadget-like-non-rectangular-window, showing some information. For this kind of window, a taskbar-button is not wanted. But, as from delphi 2007, Application.MainFormOnTaskbar will solve both popupmenu and thumbnail. I don't know about WinSplit, though. – Vegar Feb 10 '09 at 19:58

3 Answers3

12

Warning It was suggested that you can accomplish this by calling SetParent and setting the window to be a child of the Desktop. If you do this, you cause the Win32 Window Manager to combine the input queue of the Desktop to your child window, this is a bad thing - Raymond Chen explains why.

Also, keep in mind that calling SetWindowPos with HWND_BOTTOM is incomplete. You need to do this whenever your window is changing zorder. Handle the WM_WINDOWPOSCHANGING event, look at SWP_NOZORDER for more info.

Maurice Flanagan
  • 5,179
  • 3
  • 30
  • 37
8

SetWindowPos can make windows AlwaysOnTop. Most likely it can give the opposite result. Try something along these lines:

[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,
   int Y, int cx, int cy, uint uFlags);


 public const uint SWP_NOSIZE          = 0x0001;
 public const uint SWP_NOMOVE          = 0x0002;
 public const uint SWP_NOACTIVATE      = 0x0010;
 public const int HWND_BOTTOM = 1;


SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);

Note:

  • Haven't tested this approach (for making windows always on bottom)
  • If it happens to work, then most likely the show desktop operation will hide the window. So maybe you should go even deeper into this 'nice' API.

EDIT: Done some searching along these lines to confirm whether it will do the trick and found something interesting - a duplicate.

Community
  • 1
  • 1
Anonymous
  • 18,162
  • 2
  • 41
  • 64
  • 1
    +1 for the link to the other SO question, it should contain everything to get the OP started. – mghie Feb 09 '09 at 13:31
4

Here is solution for ATL window. If you can apply to c#, it will help you.


BEGIN_MSG_MAP(...)
   ...
   MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWindowPosChanging)
   ...
END_MSG_MAP()

LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)

{

    if (_bStayOnBottom)
    {
        auto pwpos = (WINDOWPOS*)lParam;

        pwpos->hwndInsertAfter = HWND_BOTTOM;

        pwpos->flags &= (~SWP_NOZORDER);

    }
    return 0;
}
CharlesB
  • 86,532
  • 28
  • 194
  • 218