diff --git a/lib/wxExtend/build/wxExtend.vcxproj b/lib/wxExtend/build/wxExtend.vcxproj
new file mode 100644
index 0000000..0845e5b
--- /dev/null
+++ b/lib/wxExtend/build/wxExtend.vcxproj
@@ -0,0 +1,90 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
+
+ {A3A36689-AC35-4026-93DA-A3BA0C0E767C}
+ wxExtend
+
+
+
+ StaticLibrary
+ true
+ Unicode
+
+
+ StaticLibrary
+ true
+ Unicode
+
+
+ StaticLibrary
+ false
+ true
+ Unicode
+
+
+ StaticLibrary
+ false
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/wxExtend/build/wxExtend.vcxproj.filters b/lib/wxExtend/build/wxExtend.vcxproj.filters
new file mode 100644
index 0000000..ec75aac
--- /dev/null
+++ b/lib/wxExtend/build/wxExtend.vcxproj.filters
@@ -0,0 +1,36 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/lib/wxExtend/include/wxex/appbar.h b/lib/wxExtend/include/wxex/appbar.h
new file mode 100644
index 0000000..fce993e
--- /dev/null
+++ b/lib/wxExtend/include/wxex/appbar.h
@@ -0,0 +1,663 @@
+/*
+ Copyright 2016 Amebis
+
+ This file is part of wxExtend.
+
+ wxExtend is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ wxExtend is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with wxExtend. If not, see .
+*/
+
+#pragma once
+
+#include
+#include
+
+#include
+
+
+#define wxABT_AUTOHIDETIMERID 1
+#define wxABT_AUTOHIDETIME 300
+#define wxABT_AUTOHIDETIMERINTERVAL 3000
+
+
+///
+/// Dockable application bar
+///
+class wxAppBar : public wxFrame
+{
+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_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?
+
+ // Internal flags
+ wxFLAG_FULLSCREENAPPOPEN = 1 << 12, ///< Is full-screen application open?
+ wxFLAG_AUTOHIDDEN = 1 << 13, ///< Is application bar auto-hidden right now?
+ wxFLAG_POSITIONSET = 1 << 14, ///< Is application bar's position correct?
+
+ 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_ALWAYSHIDETASKBARTAB = (wxFLAG_HIDETASKBARTABWHENFLOATING | wxFLAG_HIDETASKBARTABWHENDOCKED), ///< Should application bar's tab on the system taskbar hide always?
+ };
+
+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();
+
+public:
+ /// \name Application bar general management
+ /// @{
+
+ ///
+ /// Returns current state of the application bar.
+ ///
+ inline wxState GetState() const;
+
+ ///
+ /// Returns whether application bar is displayed always on top.
+ ///
+ /// \returns
+ /// - true when application bar is always on top
+ /// - false otherwise
+ ///
+ inline bool IsAlwaysOnTop() const;
+
+ ///
+ /// Sets whether application bar is displayed always on top.
+ ///
+ /// \param[in] alwaysOnTop Logical variable to control whether always-on-top behaviour is to be enabled (true) or disabled (false).
+ ///
+ inline bool SetAlwaysOnTop(bool alwaysOnTop = true);
+
+ ///
+ /// Returns if application bar is configured for auto-hide.
+ ///
+ /// \returns
+ /// - true if application bar is configured for auto-hide
+ /// - false otherwise
+ ///
+ inline bool IsAutoHide() const;
+
+ ///
+ /// Sets whether application bar is displayed always on top.
+ ///
+ /// \param[in] autoHide Logical variable to control whether auto-hide behaviour is to be enabled (true) or disabled (false).
+ ///
+ inline bool SetAutoHide(bool autoHide = true);
+
+ ///
+ /// Returns if sizing of the application bar is allowed.
+ ///
+ /// \returns
+ /// - true if sizing of the application bar is allowed
+ /// - false otherwise
+ ///
+ inline bool GetAllowSizing() const;
+
+ ///
+ /// 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).
+ ///
+ inline bool SetAllowSizing(bool bAllowSizing = true);
+
+ ///
+ /// Returns if application bar is auto-hidden right now.
+ ///
+ /// \returns
+ /// - true if application bar is auto-hidden right now
+ /// - false otherwise
+ inline bool GetAutoHidden() const;
+
+ //bool GetAppBarPlacement(LPAPPBARPLACEMENT lpPlacement) const;
+ //bool SetAppBarPlacement(LPCAPPBARPLACEMENT lpPlacement);
+
+ ///
+ /// Minimize application bar to the edge of the desktop.
+ ///
+ /// \param[in] state The edge at which to dock. Must be either of: wxSTATE_LEFT, wxSTATE_TOP, wxSTATE_RIGHT, or wxSTATE_BOTTOM.
+ /// \param[in] wnd When the undocked and docked window is different, this parameter denotes the undocked version.
+ ///
+ void MinimiseToEdge(wxState state, wxWindow* wnd = NULL);
+
+ ///
+ /// Restore application bar from the edge of the desktop.
+ ///
+ /// \param[in] rect The desired coordinates of the restored window. If NULL internally saved coordinates are used.
+ /// \param[in] wnd When the undocked and docked window is different, this parameter denotes the undocked version.
+ ///
+ void MaximiseFromEdge(const RECT* rect = NULL);
+ void MaximiseFromEdge(wxWindow *wnd);
+
+ ///
+ /// Shows or hides auto-hide application bar.
+ ///
+ /// \param[in] bShow Logical variable to control whether application bar is be shown (true) or hidden (false).
+ ///
+ void ShowAutoHideAppBar(bool bShow = true);
+
+ ///
+ /// Hides auto-hide application bar.
+ ///
+ inline void HideAutoHideAppBar() { ShowAutoHideAppBar(false); }
+
+ /// @}
+
+protected:
+ /// \name Notification handlers
+ /// @{
+
+ ///
+ /// Notification handler when the new state of the application bar is proposed.
+ ///
+ /// Derived classes can implement their own. However, overriden virtual method should call the parent's implementation too.
+ ///
+ /// \param[in] stateNew New state about to take effect.
+ ///
+ virtual void OnChangeState(wxState stateNew);
+
+ ///
+ /// Notification handler when the Windows' task bar 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.
+ ///
+ virtual void OnChangeTaskBarState(UINT_PTR state);
+
+ ///
+ /// Notification handler when desktop windows are being arranged (cascaded, tiled, ...)
+ ///
+ /// 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.
+ ///
+ virtual void OnWindowsArrange(bool bBeginning);
+
+ ///
+ /// Called when application bar was forced from auto-hide to normal docking.
+ ///
+ /// Default implementation displays a warning dialog.
+ ///
+ virtual void OnAutoHideDenied();
+
+ /// @}
+
+protected:
+ virtual WXLRESULT MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam);
+
+private:
+ inline bool DockAppBar(wxState 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();
+
+protected:
+ wxState m_state; ///< Current state of the application bar
+ wxState m_stateDesired; ///< Desired state of the application bar while moving/resizing
+ int m_flags; ///< Flags describing application bar's behaviour
+
+ RECT m_rect; ///< Window rectangle
+ 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_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
+{
+ return m_stateDesired != wxSTATE_UNKNOWN ? m_stateDesired : m_state;
+}
+
+
+inline bool wxAppBar::IsAlwaysOnTop() const
+{
+ return (m_flags & wxFLAG_ALWAYSONTOP) ? true : false;
+}
+
+
+inline bool wxAppBar::SetAlwaysOnTop(bool alwaysOnTop)
+{
+ if (alwaysOnTop)
+ m_flags |= wxFLAG_ALWAYSONTOP;
+ else
+ m_flags &= ~wxFLAG_ALWAYSONTOP;
+
+ if (::IsWindowVisible(m_hWnd)) {
+ // Set the Z-order. SWP_NOSENDCHANGING flag prevents our OnWindowPosChanging() method to be called, since moving is not necessary.
+ wxCHECK(::SetWindowPos(m_hWnd, GetZWnd(m_state, m_flags), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOSENDCHANGING), false);
+ }
+
+ return true;
+}
+
+
+inline bool wxAppBar::IsAutoHide() const
+{
+ 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));
+
+ APPBARDATA abd = {
+ sizeof(abd),
+ m_hWnd,
+ 0,
+ state
+ };
+
+ // Calculate docked window rect and dock the window there.
+ GetDockedRect(state, &(abd.rc));
+ wxCHECK(::SHAppBarMessage(ABM_SETPOS, &abd), false);
+ m_flags |= wxFLAG_POSITIONSET;
+ m_rect = abd.rc;
+ wxCHECK(::SetWindowPos(m_hWnd, GetZWnd(state, m_flags), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_FRAMECHANGED), false);
+
+ return true;
+}
+
+
+inline bool wxAppBar::UndockAppBar()
+{
+ APPBARDATA abd = {
+ sizeof(abd),
+ m_hWnd,
+ 0,
+ wxSTATE_LEFT
+ };
+
+ // Free application bar's space to undock.
+ 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));
+
+ APPBARDATA abd = {
+ sizeof(abd),
+ m_hWnd,
+ 0,
+ state,
+ {},
+ (LPARAM)true
+ };
+
+ // Register application bar as auto-hide.
+ 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));
+ m_flags |= wxFLAG_POSITIONSET;
+ m_rect = abd.rc;
+ wxCHECK(::SetWindowPos(m_hWnd, GetZWnd(state, m_flags), 0, 0, 0, 0, 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));
+
+ APPBARDATA abd = {
+ sizeof(abd),
+ m_hWnd,
+ 0,
+ state,
+ {},
+ (LPARAM)false
+ };
+
+ // Unregister application bar as auto-hide.
+ 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));
+
+ APPBARDATA abd = {
+ sizeof(abd),
+ m_hWnd,
+ 0,
+ state,
+ {
+ // Set dimensions to full screen.
+ 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 full screen app is open, clear the always-on-top flag.
+ return HWND_NOTOPMOST;
+ }
+
+ //_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
+ //if (::IsWindow(pThreadState->m_hTrackingWindow)) {
+ // // We're tracking another window/menu, position behind it.
+ // return pThreadState->m_hTrackingWindow;
+ // }
+
+ if (state == wxSTATE_FLOAT) {
+ // When floating, decide according to the flags.
+ return (flags & wxFLAG_ALWAYSONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST;
+ }
+
+ if (IsDocked(state)) {
+ if (flags & wxFLAG_AUTOHIDE) {
+ // Auto-hidden docked application bar is always on top.
+ return HWND_TOPMOST;
+ }
+
+ if (flags & wxFLAG_ALWAYSONTOP) {
+ // Regular docked always-on-top application bar.
+ WXHWND hWndTaskbar = ::FindWindow(_T("Shell_TrayWnd"), _T(""));
+ if (hWndTaskbar) {
+ // We found the taskbar window. Position directly after it. Otherwise our window overlaps Vista's Start button orb.
+ return hWndTaskbar;
+ } else {
+ // Only always-on-top windows are allowed to resize properly outside the desktop rect.
+ // If window is docked and not always on top, resizing a window to smaller size is obstructed by desktop rect limit.
+ return HWND_TOPMOST;
+ }
+ }
+
+
+ // Regular docked non-always-on-top application bar.
+ return HWND_NOTOPMOST;
+ } else {
+ // Unknown state. Do nothing.
+ wxFAIL;
+ return HWND_TOP;
+ }
+}
+
+
+inline UINT_PTR wxAppBar::GetTaskBarState()
+{
+ APPBARDATA abd = { sizeof(abd) };
+
+ return ::SHAppBarMessage(ABM_GETSTATE, &abd);
+}
diff --git a/lib/wxExtend/include/wxex/common.h b/lib/wxExtend/include/wxex/common.h
new file mode 100644
index 0000000..aa98f2f
--- /dev/null
+++ b/lib/wxExtend/include/wxex/common.h
@@ -0,0 +1,77 @@
+/*
+ Copyright 2016 Amebis
+
+ This file is part of wxExtend.
+
+ wxExtend is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ wxExtend is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with wxExtend. If not, see .
+*/
+
+#pragma once
+
+#include
+#include
+#include
+
+
+//---------------------------------------------------------------------------
+// Usual debugging macros
+//---------------------------------------------------------------------------
+#if wxDEBUG_LEVEL
+#define wxVERIFY(x) wxASSERT((x))
+#else
+#define wxVERIFY(x) (x)
+#endif
+
+
+///
+/// Returns whether windows animation is enabled.
+///
+/// \returns
+/// - true when window animation is enabled
+/// - false otherwise
+///
+inline bool wxGetDoWndAnimation()
+{
+ ANIMATIONINFO ai = { sizeof(ai) };
+ wxCHECK(SystemParametersInfo(SPI_GETANIMATION, sizeof(ai), &ai, 0), false);
+ return ai.iMinAnimate ? true : false;
+}
+
+
+///
+/// Modifies window extended style.
+///
+/// \param[in] hWnd Handle of the window to modify.
+/// \param[in] dwRemove Set of extended styles to remove.
+/// \param[in] dwAdd Set of extended styles to add.
+/// \param[in] nFlags Additional SWP_ flags to pass to SetWindowPos(). If zero, SetWindowPos() is not called.
+/// \returns
+/// - true when the window extended style was modified
+/// - false if the window extended style was not neccessary
+///
+inline bool wxModifyStyleEx(_In_ WXHWND hWnd, _In_ DWORD dwRemove, _In_ DWORD dwAdd, _In_ UINT nFlags = 0)
+{
+ wxASSERT(IsWindow(hWnd));
+
+ DWORD dwStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
+ DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
+ if(dwStyle == dwNewStyle)
+ return false;
+
+ SetWindowLong(hWnd, GWL_EXSTYLE, dwNewStyle);
+ if(nFlags != 0)
+ SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
+
+ return true;
+}
diff --git a/lib/wxExtend/src/appbar.cpp b/lib/wxExtend/src/appbar.cpp
new file mode 100644
index 0000000..a663dcf
--- /dev/null
+++ b/lib/wxExtend/src/appbar.cpp
@@ -0,0 +1,847 @@
+/*
+ Copyright 2016 Amebis
+
+ This file is part of wxExtend.
+
+ wxExtend is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ wxExtend is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with wxExtend. If not, see .
+*/
+
+#include "stdafx.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+// wxAppBar
+//////////////////////////////////////////////////////////////////////////
+
+const UINT wxAppBar::WM_AB_NOTIFY = ::RegisterWindowMessage(_T("AppBarNotify"));
+
+
+wxAppBar::wxAppBar() :
+ m_timerID(0),
+ m_taskbarList(NULL),
+ wxFrame()
+{
+}
+
+
+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()
+{
+ 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)
+{
+ // Save initial window rectangle.
+ m_rect.left = pos.x;
+ m_rect.top = pos.y;
+ m_rect.right = pos.x + size.x;
+ m_rect.bottom = pos.y + size.y;
+
+ // 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 (m_flags & wxFLAG_ALWAYSHIDETASKBARTAB)
+ style |= wxFRAME_TOOL_WINDOW;
+
+ // 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);
+ }
+
+ return true;
+}
+
+
+wxAppBar::~wxAppBar()
+{
+ 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();
+}
+
+
+//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 state, wxWindow *wnd)
+{
+ wxASSERT(IsDocked(state));
+
+ if (!wnd) {
+ // No other window was specified. Minimize ourself.
+ wnd = this;
+ }
+
+ WXHWND 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.
+ m_sizeFloat.cx = m_rect.right - m_rect.left;
+ m_sizeFloat.cy = m_rect.bottom - m_rect.top;
+ }
+
+ RECT rectTo;
+ if (IsAutoHide())
+ GetAutoHideRect(state, false, &rectTo);
+ else
+ GetDockedRect(state, &rectTo);
+
+ if (::wxGetDoWndAnimation()) {
+ RECT rectFrom;
+
+ // Calculate source and destination rectangles.
+ if (hWnd != m_hWnd)
+ ::GetWindowRect(hWnd, &rectFrom);
+ else
+ rectFrom = m_rect;
+
+ // Do the animation.
+ wxVERIFY(::DrawAnimatedRects(hWnd, IDANI_CAPTION, &rectFrom, &rectTo));
+ }
+
+ // Set the window rect.
+ m_flags |= wxFLAG_POSITIONSET;
+ m_rect = rectTo;
+
+ // Notify about the change of state.
+ OnChangeState(state);
+ m_state = state;
+
+ 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(state);
+ } else {
+ // Auto-hide failed or wasn't desired at all.
+ DockAppBar(state);
+ }
+ }
+
+ ::SetActiveWindow(m_hWnd);
+}
+
+
+void wxAppBar::MaximiseFromEdge(const RECT* rect)
+{
+ wxASSERT(::IsWindowVisible(m_hWnd));
+
+ RECT rc;
+
+ if (!rect) {
+ // Calculate the destination rect.
+ rc.left = (::GetSystemMetrics(SM_CXSCREEN) - m_sizeFloat.cx) / 2;
+ rc.top = (::GetSystemMetrics(SM_CYSCREEN) - m_sizeFloat.cy) / 2;
+ rc.right = rc.left + m_sizeFloat.cx;
+ rc.bottom = rc.top + m_sizeFloat.cy;
+
+ rect = &rc;
+ } else {
+ m_sizeFloat.cx = rect->right - rect->left;
+ m_sizeFloat.cy = rect->bottom - rect->top;
+ }
+
+ if (::wxGetDoWndAnimation()) {
+ // Do the animation.
+ wxVERIFY(::DrawAnimatedRects(m_hWnd, IDANI_CAPTION, &m_rect, rect));
+ }
+
+ // Clean previous docking/auto-hide settings if required.
+ if (IsDocked(m_state)) {
+ if (IsAutoHide())
+ UnregisterAutoHide(m_state);
+ else
+ UndockAppBar();
+ }
+
+ // Set the window rect.
+ m_flags |= wxFLAG_POSITIONSET;
+ m_rect = *rect;
+
+ // Notify about the change of state.
+ OnChangeState(wxSTATE_FLOAT);
+ m_state = wxSTATE_FLOAT;
+
+ ::SetWindowPos(m_hWnd, GetZWnd(wxSTATE_FLOAT, m_flags), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_FRAMECHANGED);
+}
+
+
+void wxAppBar::MaximiseFromEdge(wxWindow *wnd)
+{
+ wxASSERT(wnd);
+ wxASSERT(::IsWindowVisible(m_hWnd));
+
+ WXHWND hWnd = wnd->GetHWND();
+ RECT rectTo;
+
+ ::GetWindowRect(hWnd, &rectTo);
+ m_sizeFloat.cx = rectTo.right - rectTo.left;
+ m_sizeFloat.cy = rectTo.bottom - rectTo.top;
+
+ if (::wxGetDoWndAnimation()) {
+ // Do the animation.
+ wxVERIFY(::DrawAnimatedRects(hWnd, IDANI_CAPTION, &m_rect, &rectTo));
+ }
+
+ Hide();
+
+ // Show the destination window.
+ 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;
+
+ m_flags |= wxFLAG_POSITIONSET;
+
+ while ((dwTimeElapsed = ::GetTickCount() - dwTimeStart) < wxABT_AUTOHIDETIME) {
+ // Do the linear interpolation.
+ m_rect.left = rcStart.left + ::MulDiv(rcDelta.left, dwTimeElapsed, wxABT_AUTOHIDETIME);
+ m_rect.top = rcStart.top + ::MulDiv(rcDelta.top, dwTimeElapsed, wxABT_AUTOHIDETIME);
+ m_rect.right = rcStart.right + ::MulDiv(rcDelta.right, dwTimeElapsed, wxABT_AUTOHIDETIME);
+ m_rect.bottom = rcStart.bottom + ::MulDiv(rcDelta.bottom, dwTimeElapsed, wxABT_AUTOHIDETIME);
+
+ // Show the window at its changed position
+ ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE);
+ ::UpdateWindow(m_hWnd);
+ }
+ }
+ }
+
+ // Make sure that the window is at its final position
+ m_flags |= wxFLAG_POSITIONSET;
+ m_rect = rcEnd;
+
+ if (bShow)
+ m_flags &= ~wxFLAG_AUTOHIDDEN;
+ else
+ m_flags |= wxFLAG_AUTOHIDDEN;
+
+ if (bVisible) {
+ ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE);
+ ::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: {
+ wxASSERT(lParam);
+ LPWINDOWPOS lpwndpos = (LPWINDOWPOS)lParam;
+
+ // Sync to our window rect.
+ if (!(m_flags & wxFLAG_POSITIONSET) && !(lpwndpos->flags & SWP_NOMOVE)) {
+ // Get the window position first time the SetWindowPos() is called.
+ m_rect.right = lpwndpos->x + m_rect.right - m_rect.left;
+ m_rect.bottom = lpwndpos->y + m_rect.bottom - m_rect.top;
+ m_rect.left = lpwndpos->x;
+ m_rect.top = lpwndpos->y;
+ m_flags |= wxFLAG_POSITIONSET;
+ } else {
+ lpwndpos->x = m_rect.left;
+ lpwndpos->y = m_rect.top;
+ }
+ lpwndpos->cx = m_rect.right - m_rect.left;
+ lpwndpos->cy = m_rect.bottom - m_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)) {
+ APPBARDATA abd = {
+ sizeof(abd),
+ m_hWnd
+ };
+
+ // 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.
+ wxVERIFY(::SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd));
+ }
+
+ return lResult;
+ }
+
+ case WM_ENTERSIZEMOVE:
+ m_stateDesired = m_state;
+
+ return 0;
+
+ case WM_EXITSIZEMOVE:
+ // 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 0;
+
+ 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;
+ }
+
+ // Set the window rect.
+ m_flags |= wxFLAG_POSITIONSET;
+ m_rect = *lpRect;
+
+ 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;
+
+ m_flags |= wxFLAG_POSITIONSET;
+ m_rect = *lpRect;
+
+ 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 rc = {};
+ wxVERIFY(::GetClientRect(m_hWnd, &rc));
+ if (rc.right - rc.left && rc.bottom - rc.top) {
+ lpMMI->ptMinTrackSize.x = m_sizeMin.cx + (m_rect.right - m_rect.left) - (rc.right - rc.left);
+ lpMMI->ptMinTrackSize.y = m_sizeMin.cy + (m_rect.bottom - m_rect.top ) - (rc.bottom - rc.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)) {
+ APPBARDATA abd = {
+ sizeof(abd),
+ m_hWnd
+ };
+
+ // 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.
+ 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 pt(GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint));
+ wxRect rc(m_rect.left, m_rect.top, m_rect.right - m_rect.left, m_rect.bottom - m_rect.top);
+
+ // Add a little margin around the application bar
+ rc.Inflate(2 * ::GetSystemMetrics(SM_CXDOUBLECLK), 2 * ::GetSystemMetrics(SM_CYDOUBLECLK));
+ if (!rc.Contains(pt)) {
+ // 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. SWP_NOSENDCHANGING flag prevents our OnWindowPosChanging() method to be called, since moving is not desired.
+ 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);
+ }
+}
diff --git a/lib/wxExtend/src/stdafx.cpp b/lib/wxExtend/src/stdafx.cpp
new file mode 100644
index 0000000..2ff81d0
--- /dev/null
+++ b/lib/wxExtend/src/stdafx.cpp
@@ -0,0 +1,20 @@
+/*
+ Copyright 2016 Amebis
+
+ This file is part of wxExtend.
+
+ wxExtend is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ wxExtend is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with wxExtend. If not, see .
+*/
+
+#include "stdafx.h"
diff --git a/lib/wxExtend/src/stdafx.h b/lib/wxExtend/src/stdafx.h
new file mode 100644
index 0000000..e2693c8
--- /dev/null
+++ b/lib/wxExtend/src/stdafx.h
@@ -0,0 +1,27 @@
+/*
+ Copyright 2016 Amebis
+
+ This file is part of wxExtend.
+
+ wxExtend is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ wxExtend is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with wxExtend. If not, see .
+*/
+
+#pragma once
+
+#include "../include/wxex/appbar.h"
+
+#include "../include/wxex/common.h"
+
+#include
+#include