wxExtend
Additional templates and function helpers for wxWidgets
Loading...
Searching...
No Matches
appbar.h
1/*
2 ​​SPDX-License-Identifier: GPL-3.0-or-later
3 Copyright © 2015-2022 Amebis
4 Copyright © 2016 GÉANT
5 Based on code written by Jeffrey Richter.
6*/
7
8#pragma once
9
10#include "common.h"
11
12#include <codeanalysis\warnings.h>
13#pragma warning(push)
14#pragma warning(disable: WXWIDGETS_CODE_ANALYSIS_WARNINGS)
15#include <wx/dialog.h>
16#include <wx/frame.h>
17#include <wx/string.h>
18#pragma warning(pop)
19
20#include <Windowsx.h>
21#include <shellapi.h>
22#include <ShlObj.h>
23
24
27
31#define wxABT_AUTOHIDETIMERID 1
32
36#define wxABT_AUTOHIDETIME 300
37
41#define wxABT_AUTOHIDETIMERINTERVAL 3000
42
52#define WM_AB_NOTIFY 0x6f00
53
54
58enum class wxAppBarState {
59 UNKNOWN = -2,
60 FLOAT = -1,
61 LEFT = ABE_LEFT,
62 TOP = ABE_TOP,
63 RIGHT = ABE_RIGHT,
64 BOTTOM = ABE_BOTTOM,
65};
66
67
71#define wxABF_ALLOWFLOAT (1 << 0)
72#define wxABF_ALLOWDOCKTOP (1 << 1)
73#define wxABF_ALLOWDOCKBOTTOM (1 << 2)
74#define wxABF_ALLOWDOCKLEFT (1 << 3)
75#define wxABF_ALLOWDOCKRIGHT (1 << 4)
76#define wxABF_ALLOWDOCKANY (wxABF_ALLOWDOCKTOP | wxABF_ALLOWDOCKBOTTOM | wxABF_ALLOWDOCKLEFT | wxABF_ALLOWDOCKRIGHT)
77#define wxABF_ALLOWDOCKHORIZONTAL (wxABF_ALLOWDOCKTOP | wxABF_ALLOWDOCKBOTTOM)
78#define wxABF_ALLOWDOCKVERTICAL (wxABF_ALLOWDOCKLEFT | wxABF_ALLOWDOCKRIGHT)
79#define wxABF_ALLOWANY (wxABF_ALLOWFLOAT | wxABF_ALLOWDOCKANY)
80
81#define wxABF_ALWAYSONTOP (1 << 5)
82#define wxABF_ALWAYSONTOPTASKBAR (1 << 6)
83
84#define wxABF_AUTOHIDE (1 << 7)
85#define wxABF_AUTOHIDETASKBAR (1 << 8)
86
87#define wxABF_ALLOWSIZING (1 << 9)
88
89#define wxABF_HIDETASKBARTABWHENFLOATING (1 << 10)
90#define wxABF_HIDETASKBARTABWHENDOCKED (1 << 11)
91#define wxABF_ALWAYSHIDETASKBARTAB (wxABF_HIDETASKBARTABWHENFLOATING | wxABF_HIDETASKBARTABWHENDOCKED)
92
93// Internal flags
94#define wxABF_FULLSCREENAPPOPEN (1 << 12)
95#define wxABF_AUTOHIDDEN (1 << 13)
96
97
101template <class W>
102class wxAppBar : public W
103{
104public:
109
113 virtual ~wxAppBar();
114
115protected:
117 void PreCreate(wxAppBarState& state, int& flags, const wxSize& size, long& style);
119
120public:
123
127 inline wxAppBarState GetState() const;
128
136 inline bool IsAlwaysOnTop() const;
137
143 inline bool SetAlwaysOnTop(bool alwaysOnTop = true);
144
152 inline bool IsAutoHide() const;
153
159 inline bool SetAutoHide(bool autoHide = true);
160
168 inline bool GetAllowSizing() const;
169
175 inline bool SetAllowSizing(bool allow = true);
176
183 inline bool GetAutoHidden() const;
184
185 //bool GetAppBarPlacement(LPAPPBARPLACEMENT lpPlacement) const;
186 //bool SetAppBarPlacement(LPCAPPBARPLACEMENT lpPlacement);
187
194 void MinimiseToEdge(wxAppBarState edge, wxWindow* wnd = NULL);
195
201 void MaximiseFromEdge(_In_opt_ const RECT* rect = NULL);
202
208 void MaximiseFromEdge(_In_ wxWindow *wnd);
209
215 void ShowAutoHideAppBar(bool show = true);
216
220 inline void HideAutoHideAppBar() { ShowAutoHideAppBar(false); }
221
223
224protected:
227
235 virtual void OnChangeState(wxAppBarState stateNew);
236
244 virtual void OnChangeTaskBarState(UINT_PTR state);
245
253 virtual void OnWindowsArrange(bool beginning);
254
260 virtual void OnAutoHideDenied();
261
263
264protected:
266 virtual WXLRESULT MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam);
268
269private:
271 inline _Success_(return != 0) bool DockAppBar(_In_ wxAppBarState state);
272 inline _Success_(return != 0) bool UndockAppBar();
273 inline _Success_(return != 0) bool RegisterAutoHide(_In_ wxAppBarState state);
274 inline _Success_(return != 0) bool UnregisterAutoHide(_In_ wxAppBarState state);
275 inline _Success_(return != 0) bool GetDockedRect(_In_ wxAppBarState state, _Out_ LPRECT rect) const;
276 inline _Success_(return != 0) bool GetAutoHideRect(_In_ wxAppBarState state, _In_ bool bAutoHidden, _Out_ LPRECT rect) const;
278
279protected:
283
287
288 UINT_PTR m_stateTaskBar;
289 UINT_PTR m_timerID;
290
291 ITaskbarList *m_taskbarList;
292};
293
294
295#ifdef __VISUALC__
296// non dll-interface class 'xxx' used as base for dll-interface class 'yyy'
297#pragma warning (push)
298#pragma warning (disable:4275)
299#endif
300
304class WXEXTEND_API wxAppBarFrame : public wxAppBar<wxFrame>
305{
306public:
311
315 wxAppBarFrame(wxWindow *parent,
316 wxWindowID id,
317 const wxString& title,
319 int flags = wxABF_ALLOWANY,
320 const wxPoint& pos = wxDefaultPosition,
321 const wxSize& size = wxDefaultSize,
322 long style = wxDEFAULT_FRAME_STYLE,
323 const wxString& name = wxFrameNameStr);
324
328 bool Create(wxWindow *parent,
329 wxWindowID id,
330 const wxString& title,
332 int flags = wxABF_ALLOWANY,
333 const wxPoint& pos = wxDefaultPosition,
334 const wxSize& size = wxDefaultSize,
335 long style = wxDEFAULT_FRAME_STYLE,
336 const wxString& name = wxFrameNameStr);
337};
338
339
343class WXEXTEND_API wxAppBarDialog : public wxAppBar<wxDialog>
344{
345public:
350
354 wxAppBarDialog(wxWindow *parent,
355 wxWindowID id,
356 const wxString& title,
358 int flags = wxABF_ALLOWANY,
359 const wxPoint& pos = wxDefaultPosition,
360 const wxSize& size = wxDefaultSize,
361 long style = wxDEFAULT_DIALOG_STYLE,
362 const wxString& name = wxDialogNameStr);
363
367 bool Create(wxWindow *parent,
368 wxWindowID id,
369 const wxString& title,
371 int flags = wxABF_ALLOWANY,
372 const wxPoint& pos = wxDefaultPosition,
373 const wxSize& size = wxDefaultSize,
374 long style = wxDEFAULT_DIALOG_STYLE,
375 const wxString& name = wxDialogNameStr);
376};
377
378#ifdef __VISUALC__
379#pragma warning(pop)
380#endif
381
382
393{
394 return wxAppBarState::LEFT <= state && state <= wxAppBarState::BOTTOM;
395}
396
397
408{
409 return state == wxAppBarState::LEFT || state == wxAppBarState::RIGHT;
410}
411
412
423{
424 return state == wxAppBarState::TOP || state == wxAppBarState::BOTTOM;
425}
426
427
437inline WXHWND wxAppBarGetZWnd(wxAppBarState state, int flags)
438{
439 if (flags & wxABF_FULLSCREENAPPOPEN) {
440 // If full screen app is open, clear the always-on-top flag.
441 return HWND_NOTOPMOST;
442 }
443
444 //_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
445 //if (::IsWindow(pThreadState->m_hTrackingWindow)) {
446 // // We're tracking another window/menu, position behind it.
447 // return pThreadState->m_hTrackingWindow;
448 // }
449
450 if (state == wxAppBarState::FLOAT) {
451 // When floating, decide according to the flags.
452 return (flags & wxABF_ALWAYSONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST;
453 } else if (wxAppBarIsDocked(state)) {
454 if (flags & wxABF_AUTOHIDE) {
455 // Auto-hidden docked application bar is always on top.
456 return HWND_TOPMOST;
457 }
458
459 if (flags & wxABF_ALWAYSONTOP) {
460 // Regular docked always-on-top application bar.
461 WXHWND hWndTaskbar = ::FindWindow(_T("Shell_TrayWnd"), _T(""));
462 if (hWndTaskbar) {
463 // We found the taskbar window. Position directly after it. Otherwise our window overlaps Vista's Start button orb.
464 return hWndTaskbar;
465 } else {
466 // Only always-on-top windows are allowed to resize properly outside the desktop rect.
467 // If window is docked and not always on top, resizing a window to smaller size is obstructed by desktop rect limit.
468 return HWND_TOPMOST;
469 }
470 }
471
472
473 // Regular docked non-always-on-top application bar.
474 return HWND_NOTOPMOST;
475 } else {
476 // Unknown state. Do nothing.
477 wxFAIL_MSG(wxT("unknown application bar state"));
478 return HWND_TOP;
479 }
480}
481
482
491inline UINT_PTR wxAppBarGetTaskBarState()
492{
493 APPBARDATA abd = { sizeof(abd) };
494 return ::SHAppBarMessage(ABM_GETSTATE, &abd);
495}
496
497
499
501// wxAppBar
503
504template <class W>
506 m_state(wxAppBarState::UNKNOWN),
508 m_flags(0),
510 m_timerID(0),
511 m_taskbarList(NULL)
512{
513 m_sizeFloat .cx = -1;
514 m_sizeFloat .cy = -1;
515 m_sizeDocked.cx = -1;
516 m_sizeDocked.cy = -1;
517 m_sizeMin .cx = -1;
518 m_sizeMin .cy = -1;
519}
520
521
522template <class W>
524{
525 if (m_taskbarList)
526 m_taskbarList->Release();
527}
528
529
531template <class W>
532void wxAppBar<W>::PreCreate(wxAppBarState& state, int& flags, const wxSize& size, long& style)
533{
534 wxASSERT_MSG(!m_taskbarList || !m_timerID, wxT("application bar is already initialized"));
535
536 // Save initial floating window size.
537 m_sizeFloat.cx = size.x;
538 m_sizeFloat.cy = size.y;
539
540 // Save initial docked window width/height.
541 m_sizeDocked.cx = size.x;
542 m_sizeDocked.cy = size.y;
543
544 // Save initial state and flags.
545 m_state = state;
546 m_stateDesired = wxAppBarState::UNKNOWN;
547 m_flags = flags;
548
549 // 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.
550 if (state == wxAppBarState::FLOAT) {
552 // Hide our application bar's entry on the Windows's taskbar.
553 style |= wxFRAME_TOOL_WINDOW;
554 } else if (flags & wxABF_HIDETASKBARTABWHENDOCKED) {
555 // Show our application bar's entry on the Windows's taskbar.
556 style &= ~wxFRAME_TOOL_WINDOW;
557 }
558 } else if (wxAppBarIsDocked(state)) {
559 if (flags & wxABF_HIDETASKBARTABWHENDOCKED) {
560 // Hide our application bar's entry on the Windows's taskbar.
561 style |= wxFRAME_TOOL_WINDOW;
562 } else if (flags & wxABF_HIDETASKBARTABWHENFLOATING) {
563 // Show our application bar's entry on the Windows's taskbar.
564 style &= ~wxFRAME_TOOL_WINDOW;
565 }
566 } else {
567 // Unknown state.
568 wxFAIL_MSG(wxT("unknown application bar state"));
569 }
570
571 // Find the taskbar list's interface.
572 HRESULT hr = ::CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_ALL, IID_ITaskbarList, (LPVOID*)&m_taskbarList);
573 if (SUCCEEDED(hr)) {
574 hr = m_taskbarList->HrInit();
575 if (FAILED(hr)) {
576 wxFAIL_MSG(wxString::Format(wxT("ITaskbarList::HrInit() failed 0x%x"), hr));
577 m_taskbarList->Release();
578 m_taskbarList = NULL;
579 }
580 } else
581 wxFAIL_MSG(wxString::Format(wxT("TaskbarList creation failed 0x%x"), hr));
582}
584
585
586template <class W>
588{
589 return m_stateDesired != wxAppBarState::UNKNOWN ? m_stateDesired : m_state;
590}
591
592
593template <class W>
594inline bool wxAppBar<W>::IsAlwaysOnTop() const
595{
596 return (m_flags & wxABF_ALWAYSONTOP) ? true : false;
597}
598
599
600template <class W>
601inline bool wxAppBar<W>::SetAlwaysOnTop(bool alwaysOnTop)
602{
603 if (alwaysOnTop)
604 m_flags |= wxABF_ALWAYSONTOP;
605 else
606 m_flags &= ~wxABF_ALWAYSONTOP;
607
608 if (::IsWindowVisible(m_hWnd)) {
609 // Set the Z-order.
610 wxCHECK(::SetWindowPos(m_hWnd, wxAppBarGetZWnd(m_state, m_flags), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOSENDCHANGING), false);
611 }
612
613 return true;
614}
615
616
617template <class W>
618inline bool wxAppBar<W>::IsAutoHide() const
619{
620 return (m_flags & wxABF_AUTOHIDE) ? true : false;
621}
622
623
624template <class W>
625inline bool wxAppBar<W>::SetAutoHide(bool autoHide)
626{
627 bool autoHidePrev = IsAutoHide();
628
629 if (autoHide)
630 m_flags |= wxABF_AUTOHIDE;
631 else
632 m_flags &= ~wxABF_AUTOHIDE;
633
634 if (autoHidePrev != autoHide && wxAppBarIsDocked(m_state) && ::IsWindowVisible(m_hWnd)) {
635 if (autoHide) {
636 // Application bar should be auto-hidden. Try to setup it so.
637
638 // We undock to free the space before registering auto-hide, otherwise system will leave application bar's space reserved.
639 UndockAppBar();
640
641 // Register auto-hide application bar.
642 if (!RegisterAutoHide(m_state)) {
643 // Auto-hide failed; some other application bar must be hidden on this edge already. Dock back instead.
644 DockAppBar(m_state);
645 return false;
646 }
647 } else {
648 // Unregister the auto-hidden application bar and dock.
649 UnregisterAutoHide(m_state);
650 DockAppBar(m_state);
651 }
652 }
653
654 return true;
655}
656
657
658template <class W>
660{
661 return (m_flags & wxABF_ALLOWSIZING) ? true : false;
662}
663
664
665template <class W>
666inline bool wxAppBar<W>::SetAllowSizing(bool allow)
667{
668 if (allow)
669 m_flags |= wxABF_ALLOWSIZING;
670 else
671 m_flags &= ~wxABF_ALLOWSIZING;
672
673 return true;
674}
675
676
677template <class W>
678inline bool wxAppBar<W>::GetAutoHidden() const
679{
680 return (m_flags & wxABF_AUTOHIDDEN) ? true : false;
681}
682
683
684//template <class W>
685//bool wxAppBar<W>::GetAppBarPlacement(LPAPPBARPLACEMENT lpPlacement) const
686//{
687// wxASSERT(lpPlacement);
688//
689// if (lpPlacement->dwSize >= sizeof(APPBARPLACEMENT1)) {
690// lpPlacement->dwState = (DWORD)m_state;
691// lpPlacement->dwFlags = m_flags;
692// if (m_state == wxAppBarState::FLOAT) {
693// // Current application bar's rect is floating rect.
694// lpPlacement->rcFloat = m_rect;
695// } else if (wxAppBarIsDocked(m_state)) {
696// // Application bar is docked. Calc floating rect from m_sizeFloat.
697// lpPlacement->rcFloat.left = 0;
698// lpPlacement->rcFloat.top = 0;
699// lpPlacement->rcFloat.right = m_sizeFloat.cx;
700// lpPlacement->rcFloat.bottom = m_sizeFloat.cy;
701// } else {
702// // Application bar's state is unknown.
703// return false;
704// }
705// lpPlacement->szDocked = m_sizeDocked;
706// }
707//
708// lpPlacement->dwSize = sizeof(*lpPlacement);
709//
710// return true;
711//}
712//
713//
714//template <class W>
715//bool wxAppBar<W>::SetAppBarPlacement(LPCAPPBARPLACEMENT lpPlacement)
716//{
717// wxASSERT(lpPlacement);
718//
719// if (lpPlacement->dwSize >= sizeof(APPBARPLACEMENT1)) {
720// if (lpPlacement->dwState != wxAppBarState::FLOAT && !wxAppBarIsDocked(lpPlacement->dwState)) {
721// // The state is unknown. Abort, before we mix up internal state.
722// return false;
723// }
724//
725// // Clean previous docking/auto-hide settings if required.
726// if (wxAppBarIsDocked(m_state) &&
727// (lpPlacement->dwState == wxAppBarState::FLOAT || lpPlacement->dwState != m_state && wxAppBarIsDocked(lpPlacement->dwState)))
728// {
729// if (IsAutoHide())
730// UnregisterAutoHide(m_state);
731// else if (lpPlacement->dwState == wxAppBarState::FLOAT)
732// UndockAppBar();
733// }
734//
735// // Update application bar's flags, size and position.
736// m_flags |= wxABF_POSITIONSET;
737// m_sizeDocked = lpPlacement->szDocked;
738// if (lpPlacement->dwState == wxAppBarState::FLOAT) {
739// m_rect = lpPlacement->rcFloat;
740// } else if (wxAppBarIsDocked(lpPlacement->dwState)) {
741// m_sizeFloat.cx = lpPlacement->rcFloat.right - lpPlacement->rcFloat.left;
742// m_sizeFloat.cy = lpPlacement->rcFloat.bottom - lpPlacement->rcFloat.top;
743// GetDockedRect(lpPlacement->dwState, &m_rect);
744// } else {
745// // Application bar's state is unknown.
746// wxFAIL;
747// return false;
748// }
749//
750// // Notify about the change of state.
751// OnChangeState(lpPlacement->dwState);
752// m_state = lpPlacement->dwState;
753//
754// SetAutoHide(lpPlacement->dwFlags & wxABF_AUTOHIDE);
755// SetAlwaysOnTop(lpPlacement->dwFlags & wxABF_ALWAYSONTOP);
756// }
757//
758// return true;
759//}
760
761
762template <class W>
764{
765 wxASSERT(wxAppBarIsDocked(edge));
766
767 WXHWND hWnd;
768 if (!wnd) {
769 // No other window was specified. Minimize ourself.
770 wnd = this;
771 hWnd = m_hWnd;
772 } else
773 hWnd = wnd->GetHWND();
774
775 // If our window is hidden, there's nothing we can do.
776 if (hWnd == m_hWnd && !::IsWindowVisible(m_hWnd))
777 return;
778
779 if (m_state == wxAppBarState::FLOAT) {
780 // Remember the last floating size.
781 RECT rect = {};
782 wxVERIFY(::GetWindowRect(hWnd, &rect));
783 m_sizeFloat.cx = rect.right - rect.left;
784 m_sizeFloat.cy = rect.bottom - rect.top;
785 }
786
787 RECT rectTo;
788 if (IsAutoHide())
789 GetAutoHideRect(edge, false, &rectTo);
790 else
791 GetDockedRect(edge, &rectTo);
792
793 if (::wxGetDoWndAnimation()) {
794 // Do the animation.
795 RECT rectFrom;
796 wxVERIFY(::GetWindowRect(hWnd, &rectFrom));
797 wxVERIFY(::DrawAnimatedRects(hWnd, IDANI_CAPTION, &rectFrom, &rectTo));
798 }
799
800 // Notify about the change of state.
801 OnChangeState(edge);
802 m_state = edge;
803
804 if (hWnd != m_hWnd) {
805 // Hide the source window.
806 wnd->Hide();
807 // ::SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) &~ WS_VISIBLE);
808
809 // Show the application bar.
810 Show();
811 } else {
812 if (IsAutoHide()) {
813 // Register auto-hide application bar.
814 RegisterAutoHide(edge);
815 } else {
816 // Auto-hide failed or wasn't desired at all.
817 DockAppBar(edge);
818 }
819 }
820
821 ::SetActiveWindow(m_hWnd);
822}
823
824
825template <class W>
826void wxAppBar<W>::MaximiseFromEdge(_In_opt_ const RECT* rect)
827{
828 wxASSERT(::IsWindowVisible(m_hWnd));
829
830 RECT rectTo;
831
832 if (!rect) {
833 // Calculate the destination rect.
834 rectTo.left = (::GetSystemMetrics(SM_CXSCREEN) - m_sizeFloat.cx) / 2;
835 rectTo.top = (::GetSystemMetrics(SM_CYSCREEN) - m_sizeFloat.cy) / 2;
836 rectTo.right = rectTo.left + m_sizeFloat.cx;
837 rectTo.bottom = rectTo.top + m_sizeFloat.cy;
838
839 rect = &rectTo;
840 } else {
841 m_sizeFloat.cx = rect->right - rect->left;
842 m_sizeFloat.cy = rect->bottom - rect->top;
843 }
844
845 if (::wxGetDoWndAnimation()) {
846 // Do the animation.
847 RECT rectFrom;
848 wxVERIFY(::GetWindowRect(m_hWnd, &rectFrom));
849 wxVERIFY(::DrawAnimatedRects(m_hWnd, IDANI_CAPTION, &rectFrom, rect));
850 }
851
852 // Clean previous docking/auto-hide settings if required.
853 if (wxAppBarIsDocked(m_state)) {
854 if (IsAutoHide())
855 UnregisterAutoHide(m_state);
856 else
857 UndockAppBar();
858 }
859
860 // Notify about the change of state.
861 OnChangeState(wxAppBarState::FLOAT);
862 m_state = wxAppBarState::FLOAT;
863
864 wxVERIFY(::SetWindowPos(m_hWnd, wxAppBarGetZWnd(wxAppBarState::FLOAT, m_flags), rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top, SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_FRAMECHANGED));
865}
866
867
868template <class W>
869void wxAppBar<W>::MaximiseFromEdge(_In_ wxWindow *wnd)
870{
871 wxASSERT(wnd);
872 wxASSERT(::IsWindowVisible(m_hWnd));
873
874 WXHWND hWnd = wnd->GetHWND();
875
876 RECT rectTo = {};
877 wxVERIFY(::GetWindowRect(hWnd, &rectTo));
878 m_sizeFloat.cx = rectTo.right - rectTo.left;
879 m_sizeFloat.cy = rectTo.bottom - rectTo.top;
880
881 if (::wxGetDoWndAnimation()) {
882 // Do the animation.
883 RECT rectFrom;
884 wxVERIFY(::GetWindowRect(m_hWnd, &rectFrom));
885 wxVERIFY(::DrawAnimatedRects(hWnd, IDANI_CAPTION, &rectFrom, &rectTo));
886 }
887
888 // Hide our window and show the destination window.
889 Hide();
890 wnd->Show();
891 // ::SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) | WS_VISIBLE);
892 wxVERIFY(::SetForegroundWindow(hWnd));
893 ::SetActiveWindow(hWnd);
894 // wxVERIFY(::RedrawWindow(hWnd, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_FRAME | RDW_INVALIDATE | RDW_ERASE));
895}
896
897
898template <class W>
900{
901 RECT rcEnd;
902 bool
903 bFullDragOn,
904 bHidden = GetAutoHidden(),
905 bVisible = ::IsWindowVisible(m_hWnd) ? true : false;
906
907 if (!IsAutoHide() || bHidden != show) {
908 // We're not setup for auto-hide or already in the desired state.
909 return;
910 }
911
912 // Get our end window location.
913 GetAutoHideRect(m_state, !bHidden, &rcEnd);
914
915 if (bVisible) {
916 RECT rcStart;
917
918 // Only slide the window if the user has FullDrag turned on.
919 if (!::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &bFullDragOn, 0))
920 bFullDragOn = false;
921
922 // Get our start window location.
923 GetAutoHideRect(m_state, bHidden, &rcStart);
924
925 if (bFullDragOn && (rcStart.left != rcEnd.left || rcStart.top != rcEnd.top || rcStart.right != rcEnd.right || rcStart.bottom != rcEnd.bottom)) {
926 #pragma warning(push)
927 #pragma warning(disable: 28159)
928
929 // Get our starting and ending time.
930 DWORD dwTimeStart = ::GetTickCount();
931 DWORD dwTimeElapsed;
932 RECT rcDelta;
933
934 // Calculate difference between ending and starting rectangle.
935 rcDelta.left = rcEnd.left - rcStart.left;
936 rcDelta.top = rcEnd.top - rcStart.top;
937 rcDelta.right = rcEnd.right - rcStart.right;
938 rcDelta.bottom = rcEnd.bottom - rcStart.bottom;
939
940 while ((dwTimeElapsed = ::GetTickCount() - dwTimeStart) < wxABT_AUTOHIDETIME) {
941 // Do the linear interpolation.
942 RECT rect;
943 rect.left = rcStart.left + ::MulDiv(rcDelta.left, dwTimeElapsed, wxABT_AUTOHIDETIME);
944 rect.top = rcStart.top + ::MulDiv(rcDelta.top, dwTimeElapsed, wxABT_AUTOHIDETIME);
945 rect.right = rcStart.right + ::MulDiv(rcDelta.right, dwTimeElapsed, wxABT_AUTOHIDETIME);
946 rect.bottom = rcStart.bottom + ::MulDiv(rcDelta.bottom, dwTimeElapsed, wxABT_AUTOHIDETIME);
947
948 // Show the window at its changed position
949 wxVERIFY(::SetWindowPos(m_hWnd, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE));
950 wxVERIFY(::UpdateWindow(m_hWnd));
951 }
952
953 #pragma warning(pop)
954 }
955 }
956
957 if (show)
958 m_flags &= ~wxABF_AUTOHIDDEN;
959 else
960 m_flags |= wxABF_AUTOHIDDEN;
961
962 if (bVisible) {
963 wxVERIFY(::SetWindowPos(m_hWnd, NULL, rcEnd.left, rcEnd.top, rcEnd.right - rcEnd.left, rcEnd.bottom - rcEnd.top, SWP_NOZORDER | SWP_NOACTIVATE));
964 wxVERIFY(::UpdateWindow(m_hWnd));
965 // Reset auto-hide timer.
966 m_timerID = ::SetTimer(m_hWnd, wxABT_AUTOHIDETIMERID, wxABT_AUTOHIDETIMERINTERVAL, NULL);
967 }
968}
969
970
971template <class W>
973{
974 if (stateNew == wxAppBarState::FLOAT) {
975 if (m_flags & wxABF_HIDETASKBARTABWHENFLOATING) {
976 // Hide our application bar's entry on the Windows's taskbar.
977 wxModifyStyleEx(m_hWnd, 0, WS_EX_TOOLWINDOW);
978 if (m_taskbarList)
979 wxVERIFY(SUCCEEDED(m_taskbarList->DeleteTab(m_hWnd)));
980 } else if (m_flags & wxABF_HIDETASKBARTABWHENDOCKED) {
981 // Show our application bar's entry on the Windows's taskbar.
982 wxModifyStyleEx(m_hWnd, WS_EX_TOOLWINDOW, 0);
983 if (m_taskbarList)
984 wxVERIFY(SUCCEEDED(m_taskbarList->AddTab(m_hWnd)));
985 }
986 } else if (wxAppBarIsDocked(stateNew)) {
987 if (m_flags & wxABF_HIDETASKBARTABWHENDOCKED) {
988 // Hide our application bar's entry on the Windows's taskbar.
989 wxModifyStyleEx(m_hWnd, 0, WS_EX_TOOLWINDOW);
990 if (m_taskbarList)
991 wxVERIFY(SUCCEEDED(m_taskbarList->DeleteTab(m_hWnd)));
992 } else if (m_flags & wxABF_HIDETASKBARTABWHENFLOATING) {
993 // Show our application bar's entry on the Windows's taskbar.
994 wxModifyStyleEx(m_hWnd, WS_EX_TOOLWINDOW, 0);
995 if (m_taskbarList)
996 wxVERIFY(SUCCEEDED(m_taskbarList->AddTab(m_hWnd)));
997 }
998 } else {
999 // Unknown state.
1000 wxFAIL_MSG(wxT("unknown application bar state"));
1001 }
1002}
1003
1004
1005template <class W>
1007{
1008 if (state != m_stateTaskBar) {
1009 // No change, no fun.
1010 return;
1011 }
1012
1013 if ((m_flags & wxABF_ALWAYSONTOPTASKBAR) &&
1014 (m_stateTaskBar & ABS_ALWAYSONTOP) != (state & ABS_ALWAYSONTOP)) {
1015 // Always-on-top state of the taskbar changed and we're supposed to mimic it.
1016 SetAlwaysOnTop((state & ABS_ALWAYSONTOP) ? true : false);
1017 }
1018
1019 if ((m_flags & wxABF_AUTOHIDETASKBAR) &&
1020 (m_stateTaskBar & ABS_AUTOHIDE) != (state & ABS_AUTOHIDE)) {
1021 // Auto-hide state of the taskbar changed and we're supposed to mimic it.
1022 SetAutoHide((state & ABS_AUTOHIDE) ? true : false);
1023 }
1024
1025 // Remember the state.
1026 m_stateTaskBar = state;
1027}
1028
1029
1030template <class W>
1031void wxAppBar<W>::OnWindowsArrange(bool WXUNUSED(beginning))
1032{
1033}
1034
1035
1036template <class W>
1038{
1039 wxMessageBox(_("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."), _("Warning"), wxOK | wxICON_WARNING, this);
1040}
1041
1042
1044template <class W>
1045WXLRESULT wxAppBar<W>::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
1046{
1047 switch (message) {
1048 case WM_CREATE: {
1049 WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam);
1050
1051 // Register our application bar.
1052 APPBARDATA abd = { sizeof(abd), m_hWnd, WM_AB_NOTIFY, static_cast<UINT>(m_state) };
1053 wxCHECK(::SHAppBarMessage(ABM_NEW, &abd), false);
1054
1055 // Get the state of the Windows taskbar.
1056 m_stateTaskBar = wxAppBarGetTaskBarState();
1057
1058 if (m_flags & wxABF_AUTOHIDETASKBAR) {
1059 // Mimic the auto-hide state of taskbar.
1060 SetAutoHide((m_stateTaskBar & ABS_AUTOHIDE) ? true : false);
1061 }
1062
1063 if (m_flags & wxABF_ALWAYSONTOPTASKBAR) {
1064 // Mimic the always-on-top state of taskbar.
1065 SetAlwaysOnTop((m_stateTaskBar & ABS_ALWAYSONTOP) ? true : false);
1066 }
1067
1068 return lResult;
1069 }
1070
1071 case WM_DESTROY: {
1072 wxASSERT_MSG(m_timerID == 0, wxT("timer still active"));
1073
1074 // Remove the application bar.
1075 APPBARDATA abd = { sizeof(abd), m_hWnd };
1076 wxVERIFY(::SHAppBarMessage(ABM_REMOVE, &abd));
1077
1078 return W::MSWWindowProc(message, wParam, lParam);
1079 }
1080
1081 case WM_SHOWWINDOW:
1082 if (wParam) {
1083 // Do the false change of state notification, to allow initialization.
1084 OnChangeState(m_state);
1085
1086 if (wxAppBarIsDocked(m_state)) {
1087 if (IsAutoHide()) {
1088 // Register auto-hide application bar.
1089 RegisterAutoHide(m_state);
1090 } else {
1091 // Auto-hide failed or wasn't desired at all.
1092 DockAppBar(m_state);
1093 }
1094 }
1095
1096 // We're all set. Show the window now.
1097 return W::MSWWindowProc(message, wParam, lParam);
1098 } else {
1099 // Hide the window first, to avoid flicker.
1100 WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam);
1101
1102 // Clean previous docking/auto-hide settings if required.
1103 if (wxAppBarIsDocked(m_state)) {
1104 if (IsAutoHide())
1105 UnregisterAutoHide(m_state);
1106 else
1107 UndockAppBar();
1108 }
1109
1110 return lResult;
1111 }
1112
1113 case WM_WINDOWPOSCHANGING: {
1114 if (m_state != m_stateDesired && wxAppBarIsDocked(m_stateDesired)) {
1115 wxASSERT(lParam);
1116 LPWINDOWPOS lpwndpos = (LPWINDOWPOS)lParam;
1117 if (lpwndpos) {
1118 // When about to get docked, fix position and size to avoid Aero Snap interfering with window size.
1119 RECT rect;
1120 GetDockedRect(m_stateDesired, &rect);
1121 lpwndpos->x = rect.left;
1122 lpwndpos->y = rect.top;
1123 lpwndpos->cx = rect.right - rect.left;
1124 lpwndpos->cy = rect.bottom - rect.top;
1125 lpwndpos->flags &= ~(SWP_NOMOVE | SWP_NOSIZE);
1126 }
1127 }
1128
1129 return W::MSWWindowProc(message, wParam, lParam);
1130 }
1131
1132 case WM_WINDOWPOSCHANGED: {
1133 WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam);
1134
1135 if (wxAppBarIsDocked(m_state)) {
1136 // When our window changes position, tell the Shell so that any
1137 // auto-hidden application bar on our edge stays on top of our window making it
1138 // always accessible to the user.
1139 APPBARDATA abd = { sizeof(abd), m_hWnd };
1140 wxVERIFY(::SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd));
1141 }
1142
1143 return lResult;
1144 }
1145
1146 case WM_ENTERSIZEMOVE:
1147 m_stateDesired = m_state;
1148 return W::MSWWindowProc(message, wParam, lParam);
1149
1150 case WM_EXITSIZEMOVE: {
1151 WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam);
1152
1153 // Clean previous docking/auto-hide settings if required.
1154 if (wxAppBarIsDocked(m_state) &&
1155 (m_stateDesired == wxAppBarState::FLOAT || m_stateDesired != m_state && wxAppBarIsDocked(m_stateDesired)))
1156 {
1157 if (IsAutoHide())
1158 UnregisterAutoHide(m_state);
1159 else if (m_stateDesired == wxAppBarState::FLOAT)
1160 UndockAppBar();
1161 }
1162
1163 // Setup new docking/auto-hide settings.
1164 if (wxAppBarIsDocked(m_stateDesired)) {
1165 if (IsAutoHide()) {
1166 // Application bar should be auto-hide. Try to setup it as so.
1167 // Register auto-hide application bar.
1168 RegisterAutoHide(m_stateDesired);
1169 } else {
1170 // Auto-hide failed or wasn't desired at all.
1171 DockAppBar(m_stateDesired);
1172 }
1173 }
1174
1175 // Notify about the change of state.
1176 OnChangeState(m_stateDesired);
1177 m_state = m_stateDesired;
1178 m_stateDesired = wxAppBarState::UNKNOWN;
1179
1180 return lResult;
1181 }
1182
1183 case WM_MOVING: {
1184 WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam);
1185
1186 wxASSERT(lParam);
1187 LPRECT lpRect = (LPRECT)lParam;
1188
1189 // Phase 1. - Determine the desired state (which screen edge or floating) according to the mouse position.
1190
1191 wxAppBarState uStateDesiredPrev = m_stateDesired;
1192 DWORD dwPoint = ::GetMessagePos();
1193 wxPoint ptMouse(GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint));
1194
1195 m_stateDesired = wxAppBarState::UNKNOWN;
1196
1197 if ((m_flags & wxABF_ALLOWFLOAT) && (::GetKeyState(VK_CONTROL) < 0 || !(m_flags & wxABF_ALLOWDOCKANY))) {
1198 // 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.
1199 m_stateDesired = wxAppBarState::FLOAT;
1200 } else {
1201 RECT rcWorkArea = {};
1202 INT iDist, iDistMin = INT_MAX;
1203
1204 // Get the rectangle that bounds the size of the screen
1205 // minus any docked (but not-autohidden) AppBars.
1206 wxVERIFY(::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0));
1207
1208 // Test all four edges, to find the closest one.
1209 if ((m_flags & wxABF_ALLOWDOCKTOP) && (iDist = ptMouse.y - rcWorkArea.top) < iDistMin) {
1210 m_stateDesired = wxAppBarState::TOP;
1211 iDistMin = iDist;
1212 }
1213 if ((m_flags & wxABF_ALLOWDOCKBOTTOM) && (iDist = rcWorkArea.bottom - ptMouse.y) < iDistMin) {
1214 m_stateDesired = wxAppBarState::BOTTOM;
1215 iDistMin = iDist;
1216 }
1217 if ((m_flags & wxABF_ALLOWDOCKLEFT) && (iDist = ptMouse.x - rcWorkArea.left) < iDistMin) {
1218 m_stateDesired = wxAppBarState::LEFT;
1219 iDistMin = iDist;
1220 }
1221 if ((m_flags & wxABF_ALLOWDOCKRIGHT) && (iDist = rcWorkArea.right - ptMouse.x) < iDistMin) {
1222 m_stateDesired = wxAppBarState::RIGHT;
1223 iDistMin = iDist;
1224 }
1225 if ((m_flags & wxABF_ALLOWFLOAT) && (iDist = wxMax(::GetSystemMetrics(SM_CXVSCROLL), ::GetSystemMetrics(SM_CYHSCROLL))) < iDistMin) {
1226 m_stateDesired = wxAppBarState::FLOAT;
1227 iDistMin = iDist;
1228 }
1229 }
1230
1231 wxASSERT_MSG(m_stateDesired != wxAppBarState::UNKNOWN, wxT("undetermined application bar state"));
1232
1233 // Phase 2. - Calculate the desired rectangle, according to the desired state.
1234
1235 if (m_stateDesired == wxAppBarState::FLOAT) {
1236 if (wxAppBarIsDocked(uStateDesiredPrev)) {
1237 // We just switched from docked to floating state. Align the window according to the mouse pointer.
1238 lpRect->left = ptMouse.x - m_sizeFloat.cx / 2;
1239 lpRect->top = ptMouse.y;
1240
1241 // We also resize back to floating window size.
1242 lpRect->right = lpRect->left + m_sizeFloat.cx;
1243 lpRect->bottom = lpRect->top + m_sizeFloat.cy;
1244 }
1245 } else if (wxAppBarIsDocked(m_stateDesired)) {
1246 if (IsAutoHide()) {
1247 // Calculate auto-hide window rect.
1248 GetAutoHideRect(m_stateDesired, false, lpRect);
1249 } else {
1250 // Calculate docked window rect.
1251 GetDockedRect(m_stateDesired, lpRect);
1252 }
1253 } else {
1254 // Window is not floating. It's not docked either. Then what?
1255 wxFAIL_MSG(wxT("unknown application bar state"));
1256 }
1257
1258 if (m_stateDesired != uStateDesiredPrev) {
1259 // Notify about the proposed change of state, but don't change the state yet.
1260 OnChangeState(m_stateDesired);
1261 }
1262
1263 return lResult;
1264 }
1265
1266 case WM_SIZING: {
1267 wxASSERT(lParam);
1268 LPRECT lpRect = (LPRECT)lParam;
1269
1270 if (m_stateDesired == wxAppBarState::FLOAT) {
1271 // Remember the floating window size.
1272 m_sizeFloat.cx = lpRect->right - lpRect->left;
1273 m_sizeFloat.cy = lpRect->bottom - lpRect->top;
1274 } else if (wxAppBarIsDocked(m_stateDesired)) {
1275 // Remember the docked window size.
1276 if (wxAppBarIsDockedVert(m_stateDesired))
1277 m_sizeDocked.cx = lpRect->right - lpRect->left;
1278 else
1279 m_sizeDocked.cy = lpRect->bottom - lpRect->top;
1280 } else {
1281 // Unknown state.
1282 wxFAIL_MSG(wxT("unknown application bar state"));
1283 }
1284
1285 return W::MSWWindowProc(message, wParam, lParam);
1286 }
1287
1288 case WM_GETMINMAXINFO: {
1289 WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam);
1290
1291 wxASSERT(lParam);
1292 LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
1293
1294 // Convert client size to window size.
1295 RECT rectClient = {};
1296 wxVERIFY(::GetClientRect(m_hWnd, &rectClient));
1297 if (rectClient.right - rectClient.left && rectClient.bottom - rectClient.top) {
1298 RECT rectWindow = {};
1299 wxVERIFY(::GetWindowRect(m_hWnd, &rectWindow));
1300 lpMMI->ptMinTrackSize.x = m_sizeMin.cx + (rectWindow.right - rectWindow.left) - (rectClient.right - rectClient.left);
1301 lpMMI->ptMinTrackSize.y = m_sizeMin.cy + (rectWindow.bottom - rectWindow.top ) - (rectClient.bottom - rectClient.top );
1302 }
1303
1304 return lResult;
1305 }
1306
1307 case WM_NCMOUSEMOVE:
1308 // If we are a docked, auto-hidden application bar, shown us
1309 // when the user moves over our non-client area
1310 ShowAutoHideAppBar(true);
1311
1312 return W::MSWWindowProc(message, wParam, lParam);
1313
1314 case WM_NCHITTEST: {
1315 // Find out what the base class thinks is the hit test code.
1316 WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam);
1317
1318 if (HTSIZEFIRST <= lResult && lResult <= HTSIZELAST) {
1319 if (GetAllowSizing()) {
1320 if (wxAppBarIsDocked(m_state)) {
1321 // When the application bar is docked, the user can resize only one edge.
1322 // This next section determines which edge the user can resize.
1323 // To allow resizing, the application bar window must have the WS_THICKFRAME style.
1324
1325 RECT rcClient = {};
1326 wxPoint point(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
1327
1328 // Resizing IS allowed for the edge that the application bar is docked on.
1329 // Get the location of the appbar's client area in screen coordinates.
1330 wxVERIFY(::GetClientRect(m_hWnd, &rcClient));
1331 wxVERIFY(::ClientToScreen(m_hWnd, (LPPOINT)&rcClient));
1332 wxVERIFY(::ClientToScreen(m_hWnd, ((LPPOINT)&rcClient) + 1));
1333
1334 // Assume that we can't resize
1335 lResult = HTBORDER;
1336
1337 switch (m_state) {
1338 case wxAppBarState::LEFT: if (point.x > rcClient.right) lResult = HTRIGHT; break;
1339 case wxAppBarState::TOP: if (point.y > rcClient.bottom) lResult = HTBOTTOM; break;
1340 case wxAppBarState::RIGHT: if (point.x < rcClient.left) lResult = HTLEFT; break;
1341 case wxAppBarState::BOTTOM: if (point.y < rcClient.top) lResult = HTTOP; break;
1342 }
1343 }
1344 } else {
1345 // The sizing is locked. Pretend that the mouse is not on a resize border.
1346 lResult = HTBORDER;
1347 }
1348 }
1349
1350 return lResult;
1351 }
1352
1353 case WM_ACTIVATE: {
1354 WXLRESULT lResult = W::MSWWindowProc(message, wParam, lParam);
1355
1356 if (wxAppBarIsDocked(m_state)) {
1357 // When our window changes activation state, tell the Shell so that any
1358 // auto-hidden application bar on our edge stays on top of our window making it
1359 // always accessible to the user.
1360 APPBARDATA abd = { sizeof(abd), m_hWnd };
1361 wxVERIFY(::SHAppBarMessage(ABM_ACTIVATE, &abd));
1362
1363 if (LOWORD(wParam) == WA_INACTIVE && IsAutoHide()) {
1364 // Hide the application bar if we are docked and auto-hidden.
1365 ShowAutoHideAppBar(false);
1366 }
1367 }
1368
1369 return lResult;
1370 }
1371
1372 case WM_TIMER:
1373 if (wParam == wxABT_AUTOHIDETIMERID) {
1374 if (!GetAutoHidden() &&
1375 wxAppBarIsDocked(m_state) &&
1376 GetActiveWindow() != m_hWnd)
1377 {
1378 // Get the position of the mouse and the application bar's position
1379 // Everything must be in screen coordinates.
1380 DWORD dwPoint = ::GetMessagePos();
1381 wxPoint pointMouse(GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint));
1382 RECT rect = {};
1383 wxVERIFY(::GetWindowRect(m_hWnd, &rect));
1384 wxRect rectBounds(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
1385
1386 // Add a little margin around the application bar
1387 rectBounds.Inflate(2 * ::GetSystemMetrics(SM_CXDOUBLECLK), 2 * ::GetSystemMetrics(SM_CYDOUBLECLK));
1388 if (!rectBounds.Contains(pointMouse)) {
1389 // If the mouse is NOT over or near the application bar, hide it.
1390 ShowAutoHideAppBar(false);
1391 }
1392 }
1393
1394 return 0;
1395 } else
1396 return W::MSWWindowProc(message, wParam, lParam);
1397
1398 case WM_AB_NOTIFY:
1399 switch (wParam) {
1400 case ABN_FULLSCREENAPP:
1401 if (lParam)
1402 m_flags |= wxABF_FULLSCREENAPPOPEN;
1403 else
1404 m_flags &= ~wxABF_FULLSCREENAPPOPEN;
1405 OnChangeTaskBarState(wxAppBarGetTaskBarState());
1406
1407 if (::IsWindowVisible(m_hWnd)) {
1408 // Set the Z-order.
1409 wxVERIFY(::SetWindowPos(m_hWnd, wxAppBarGetZWnd(m_state, m_flags), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOSENDCHANGING));
1410 }
1411 break;
1412
1413 case ABN_POSCHANGED:
1414 if (wxAppBarIsDocked(m_state) && !IsAutoHide())
1415 DockAppBar(m_state);
1416 break;
1417
1418 case ABN_STATECHANGE:
1419 // Taskbar's state changed.
1420 OnChangeTaskBarState(wxAppBarGetTaskBarState());
1421 break;
1422
1423 case ABN_WINDOWARRANGE:
1424 OnWindowsArrange(lParam ? true : false);
1425 break;
1426
1427 default:
1428 // Unknown message.
1429 wxFAIL_MSG(wxString::Format(wxT("unknown application bar notification 0x%x"), wParam));
1430 break;
1431 }
1432
1433 return 0;
1434
1435 default:
1436 return W::MSWWindowProc(message, wParam, lParam);
1437 }
1438}
1440
1441
1443
1444template <class W>
1445_Use_decl_annotations_
1446inline bool wxAppBar<W>::DockAppBar(wxAppBarState state)
1447{
1448 wxASSERT(wxAppBarIsDocked(state));
1449
1450 // Calculate docked window rect and dock the window there.
1451 APPBARDATA abd = { sizeof(abd), m_hWnd, 0, static_cast<UINT>(state) };
1452 GetDockedRect(state, &(abd.rc));
1453 wxCHECK(::SHAppBarMessage(ABM_SETPOS, &abd), false);
1454 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);
1455
1456 return true;
1457}
1458
1459
1460template <class W>
1461_Use_decl_annotations_
1462inline bool wxAppBar<W>::UndockAppBar()
1463{
1464 // Free application bar's space to undock.
1465 APPBARDATA abd = { sizeof(abd), m_hWnd, 0, ABE_LEFT };
1466 wxASSERT(!abd.rc.left && !abd.rc.top && !abd.rc.right && !abd.rc.bottom);
1467 wxCHECK(::SHAppBarMessage(ABM_SETPOS, &abd), false);
1468
1469 return true;
1470}
1471
1472
1473template <class W>
1474_Use_decl_annotations_
1476{
1477 wxASSERT(wxAppBarIsDocked(state));
1478
1479 // Register application bar as auto-hide.
1480 APPBARDATA abd = { sizeof(abd), m_hWnd, 0, static_cast<UINT>(state), {}, (LPARAM)true };
1481 if (::SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd)) {
1482 // Auto-hide succeeded.
1483 m_flags |= wxABF_AUTOHIDE;
1484 m_flags &= ~wxABF_AUTOHIDDEN;
1485
1486 // Calculate auto-hidden window rect and move the window there.
1487 GetAutoHideRect(state, false, &(abd.rc));
1488 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);
1489
1490 // Reset auto-hide timer.
1491 m_timerID = ::SetTimer(m_hWnd, wxABT_AUTOHIDETIMERID, wxABT_AUTOHIDETIMERINTERVAL, NULL);
1492
1493 return true;
1494 } else {
1495 // Auto-hide failed; some other application bar must be hidden on this edge already.
1496 m_flags &= ~(wxABF_AUTOHIDE | wxABF_AUTOHIDDEN);
1497
1498 // Post a message to user.
1499 OnAutoHideDenied();
1500
1501 return false;
1502 }
1503}
1504
1505
1506template <class W>
1507_Use_decl_annotations_
1509{
1510 wxASSERT(wxAppBarIsDocked(state));
1511
1512 // Unregister application bar as auto-hide.
1513 APPBARDATA abd = { sizeof(abd), m_hWnd, 0, static_cast<UINT>(state), {}, (LPARAM)false };
1514 wxCHECK(::SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd), false);
1515 m_flags &= ~wxABF_AUTOHIDDEN;
1516
1517 // Cancel the timer.
1518 if (m_timerID) {
1519 ::KillTimer(m_hWnd, m_timerID);
1520 m_timerID = 0;
1521 }
1522
1523 return true;
1524}
1525
1526
1527template <class W>
1528_Use_decl_annotations_
1529inline bool wxAppBar<W>::GetDockedRect(wxAppBarState state, LPRECT rect) const
1530{
1531 wxASSERT(wxAppBarIsDocked(state));
1532 wxASSERT(rect);
1533
1534 // Set dimensions to full screen.
1535 APPBARDATA abd = { sizeof(abd), m_hWnd, 0, static_cast<UINT>(state), { 0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN) } };
1536 wxCHECK(::SHAppBarMessage(ABM_QUERYPOS, &abd), false);
1537
1538 // Correct our dimensions accordingly.
1539 switch (state) {
1541 rect->left = abd.rc.left;
1542 rect->top = abd.rc.top;
1543 rect->right = abd.rc.left + m_sizeDocked.cx;
1544 rect->bottom = abd.rc.bottom;
1545 break;
1546
1547 case wxAppBarState::TOP:
1548 rect->left = abd.rc.left;
1549 rect->top = abd.rc.top;
1550 rect->right = abd.rc.right;
1551 rect->bottom = abd.rc.top + m_sizeDocked.cy;
1552 break;
1553
1555 rect->left = abd.rc.right - m_sizeDocked.cx;
1556 rect->top = abd.rc.top;
1557 rect->right = abd.rc.right;
1558 rect->bottom = abd.rc.bottom;
1559 break;
1560
1562 rect->left = abd.rc.left;
1563 rect->top = abd.rc.bottom - m_sizeDocked.cy;
1564 rect->right = abd.rc.right;
1565 rect->bottom = abd.rc.bottom;
1566 break;
1567
1568 default:
1569 // Unknown state.
1570 wxFAIL_MSG(wxT("unsupported application bar state"));
1571 return false;
1572 }
1573
1574 return true;
1575}
1576
1577
1578template <class W>
1579_Use_decl_annotations_
1580inline bool wxAppBar<W>::GetAutoHideRect(wxAppBarState state, bool bAutoHidden, LPRECT rect) const
1581{
1582 wxASSERT(wxAppBarIsDocked(state));
1583 wxASSERT(rect);
1584
1585 // Keep a part of the application bar visible at all times
1586 const int iBorder = ::GetSystemMetrics(wxAppBarIsDockedVert(state) ? SM_CXBORDER : SM_CYBORDER) * 2;
1587 const RECT rcScreen = {
1588 0,
1589 0,
1590 ::GetSystemMetrics(SM_CXSCREEN),
1591 ::GetSystemMetrics(SM_CYSCREEN)
1592 };
1593
1594 // Correct our dimensions accordingly.
1595 switch (state) {
1597 rect->top = rcScreen.top;
1598 rect->bottom = rcScreen.bottom;
1599 rect->right = rcScreen.left + (bAutoHidden ? iBorder : m_sizeDocked.cx);
1600 rect->left = rect->right - m_sizeDocked.cx;
1601 break;
1602
1603 case wxAppBarState::TOP:
1604 rect->left = rcScreen.left;
1605 rect->right = rcScreen.right;
1606 rect->bottom = rcScreen.top + (bAutoHidden ? iBorder : m_sizeDocked.cy);
1607 rect->top = rect->bottom - m_sizeDocked.cy;
1608 break;
1609
1611 rect->left = rcScreen.right - (bAutoHidden ? iBorder : m_sizeDocked.cx);
1612 rect->top = rcScreen.top;
1613 rect->right = rect->left + m_sizeDocked.cx;
1614 rect->bottom = rcScreen.bottom;
1615 break;
1616
1618 rect->left = rcScreen.left;
1619 rect->top = rcScreen.bottom - (bAutoHidden ? iBorder : m_sizeDocked.cy);
1620 rect->right = rcScreen.right;
1621 rect->bottom = rect->top + m_sizeDocked.cy;
1622 break;
1623
1624 default:
1625 // Unknown state.
1626 wxFAIL_MSG(wxT("unsupported application bar state"));
1627 return false;
1628 }
1629
1630 return true;
1631}
1632
Dockable application bar dialog.
Definition appbar.h:344
Dockable application bar frame.
Definition appbar.h:305
Dockable application bar template.
Definition appbar.h:103
UINT_PTR m_timerID
Application bar's timer id.
Definition appbar.h:289
bool IsAutoHide() const
Returns if application bar is configured for auto-hide.
Definition appbar.h:618
bool IsAlwaysOnTop() const
Returns whether application bar is displayed always on top.
Definition appbar.h:594
wxAppBarState GetState() const
Returns current state of the application bar.
Definition appbar.h:587
ITaskbarList * m_taskbarList
Windows's taskbar list interface.
Definition appbar.h:291
void MaximiseFromEdge(wxWindow *wnd)
Restore application bar from the edge of the desktop.
Definition appbar.h:869
UINT_PTR m_stateTaskBar
TaskBar's current state.
Definition appbar.h:288
virtual ~wxAppBar()
Destructor.
Definition appbar.h:523
virtual void OnWindowsArrange(bool beginning)
Notification handler when desktop windows are being arranged (cascaded, tiled, ......
Definition appbar.h:1031
wxAppBar()
Creates new application bar.
Definition appbar.h:505
SIZE m_sizeFloat
Window size when floating (we need it to restore floating size, when we undock)
Definition appbar.h:284
int m_flags
Flags describing application bar's behaviour.
Definition appbar.h:282
void MaximiseFromEdge(const RECT *rect=NULL)
Restore application bar from the edge of the desktop.
Definition appbar.h:826
void MinimiseToEdge(wxAppBarState edge, wxWindow *wnd=NULL)
Minimize application bar to the edge of the desktop.
Definition appbar.h:763
bool GetAllowSizing() const
Returns if sizing of the application bar is allowed.
Definition appbar.h:659
void HideAutoHideAppBar()
Hides auto-hide application bar.
Definition appbar.h:220
wxAppBarState m_state
Current state of the application bar.
Definition appbar.h:280
bool SetAutoHide(bool autoHide=true)
Sets whether application bar is displayed always on top.
Definition appbar.h:625
virtual void OnAutoHideDenied()
Called when application bar was forced from auto-hide to normal docking.
Definition appbar.h:1037
SIZE m_sizeMin
Minimum window size.
Definition appbar.h:286
wxAppBarState m_stateDesired
Desired state of the application bar while moving/resizing.
Definition appbar.h:281
bool SetAllowSizing(bool allow=true)
Sets whether resizing of the application bar is allowed.
Definition appbar.h:666
SIZE m_sizeDocked
Size of the window when docked (height when wxAppBarState::TOP or wxAppBarState::BOTTOM,...
Definition appbar.h:285
virtual void OnChangeState(wxAppBarState stateNew)
Notification handler when the new state of the application bar is proposed.
Definition appbar.h:972
virtual void OnChangeTaskBarState(UINT_PTR state)
Notification handler when the Windows' taskbar state changes.
Definition appbar.h:1006
bool SetAlwaysOnTop(bool alwaysOnTop=true)
Sets whether application bar is displayed always on top.
Definition appbar.h:601
bool GetAutoHidden() const
Returns if application bar is auto-hidden right now.
Definition appbar.h:678
void ShowAutoHideAppBar(bool show=true)
Shows or hides auto-hide application bar.
Definition appbar.h:899
WXHWND wxAppBarGetZWnd(wxAppBarState state, int flags)
Returns the window above which to Z-order the application bar.
Definition appbar.h:437
#define wxABF_ALLOWDOCKLEFT
Is docking left of the screen allowed?
Definition appbar.h:74
#define wxABT_AUTOHIDETIME
Application bar auto-hide timer timeout.
Definition appbar.h:36
#define wxABF_FULLSCREENAPPOPEN
Is full-screen application open?
Definition appbar.h:94
UINT_PTR wxAppBarGetTaskBarState()
Returns the current taskbar state.
Definition appbar.h:491
#define WM_AB_NOTIFY
Posted to notify application bar about system changes.
Definition appbar.h:52
bool wxGetDoWndAnimation()
Returns whether windows animation is enabled.
Definition common.h:95
#define wxABT_AUTOHIDETIMERID
Application bar auto-hide timer ID.
Definition appbar.h:31
#define wxABF_ALLOWSIZING
Is application bar's sizing allowed?
Definition appbar.h:87
#define wxABF_ALLOWDOCKTOP
Is docking on top of the screen allowed?
Definition appbar.h:72
#define wxABF_HIDETASKBARTABWHENFLOATING
Should application bar's tab on the system taskbar hide when floating?
Definition appbar.h:89
#define wxABF_ALLOWDOCKBOTTOM
Is docking on bottom of the screen allowed?
Definition appbar.h:73
bool wxAppBarIsDocked(wxAppBarState state)
Returns if the application bar state represents docked state.
Definition appbar.h:392
bool wxModifyStyleEx(WXHWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags=0)
Modifies window extended style.
Definition common.h:115
#define WXEXTEND_API
Public function calling convention.
Definition common.h:56
#define wxABT_AUTOHIDETIMERINTERVAL
Application bar auto-hide timer interval.
Definition appbar.h:41
#define wxABF_AUTOHIDE
Is application bar setup for auto-hide?
Definition appbar.h:84
bool wxAppBarIsDockedHoriz(wxAppBarState state)
Returns if the application bar state represents horizontally docked state.
Definition appbar.h:422
#define wxABF_ALLOWDOCKANY
Is docking at any edge of the screen allowed?
Definition appbar.h:76
#define wxABF_AUTOHIDDEN
Is application bar auto-hidden right now?
Definition appbar.h:95
#define wxABF_HIDETASKBARTABWHENDOCKED
Should application bar's tab on the system taskbar hide when docked?
Definition appbar.h:90
#define wxABF_ALLOWFLOAT
Dockable application bar flags.
Definition appbar.h:71
#define wxABF_ALLOWDOCKRIGHT
Is docking right of the screen allowed?
Definition appbar.h:75
#define wxABF_ALWAYSONTOP
Is application bar always on top?
Definition appbar.h:81
wxAppBarState
Dockable application bar states.
Definition appbar.h:58
bool wxAppBarIsDockedVert(wxAppBarState state)
Returns if the application bar state represents vertically docked state.
Definition appbar.h:407
#define wxABF_ALWAYSONTOPTASKBAR
Does application bar follow always on top state of the system taskbar?
Definition appbar.h:82
#define wxVERIFY(cond)
Test if condition is true. When not true, raise debug assertion with the given message.
Definition common.h:84
#define wxABF_AUTOHIDETASKBAR
Does application bar follow auto-hide state of the system taskbar?
Definition appbar.h:85
#define wxABF_ALLOWANY
Is floating and docking at any edge of the screen allowed?
Definition appbar.h:79
@ BOTTOM
Application bar is docked at the bottom edge of the desktop.
@ RIGHT
Application bar is docked at the right edge of the desktop.
@ TOP
Application bar is docked at the top edge of the desktop.
@ LEFT
Application bar is docked at the left edge of the desktop.
@ FLOAT
Application bar is floating on the desktop (normal window)