Link to home
Start Free TrialLog in
Avatar of GPaterson
GPaterson

asked on

Setting the window Z Order

Okay, an interesting one here. I need to set a toolbar application to be a topmost window. HOWEVER! I need to start menu/taskbar to stay absolutely top most. Is there any way to set a window to be always second topmost so that it remains above all other windows apart from the taskbar/startmenu.

I've tried playing with SetWindowPos and HWND_TOPMOST e.t.c. including getting a handle for the taskbar using FindWindow(_T("Shell_TrayWnd"), NULL); and then setting the taskbar to be topmost immediately after setting my toolbar to topmost.

I've also tried playing with WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED but to no avail.

If anyone knows how to do this I'd appreciate your help.

Thanks
ASKER CERTIFIED SOLUTION
Avatar of Axter
Axter
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I'm not sure if I fully understand the question, but if you have two windows (taskbar_hWnd and Second_hWnd), then you can do the following to set the second window as the second topmost.

::SetWindowPos( Second_hWnd, GetDesktopWindow() , 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
::SetWindowPos( taskbar_hWnd , Second_hWnd, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

Or -------

::SetWindowPos( Second_hWnd, HWND_TOPMOST, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
::SetWindowPos( taskbar_hWnd , Second_hWnd, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
Avatar of tinchos
tinchos

No comment has been added lately, so it's time to clean up this TA.
I will leave the following recommendation for this question in the Cleanup topic area:

Accept: Axter {http:#10190259}

Please leave any comments here within the next four days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Tinchos
EE Cleanup Volunteer
Avatar of GPaterson

ASKER

Neither of the solutions provided worked.
If the solution didn't work, you should have provided some feedback so that we could further assist you.

How did the solution not work?

And can you provide the code you use to implement the solution?
Hi,
I guess it's a bit late for any of you to answer now anyway, the code is as follows:


BOOL ScreenResX::SetOptions(DWORD dwOptions)
{
      HWND hWndRB = GetDlgItem(m_hWnd, ID_REBAR);
      RECT rcWindow, rcDesktop;
      UINT nWidthBar, nHeightBar;

      GetWindowRect(m_hWnd,&rcWindow);

      nWidthBar = rcWindow.right - rcWindow.left;
      nHeightBar = rcWindow.bottom - rcWindow.top;

      SystemParametersInfo(SPI_GETWORKAREA,0,&rcDesktop,0);

      // Readjust our desktop area if Always on Top
      if(m_dwOptions & SRX_SET_ALWAYSONTOP)
      {
            switch(ISDOCKED(m_dwOptions))
            {            
            case SRX_DOCK_TOP|SRX_DOCK_HORZ:
                  {
                        rcDesktop.top -= nHeightBar;
                  }
                  break;

            case SRX_DOCK_LEFT|SRX_DOCK_VERT:
                  {
                        rcDesktop.left -= nWidthBar;
                  }
                  break;

            case SRX_DOCK_RIGHT|SRX_DOCK_VERT:
                  {
                        rcDesktop.right += nWidthBar;
                  }
                  break;

            case SRX_DOCK_BOTTOM|SRX_DOCK_HORZ:
                  {
                        rcDesktop.bottom += nHeightBar;
                  }
                  break;

            default:
                  break;
            }
      }

      // If our new setting does not have Always on Top
      // Or if we have undocked a bar which did have always on top.
      // Reset out desktop area
      if(~dwOptions & SRX_SET_ALWAYSONTOP || ((!ISDOCKED(dwOptions)) && m_dwOptions & SRX_SET_ALWAYSONTOP))
      {
            SystemParametersInfo(SPI_SETWORKAREA,0,      &rcDesktop,SPIF_SENDCHANGE);
            EnumWindows(EnumWindowsProc,(LPARAM)&rcDesktop);
      }
      

      // If auto hide is enabled, disable and place bar back on screen.
      if(m_dwOptions & SRX_SET_INACTIVEHIDE)
      {
            // Disable mouse tracking if it is on
            TRACKMOUSEEVENT tme;
            
            tme.cbSize = sizeof(TRACKMOUSEEVENT);
            tme.dwFlags = TME_LEAVE|TME_CANCEL;
            tme.hwndTrack = m_hWnd;
            tme.dwHoverTime = 0;

            CustomTrackMouseEvent(&tme);

            // Unhide the bar if hidden
            switch(ISHIDDEN(m_dwOptions))
            {
                  case SRX_SET_HIDDEN_TOP:
                  {
                        SetWindowPos(m_hWnd,0,rcWindow.left,rcDesktop.top,0,0,SWP_NOSIZE|SWP_NOZORDER);
                        m_dwOptions &= ~SRX_SET_HIDDEN_TOP;
                  }
                  break;

                  case SRX_SET_HIDDEN_LEFT:
                  {
                        SetWindowPos(m_hWnd,0,rcDesktop.left,rcWindow.top,0,0,SWP_NOSIZE|SWP_NOZORDER);
                        m_dwOptions &= ~SRX_SET_HIDDEN_LEFT;
                  }
                  break;

                  case SRX_SET_HIDDEN_RIGHT:
                  {
                        SetWindowPos(m_hWnd,0,rcDesktop.right-nWidthBar,rcWindow.top,0,0,SWP_NOSIZE|SWP_NOZORDER);
                        m_dwOptions &= ~SRX_SET_HIDDEN_RIGHT;
                  }
                  break;

                  case SRX_SET_HIDDEN_BOTTOM:
                  {
                        SetWindowPos(m_hWnd,0,rcWindow.left,rcDesktop.bottom-nHeightBar,0,0,SWP_NOSIZE|SWP_NOZORDER);
                        m_dwOptions &= ~SRX_SET_HIDDEN_BOTTOM;
                  }
                  break;

                  default:
                        break;
            }
      }

      

      // Undocking
      if((~dwOptions & SRX_SET_DOCKING) && (m_dwOptions & SRX_SET_DOCKING))
      {
            // Undock m_dwOptions also or else everything else will run
            // Undock here
            SetWindowPos(m_hWnd,0,100,100,0,0,SWP_NOSIZE|SWP_NOZORDER);

            // Undock
            UNDOCK(m_dwOptions);
      }


      // Apply new settings
      // Show title is setting enabled and not docked, otherwise hide
      if(dwOptions & SRX_SET_NOTITLE || ISDOCKED(m_dwOptions))
      {
            ShowTitle(m_hWnd,FALSE);
            FitWindowToBar(m_hWnd);
      }
      else
      {
            ShowTitle(m_hWnd,TRUE);
            FitWindowToBar(m_hWnd);
      }
      
      // If bar is docked and new vertical state is set, change this to a pending state
      // SRX_STATE_VERTICAL
      if((dwOptions&SRX_SET_VERTICAL) && (m_dwOptions&SRX_DOCK_HORZ))
      {
            dwOptions &= ~SRX_SET_VERTICAL;
            dwOptions |= SRX_STATE_VERTICAL;
      }

      if((~m_dwOptions&SRX_SET_VERTICAL) && (m_dwOptions&SRX_DOCK_VERT))
      {
            dwOptions |= SRX_SET_VERTICAL;
            dwOptions &= ~SRX_STATE_VERTICAL;
      }

      // Set our new options to member variable
      m_dwOptions = (m_dwOptions & 0x7F000000L)|dwOptions;

      // Create a rebar
      BarIsVertical(hWndRB,(m_dwOptions&SRX_SET_VERTICAL)?TRUE:FALSE, TRUE);

      // Fit our window to our bar
      FitWindowToBar(m_hWnd);

      
      RECT rcNewWnd;
      GetWindowRect(m_hWnd,&rcNewWnd);


      // Reposition the bar
      if(ISDOCKED(m_dwOptions))
      {
            switch(ISDOCKED(m_dwOptions))
            {            
            case SRX_DOCK_TOP|SRX_DOCK_HORZ:
                  {
                        SetWindowPos(m_hWnd,0,rcDesktop.left,rcDesktop.top,0,0,SWP_NOSIZE|SWP_NOZORDER);
                  }
                  break;

            case SRX_DOCK_LEFT|SRX_DOCK_VERT:
                  {
                        SetWindowPos(m_hWnd,0,rcDesktop.left,rcDesktop.top,0,0,SWP_NOSIZE|SWP_NOZORDER);
                  }
                  break;

            case SRX_DOCK_RIGHT|SRX_DOCK_VERT:
                  {
                        SetWindowPos(m_hWnd,0,rcDesktop.right - (rcNewWnd.right-rcNewWnd.left),rcDesktop.top,0,0,SWP_NOSIZE|SWP_NOZORDER);
                  }
                  break;

            case SRX_DOCK_BOTTOM|SRX_DOCK_HORZ:
                  {
                        SetWindowPos(m_hWnd,0,rcDesktop.left,rcDesktop.bottom - (rcNewWnd.bottom-rcNewWnd.top),0,0,SWP_NOSIZE|SWP_NOZORDER);
                  }
                  break;

            default:
                  break;
            }
      }


      // Reset our desktop area if always on top selected
      if(m_dwOptions & SRX_SET_ALWAYSONTOP)
      {
            switch(ISDOCKED(m_dwOptions))
            {            
            case SRX_DOCK_TOP|SRX_DOCK_HORZ:
                  {
                        rcDesktop.top += (rcNewWnd.bottom-rcNewWnd.top);

                        SystemParametersInfo(SPI_SETWORKAREA,0,      &rcDesktop,SPIF_SENDCHANGE);
                        EnumWindows(EnumWindowsProc,(LPARAM)&rcDesktop);
                  }
                  break;

            case SRX_DOCK_LEFT|SRX_DOCK_VERT:
                  {
                        rcDesktop.left += (rcNewWnd.right-rcNewWnd.left);

                        SystemParametersInfo(SPI_SETWORKAREA,0,      &rcDesktop,SPIF_SENDCHANGE);
                        EnumWindows(EnumWindowsProc,(LPARAM)&rcDesktop);
                  }
                  break;

            case SRX_DOCK_RIGHT|SRX_DOCK_VERT:
                  {
                        rcDesktop.right -= (rcNewWnd.right-rcNewWnd.left);

                        SystemParametersInfo(SPI_SETWORKAREA,0,      &rcDesktop,SPIF_SENDCHANGE);
                        EnumWindows(EnumWindowsProc,(LPARAM)&rcDesktop);
                  }
                  break;

            case SRX_DOCK_BOTTOM|SRX_DOCK_HORZ:
                  {
                        rcDesktop.bottom -= (rcNewWnd.bottom-rcNewWnd.top);

                        SystemParametersInfo(SPI_SETWORKAREA,0,      &rcDesktop,SPIF_SENDCHANGE);
                        EnumWindows(EnumWindowsProc,(LPARAM)&rcDesktop);
                  }
                  break;

            default:
                  break;
            }
      }

              // Settings go in here for placing it second topmost.....

      SetRegSettings();
      
      return TRUE;
}


It is part of a toolbar I have been making. Basically, if the toolbar is set NOT to always be on top but to enable docking and hiding between uses (it slides off the edge of the screen) I need it to be the Second Topmost window. It MUST be one position in the z-order below the taskbar so that when it slides down it goes behind the start menu. However it MUST also remain a topmost window because otherwise if you maximize another window you lose the edge of the toolbar and have to bring it to the top before you can move the mouse over it and bring it back (slides back out) onto the screen.

The problem is using any of the tactics described above the window either goes above the taskbar covering it which is no use or it does not stay top most, i.e. another window can maximise over it.




For the record for anyone reading this question at a later date looking for an answer forget the accepted answer this question/answer is null and void unless someone answers after this.