diff --git a/include/wxex/appbar.h b/include/wxex/appbar.h index bae751f..c05be52 100644 --- a/include/wxex/appbar.h +++ b/include/wxex/appbar.h @@ -20,12 +20,16 @@ #pragma once -#include -#include +#include "common.h" +#include #include #include +#include +#include +#include + #define wxABT_AUTOHIDETIMERID 1 #define wxABT_AUTOHIDETIME 300 @@ -33,79 +37,79 @@ /// -/// Dockable application bar +/// Posted to notify application bar about system changes /// -class wxAppBar : public wxFrame +/// \param[in] wParam Event identifier. One of the following values +/// - ABN_FULLSCREENAPP Notifies an appbar when a full-screen application is opening or closing. \p lParam is boolean flag specifying whether a full-screen application is opening or closing. This parameter is TRUE if the application is opening or FALSE if it is closing. +/// - ABN_POSCHANGED Notifies an appbar when an event has occurred that may affect the appbar's size and position. Events include changes in the taskbar's size, position, and visibility state, as well as the addition, removal, or resizing of another appbar on the same side of the screen. \p lParam is not used. +/// - ABN_STATECHANGE Notifies an appbar that the taskbar's autohide or always-on-top state has changed—that is, the user has selected or cleared the "Always on top" or "Auto hide" check box on the taskbar's property sheet. \p lParam is not used. +/// \param[in] lParam Event specific. See \p wParam for details. +/// +#define WM_AB_NOTIFY 0x6f00 + + +/// +/// Dockable application bar states +/// +enum wxAppBarState { + wxABS_UNKNOWN = -2, + wxABS_FLOAT = -1, ///< Application bar is floating on the desktop (normal window) + wxABS_LEFT = ABE_LEFT, ///< Application bar is docked at the left edge of the desktop + wxABS_TOP = ABE_TOP, ///< Application bar is docked at the top edge of the desktop + wxABS_RIGHT = ABE_RIGHT, ///< Application bar is docked at the right edge of the desktop + wxABS_BOTTOM = ABE_BOTTOM, ///< Application bar is docked at the bottom edge of the desktop +}; + + +/// +/// Dockable application bar flags +/// +enum wxAppBarFlags { + wxABF_ALLOWFLOAT = 1 << 0, ///< Is floating application bar allowed? + wxABF_ALLOWDOCKTOP = 1 << 1, ///< Is docking on top of the screen allowed? + wxABF_ALLOWDOCKBOTTOM = 1 << 2, ///< Is docking on bottom of the screen allowed? + wxABF_ALLOWDOCKLEFT = 1 << 3, ///< Is docking left of the screen allowed? + wxABF_ALLOWDOCKRIGHT = 1 << 4, ///< Is docking right of the screen allowed? + wxABF_ALLOWDOCKANY = (wxABF_ALLOWDOCKTOP | wxABF_ALLOWDOCKBOTTOM | wxABF_ALLOWDOCKLEFT | wxABF_ALLOWDOCKRIGHT), ///< Is docking at any edge of the screen allowed? + wxABF_ALLOWDOCKHORIZONTAL = (wxABF_ALLOWDOCKTOP | wxABF_ALLOWDOCKBOTTOM), ///< Is docking on top or bottom of the screen allowed? + wxABF_ALLOWDOCKVERTICAL = (wxABF_ALLOWDOCKLEFT | wxABF_ALLOWDOCKRIGHT), ///< Is docking left or right of the screen allowed? + wxABF_ALLOWANY = (wxABF_ALLOWFLOAT | wxABF_ALLOWDOCKANY), ///< Is floating and docking at any edge of the screen allowed? + + wxABF_ALWAYSONTOP = 1 << 5, ///< Is application bar always on top? + wxABF_ALWAYSONTOPTASKBAR = 1 << 6, ///< Does application bar follow always on top state of the system taskbar? + + wxABF_AUTOHIDE = 1 << 7, ///< Is application bar setup for auto-hide? + wxABF_AUTOHIDETASKBAR = 1 << 8, ///< Does application bar follow auto-hide state of the system taskbar? + + wxABF_ALLOWSIZING = 1 << 9, ///< Is application bar's sizing allowed? + + wxABF_HIDETASKBARTABWHENFLOATING = 1 << 10, ///< Should application bar's tab on the system taskbar hide when floating? + wxABF_HIDETASKBARTABWHENDOCKED = 1 << 11, ///< Should application bar's tab on the system taskbar hide when docked? + wxABF_ALWAYSHIDETASKBARTAB = (wxABF_HIDETASKBARTABWHENFLOATING | wxABF_HIDETASKBARTABWHENDOCKED), ///< Should application bar's tab on the system taskbar hide always? + + // Internal flags + wxABF_FULLSCREENAPPOPEN = 1 << 12, ///< Is full-screen application open? + wxABF_AUTOHIDDEN = 1 << 13, ///< Is application bar auto-hidden right now? +}; + + +/// +/// Dockable application bar template +/// +template +class wxAppBar : public W { -public: - /// - /// Application bar states - /// - enum wxState { - wxSTATE_UNKNOWN = -2, - wxSTATE_FLOAT = -1, - wxSTATE_LEFT = ABE_LEFT, - wxSTATE_TOP = ABE_TOP, - wxSTATE_RIGHT = ABE_RIGHT, - wxSTATE_BOTTOM = ABE_BOTTOM, - }; - - - /// - /// Application bar flags - /// - enum wxFlags { - wxFLAG_ALLOWFLOAT = 1 << 0, ///< Is floating application bar allowed? - wxFLAG_ALLOWDOCKTOP = 1 << 1, ///< Is docking on top of the screen allowed? - wxFLAG_ALLOWDOCKBOTTOM = 1 << 2, ///< Is docking on bottom of the screen allowed? - wxFLAG_ALLOWDOCKLEFT = 1 << 3, ///< Is docking left of the screen allowed? - wxFLAG_ALLOWDOCKRIGHT = 1 << 4, ///< Is docking right of the screen allowed? - wxFLAG_ALLOWDOCKANY = (wxFLAG_ALLOWDOCKTOP | wxFLAG_ALLOWDOCKBOTTOM | wxFLAG_ALLOWDOCKLEFT | wxFLAG_ALLOWDOCKRIGHT), ///< Is docking at any edge of the screen allowed? - wxFLAG_ALLOWDOCKHORIZONTAL = (wxFLAG_ALLOWDOCKTOP | wxFLAG_ALLOWDOCKBOTTOM), ///< Is docking on top or bottom of the screen allowed? - wxFLAG_ALLOWDOCKVERTICAL = (wxFLAG_ALLOWDOCKLEFT | wxFLAG_ALLOWDOCKRIGHT), ///< Is docking left or right of the screen allowed? - wxFLAG_ALLOWANY = (wxFLAG_ALLOWFLOAT | wxFLAG_ALLOWDOCKANY), ///< Is floating and docking at any edge of the screen allowed? - - wxFLAG_ALWAYSONTOP = 1 << 5, ///< Is application bar always on top? - wxFLAG_ALWAYSONTOPTASKBAR = 1 << 6, ///< Does application bar follow always on top state of the system taskbar? - - wxFLAG_AUTOHIDE = 1 << 7, ///< Is application bar setup for auto-hide? - wxFLAG_AUTOHIDETASKBAR = 1 << 8, ///< Does application bar follow auto-hide state of the system taskbar? - - wxFLAG_ALLOWSIZING = 1 << 9, ///< Is application bar's sizing allowed? - - wxFLAG_HIDETASKBARTABWHENFLOATING = 1 << 10, ///< Should application bar's tab on the system taskbar hide when floating? - wxFLAG_HIDETASKBARTABWHENDOCKED = 1 << 11, ///< Should application bar's tab on the system taskbar hide when docked? - wxFLAG_ALWAYSHIDETASKBARTAB = (wxFLAG_HIDETASKBARTABWHENFLOATING | wxFLAG_HIDETASKBARTABWHENDOCKED), ///< Should application bar's tab on the system taskbar hide always? - - // Internal flags - wxFLAG_FULLSCREENAPPOPEN = 1 << 12, ///< Is full-screen application open? - wxFLAG_AUTOHIDDEN = 1 << 13, ///< Is application bar auto-hidden right now? - }; +protected: + // common part of all ctors + void Init(); public: wxAppBar(); - wxAppBar(wxWindow *parent, - wxWindowID id, - const wxString& title, - wxState state = wxSTATE_FLOAT, - int flags = wxFLAG_ALLOWANY, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxDEFAULT_FRAME_STYLE, - const wxString& name = wxFrameNameStr); - - bool Create(wxWindow *parent, - wxWindowID id, - const wxString& title, - wxState state = wxSTATE_FLOAT, - int flags = wxFLAG_ALLOWANY, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxDEFAULT_FRAME_STYLE, - const wxString& name = wxFrameNameStr); - virtual ~wxAppBar(); +protected: + void PreCreate(wxAppBarState& state, int& flags, const wxSize& size, long& style); + public: /// \name Application bar general management /// @{ @@ -113,7 +117,7 @@ public: /// /// Returns current state of the application bar. /// - inline wxState GetState() const; + inline wxAppBarState GetState() const; /// /// Returns whether application bar is displayed always on top. @@ -159,9 +163,9 @@ public: /// /// Sets whether resizing of the application bar is allowed. /// - /// \param[in] bAllowSizing Logical variable to control whether resizing is to be enabled (true) or disabled (false). + /// \param[in] allow Logical variable to control whether resizing is to be enabled (true) or disabled (false). /// - inline bool SetAllowSizing(bool bAllowSizing = true); + inline bool SetAllowSizing(bool allow = true); /// /// Returns if application bar is auto-hidden right now. @@ -177,10 +181,10 @@ public: /// /// Minimize application bar to the edge of the desktop. /// - /// \param[in] edge The edge at which to dock. Must be either of: wxSTATE_LEFT, wxSTATE_TOP, wxSTATE_RIGHT, or wxSTATE_BOTTOM. + /// \param[in] edge The edge at which to dock. Must be either of: wxABS_LEFT, wxABS_TOP, wxABS_RIGHT, or wxABS_BOTTOM. /// \param[in] wnd When the undocked and docked window is different, this parameter denotes the undocked version. /// - void MinimiseToEdge(wxState edge, wxWindow* wnd = NULL); + void MinimiseToEdge(wxAppBarState edge, wxWindow* wnd = NULL); /// /// Restore application bar from the edge of the desktop. @@ -194,9 +198,9 @@ public: /// /// Shows or hides auto-hide application bar. /// - /// \param[in] bShow Logical variable to control whether application bar is be shown (true) or hidden (false). + /// \param[in] show Logical variable to control whether application bar is be shown (true) or hidden (false). /// - void ShowAutoHideAppBar(bool bShow = true); + void ShowAutoHideAppBar(bool show = true); /// /// Hides auto-hide application bar. @@ -216,14 +220,14 @@ protected: /// /// \param[in] stateNew New state about to take effect. /// - virtual void OnChangeState(wxState stateNew); + virtual void OnChangeState(wxAppBarState stateNew); /// - /// Notification handler when the Windows' task bar state changes. + /// Notification handler when the Windows' taskbar state changes. /// /// Derived classes can implement their own. However, overriden virtual method should call the parent's implementation too. /// - /// \param[in] state New task bar state. + /// \param[in] state New taskbar state. /// virtual void OnChangeTaskBarState(UINT_PTR state); @@ -232,9 +236,9 @@ protected: /// /// Derived classes can implement their own. However, overriden virtual method should call the parent's implementation too. /// - /// \param[in] bBeginning true when windows arrangement starts and false when arrangement ends. + /// \param[in] beginning true when windows arrangement starts and false when arrangement ends. /// - virtual void OnWindowsArrange(bool bBeginning); + virtual void OnWindowsArrange(bool beginning); /// /// Called when application bar was forced from auto-hide to normal docking. @@ -249,326 +253,144 @@ protected: virtual WXLRESULT MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam); private: - inline bool DockAppBar(wxState state); + inline bool DockAppBar(wxAppBarState state); inline bool UndockAppBar(); - inline bool RegisterAutoHide(wxState state); - inline bool UnregisterAutoHide(wxState state); - inline bool GetDockedRect(wxState state, LPRECT rect) const; - inline bool GetAutoHideRect(wxState state, bool bAutoHidden, LPRECT rect) const; - inline static bool IsDocked(wxState state); - inline static bool IsDockedVert(wxState state); - inline static bool IsDockedHoriz(wxState state); - inline static WXHWND GetZWnd(wxState state, int flags); - inline static UINT_PTR GetTaskBarState(); + inline bool RegisterAutoHide(wxAppBarState state); + inline bool UnregisterAutoHide(wxAppBarState state); + inline bool GetDockedRect(wxAppBarState state, LPRECT rect) const; + inline bool GetAutoHideRect(wxAppBarState state, bool bAutoHidden, LPRECT rect) const; protected: - wxState m_state; ///< Current state of the application bar - wxState m_stateDesired; ///< Desired state of the application bar while moving/resizing + wxAppBarState m_state; ///< Current state of the application bar + wxAppBarState m_stateDesired; ///< Desired state of the application bar while moving/resizing int m_flags; ///< Flags describing application bar's behaviour SIZE m_sizeFloat; ///< Window size when floating (we need it to restore floating size, when we undock) - SIZE m_sizeDocked; ///< Size of the window when docked (height when wxSTATE_TOP or wxSTATE_BOTTOM, width when wxSTATE_LEFT or wxSTATE_RIGHT) + SIZE m_sizeDocked; ///< Size of the window when docked (height when wxABS_TOP or wxABS_BOTTOM, width when wxABS_LEFT or wxABS_RIGHT) SIZE m_sizeMin; ///< Minimum window size UINT_PTR m_stateTaskBar; ///< TaskBar's current state UINT_PTR m_timerID; ///< Application bar's timer id. ITaskbarList *m_taskbarList; ///< Windows's taskbar list interface - -private: - static const UINT WM_AB_NOTIFY; ///< Application bar notification message }; -inline wxAppBar::wxState wxAppBar::GetState() const +/// +/// Dockable application bar frame +/// +class wxAppBarFrame : public wxAppBar { - return m_stateDesired != wxSTATE_UNKNOWN ? m_stateDesired : m_state; +public: + wxAppBarFrame(); + wxAppBarFrame(wxWindow *parent, + wxWindowID id, + const wxString& title, + wxAppBarState state = wxABS_FLOAT, + int flags = wxABF_ALLOWANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE, + const wxString& name = wxFrameNameStr); + + bool Create(wxWindow *parent, + wxWindowID id, + const wxString& title, + wxAppBarState state = wxABS_FLOAT, + int flags = wxABF_ALLOWANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE, + const wxString& name = wxFrameNameStr); +}; + + +/// +/// Dockable application bar dialog +/// +class wxAppBarDialog : public wxAppBar +{ +public: + wxAppBarDialog(); + wxAppBarDialog(wxWindow *parent, + wxWindowID id, + const wxString& title, + wxAppBarState state = wxABS_FLOAT, + int flags = wxABF_ALLOWANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_DIALOG_STYLE, + const wxString& name = wxDialogNameStr); + + bool Create(wxWindow *parent, + wxWindowID id, + const wxString& title, + wxAppBarState state = wxABS_FLOAT, + int flags = wxABF_ALLOWANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_DIALOG_STYLE, + const wxString& name = wxDialogNameStr); +}; + + +/// +/// Returns if the application bar state represents docked state. +/// +/// \param[in] state The state of the application bar +/// +/// \returns +/// - true if the application bar state represents docked state +/// - false otherwise +/// +inline bool wxAppBarIsDocked(wxAppBarState state) +{ + return wxABS_LEFT <= state && state <= wxABS_BOTTOM; } -inline bool wxAppBar::IsAlwaysOnTop() const +/// +/// Returns if the application bar state represents vertically docked state. +/// +/// \param[in] state The state of the application bar +/// +/// \returns +/// - true if the application bar state represents vertically docked state +/// - false otherwise +/// +inline bool wxAppBarIsDockedVert(wxAppBarState state) { - return (m_flags & wxFLAG_ALWAYSONTOP) ? true : false; + return state == wxABS_LEFT || state == wxABS_RIGHT; } -inline bool wxAppBar::SetAlwaysOnTop(bool alwaysOnTop) +/// +/// Returns if the application bar state represents horizontally docked state. +/// +/// \param[in] state The state of the application bar +/// +/// \returns +/// - true if the application bar state represents horizontally docked state +/// - false otherwise +/// +inline bool wxAppBarIsDockedHoriz(wxAppBarState state) { - if (alwaysOnTop) - m_flags |= wxFLAG_ALWAYSONTOP; - else - m_flags &= ~wxFLAG_ALWAYSONTOP; - - if (::IsWindowVisible(m_hWnd)) { - // Set the Z-order. - wxCHECK(::SetWindowPos(m_hWnd, GetZWnd(m_state, m_flags), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOSENDCHANGING), false); - } - - return true; + return state == wxABS_TOP || state == wxABS_BOTTOM; } -inline bool wxAppBar::IsAutoHide() const +/// +/// Returns the window above which to Z-order the application bar. +/// +/// \param[in] state The state of the application bar +/// \param[in] flags The flags of the application bar +/// +/// \returns +/// The handle of the window +/// +inline WXHWND wxAppBarGetZWnd(wxAppBarState state, int flags) { - return (m_flags & wxFLAG_AUTOHIDE) ? true : false; -} - - -inline bool wxAppBar::SetAutoHide(bool autoHide) -{ - bool autoHidePrev = IsAutoHide(); - - if (autoHide) - m_flags |= wxFLAG_AUTOHIDE; - else - m_flags &= ~wxFLAG_AUTOHIDE; - - if (autoHidePrev != autoHide && IsDocked(m_state) && ::IsWindowVisible(m_hWnd)) { - if (autoHide) { - // Application bar should be auto-hidden. Try to setup it so. - - // We undock to free the space before registering auto-hide, otherwise system will leave application bar's space reserved. - UndockAppBar(); - - // Register auto-hide application bar. - if (!RegisterAutoHide(m_state)) { - // Auto-hide failed; some other application bar must be hidden on this edge already. Dock back instead. - DockAppBar(m_state); - return false; - } - } else { - // Unregister the auto-hidden application bar and dock. - UnregisterAutoHide(m_state); - DockAppBar(m_state); - } - } - - return true; -} - - -inline bool wxAppBar::GetAllowSizing() const -{ - return (m_flags & wxFLAG_ALLOWSIZING) ? true : false; -} - - -inline bool wxAppBar::SetAllowSizing(bool bAllowSizing) -{ - if (bAllowSizing) - m_flags |= wxFLAG_ALLOWSIZING; - else - m_flags &= ~wxFLAG_ALLOWSIZING; - - return true; -} - - -inline bool wxAppBar::GetAutoHidden() const -{ - return (m_flags & wxFLAG_AUTOHIDDEN) ? true : false; -} - - -inline bool wxAppBar::DockAppBar(wxState state) -{ - wxASSERT(IsDocked(state)); - - // Calculate docked window rect and dock the window there. - APPBARDATA abd = { sizeof(abd), m_hWnd, 0, state }; - GetDockedRect(state, &(abd.rc)); - wxCHECK(::SHAppBarMessage(ABM_SETPOS, &abd), false); - wxCHECK(::SetWindowPos(m_hWnd, GetZWnd(state, m_flags), abd.rc.left, abd.rc.top, abd.rc.right - abd.rc.left, abd.rc.bottom - abd.rc.top, SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_FRAMECHANGED), false); - - return true; -} - - -inline bool wxAppBar::UndockAppBar() -{ - // Free application bar's space to undock. - APPBARDATA abd = { sizeof(abd), m_hWnd, 0, wxSTATE_LEFT }; - wxASSERT(!abd.rc.left && !abd.rc.top && !abd.rc.right && !abd.rc.bottom); - wxCHECK(::SHAppBarMessage(ABM_SETPOS, &abd), false); - - return true; -} - - -inline bool wxAppBar::RegisterAutoHide(wxState state) -{ - wxASSERT(IsDocked(state)); - - // Register application bar as auto-hide. - APPBARDATA abd = { sizeof(abd), m_hWnd, 0, state, {}, (LPARAM)true }; - if (::SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd)) { - // Auto-hide succeeded. - m_flags |= wxFLAG_AUTOHIDE; - m_flags &= ~wxFLAG_AUTOHIDDEN; - - // Calculate auto-hidden window rect and move the window there. - GetAutoHideRect(state, false, &(abd.rc)); - wxCHECK(::SetWindowPos(m_hWnd, GetZWnd(state, m_flags), abd.rc.left, abd.rc.top, abd.rc.right - abd.rc.left, abd.rc.bottom - abd.rc.top, SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_FRAMECHANGED), false); - - // Reset auto-hide timer. - m_timerID = ::SetTimer(m_hWnd, wxABT_AUTOHIDETIMERID, wxABT_AUTOHIDETIMERINTERVAL, NULL); - - return true; - } else { - // Auto-hide failed; some other application bar must be hidden on this edge already. - m_flags &= ~(wxFLAG_AUTOHIDE | wxFLAG_AUTOHIDDEN); - - // Post a message to user. - OnAutoHideDenied(); - - return false; - } -} - - -inline bool wxAppBar::UnregisterAutoHide(wxState state) -{ - wxASSERT(IsDocked(state)); - - // Unregister application bar as auto-hide. - APPBARDATA abd = { sizeof(abd), m_hWnd, 0, state, {}, (LPARAM)false }; - wxCHECK(::SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd), false); - m_flags &= ~wxFLAG_AUTOHIDDEN; - - // Cancel the timer. - if (m_timerID) { - ::KillTimer(m_hWnd, m_timerID); - m_timerID = 0; - } - - return true; -} - - -inline bool wxAppBar::GetDockedRect(wxState state, LPRECT rect) const -{ - wxASSERT(rect); - wxASSERT(IsDocked(state)); - - // Set dimensions to full screen. - APPBARDATA abd = { sizeof(abd), m_hWnd, 0, state, { 0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN) } }; - wxCHECK(::SHAppBarMessage(ABM_QUERYPOS, &abd), false); - - // Correct our dimensions accordingly. - switch (state) { - case wxSTATE_LEFT: - rect->left = abd.rc.left; - rect->top = abd.rc.top; - rect->right = abd.rc.left + m_sizeDocked.cx; - rect->bottom = abd.rc.bottom; - break; - - case wxSTATE_TOP: - rect->left = abd.rc.left; - rect->top = abd.rc.top; - rect->right = abd.rc.right; - rect->bottom = abd.rc.top + m_sizeDocked.cy; - break; - - case wxSTATE_RIGHT: - rect->left = abd.rc.right - m_sizeDocked.cx; - rect->top = abd.rc.top; - rect->right = abd.rc.right; - rect->bottom = abd.rc.bottom; - break; - - case wxSTATE_BOTTOM: - rect->left = abd.rc.left; - rect->top = abd.rc.bottom - m_sizeDocked.cy; - rect->right = abd.rc.right; - rect->bottom = abd.rc.bottom; - break; - - default: - // Unknown state. - wxFAIL; - return false; - } - - return true; -} - - -inline bool wxAppBar::GetAutoHideRect(wxState state, bool bAutoHidden, LPRECT rect) const -{ - wxASSERT(rect); - wxASSERT(IsDocked(state)); - - // Keep a part of the application bar visible at all times - const int iBorder = ::GetSystemMetrics(IsDockedVert(state) ? SM_CXBORDER : SM_CYBORDER) * 2; - const RECT rcScreen = { - 0, - 0, - ::GetSystemMetrics(SM_CXSCREEN), - ::GetSystemMetrics(SM_CYSCREEN) - }; - - // Correct our dimensions accordingly. - switch (state) { - case wxSTATE_LEFT: - rect->top = rcScreen.top; - rect->bottom = rcScreen.bottom; - rect->right = rcScreen.left + (bAutoHidden ? iBorder : m_sizeDocked.cx); - rect->left = rect->right - m_sizeDocked.cx; - break; - - case wxSTATE_TOP: - rect->left = rcScreen.left; - rect->right = rcScreen.right; - rect->bottom = rcScreen.top + (bAutoHidden ? iBorder : m_sizeDocked.cy); - rect->top = rect->bottom - m_sizeDocked.cy; - break; - - case wxSTATE_RIGHT: - rect->left = rcScreen.right - (bAutoHidden ? iBorder : m_sizeDocked.cx); - rect->top = rcScreen.top; - rect->right = rect->left + m_sizeDocked.cx; - rect->bottom = rcScreen.bottom; - break; - - case wxSTATE_BOTTOM: - rect->left = rcScreen.left; - rect->top = rcScreen.bottom - (bAutoHidden ? iBorder : m_sizeDocked.cy); - rect->right = rcScreen.right; - rect->bottom = rect->top + m_sizeDocked.cy; - break; - - default: - // Unknown state. - wxFAIL; - return false; - } - - return true; -} - - -inline bool wxAppBar::IsDocked(wxState state) -{ - return wxSTATE_LEFT <= state && state <= wxSTATE_BOTTOM; -} - - -inline bool wxAppBar::IsDockedVert(wxState state) -{ - return state == wxSTATE_LEFT || state == wxSTATE_RIGHT; -} - - -inline bool wxAppBar::IsDockedHoriz(wxState state) -{ - return state == wxSTATE_TOP || state == wxSTATE_BOTTOM; -} - - -inline WXHWND wxAppBar::GetZWnd(wxState state, int flags) -{ - if (flags & wxFLAG_FULLSCREENAPPOPEN) { + if (flags & wxABF_FULLSCREENAPPOPEN) { // If full screen app is open, clear the always-on-top flag. return HWND_NOTOPMOST; } @@ -579,18 +401,18 @@ inline WXHWND wxAppBar::GetZWnd(wxState state, int flags) // return pThreadState->m_hTrackingWindow; // } - if (state == wxSTATE_FLOAT) { + if (state == wxABS_FLOAT) { // When floating, decide according to the flags. - return (flags & wxFLAG_ALWAYSONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST; + return (flags & wxABF_ALWAYSONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST; } - if (IsDocked(state)) { - if (flags & wxFLAG_AUTOHIDE) { + if (wxAppBarIsDocked(state)) { + if (flags & wxABF_AUTOHIDE) { // Auto-hidden docked application bar is always on top. return HWND_TOPMOST; } - if (flags & wxFLAG_ALWAYSONTOP) { + if (flags & wxABF_ALWAYSONTOP) { // Regular docked always-on-top application bar. WXHWND hWndTaskbar = ::FindWindow(_T("Shell_TrayWnd"), _T("")); if (hWndTaskbar) { @@ -614,8 +436,1127 @@ inline WXHWND wxAppBar::GetZWnd(wxState state, int flags) } -inline UINT_PTR wxAppBar::GetTaskBarState() +/// +/// Returns the current taskbar state. +/// +/// \returns +/// The taskbar state +/// +/// \sa [SHAppBarMessage function](https://msdn.microsoft.com/en-us/library/windows/desktop/bb762108.aspx) +/// +inline UINT_PTR wxAppBarGetTaskBarState() { APPBARDATA abd = { sizeof(abd) }; return ::SHAppBarMessage(ABM_GETSTATE, &abd); } + + +////////////////////////////////////////////////////////////////////////// +// wxAppBar +////////////////////////////////////////////////////////////////////////// + +template +void wxAppBar::Init() +{ + // Find the taskbar list's interface. + if (SUCCEEDED(::CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_ALL, IID_ITaskbarList, (LPVOID*)&m_taskbarList))) { + if (FAILED(m_taskbarList->HrInit())) { + wxFAIL; + m_taskbarList->Release(); + m_taskbarList = NULL; + } + } else { + wxFAIL; + m_taskbarList = NULL; + } + + m_timerID = 0; +} + + +template +wxAppBar::wxAppBar() +{ + Init(); +} + + +template +wxAppBar::~wxAppBar() +{ + if (m_taskbarList) + m_taskbarList->Release(); +} + + +template +void wxAppBar::PreCreate(wxAppBarState& state, int& flags, const wxSize& size, long& style) +{ + // Save initial floating window size. + m_sizeFloat.cx = size.x; + m_sizeFloat.cy = size.y; + + // Save initial docked window width/height. + m_sizeDocked.cx = size.x; + m_sizeDocked.cy = size.y; + + // Save initial state and flags. + m_state = state; + m_stateDesired = wxABS_UNKNOWN; + m_flags = flags; + + // If any taskbar list tab's hiding is in affect, set application bar's style as tool window to avoid being displayed on the taskbar initially. + if (state == wxABS_FLOAT) { + if (flags & wxABF_HIDETASKBARTABWHENFLOATING) { + // Hide our application bar's entry on the Windows's taskbar. + style |= wxFRAME_TOOL_WINDOW; + } else if (flags & wxABF_HIDETASKBARTABWHENDOCKED) { + // Show our application bar's entry on the Windows's taskbar. + style &= ~wxFRAME_TOOL_WINDOW; + } + } else if (wxAppBarIsDocked(state)) { + if (flags & wxABF_HIDETASKBARTABWHENDOCKED) { + // Hide our application bar's entry on the Windows's taskbar. + style |= wxFRAME_TOOL_WINDOW; + } else if (flags & wxABF_HIDETASKBARTABWHENFLOATING) { + // Show our application bar's entry on the Windows's taskbar. + style &= ~wxFRAME_TOOL_WINDOW; + } + } else { + // Unknown state. + wxFAIL; + } +} + + +template +inline wxAppBarState wxAppBar::GetState() const +{ + return m_stateDesired != wxABS_UNKNOWN ? m_stateDesired : m_state; +} + + +template +inline bool wxAppBar::IsAlwaysOnTop() const +{ + return (m_flags & wxABF_ALWAYSONTOP) ? true : false; +} + + +template +inline bool wxAppBar::SetAlwaysOnTop(bool alwaysOnTop) +{ + if (alwaysOnTop) + m_flags |= wxABF_ALWAYSONTOP; + else + m_flags &= ~wxABF_ALWAYSONTOP; + + if (::IsWindowVisible(m_hWnd)) { + // Set the Z-order. + wxCHECK(::SetWindowPos(m_hWnd, wxAppBarGetZWnd(m_state, m_flags), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOSENDCHANGING), false); + } + + return true; +} + + +template +inline bool wxAppBar::IsAutoHide() const +{ + return (m_flags & wxABF_AUTOHIDE) ? true : false; +} + + +template +inline bool wxAppBar::SetAutoHide(bool autoHide) +{ + bool autoHidePrev = IsAutoHide(); + + if (autoHide) + m_flags |= wxABF_AUTOHIDE; + else + m_flags &= ~wxABF_AUTOHIDE; + + if (autoHidePrev != autoHide && wxAppBarIsDocked(m_state) && ::IsWindowVisible(m_hWnd)) { + if (autoHide) { + // Application bar should be auto-hidden. Try to setup it so. + + // We undock to free the space before registering auto-hide, otherwise system will leave application bar's space reserved. + UndockAppBar(); + + // Register auto-hide application bar. + if (!RegisterAutoHide(m_state)) { + // Auto-hide failed; some other application bar must be hidden on this edge already. Dock back instead. + DockAppBar(m_state); + return false; + } + } else { + // Unregister the auto-hidden application bar and dock. + UnregisterAutoHide(m_state); + DockAppBar(m_state); + } + } + + return true; +} + + +template +inline bool wxAppBar::GetAllowSizing() const +{ + return (m_flags & wxABF_ALLOWSIZING) ? true : false; +} + + +template +inline bool wxAppBar::SetAllowSizing(bool allow) +{ + if (allow) + m_flags |= wxABF_ALLOWSIZING; + else + m_flags &= ~wxABF_ALLOWSIZING; + + return true; +} + + +template +inline bool wxAppBar::GetAutoHidden() const +{ + return (m_flags & wxABF_AUTOHIDDEN) ? true : false; +} + + +//template +//bool wxAppBar::GetAppBarPlacement(LPAPPBARPLACEMENT lpPlacement) const +//{ +// wxASSERT(lpPlacement); +// +// if (lpPlacement->dwSize >= sizeof(APPBARPLACEMENT1)) { +// lpPlacement->dwState = (DWORD)m_state; +// lpPlacement->dwFlags = m_flags; +// if (m_state == wxABS_FLOAT) { +// // Current application bar's rect is floating rect. +// lpPlacement->rcFloat = m_rect; +// } else if (wxAppBarIsDocked(m_state)) { +// // Application bar is docked. Calc floating rect from m_sizeFloat. +// lpPlacement->rcFloat.left = 0; +// lpPlacement->rcFloat.top = 0; +// lpPlacement->rcFloat.right = m_sizeFloat.cx; +// lpPlacement->rcFloat.bottom = m_sizeFloat.cy; +// } else { +// // Application bar's state is unknown. +// return false; +// } +// lpPlacement->szDocked = m_sizeDocked; +// } +// +// lpPlacement->dwSize = sizeof(*lpPlacement); +// +// return true; +//} +// +// +//template +//bool wxAppBar::SetAppBarPlacement(LPCAPPBARPLACEMENT lpPlacement) +//{ +// wxASSERT(lpPlacement); +// +// if (lpPlacement->dwSize >= sizeof(APPBARPLACEMENT1)) { +// if (lpPlacement->dwState != wxABS_FLOAT && !wxAppBarIsDocked(lpPlacement->dwState)) { +// // The state is unknown. Abort, before we mix up internal state. +// return false; +// } +// +// // Clean previous docking/auto-hide settings if required. +// if (wxAppBarIsDocked(m_state) && +// (lpPlacement->dwState == wxABS_FLOAT || lpPlacement->dwState != m_state && wxAppBarIsDocked(lpPlacement->dwState))) +// { +// if (IsAutoHide()) +// UnregisterAutoHide(m_state); +// else if (lpPlacement->dwState == wxABS_FLOAT) +// UndockAppBar(); +// } +// +// // Update application bar's flags, size and position. +// m_flags |= wxABF_POSITIONSET; +// m_sizeDocked = lpPlacement->szDocked; +// if (lpPlacement->dwState == wxABS_FLOAT) { +// m_rect = lpPlacement->rcFloat; +// } else if (wxAppBarIsDocked(lpPlacement->dwState)) { +// m_sizeFloat.cx = lpPlacement->rcFloat.right - lpPlacement->rcFloat.left; +// m_sizeFloat.cy = lpPlacement->rcFloat.bottom - lpPlacement->rcFloat.top; +// GetDockedRect(lpPlacement->dwState, &m_rect); +// } else { +// // Application bar's state is unknown. +// wxFAIL; +// return false; +// } +// +// // Notify about the change of state. +// OnChangeState(lpPlacement->dwState); +// m_state = lpPlacement->dwState; +// +// SetAutoHide(lpPlacement->dwFlags & wxABF_AUTOHIDE); +// SetAlwaysOnTop(lpPlacement->dwFlags & wxABF_ALWAYSONTOP); +// } +// +// return true; +//} + + +template +void wxAppBar::MinimiseToEdge(wxAppBarState edge, wxWindow *wnd) +{ + wxASSERT(wxAppBarIsDocked(edge)); + + WXHWND hWnd; + if (!wnd) { + // No other window was specified. Minimize ourself. + wnd = this; + hWnd = m_hWnd; + } else + hWnd = wnd->GetHWND(); + + // If our window is hidden, there's nothing we can do. + if (hWnd == m_hWnd && !::IsWindowVisible(m_hWnd)) + return; + + if (m_state == wxABS_FLOAT) { + // Remember the last floating size. + RECT rect = {}; + wxVERIFY(::GetWindowRect(hWnd, &rect)); + m_sizeFloat.cx = rect.right - rect.left; + m_sizeFloat.cy = rect.bottom - rect.top; + } + + RECT rectTo; + if (IsAutoHide()) + GetAutoHideRect(edge, false, &rectTo); + else + GetDockedRect(edge, &rectTo); + + if (::wxGetDoWndAnimation()) { + // Do the animation. + RECT rectFrom; + wxVERIFY(::GetWindowRect(hWnd, &rectFrom)); + wxVERIFY(::DrawAnimatedRects(hWnd, IDANI_CAPTION, &rectFrom, &rectTo)); + } + + // Notify about the change of state. + OnChangeState(edge); + m_state = edge; + + if (hWnd != m_hWnd) { + // Hide the source window. + wnd->Hide(); + // ::SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) &~ WS_VISIBLE); + + // Show the application bar. + Show(); + } else { + if (IsAutoHide()) { + // Register auto-hide application bar. + RegisterAutoHide(edge); + } else { + // Auto-hide failed or wasn't desired at all. + DockAppBar(edge); + } + } + + ::SetActiveWindow(m_hWnd); +} + + +template +void wxAppBar::MaximiseFromEdge(const RECT* rect) +{ + wxASSERT(::IsWindowVisible(m_hWnd)); + + RECT rectTo; + + if (!rect) { + // Calculate the destination rect. + rectTo.left = (::GetSystemMetrics(SM_CXSCREEN) - m_sizeFloat.cx) / 2; + rectTo.top = (::GetSystemMetrics(SM_CYSCREEN) - m_sizeFloat.cy) / 2; + rectTo.right = rectTo.left + m_sizeFloat.cx; + rectTo.bottom = rectTo.top + m_sizeFloat.cy; + + rect = &rectTo; + } else { + m_sizeFloat.cx = rect->right - rect->left; + m_sizeFloat.cy = rect->bottom - rect->top; + } + + if (::wxGetDoWndAnimation()) { + // Do the animation. + RECT rectFrom; + wxVERIFY(::GetWindowRect(m_hWnd, &rectFrom)); + wxVERIFY(::DrawAnimatedRects(m_hWnd, IDANI_CAPTION, &rectFrom, rect)); + } + + // Clean previous docking/auto-hide settings if required. + if (wxAppBarIsDocked(m_state)) { + if (IsAutoHide()) + UnregisterAutoHide(m_state); + else + UndockAppBar(); + } + + // Notify about the change of state. + OnChangeState(wxABS_FLOAT); + m_state = wxABS_FLOAT; + + wxVERIFY(::SetWindowPos(m_hWnd, wxAppBarGetZWnd(wxABS_FLOAT, m_flags), rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top, SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_FRAMECHANGED)); +} + + +template +void wxAppBar::MaximiseFromEdge(wxWindow *wnd) +{ + wxASSERT(wnd); + wxASSERT(::IsWindowVisible(m_hWnd)); + + WXHWND hWnd = wnd->GetHWND(); + + RECT rectTo = {}; + wxVERIFY(::GetWindowRect(hWnd, &rectTo)); + m_sizeFloat.cx = rectTo.right - rectTo.left; + m_sizeFloat.cy = rectTo.bottom - rectTo.top; + + if (::wxGetDoWndAnimation()) { + // Do the animation. + RECT rectFrom; + wxVERIFY(::GetWindowRect(m_hWnd, &rectFrom)); + wxVERIFY(::DrawAnimatedRects(hWnd, IDANI_CAPTION, &rectFrom, &rectTo)); + } + + // Hide our window and show the destination window. + Hide(); + wnd->Show(); + // ::SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) | WS_VISIBLE); + wxVERIFY(::SetForegroundWindow(hWnd)); + ::SetActiveWindow(hWnd); + // wxVERIFY(::RedrawWindow(hWnd, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_FRAME | RDW_INVALIDATE | RDW_ERASE)); +} + + +template +void wxAppBar::ShowAutoHideAppBar(bool show) +{ + RECT rcEnd; + bool + bFullDragOn, + bHidden = GetAutoHidden(), + bVisible = ::IsWindowVisible(m_hWnd) ? true : false; + + if (!IsAutoHide() || bHidden != show) { + // We're not setup for auto-hide or already in the desired state. + return; + } + + // Get our end window location. + GetAutoHideRect(m_state, !bHidden, &rcEnd); + + if (bVisible) { + RECT rcStart; + + // Only slide the window if the user has FullDrag turned on. + if (!::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &bFullDragOn, 0)) + bFullDragOn = false; + + // Get our start window location. + GetAutoHideRect(m_state, bHidden, &rcStart); + + if (bFullDragOn && (rcStart.left != rcEnd.left || rcStart.top != rcEnd.top || rcStart.right != rcEnd.right || rcStart.bottom != rcEnd.bottom)) { + // Get our starting and ending time. + DWORD dwTimeStart = ::GetTickCount(); + DWORD dwTimeElapsed; + RECT rcDelta; + + // Calculate difference between ending and starting rectangle. + rcDelta.left = rcEnd.left - rcStart.left; + rcDelta.top = rcEnd.top - rcStart.top; + rcDelta.right = rcEnd.right - rcStart.right; + rcDelta.bottom = rcEnd.bottom - rcStart.bottom; + + while ((dwTimeElapsed = ::GetTickCount() - dwTimeStart) < wxABT_AUTOHIDETIME) { + // Do the linear interpolation. + RECT rect; + rect.left = rcStart.left + ::MulDiv(rcDelta.left, dwTimeElapsed, wxABT_AUTOHIDETIME); + rect.top = rcStart.top + ::MulDiv(rcDelta.top, dwTimeElapsed, wxABT_AUTOHIDETIME); + rect.right = rcStart.right + ::MulDiv(rcDelta.right, dwTimeElapsed, wxABT_AUTOHIDETIME); + rect.bottom = rcStart.bottom + ::MulDiv(rcDelta.bottom, dwTimeElapsed, wxABT_AUTOHIDETIME); + + // Show the window at its changed position + wxVERIFY(::SetWindowPos(m_hWnd, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE)); + wxVERIFY(::UpdateWindow(m_hWnd)); + } + } + } + + if (show) + m_flags &= ~wxABF_AUTOHIDDEN; + else + m_flags |= wxABF_AUTOHIDDEN; + + if (bVisible) { + wxVERIFY(::SetWindowPos(m_hWnd, NULL, rcEnd.left, rcEnd.top, rcEnd.right - rcEnd.left, rcEnd.bottom - rcEnd.top, SWP_NOZORDER | SWP_NOACTIVATE)); + wxVERIFY(::UpdateWindow(m_hWnd)); + // Reset auto-hide timer. + m_timerID = ::SetTimer(m_hWnd, wxABT_AUTOHIDETIMERID, wxABT_AUTOHIDETIMERINTERVAL, NULL); + } +} + + +template +void wxAppBar::OnChangeState(wxAppBarState stateNew) +{ + if (stateNew == wxABS_FLOAT) { + if (m_flags & wxABF_HIDETASKBARTABWHENFLOATING) { + // Hide our application bar's entry on the Windows's taskbar. + wxModifyStyleEx(m_hWnd, 0, WS_EX_TOOLWINDOW); + if (m_taskbarList) + wxVERIFY(SUCCEEDED(m_taskbarList->DeleteTab(m_hWnd))); + } else if (m_flags & wxABF_HIDETASKBARTABWHENDOCKED) { + // Show our application bar's entry on the Windows's taskbar. + wxModifyStyleEx(m_hWnd, WS_EX_TOOLWINDOW, 0); + if (m_taskbarList) + wxVERIFY(SUCCEEDED(m_taskbarList->AddTab(m_hWnd))); + } + } else if (wxAppBarIsDocked(stateNew)) { + if (m_flags & wxABF_HIDETASKBARTABWHENDOCKED) { + // Hide our application bar's entry on the Windows's taskbar. + wxModifyStyleEx(m_hWnd, 0, WS_EX_TOOLWINDOW); + if (m_taskbarList) + wxVERIFY(SUCCEEDED(m_taskbarList->DeleteTab(m_hWnd))); + } else if (m_flags & wxABF_HIDETASKBARTABWHENFLOATING) { + // Show our application bar's entry on the Windows's taskbar. + wxModifyStyleEx(m_hWnd, WS_EX_TOOLWINDOW, 0); + if (m_taskbarList) + wxVERIFY(SUCCEEDED(m_taskbarList->AddTab(m_hWnd))); + } + } else { + // Unknown state. + wxFAIL; + } +} + + +template +void wxAppBar::OnChangeTaskBarState(UINT_PTR state) +{ + if (state != m_stateTaskBar) { + // No change, no fun. + return; + } + + if ((m_flags & wxABF_ALWAYSONTOPTASKBAR) && + (m_stateTaskBar & ABS_ALWAYSONTOP) != (state & ABS_ALWAYSONTOP)) { + // Always-on-top state of the taskbar changed and we're supposed to mimic it. + SetAlwaysOnTop((state & ABS_ALWAYSONTOP) ? true : false); + } + + if ((m_flags & wxABF_AUTOHIDETASKBAR) && + (m_stateTaskBar & ABS_AUTOHIDE) != (state & ABS_AUTOHIDE)) { + // Auto-hide state of the taskbar changed and we're supposed to mimic it. + SetAutoHide((state & ABS_AUTOHIDE) ? true : false); + } + + // Remember the state. + m_stateTaskBar = state; +} + + +template +void wxAppBar::OnWindowsArrange(bool WXUNUSED(beginning)) +{ +} + + +template +void wxAppBar::OnAutoHideDenied() +{ + wxMessageBox(wxT("There is already an auto hidden bar on this edge.\nOnly one auto hidden bar is allowed on each edge.\nAuto-hide feature is now off."), wxT("Warning"), wxOK | wxICON_WARNING, this); +} + + +template +WXLRESULT wxAppBar::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +{ + switch (message) { + case WM_CREATE: { + WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam); + + // Register our application bar. + APPBARDATA abd = { sizeof(abd), m_hWnd, WM_AB_NOTIFY, m_state }; + wxCHECK(::SHAppBarMessage(ABM_NEW, &abd), false); + + // Get the state of the Windows taskbar. + m_stateTaskBar = wxAppBarGetTaskBarState(); + + if (m_flags & wxABF_AUTOHIDETASKBAR) { + // Mimic the auto-hide state of taskbar. + SetAutoHide((m_stateTaskBar & ABS_AUTOHIDE) ? true : false); + } + + if (m_flags & wxABF_ALWAYSONTOPTASKBAR) { + // Mimic the always-on-top state of taskbar. + SetAlwaysOnTop((m_stateTaskBar & ABS_ALWAYSONTOP) ? true : false); + } + + return lResult; + } + + case WM_DESTROY: { + wxASSERT(m_timerID == 0); + + // Remove the application bar. + APPBARDATA abd = { sizeof(abd), m_hWnd }; + wxVERIFY(::SHAppBarMessage(ABM_REMOVE, &abd)); + + return W::MSWWindowProc(message, wParam, lParam); + } + + case WM_SHOWWINDOW: + if (wParam) { + // Do the false change of state notification, to allow initialization. + OnChangeState(m_state); + + if (wxAppBarIsDocked(m_state)) { + if (IsAutoHide()) { + // Register auto-hide application bar. + RegisterAutoHide(m_state); + } else { + // Auto-hide failed or wasn't desired at all. + DockAppBar(m_state); + } + } + + // We're all set. Show the window now. + return W::MSWWindowProc(message, wParam, lParam); + } else { + // Hide the window first, to avoid flicker. + WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam); + + // Clean previous docking/auto-hide settings if required. + if (wxAppBarIsDocked(m_state)) { + if (IsAutoHide()) + UnregisterAutoHide(m_state); + else + UndockAppBar(); + } + + return lResult; + } + + case WM_WINDOWPOSCHANGING: { + if (m_state != m_stateDesired && wxAppBarIsDocked(m_stateDesired)) { + wxASSERT(lParam); + LPWINDOWPOS lpwndpos = (LPWINDOWPOS)lParam; + + // When about to get docked, fix position and size to avoid Aero Snap interfering with window size. + RECT rect; + GetDockedRect(m_stateDesired, &rect); + lpwndpos->x = rect.left; + lpwndpos->y = rect.top; + lpwndpos->cx = rect.right - rect.left; + lpwndpos->cy = rect.bottom - rect.top; + lpwndpos->flags &= ~(SWP_NOMOVE | SWP_NOSIZE); + } + + return W::MSWWindowProc(message, wParam, lParam); + } + + case WM_WINDOWPOSCHANGED: { + WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam); + + if (wxAppBarIsDocked(m_state)) { + // When our window changes position, tell the Shell so that any + // auto-hidden application bar on our edge stays on top of our window making it + // always accessible to the user. + APPBARDATA abd = { sizeof(abd), m_hWnd }; + wxVERIFY(::SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd)); + } + + return lResult; + } + + case WM_ENTERSIZEMOVE: + m_stateDesired = m_state; + return W::MSWWindowProc(message, wParam, lParam); + + case WM_EXITSIZEMOVE: { + WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam); + + // Clean previous docking/auto-hide settings if required. + if (wxAppBarIsDocked(m_state) && + (m_stateDesired == wxABS_FLOAT || m_stateDesired != m_state && wxAppBarIsDocked(m_stateDesired))) + { + if (IsAutoHide()) + UnregisterAutoHide(m_state); + else if (m_stateDesired == wxABS_FLOAT) + UndockAppBar(); + } + + // Setup new docking/auto-hide settings. + if (wxAppBarIsDocked(m_stateDesired)) { + if (IsAutoHide()) { + // Application bar should be auto-hide. Try to setup it as so. + // Register auto-hide application bar. + RegisterAutoHide(m_stateDesired); + } else { + // Auto-hide failed or wasn't desired at all. + DockAppBar(m_stateDesired); + } + } + + // Notify about the change of state. + OnChangeState(m_stateDesired); + m_state = m_stateDesired; + m_stateDesired = wxABS_UNKNOWN; + + return lResult; + } + + case WM_MOVING: { + WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam); + + wxASSERT(lParam); + LPRECT lpRect = (LPRECT)lParam; + + // Phase 1. - Determine the desired state (which screen edge or floating) according to the mouse position. + + wxAppBarState uStateDesiredPrev = m_stateDesired; + DWORD dwPoint = ::GetMessagePos(); + wxPoint ptMouse(GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint)); + + m_stateDesired = wxABS_UNKNOWN; + + if ((m_flags & wxABF_ALLOWFLOAT) && (::GetKeyState(VK_CONTROL) < 0 || !(m_flags & wxABF_ALLOWDOCKANY))) { + // The application bar's style allows floating and user is holding down the Ctrl key, or docking is disabled anyway, so we'll force float. + m_stateDesired = wxABS_FLOAT; + } else { + RECT rcWorkArea = {}; + INT iDist, iDistMin = INT_MAX; + + // Get the rectangle that bounds the size of the screen + // minus any docked (but not-autohidden) AppBars. + wxVERIFY(::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0)); + + // Test all four edges, to find the closest one. + if ((m_flags & wxABF_ALLOWDOCKTOP) && (iDist = ptMouse.y - rcWorkArea.top) < iDistMin) { + m_stateDesired = wxABS_TOP; + iDistMin = iDist; + } + if ((m_flags & wxABF_ALLOWDOCKBOTTOM) && (iDist = rcWorkArea.bottom - ptMouse.y) < iDistMin) { + m_stateDesired = wxABS_BOTTOM; + iDistMin = iDist; + } + if ((m_flags & wxABF_ALLOWDOCKLEFT) && (iDist = ptMouse.x - rcWorkArea.left) < iDistMin) { + m_stateDesired = wxABS_LEFT; + iDistMin = iDist; + } + if ((m_flags & wxABF_ALLOWDOCKRIGHT) && (iDist = rcWorkArea.right - ptMouse.x) < iDistMin) { + m_stateDesired = wxABS_RIGHT; + iDistMin = iDist; + } + if ((m_flags & wxABF_ALLOWFLOAT) && (iDist = wxMax(::GetSystemMetrics(SM_CXVSCROLL), ::GetSystemMetrics(SM_CYHSCROLL))) < iDistMin) { + m_stateDesired = wxABS_FLOAT; + iDistMin = iDist; + } + } + + // We must had come up with some useful state. + wxASSERT(m_stateDesired != wxABS_UNKNOWN); + + // Phase 2. - Calculate the desired rectangle, according to the desired state. + + if (m_stateDesired == wxABS_FLOAT) { + if (wxAppBarIsDocked(uStateDesiredPrev)) { + // We just switched from docked to floating state. Align the window according to the mouse pointer. + lpRect->left = ptMouse.x - m_sizeFloat.cx / 2; + lpRect->top = ptMouse.y; + + // We also resize back to floating window size. + lpRect->right = lpRect->left + m_sizeFloat.cx; + lpRect->bottom = lpRect->top + m_sizeFloat.cy; + } + } else if (wxAppBarIsDocked(m_stateDesired)) { + if (IsAutoHide()) { + // Calculate auto-hide window rect. + GetAutoHideRect(m_stateDesired, false, lpRect); + } else { + // Calculate docked window rect. + GetDockedRect(m_stateDesired, lpRect); + } + } else { + // Window is not floating. It's not docked either. Then what? + wxFAIL; + } + + if (m_stateDesired != uStateDesiredPrev) { + // Notify about the proposed change of state, but don't change the state yet. + OnChangeState(m_stateDesired); + } + + return lResult; + } + + case WM_SIZING: { + wxASSERT(lParam); + LPRECT lpRect = (LPRECT)lParam; + + if (m_stateDesired == wxABS_FLOAT) { + // Remember the floating window size. + m_sizeFloat.cx = lpRect->right - lpRect->left; + m_sizeFloat.cy = lpRect->bottom - lpRect->top; + } else if (wxAppBarIsDocked(m_stateDesired)) { + // Remember the docked window size. + if (wxAppBarIsDockedVert(m_stateDesired)) + m_sizeDocked.cx = lpRect->right - lpRect->left; + else + m_sizeDocked.cy = lpRect->bottom - lpRect->top; + } else { + // Unknown state. + wxFAIL; + } + + return W::MSWWindowProc(message, wParam, lParam); + } + + case WM_GETMINMAXINFO: { + WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam); + + wxASSERT(lParam); + LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam; + + // Convert client size to window size. + RECT rectClient = {}; + wxVERIFY(::GetClientRect(m_hWnd, &rectClient)); + if (rectClient.right - rectClient.left && rectClient.bottom - rectClient.top) { + RECT rectWindow = {}; + wxVERIFY(::GetWindowRect(m_hWnd, &rectWindow)); + lpMMI->ptMinTrackSize.x = m_sizeMin.cx + (rectWindow.right - rectWindow.left) - (rectClient.right - rectClient.left); + lpMMI->ptMinTrackSize.y = m_sizeMin.cy + (rectWindow.bottom - rectWindow.top ) - (rectClient.bottom - rectClient.top ); + } + + return lResult; + } + + case WM_NCMOUSEMOVE: + // If we are a docked, auto-hidden application bar, shown us + // when the user moves over our non-client area + ShowAutoHideAppBar(true); + + return W::MSWWindowProc(message, wParam, lParam); + + case WM_NCHITTEST: { + // Find out what the base class thinks is the hit test code. + WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam); + + if (HTSIZEFIRST <= lResult && lResult <= HTSIZELAST) { + if (GetAllowSizing()) { + if (wxAppBarIsDocked(m_state)) { + // When the application bar is docked, the user can resize only one edge. + // This next section determines which edge the user can resize. + // To allow resizing, the application bar window must have the WS_THICKFRAME style. + + RECT rcClient = {}; + wxPoint point(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + + // Resizing IS allowed for the edge that the application bar is docked on. + // Get the location of the appbar's client area in screen coordinates. + wxVERIFY(::GetClientRect(m_hWnd, &rcClient)); + wxVERIFY(::ClientToScreen(m_hWnd, (LPPOINT)&rcClient)); + wxVERIFY(::ClientToScreen(m_hWnd, ((LPPOINT)&rcClient) + 1)); + + // Assume that we can't resize + lResult = HTBORDER; + + switch (m_state) { + case wxABS_LEFT: if (point.x > rcClient.right) lResult = HTRIGHT; break; + case wxABS_TOP: if (point.y > rcClient.bottom) lResult = HTBOTTOM; break; + case wxABS_RIGHT: if (point.x < rcClient.left) lResult = HTLEFT; break; + case wxABS_BOTTOM: if (point.y < rcClient.top) lResult = HTTOP; break; + } + } + } else { + // The sizing is locked. Pretend that the mouse is not on a resize border. + lResult = HTBORDER; + } + } + + return lResult; + } + + case WM_ACTIVATE: { + WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam); + + if (wxAppBarIsDocked(m_state)) { + // When our window changes activation state, tell the Shell so that any + // auto-hidden application bar on our edge stays on top of our window making it + // always accessible to the user. + APPBARDATA abd = { sizeof(abd), m_hWnd }; + wxVERIFY(::SHAppBarMessage(ABM_ACTIVATE, &abd)); + + if (LOWORD(wParam) == WA_INACTIVE && IsAutoHide()) { + // Hide the application bar if we are docked and auto-hidden. + ShowAutoHideAppBar(false); + } + } + + return lResult; + } + + case WM_TIMER: + if (wParam == wxABT_AUTOHIDETIMERID) { + if (!GetAutoHidden() && + wxAppBarIsDocked(m_state) && + GetActiveWindow() != m_hWnd) + { + // Get the position of the mouse and the application bar's position + // Everything must be in screen coordinates. + DWORD dwPoint = ::GetMessagePos(); + wxPoint pointMouse(GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint)); + RECT rect = {}; + wxVERIFY(::GetWindowRect(m_hWnd, &rect)); + wxRect rectBounds(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); + + // Add a little margin around the application bar + rectBounds.Inflate(2 * ::GetSystemMetrics(SM_CXDOUBLECLK), 2 * ::GetSystemMetrics(SM_CYDOUBLECLK)); + if (!rectBounds.Contains(pointMouse)) { + // If the mouse is NOT over or near the application bar, hide it. + ShowAutoHideAppBar(false); + } + } + + return 0; + } else + return W::MSWWindowProc(message, wParam, lParam); + + case WM_AB_NOTIFY: + switch (wParam) { + case ABN_FULLSCREENAPP: + if (lParam) + m_flags |= wxABF_FULLSCREENAPPOPEN; + else + m_flags &= ~wxABF_FULLSCREENAPPOPEN; + OnChangeTaskBarState(wxAppBarGetTaskBarState()); + + if (::IsWindowVisible(m_hWnd)) { + // Set the Z-order. + wxVERIFY(::SetWindowPos(m_hWnd, wxAppBarGetZWnd(m_state, m_flags), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOSENDCHANGING)); + } + break; + + case ABN_POSCHANGED: + if (wxAppBarIsDocked(m_state) && !IsAutoHide()) + DockAppBar(m_state); + break; + + case ABN_STATECHANGE: + // Taskbar's state changed. + OnChangeTaskBarState(wxAppBarGetTaskBarState()); + break; + + case ABN_WINDOWARRANGE: + OnWindowsArrange(lParam ? true : false); + break; + + default: + // Unknown message. + wxFAIL; + break; + } + + return 0; + + default: + return W::MSWWindowProc(message, wParam, lParam); + } +} + + +template +inline bool wxAppBar::DockAppBar(wxAppBarState state) +{ + wxASSERT(wxAppBarIsDocked(state)); + + // Calculate docked window rect and dock the window there. + APPBARDATA abd = { sizeof(abd), m_hWnd, 0, state }; + GetDockedRect(state, &(abd.rc)); + wxCHECK(::SHAppBarMessage(ABM_SETPOS, &abd), false); + wxCHECK(::SetWindowPos(m_hWnd, wxAppBarGetZWnd(state, m_flags), abd.rc.left, abd.rc.top, abd.rc.right - abd.rc.left, abd.rc.bottom - abd.rc.top, SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_FRAMECHANGED), false); + + return true; +} + + +template +inline bool wxAppBar::UndockAppBar() +{ + // Free application bar's space to undock. + APPBARDATA abd = { sizeof(abd), m_hWnd, 0, wxABS_LEFT }; + wxASSERT(!abd.rc.left && !abd.rc.top && !abd.rc.right && !abd.rc.bottom); + wxCHECK(::SHAppBarMessage(ABM_SETPOS, &abd), false); + + return true; +} + + +template +inline bool wxAppBar::RegisterAutoHide(wxAppBarState state) +{ + wxASSERT(wxAppBarIsDocked(state)); + + // Register application bar as auto-hide. + APPBARDATA abd = { sizeof(abd), m_hWnd, 0, state, {}, (LPARAM)true }; + if (::SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd)) { + // Auto-hide succeeded. + m_flags |= wxABF_AUTOHIDE; + m_flags &= ~wxABF_AUTOHIDDEN; + + // Calculate auto-hidden window rect and move the window there. + GetAutoHideRect(state, false, &(abd.rc)); + wxCHECK(::SetWindowPos(m_hWnd, wxAppBarGetZWnd(state, m_flags), abd.rc.left, abd.rc.top, abd.rc.right - abd.rc.left, abd.rc.bottom - abd.rc.top, SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_FRAMECHANGED), false); + + // Reset auto-hide timer. + m_timerID = ::SetTimer(m_hWnd, wxABT_AUTOHIDETIMERID, wxABT_AUTOHIDETIMERINTERVAL, NULL); + + return true; + } else { + // Auto-hide failed; some other application bar must be hidden on this edge already. + m_flags &= ~(wxABF_AUTOHIDE | wxABF_AUTOHIDDEN); + + // Post a message to user. + OnAutoHideDenied(); + + return false; + } +} + + +template +inline bool wxAppBar::UnregisterAutoHide(wxAppBarState state) +{ + wxASSERT(wxAppBarIsDocked(state)); + + // Unregister application bar as auto-hide. + APPBARDATA abd = { sizeof(abd), m_hWnd, 0, state, {}, (LPARAM)false }; + wxCHECK(::SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd), false); + m_flags &= ~wxABF_AUTOHIDDEN; + + // Cancel the timer. + if (m_timerID) { + ::KillTimer(m_hWnd, m_timerID); + m_timerID = 0; + } + + return true; +} + + +template +inline bool wxAppBar::GetDockedRect(wxAppBarState state, LPRECT rect) const +{ + wxASSERT(rect); + wxASSERT(wxAppBarIsDocked(state)); + + // Set dimensions to full screen. + APPBARDATA abd = { sizeof(abd), m_hWnd, 0, state, { 0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN) } }; + wxCHECK(::SHAppBarMessage(ABM_QUERYPOS, &abd), false); + + // Correct our dimensions accordingly. + switch (state) { + case wxABS_LEFT: + rect->left = abd.rc.left; + rect->top = abd.rc.top; + rect->right = abd.rc.left + m_sizeDocked.cx; + rect->bottom = abd.rc.bottom; + break; + + case wxABS_TOP: + rect->left = abd.rc.left; + rect->top = abd.rc.top; + rect->right = abd.rc.right; + rect->bottom = abd.rc.top + m_sizeDocked.cy; + break; + + case wxABS_RIGHT: + rect->left = abd.rc.right - m_sizeDocked.cx; + rect->top = abd.rc.top; + rect->right = abd.rc.right; + rect->bottom = abd.rc.bottom; + break; + + case wxABS_BOTTOM: + rect->left = abd.rc.left; + rect->top = abd.rc.bottom - m_sizeDocked.cy; + rect->right = abd.rc.right; + rect->bottom = abd.rc.bottom; + break; + + default: + // Unknown state. + wxFAIL; + return false; + } + + return true; +} + + +template +inline bool wxAppBar::GetAutoHideRect(wxAppBarState state, bool bAutoHidden, LPRECT rect) const +{ + wxASSERT(rect); + wxASSERT(wxAppBarIsDocked(state)); + + // Keep a part of the application bar visible at all times + const int iBorder = ::GetSystemMetrics(wxAppBarIsDockedVert(state) ? SM_CXBORDER : SM_CYBORDER) * 2; + const RECT rcScreen = { + 0, + 0, + ::GetSystemMetrics(SM_CXSCREEN), + ::GetSystemMetrics(SM_CYSCREEN) + }; + + // Correct our dimensions accordingly. + switch (state) { + case wxABS_LEFT: + rect->top = rcScreen.top; + rect->bottom = rcScreen.bottom; + rect->right = rcScreen.left + (bAutoHidden ? iBorder : m_sizeDocked.cx); + rect->left = rect->right - m_sizeDocked.cx; + break; + + case wxABS_TOP: + rect->left = rcScreen.left; + rect->right = rcScreen.right; + rect->bottom = rcScreen.top + (bAutoHidden ? iBorder : m_sizeDocked.cy); + rect->top = rect->bottom - m_sizeDocked.cy; + break; + + case wxABS_RIGHT: + rect->left = rcScreen.right - (bAutoHidden ? iBorder : m_sizeDocked.cx); + rect->top = rcScreen.top; + rect->right = rect->left + m_sizeDocked.cx; + rect->bottom = rcScreen.bottom; + break; + + case wxABS_BOTTOM: + rect->left = rcScreen.left; + rect->top = rcScreen.bottom - (bAutoHidden ? iBorder : m_sizeDocked.cy); + rect->right = rcScreen.right; + rect->bottom = rect->top + m_sizeDocked.cy; + break; + + default: + // Unknown state. + wxFAIL; + return false; + } + + return true; +} diff --git a/src/appbar.cpp b/src/appbar.cpp index acc2c3f..a8dd5d2 100644 --- a/src/appbar.cpp +++ b/src/appbar.cpp @@ -22,809 +22,58 @@ ////////////////////////////////////////////////////////////////////////// -// wxAppBar +// wxAppBarFrame ////////////////////////////////////////////////////////////////////////// -const UINT wxAppBar::WM_AB_NOTIFY = ::RegisterWindowMessage(_T("AppBarNotify")); - - -wxAppBar::wxAppBar() : - m_timerID(0), - m_taskbarList(NULL), - wxFrame() +wxAppBarFrame::wxAppBarFrame() { + Init(); } -wxAppBar::wxAppBar(wxWindow *parent, wxWindowID id, const wxString& title, wxState state, int flags, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : - m_timerID(0), - m_taskbarList(NULL), - wxFrame() +wxAppBarFrame::wxAppBarFrame(wxWindow *parent, wxWindowID id, const wxString& title, wxAppBarState state, int flags, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { + Init(); Create(parent, id, title, state, flags, pos, size, style, name); } -bool wxAppBar::Create(wxWindow *parent, wxWindowID id, const wxString& title, wxState state, int flags, const wxPoint& pos, const wxSize& size, long style, const wxString& name) +bool wxAppBarFrame::Create(wxWindow *parent, wxWindowID id, const wxString& title, wxAppBarState state, int flags, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { - // Save initial floating window size. - m_sizeFloat.cx = size.x; - m_sizeFloat.cy = size.y; - - // Save initial docked window width/height. - m_sizeDocked.cx = size.x; - m_sizeDocked.cy = size.y; - - // Save initial state and flags. - m_state = state; - m_stateDesired = wxSTATE_UNKNOWN; - m_flags = flags; - - // Find the taskbar list's interface. - wxCHECK(SUCCEEDED(::CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_ALL, IID_ITaskbarList, (LPVOID*)&m_taskbarList)), false); - wxCHECK(SUCCEEDED(m_taskbarList->HrInit()), false); - - // If any taskbar list tab's hiding is in affect, set application bar's style as tool window to avoid being displayed on the taskbar initially. - if (state == wxSTATE_FLOAT) { - if (flags & wxFLAG_HIDETASKBARTABWHENFLOATING) { - // Hide our application bar's entry on the Windows's taskbar. - style |= wxFRAME_TOOL_WINDOW; - } else if (flags & wxFLAG_HIDETASKBARTABWHENDOCKED) { - // Show our application bar's entry on the Windows's taskbar. - style &= ~wxFRAME_TOOL_WINDOW; - } - } else if (IsDocked(state)) { - if (flags & wxFLAG_HIDETASKBARTABWHENDOCKED) { - // Hide our application bar's entry on the Windows's taskbar. - style |= wxFRAME_TOOL_WINDOW; - } else if (flags & wxFLAG_HIDETASKBARTABWHENFLOATING) { - // Show our application bar's entry on the Windows's taskbar. - style &= ~wxFRAME_TOOL_WINDOW; - } - } else { - // Unknown state. - wxFAIL; - } + // Modify parameters if required. + PreCreate(state, flags, size, style); // Create frame. - wxCHECK(wxFrame::Create(parent, id, title, pos, size, style, name), false); - - // Register our application bar. - APPBARDATA abd = { sizeof(abd), m_hWnd, WM_AB_NOTIFY, m_state }; - wxCHECK(::SHAppBarMessage(ABM_NEW, &abd), false); - - // Get the state of the Windows taskbar. - m_stateTaskBar = GetTaskBarState(); - - if (m_flags & wxFLAG_AUTOHIDETASKBAR) { - // Mimic the auto-hide state of taskbar. - SetAutoHide((m_stateTaskBar & ABS_AUTOHIDE) ? true : false); - } - - if (m_flags & wxFLAG_ALWAYSONTOPTASKBAR) { - // Mimic the always-on-top state of taskbar. - SetAlwaysOnTop((m_stateTaskBar & ABS_ALWAYSONTOP) ? true : false); - } + wxCHECK(wxAppBar::Create(parent, id, title, pos, size, style, name), false); return true; } -wxAppBar::~wxAppBar() +////////////////////////////////////////////////////////////////////////// +// wxAppBarDialog +////////////////////////////////////////////////////////////////////////// + +wxAppBarDialog::wxAppBarDialog() { - wxASSERT(m_timerID == 0); - - // Remove the application bar. - APPBARDATA abd = { sizeof(abd), m_hWnd }; - wxVERIFY(::SHAppBarMessage(ABM_REMOVE, &abd)); - - if (m_taskbarList) - m_taskbarList->Release(); + Init(); } -//bool wxAppBar::GetAppBarPlacement(LPAPPBARPLACEMENT lpPlacement) const -//{ -// wxASSERT(lpPlacement); -// -// if (lpPlacement->dwSize >= sizeof(APPBARPLACEMENT1)) { -// lpPlacement->dwState = (DWORD)m_state; -// lpPlacement->dwFlags = m_flags; -// if (m_state == wxSTATE_FLOAT) { -// // Current application bar's rect is floating rect. -// lpPlacement->rcFloat = m_rect; -// } else if (IsDocked(m_state)) { -// // Application bar is docked. Calc floating rect from m_sizeFloat. -// lpPlacement->rcFloat.left = 0; -// lpPlacement->rcFloat.top = 0; -// lpPlacement->rcFloat.right = m_sizeFloat.cx; -// lpPlacement->rcFloat.bottom = m_sizeFloat.cy; -// } else { -// // Application bar's state is unknown. -// return false; -// } -// lpPlacement->szDocked = m_sizeDocked; -// } -// -// lpPlacement->dwSize = sizeof(*lpPlacement); -// -// return true; -//} -// -// -//bool wxAppBar::SetAppBarPlacement(LPCAPPBARPLACEMENT lpPlacement) -//{ -// wxASSERT(lpPlacement); -// -// if (lpPlacement->dwSize >= sizeof(APPBARPLACEMENT1)) { -// if (lpPlacement->dwState != wxSTATE_FLOAT && !IsDocked(lpPlacement->dwState)) { -// // The state is unknown. Abort, before we mix up internal state. -// return false; -// } -// -// // Clean previous docking/auto-hide settings if required. -// if (IsDocked(m_state) && -// (lpPlacement->dwState == wxSTATE_FLOAT || lpPlacement->dwState != m_state && IsDocked(lpPlacement->dwState))) -// { -// if (IsAutoHide()) -// UnregisterAutoHide(m_state); -// else if (lpPlacement->dwState == wxSTATE_FLOAT) -// UndockAppBar(); -// } -// -// // Update application bar's flags, size and position. -// m_flags |= wxFLAG_POSITIONSET; -// m_sizeDocked = lpPlacement->szDocked; -// if (lpPlacement->dwState == wxSTATE_FLOAT) { -// m_rect = lpPlacement->rcFloat; -// } else if (IsDocked(lpPlacement->dwState)) { -// m_sizeFloat.cx = lpPlacement->rcFloat.right - lpPlacement->rcFloat.left; -// m_sizeFloat.cy = lpPlacement->rcFloat.bottom - lpPlacement->rcFloat.top; -// GetDockedRect(lpPlacement->dwState, &m_rect); -// } else { -// // Application bar's state is unknown. -// wxFAIL; -// return false; -// } -// -// // Notify about the change of state. -// OnChangeState(lpPlacement->dwState); -// m_state = lpPlacement->dwState; -// -// SetAutoHide(lpPlacement->dwFlags & wxFLAG_AUTOHIDE); -// SetAlwaysOnTop(lpPlacement->dwFlags & wxFLAG_ALWAYSONTOP); -// } -// -// return true; -//} - - -void wxAppBar::MinimiseToEdge(wxState edge, wxWindow *wnd) +wxAppBarDialog::wxAppBarDialog(wxWindow *parent, wxWindowID id, const wxString& title, wxAppBarState state, int flags, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { - wxASSERT(IsDocked(edge)); - - WXHWND hWnd; - if (!wnd) { - // No other window was specified. Minimize ourself. - wnd = this; - hWnd = m_hWnd; - } else - hWnd = wnd->GetHWND(); - - // If our window is hidden, there's nothing we can do. - if (hWnd == m_hWnd && !::IsWindowVisible(m_hWnd)) - return; - - if (m_state == wxSTATE_FLOAT) { - // Remember the last floating size. - RECT rect = {}; - wxVERIFY(::GetWindowRect(hWnd, &rect)); - m_sizeFloat.cx = rect.right - rect.left; - m_sizeFloat.cy = rect.bottom - rect.top; - } - - RECT rectTo; - if (IsAutoHide()) - GetAutoHideRect(edge, false, &rectTo); - else - GetDockedRect(edge, &rectTo); - - if (::wxGetDoWndAnimation()) { - // Do the animation. - RECT rectFrom; - wxVERIFY(::GetWindowRect(hWnd, &rectFrom)); - wxVERIFY(::DrawAnimatedRects(hWnd, IDANI_CAPTION, &rectFrom, &rectTo)); - } - - // Notify about the change of state. - OnChangeState(edge); - m_state = edge; - - if (hWnd != m_hWnd) { - // Hide the source window. - wnd->Hide(); - // ::SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) &~ WS_VISIBLE); - - // Show the application bar. - Show(); - } else { - if (IsAutoHide()) { - // Register auto-hide application bar. - RegisterAutoHide(edge); - } else { - // Auto-hide failed or wasn't desired at all. - DockAppBar(edge); - } - } - - ::SetActiveWindow(m_hWnd); + Init(); + Create(parent, id, title, state, flags, pos, size, style, name); } -void wxAppBar::MaximiseFromEdge(const RECT* rect) +bool wxAppBarDialog::Create(wxWindow *parent, wxWindowID id, const wxString& title, wxAppBarState state, int flags, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { - wxASSERT(::IsWindowVisible(m_hWnd)); + // Modify parameters if required. + PreCreate(state, flags, size, style); - RECT rectTo; + // Create dialog. + wxCHECK(wxAppBar::Create(parent, id, title, pos, size, style, name), false); - if (!rect) { - // Calculate the destination rect. - rectTo.left = (::GetSystemMetrics(SM_CXSCREEN) - m_sizeFloat.cx) / 2; - rectTo.top = (::GetSystemMetrics(SM_CYSCREEN) - m_sizeFloat.cy) / 2; - rectTo.right = rectTo.left + m_sizeFloat.cx; - rectTo.bottom = rectTo.top + m_sizeFloat.cy; - - rect = &rectTo; - } else { - m_sizeFloat.cx = rect->right - rect->left; - m_sizeFloat.cy = rect->bottom - rect->top; - } - - if (::wxGetDoWndAnimation()) { - // Do the animation. - RECT rectFrom; - wxVERIFY(::GetWindowRect(m_hWnd, &rectFrom)); - wxVERIFY(::DrawAnimatedRects(m_hWnd, IDANI_CAPTION, &rectFrom, rect)); - } - - // Clean previous docking/auto-hide settings if required. - if (IsDocked(m_state)) { - if (IsAutoHide()) - UnregisterAutoHide(m_state); - else - UndockAppBar(); - } - - // Notify about the change of state. - OnChangeState(wxSTATE_FLOAT); - m_state = wxSTATE_FLOAT; - - wxVERIFY(::SetWindowPos(m_hWnd, GetZWnd(wxSTATE_FLOAT, m_flags), rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top, SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_FRAMECHANGED)); -} - - -void wxAppBar::MaximiseFromEdge(wxWindow *wnd) -{ - wxASSERT(wnd); - wxASSERT(::IsWindowVisible(m_hWnd)); - - WXHWND hWnd = wnd->GetHWND(); - - RECT rectTo = {}; - wxVERIFY(::GetWindowRect(hWnd, &rectTo)); - m_sizeFloat.cx = rectTo.right - rectTo.left; - m_sizeFloat.cy = rectTo.bottom - rectTo.top; - - if (::wxGetDoWndAnimation()) { - // Do the animation. - RECT rectFrom; - wxVERIFY(::GetWindowRect(m_hWnd, &rectFrom)); - wxVERIFY(::DrawAnimatedRects(hWnd, IDANI_CAPTION, &rectFrom, &rectTo)); - } - - // Hide our window and show the destination window. - Hide(); - wnd->Show(); - // ::SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) | WS_VISIBLE); - wxVERIFY(::SetForegroundWindow(hWnd)); - ::SetActiveWindow(hWnd); - // wxVERIFY(::RedrawWindow(hWnd, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_FRAME | RDW_INVALIDATE | RDW_ERASE)); -} - - -void wxAppBar::ShowAutoHideAppBar(bool bShow) -{ - RECT rcEnd; - bool - bFullDragOn, - bHidden = GetAutoHidden(), - bVisible = ::IsWindowVisible(m_hWnd) ? true : false; - - if (!IsAutoHide() || bHidden != bShow) { - // We're not setup for auto-hide or already in the desired state. - return; - } - - // Get our end window location. - GetAutoHideRect(m_state, !bHidden, &rcEnd); - - if (bVisible) { - RECT rcStart; - - // Only slide the window if the user has FullDrag turned on. - if (!::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &bFullDragOn, 0)) - bFullDragOn = false; - - // Get our start window location. - GetAutoHideRect(m_state, bHidden, &rcStart); - - if (bFullDragOn && (rcStart.left != rcEnd.left || rcStart.top != rcEnd.top || rcStart.right != rcEnd.right || rcStart.bottom != rcEnd.bottom)) { - // Get our starting and ending time. - DWORD dwTimeStart = ::GetTickCount(); - DWORD dwTimeElapsed; - RECT rcDelta; - - // Calculate difference between ending and starting rectangle. - rcDelta.left = rcEnd.left - rcStart.left; - rcDelta.top = rcEnd.top - rcStart.top; - rcDelta.right = rcEnd.right - rcStart.right; - rcDelta.bottom = rcEnd.bottom - rcStart.bottom; - - while ((dwTimeElapsed = ::GetTickCount() - dwTimeStart) < wxABT_AUTOHIDETIME) { - // Do the linear interpolation. - RECT rect; - rect.left = rcStart.left + ::MulDiv(rcDelta.left, dwTimeElapsed, wxABT_AUTOHIDETIME); - rect.top = rcStart.top + ::MulDiv(rcDelta.top, dwTimeElapsed, wxABT_AUTOHIDETIME); - rect.right = rcStart.right + ::MulDiv(rcDelta.right, dwTimeElapsed, wxABT_AUTOHIDETIME); - rect.bottom = rcStart.bottom + ::MulDiv(rcDelta.bottom, dwTimeElapsed, wxABT_AUTOHIDETIME); - - // Show the window at its changed position - wxVERIFY(::SetWindowPos(m_hWnd, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE)); - wxVERIFY(::UpdateWindow(m_hWnd)); - } - } - } - - if (bShow) - m_flags &= ~wxFLAG_AUTOHIDDEN; - else - m_flags |= wxFLAG_AUTOHIDDEN; - - if (bVisible) { - wxVERIFY(::SetWindowPos(m_hWnd, NULL, rcEnd.left, rcEnd.top, rcEnd.right - rcEnd.left, rcEnd.bottom - rcEnd.top, SWP_NOZORDER | SWP_NOACTIVATE)); - wxVERIFY(::UpdateWindow(m_hWnd)); - // Reset auto-hide timer. - m_timerID = ::SetTimer(m_hWnd, wxABT_AUTOHIDETIMERID, wxABT_AUTOHIDETIMERINTERVAL, NULL); - } -} - - -void wxAppBar::OnChangeState(wxState stateNew) -{ - if (stateNew == wxSTATE_FLOAT) { - if (m_flags & wxFLAG_HIDETASKBARTABWHENFLOATING) { - // Hide our application bar's entry on the Windows's taskbar. - wxModifyStyleEx(m_hWnd, 0, WS_EX_TOOLWINDOW); - if (m_taskbarList) - wxVERIFY(SUCCEEDED(m_taskbarList->DeleteTab(m_hWnd))); - } else if (m_flags & wxFLAG_HIDETASKBARTABWHENDOCKED) { - // Show our application bar's entry on the Windows's taskbar. - wxModifyStyleEx(m_hWnd, WS_EX_TOOLWINDOW, 0); - if (m_taskbarList) - wxVERIFY(SUCCEEDED(m_taskbarList->AddTab(m_hWnd))); - } - } else if (IsDocked(stateNew)) { - if (m_flags & wxFLAG_HIDETASKBARTABWHENDOCKED) { - // Hide our application bar's entry on the Windows's taskbar. - wxModifyStyleEx(m_hWnd, 0, WS_EX_TOOLWINDOW); - if (m_taskbarList) - wxVERIFY(SUCCEEDED(m_taskbarList->DeleteTab(m_hWnd))); - } else if (m_flags & wxFLAG_HIDETASKBARTABWHENFLOATING) { - // Show our application bar's entry on the Windows's taskbar. - wxModifyStyleEx(m_hWnd, WS_EX_TOOLWINDOW, 0); - if (m_taskbarList) - wxVERIFY(SUCCEEDED(m_taskbarList->AddTab(m_hWnd))); - } - } else { - // Unknown state. - wxFAIL; - } -} - - -void wxAppBar::OnChangeTaskBarState(UINT_PTR state) -{ - if (state != m_stateTaskBar) { - // No change, no fun. - return; - } - - if ((m_flags & wxFLAG_ALWAYSONTOPTASKBAR) && - (m_stateTaskBar & ABS_ALWAYSONTOP) != (state & ABS_ALWAYSONTOP)) { - // Always-on-top state of the taskbar changed and we're supposed to mimic it. - SetAlwaysOnTop((state & ABS_ALWAYSONTOP) ? true : false); - } - - if ((m_flags & wxFLAG_AUTOHIDETASKBAR) && - (m_stateTaskBar & ABS_AUTOHIDE) != (state & ABS_AUTOHIDE)) { - // Auto-hide state of the taskbar changed and we're supposed to mimic it. - SetAutoHide((state & ABS_AUTOHIDE) ? true : false); - } - - // Remember the state. - m_stateTaskBar = state; -} - - -void wxAppBar::OnWindowsArrange(bool WXUNUSED(bBeginning)) -{ -} - - -void wxAppBar::OnAutoHideDenied() -{ - wxMessageBox(wxT("There is already an auto hidden bar on this edge.\nOnly one auto hidden bar is allowed on each edge.\nAuto-hide feature is now off."), wxT("Warning"), wxOK | wxICON_WARNING, this); -} - - -WXLRESULT wxAppBar::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) -{ - switch (message) { - case WM_SHOWWINDOW: - if (wParam) { - // Do the false change of state notification, to allow initialization. - OnChangeState(m_state); - - if (IsDocked(m_state)) { - if (IsAutoHide()) { - // Register auto-hide application bar. - RegisterAutoHide(m_state); - } else { - // Auto-hide failed or wasn't desired at all. - DockAppBar(m_state); - } - } - - // We're all set. Show the window now. - return wxFrame::MSWWindowProc(message, wParam, lParam); - } else { - // Hide the window first, to avoid flicker. - WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam); - - // Clean previous docking/auto-hide settings if required. - if (IsDocked(m_state)) { - if (IsAutoHide()) - UnregisterAutoHide(m_state); - else - UndockAppBar(); - } - - return lResult; - } - - case WM_WINDOWPOSCHANGING: { - if (m_state != m_stateDesired && IsDocked(m_stateDesired)) { - wxASSERT(lParam); - LPWINDOWPOS lpwndpos = (LPWINDOWPOS)lParam; - - // When about to get docked, fix position and size to avoid Aero Snap interfering with window size. - RECT rect; - GetDockedRect(m_stateDesired, &rect); - lpwndpos->x = rect.left; - lpwndpos->y = rect.top; - lpwndpos->cx = rect.right - rect.left; - lpwndpos->cy = rect.bottom - rect.top; - lpwndpos->flags &= ~(SWP_NOMOVE | SWP_NOSIZE); - } - - return wxFrame::MSWWindowProc(message, wParam, lParam); - } - - case WM_WINDOWPOSCHANGED: { - WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam); - - if (IsDocked(m_state)) { - // When our window changes position, tell the Shell so that any - // auto-hidden application bar on our edge stays on top of our window making it - // always accessible to the user. - APPBARDATA abd = { sizeof(abd), m_hWnd }; - wxVERIFY(::SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd)); - } - - return lResult; - } - - case WM_ENTERSIZEMOVE: - m_stateDesired = m_state; - return wxFrame::MSWWindowProc(message, wParam, lParam); - - case WM_EXITSIZEMOVE: { - WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam); - - // Clean previous docking/auto-hide settings if required. - if (IsDocked(m_state) && - (m_stateDesired == wxSTATE_FLOAT || m_stateDesired != m_state && IsDocked(m_stateDesired))) - { - if (IsAutoHide()) - UnregisterAutoHide(m_state); - else if (m_stateDesired == wxSTATE_FLOAT) - UndockAppBar(); - } - - // Setup new docking/auto-hide settings. - if (IsDocked(m_stateDesired)) { - if (IsAutoHide()) { - // Application bar should be auto-hide. Try to setup it as so. - // Register auto-hide application bar. - RegisterAutoHide(m_stateDesired); - } else { - // Auto-hide failed or wasn't desired at all. - DockAppBar(m_stateDesired); - } - } - - // Notify about the change of state. - OnChangeState(m_stateDesired); - m_state = m_stateDesired; - m_stateDesired = wxSTATE_UNKNOWN; - - return lResult; - } - - case WM_MOVING: { - WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam); - - wxASSERT(lParam); - LPRECT lpRect = (LPRECT)lParam; - - // Phase 1. - Determine the desired state (which screen edge or floating) according to the mouse position. - - wxState uStateDesiredPrev = m_stateDesired; - DWORD dwPoint = ::GetMessagePos(); - wxPoint ptMouse(GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint)); - - m_stateDesired = wxSTATE_UNKNOWN; - - if ((m_flags & wxFLAG_ALLOWFLOAT) && (::GetKeyState(VK_CONTROL) < 0 || !(m_flags & wxFLAG_ALLOWDOCKANY))) { - // The application bar's style allows floating and user is holding down the Ctrl key, or docking is disabled anyway, so we'll force float. - m_stateDesired = wxSTATE_FLOAT; - } else { - RECT rcWorkArea = {}; - INT iDist, iDistMin = INT_MAX; - - // Get the rectangle that bounds the size of the screen - // minus any docked (but not-autohidden) AppBars. - wxVERIFY(::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0)); - - // Test all four edges, to find the closest one. - if ((m_flags & wxFLAG_ALLOWDOCKTOP) && (iDist = ptMouse.y - rcWorkArea.top) < iDistMin) { - m_stateDesired = wxSTATE_TOP; - iDistMin = iDist; - } - if ((m_flags & wxFLAG_ALLOWDOCKBOTTOM) && (iDist = rcWorkArea.bottom - ptMouse.y) < iDistMin) { - m_stateDesired = wxSTATE_BOTTOM; - iDistMin = iDist; - } - if ((m_flags & wxFLAG_ALLOWDOCKLEFT) && (iDist = ptMouse.x - rcWorkArea.left) < iDistMin) { - m_stateDesired = wxSTATE_LEFT; - iDistMin = iDist; - } - if ((m_flags & wxFLAG_ALLOWDOCKRIGHT) && (iDist = rcWorkArea.right - ptMouse.x) < iDistMin) { - m_stateDesired = wxSTATE_RIGHT; - iDistMin = iDist; - } - if ((m_flags & wxFLAG_ALLOWFLOAT) && (iDist = wxMax(::GetSystemMetrics(SM_CXVSCROLL), ::GetSystemMetrics(SM_CYHSCROLL))) < iDistMin) { - m_stateDesired = wxSTATE_FLOAT; - iDistMin = iDist; - } - } - - // We must had come up with some useful state. - wxASSERT(m_stateDesired != wxSTATE_UNKNOWN); - - // Phase 2. - Calculate the desired rectangle, according to the desired state. - - if (m_stateDesired == wxSTATE_FLOAT) { - if (IsDocked(uStateDesiredPrev)) { - // We just switched from docked to floating state. Align the window according to the mouse pointer. - lpRect->left = ptMouse.x - m_sizeFloat.cx / 2; - lpRect->top = ptMouse.y; - - // We also resize back to floating window size. - lpRect->right = lpRect->left + m_sizeFloat.cx; - lpRect->bottom = lpRect->top + m_sizeFloat.cy; - } - } else if (IsDocked(m_stateDesired)) { - if (IsAutoHide()) { - // Calculate auto-hide window rect. - GetAutoHideRect(m_stateDesired, false, lpRect); - } else { - // Calculate docked window rect. - GetDockedRect(m_stateDesired, lpRect); - } - } else { - // Window is not floating. It's not docked either. Then what? - wxFAIL; - } - - if (m_stateDesired != uStateDesiredPrev) { - // Notify about the proposed change of state, but don't change the state yet. - OnChangeState(m_stateDesired); - } - - return lResult; - } - - case WM_SIZING: { - wxASSERT(lParam); - LPRECT lpRect = (LPRECT)lParam; - - if (m_stateDesired == wxSTATE_FLOAT) { - // Remember the floating window size. - m_sizeFloat.cx = lpRect->right - lpRect->left; - m_sizeFloat.cy = lpRect->bottom - lpRect->top; - } else if (IsDocked(m_stateDesired)) { - // Remember the docked window size. - if (IsDockedVert(m_stateDesired)) - m_sizeDocked.cx = lpRect->right - lpRect->left; - else - m_sizeDocked.cy = lpRect->bottom - lpRect->top; - } else { - // Unknown state. - wxFAIL; - } - - return wxFrame::MSWWindowProc(message, wParam, lParam); - } - - case WM_GETMINMAXINFO: { - WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam); - - wxASSERT(lParam); - LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam; - - // Convert client size to window size. - RECT rectClient = {}; - wxVERIFY(::GetClientRect(m_hWnd, &rectClient)); - if (rectClient.right - rectClient.left && rectClient.bottom - rectClient.top) { - RECT rectWindow = {}; - wxVERIFY(::GetWindowRect(m_hWnd, &rectWindow)); - lpMMI->ptMinTrackSize.x = m_sizeMin.cx + (rectWindow.right - rectWindow.left) - (rectClient.right - rectClient.left); - lpMMI->ptMinTrackSize.y = m_sizeMin.cy + (rectWindow.bottom - rectWindow.top ) - (rectClient.bottom - rectClient.top ); - } - - return lResult; - } - - case WM_NCMOUSEMOVE: - // If we are a docked, auto-hidden application bar, shown us - // when the user moves over our non-client area - ShowAutoHideAppBar(true); - - return wxFrame::MSWWindowProc(message, wParam, lParam); - - case WM_NCHITTEST: { - // Find out what the base class thinks is the hit test code. - WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam); - - if (HTSIZEFIRST <= lResult && lResult <= HTSIZELAST) { - if (GetAllowSizing()) { - if (IsDocked(m_state)) { - // When the application bar is docked, the user can resize only one edge. - // This next section determines which edge the user can resize. - // To allow resizing, the application bar window must have the WS_THICKFRAME style. - - RECT rcClient = {}; - wxPoint point(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); - - // Resizing IS allowed for the edge that the application bar is docked on. - // Get the location of the appbar's client area in screen coordinates. - wxVERIFY(::GetClientRect(m_hWnd, &rcClient)); - wxVERIFY(::ClientToScreen(m_hWnd, (LPPOINT)&rcClient)); - wxVERIFY(::ClientToScreen(m_hWnd, ((LPPOINT)&rcClient) + 1)); - - // Assume that we can't resize - lResult = HTBORDER; - - switch (m_state) { - case wxSTATE_LEFT: if (point.x > rcClient.right) lResult = HTRIGHT; break; - case wxSTATE_TOP: if (point.y > rcClient.bottom) lResult = HTBOTTOM; break; - case wxSTATE_RIGHT: if (point.x < rcClient.left) lResult = HTLEFT; break; - case wxSTATE_BOTTOM: if (point.y < rcClient.top) lResult = HTTOP; break; - } - } - } else { - // The sizing is locked. Pretend that the mouse is not on a resize border. - lResult = HTBORDER; - } - } - - return lResult; - } - - case WM_ACTIVATE: { - WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam); - - if (IsDocked(m_state)) { - // When our window changes activation state, tell the Shell so that any - // auto-hidden application bar on our edge stays on top of our window making it - // always accessible to the user. - APPBARDATA abd = { sizeof(abd), m_hWnd }; - wxVERIFY(::SHAppBarMessage(ABM_ACTIVATE, &abd)); - - if (LOWORD(wParam) == WA_INACTIVE && IsAutoHide()) { - // Hide the application bar if we are docked and auto-hidden. - ShowAutoHideAppBar(false); - } - } - - return lResult; - } - - case WM_TIMER: - if (wParam == wxABT_AUTOHIDETIMERID) { - if (!GetAutoHidden() && - IsDocked(m_state) && - GetActiveWindow() != m_hWnd) - { - // Get the position of the mouse and the application bar's position - // Everything must be in screen coordinates. - DWORD dwPoint = ::GetMessagePos(); - wxPoint pointMouse(GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint)); - RECT rect = {}; - wxVERIFY(::GetWindowRect(m_hWnd, &rect)); - wxRect rectBounds(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); - - // Add a little margin around the application bar - rectBounds.Inflate(2 * ::GetSystemMetrics(SM_CXDOUBLECLK), 2 * ::GetSystemMetrics(SM_CYDOUBLECLK)); - if (!rectBounds.Contains(pointMouse)) { - // If the mouse is NOT over or near the application bar, hide it. - ShowAutoHideAppBar(false); - } - } - - return 0; - } else - return wxFrame::MSWWindowProc(message, wParam, lParam); - - default: - if (message == WM_AB_NOTIFY) { - switch (wParam) { - case ABN_FULLSCREENAPP: - if (lParam) - m_flags |= wxFLAG_FULLSCREENAPPOPEN; - else - m_flags &= ~wxFLAG_FULLSCREENAPPOPEN; - OnChangeTaskBarState(GetTaskBarState()); - - if (::IsWindowVisible(m_hWnd)) { - // Set the Z-order. - wxVERIFY(::SetWindowPos(m_hWnd, GetZWnd(m_state, m_flags), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOSENDCHANGING)); - } - break; - - case ABN_POSCHANGED: - if (IsDocked(m_state) && !IsAutoHide()) - DockAppBar(m_state); - break; - - case ABN_STATECHANGE: - // Taskbar's state changed. - OnChangeTaskBarState(GetTaskBarState()); - break; - - case ABN_WINDOWARRANGE: - OnWindowsArrange(lParam ? true : false); - break; - - default: - // Unknown message. - wxFAIL; - break; - } - - return 0; - } else - return wxFrame::MSWWindowProc(message, wParam, lParam); - } + return true; } diff --git a/src/stdafx.h b/src/stdafx.h index 439ed65..0903663 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -27,5 +27,3 @@ #include "../include/wxex/appex.h" #include "../include/wxex/common.h" - -#include