wxAppBar is now a template. wxAppBarFrame and wxAppBarDialog classes for wxFrame and wxDialog based implementations added.
This commit is contained in:
parent
f14e5948a5
commit
c0a67de62f
File diff suppressed because it is too large
Load Diff
799
src/appbar.cpp
799
src/appbar.cpp
@ -22,809 +22,58 @@
|
|||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// wxAppBar
|
// wxAppBarFrame
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
const UINT wxAppBar::WM_AB_NOTIFY = ::RegisterWindowMessage(_T("AppBarNotify"));
|
wxAppBarFrame::wxAppBarFrame()
|
||||||
|
|
||||||
|
|
||||||
wxAppBar::wxAppBar() :
|
|
||||||
m_timerID(0),
|
|
||||||
m_taskbarList(NULL),
|
|
||||||
wxFrame()
|
|
||||||
{
|
{
|
||||||
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wxAppBar::wxAppBar(wxWindow *parent, wxWindowID id, const wxString& title, wxState state, int flags, const wxPoint& pos, const wxSize& size, long style, const wxString& name) :
|
wxAppBarFrame::wxAppBarFrame(wxWindow *parent, wxWindowID id, const wxString& title, wxAppBarState state, int flags, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
|
||||||
m_timerID(0),
|
|
||||||
m_taskbarList(NULL),
|
|
||||||
wxFrame()
|
|
||||||
{
|
{
|
||||||
|
Init();
|
||||||
Create(parent, id, title, state, flags, pos, size, style, name);
|
Create(parent, id, title, state, flags, pos, size, style, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool wxAppBar::Create(wxWindow *parent, wxWindowID id, const wxString& title, wxState state, int flags, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
|
bool wxAppBarFrame::Create(wxWindow *parent, wxWindowID id, const wxString& title, wxAppBarState state, int flags, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
|
||||||
{
|
{
|
||||||
// Save initial floating window size.
|
// Modify parameters if required.
|
||||||
m_sizeFloat.cx = size.x;
|
PreCreate(state, flags, size, style);
|
||||||
m_sizeFloat.cy = size.y;
|
|
||||||
|
|
||||||
// Save initial docked window width/height.
|
|
||||||
m_sizeDocked.cx = size.x;
|
|
||||||
m_sizeDocked.cy = size.y;
|
|
||||||
|
|
||||||
// Save initial state and flags.
|
|
||||||
m_state = state;
|
|
||||||
m_stateDesired = wxSTATE_UNKNOWN;
|
|
||||||
m_flags = flags;
|
|
||||||
|
|
||||||
// Find the taskbar list's interface.
|
|
||||||
wxCHECK(SUCCEEDED(::CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_ALL, IID_ITaskbarList, (LPVOID*)&m_taskbarList)), false);
|
|
||||||
wxCHECK(SUCCEEDED(m_taskbarList->HrInit()), false);
|
|
||||||
|
|
||||||
// If any taskbar list tab's hiding is in affect, set application bar's style as tool window to avoid being displayed on the taskbar initially.
|
|
||||||
if (state == wxSTATE_FLOAT) {
|
|
||||||
if (flags & wxFLAG_HIDETASKBARTABWHENFLOATING) {
|
|
||||||
// Hide our application bar's entry on the Windows's taskbar.
|
|
||||||
style |= wxFRAME_TOOL_WINDOW;
|
|
||||||
} else if (flags & wxFLAG_HIDETASKBARTABWHENDOCKED) {
|
|
||||||
// Show our application bar's entry on the Windows's taskbar.
|
|
||||||
style &= ~wxFRAME_TOOL_WINDOW;
|
|
||||||
}
|
|
||||||
} else if (IsDocked(state)) {
|
|
||||||
if (flags & wxFLAG_HIDETASKBARTABWHENDOCKED) {
|
|
||||||
// Hide our application bar's entry on the Windows's taskbar.
|
|
||||||
style |= wxFRAME_TOOL_WINDOW;
|
|
||||||
} else if (flags & wxFLAG_HIDETASKBARTABWHENFLOATING) {
|
|
||||||
// Show our application bar's entry on the Windows's taskbar.
|
|
||||||
style &= ~wxFRAME_TOOL_WINDOW;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Unknown state.
|
|
||||||
wxFAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create frame.
|
// Create frame.
|
||||||
wxCHECK(wxFrame::Create(parent, id, title, pos, size, style, name), false);
|
wxCHECK(wxAppBar<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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wxAppBar::~wxAppBar()
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// wxAppBarDialog
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
wxAppBarDialog::wxAppBarDialog()
|
||||||
{
|
{
|
||||||
wxASSERT(m_timerID == 0);
|
Init();
|
||||||
|
|
||||||
// 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
|
wxAppBarDialog::wxAppBarDialog(wxWindow *parent, wxWindowID id, const wxString& title, wxAppBarState state, int flags, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
|
||||||
//{
|
|
||||||
// wxASSERT(lpPlacement);
|
|
||||||
//
|
|
||||||
// if (lpPlacement->dwSize >= sizeof(APPBARPLACEMENT1)) {
|
|
||||||
// lpPlacement->dwState = (DWORD)m_state;
|
|
||||||
// lpPlacement->dwFlags = m_flags;
|
|
||||||
// if (m_state == wxSTATE_FLOAT) {
|
|
||||||
// // Current application bar's rect is floating rect.
|
|
||||||
// lpPlacement->rcFloat = m_rect;
|
|
||||||
// } else if (IsDocked(m_state)) {
|
|
||||||
// // Application bar is docked. Calc floating rect from m_sizeFloat.
|
|
||||||
// lpPlacement->rcFloat.left = 0;
|
|
||||||
// lpPlacement->rcFloat.top = 0;
|
|
||||||
// lpPlacement->rcFloat.right = m_sizeFloat.cx;
|
|
||||||
// lpPlacement->rcFloat.bottom = m_sizeFloat.cy;
|
|
||||||
// } else {
|
|
||||||
// // Application bar's state is unknown.
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// lpPlacement->szDocked = m_sizeDocked;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// lpPlacement->dwSize = sizeof(*lpPlacement);
|
|
||||||
//
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//bool wxAppBar::SetAppBarPlacement(LPCAPPBARPLACEMENT lpPlacement)
|
|
||||||
//{
|
|
||||||
// wxASSERT(lpPlacement);
|
|
||||||
//
|
|
||||||
// if (lpPlacement->dwSize >= sizeof(APPBARPLACEMENT1)) {
|
|
||||||
// if (lpPlacement->dwState != wxSTATE_FLOAT && !IsDocked(lpPlacement->dwState)) {
|
|
||||||
// // The state is unknown. Abort, before we mix up internal state.
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Clean previous docking/auto-hide settings if required.
|
|
||||||
// if (IsDocked(m_state) &&
|
|
||||||
// (lpPlacement->dwState == wxSTATE_FLOAT || lpPlacement->dwState != m_state && IsDocked(lpPlacement->dwState)))
|
|
||||||
// {
|
|
||||||
// if (IsAutoHide())
|
|
||||||
// UnregisterAutoHide(m_state);
|
|
||||||
// else if (lpPlacement->dwState == wxSTATE_FLOAT)
|
|
||||||
// UndockAppBar();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Update application bar's flags, size and position.
|
|
||||||
// m_flags |= wxFLAG_POSITIONSET;
|
|
||||||
// m_sizeDocked = lpPlacement->szDocked;
|
|
||||||
// if (lpPlacement->dwState == wxSTATE_FLOAT) {
|
|
||||||
// m_rect = lpPlacement->rcFloat;
|
|
||||||
// } else if (IsDocked(lpPlacement->dwState)) {
|
|
||||||
// m_sizeFloat.cx = lpPlacement->rcFloat.right - lpPlacement->rcFloat.left;
|
|
||||||
// m_sizeFloat.cy = lpPlacement->rcFloat.bottom - lpPlacement->rcFloat.top;
|
|
||||||
// GetDockedRect(lpPlacement->dwState, &m_rect);
|
|
||||||
// } else {
|
|
||||||
// // Application bar's state is unknown.
|
|
||||||
// wxFAIL;
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Notify about the change of state.
|
|
||||||
// OnChangeState(lpPlacement->dwState);
|
|
||||||
// m_state = lpPlacement->dwState;
|
|
||||||
//
|
|
||||||
// SetAutoHide(lpPlacement->dwFlags & wxFLAG_AUTOHIDE);
|
|
||||||
// SetAlwaysOnTop(lpPlacement->dwFlags & wxFLAG_ALWAYSONTOP);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
void wxAppBar::MinimiseToEdge(wxState edge, wxWindow *wnd)
|
|
||||||
{
|
{
|
||||||
wxASSERT(IsDocked(edge));
|
Init();
|
||||||
|
Create(parent, id, title, state, flags, pos, size, style, name);
|
||||||
WXHWND hWnd;
|
|
||||||
if (!wnd) {
|
|
||||||
// No other window was specified. Minimize ourself.
|
|
||||||
wnd = this;
|
|
||||||
hWnd = m_hWnd;
|
|
||||||
} else
|
|
||||||
hWnd = wnd->GetHWND();
|
|
||||||
|
|
||||||
// If our window is hidden, there's nothing we can do.
|
|
||||||
if (hWnd == m_hWnd && !::IsWindowVisible(m_hWnd))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_state == wxSTATE_FLOAT) {
|
|
||||||
// Remember the last floating size.
|
|
||||||
RECT rect = {};
|
|
||||||
wxVERIFY(::GetWindowRect(hWnd, &rect));
|
|
||||||
m_sizeFloat.cx = rect.right - rect.left;
|
|
||||||
m_sizeFloat.cy = rect.bottom - rect.top;
|
|
||||||
}
|
|
||||||
|
|
||||||
RECT rectTo;
|
|
||||||
if (IsAutoHide())
|
|
||||||
GetAutoHideRect(edge, false, &rectTo);
|
|
||||||
else
|
|
||||||
GetDockedRect(edge, &rectTo);
|
|
||||||
|
|
||||||
if (::wxGetDoWndAnimation()) {
|
|
||||||
// Do the animation.
|
|
||||||
RECT rectFrom;
|
|
||||||
wxVERIFY(::GetWindowRect(hWnd, &rectFrom));
|
|
||||||
wxVERIFY(::DrawAnimatedRects(hWnd, IDANI_CAPTION, &rectFrom, &rectTo));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify about the change of state.
|
|
||||||
OnChangeState(edge);
|
|
||||||
m_state = edge;
|
|
||||||
|
|
||||||
if (hWnd != m_hWnd) {
|
|
||||||
// Hide the source window.
|
|
||||||
wnd->Hide();
|
|
||||||
// ::SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) &~ WS_VISIBLE);
|
|
||||||
|
|
||||||
// Show the application bar.
|
|
||||||
Show();
|
|
||||||
} else {
|
|
||||||
if (IsAutoHide()) {
|
|
||||||
// Register auto-hide application bar.
|
|
||||||
RegisterAutoHide(edge);
|
|
||||||
} else {
|
|
||||||
// Auto-hide failed or wasn't desired at all.
|
|
||||||
DockAppBar(edge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
::SetActiveWindow(m_hWnd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void wxAppBar::MaximiseFromEdge(const RECT* rect)
|
bool wxAppBarDialog::Create(wxWindow *parent, wxWindowID id, const wxString& title, wxAppBarState state, int flags, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
|
||||||
{
|
{
|
||||||
wxASSERT(::IsWindowVisible(m_hWnd));
|
// Modify parameters if required.
|
||||||
|
PreCreate(state, flags, size, style);
|
||||||
|
|
||||||
RECT rectTo;
|
// Create dialog.
|
||||||
|
wxCHECK(wxAppBar<wxDialog>::Create(parent, id, title, pos, size, style, name), false);
|
||||||
|
|
||||||
if (!rect) {
|
return true;
|
||||||
// Calculate the destination rect.
|
|
||||||
rectTo.left = (::GetSystemMetrics(SM_CXSCREEN) - m_sizeFloat.cx) / 2;
|
|
||||||
rectTo.top = (::GetSystemMetrics(SM_CYSCREEN) - m_sizeFloat.cy) / 2;
|
|
||||||
rectTo.right = rectTo.left + m_sizeFloat.cx;
|
|
||||||
rectTo.bottom = rectTo.top + m_sizeFloat.cy;
|
|
||||||
|
|
||||||
rect = &rectTo;
|
|
||||||
} else {
|
|
||||||
m_sizeFloat.cx = rect->right - rect->left;
|
|
||||||
m_sizeFloat.cy = rect->bottom - rect->top;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (::wxGetDoWndAnimation()) {
|
|
||||||
// Do the animation.
|
|
||||||
RECT rectFrom;
|
|
||||||
wxVERIFY(::GetWindowRect(m_hWnd, &rectFrom));
|
|
||||||
wxVERIFY(::DrawAnimatedRects(m_hWnd, IDANI_CAPTION, &rectFrom, rect));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean previous docking/auto-hide settings if required.
|
|
||||||
if (IsDocked(m_state)) {
|
|
||||||
if (IsAutoHide())
|
|
||||||
UnregisterAutoHide(m_state);
|
|
||||||
else
|
|
||||||
UndockAppBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify about the change of state.
|
|
||||||
OnChangeState(wxSTATE_FLOAT);
|
|
||||||
m_state = wxSTATE_FLOAT;
|
|
||||||
|
|
||||||
wxVERIFY(::SetWindowPos(m_hWnd, GetZWnd(wxSTATE_FLOAT, m_flags), rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top, SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_FRAMECHANGED));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void wxAppBar::MaximiseFromEdge(wxWindow *wnd)
|
|
||||||
{
|
|
||||||
wxASSERT(wnd);
|
|
||||||
wxASSERT(::IsWindowVisible(m_hWnd));
|
|
||||||
|
|
||||||
WXHWND hWnd = wnd->GetHWND();
|
|
||||||
|
|
||||||
RECT rectTo = {};
|
|
||||||
wxVERIFY(::GetWindowRect(hWnd, &rectTo));
|
|
||||||
m_sizeFloat.cx = rectTo.right - rectTo.left;
|
|
||||||
m_sizeFloat.cy = rectTo.bottom - rectTo.top;
|
|
||||||
|
|
||||||
if (::wxGetDoWndAnimation()) {
|
|
||||||
// Do the animation.
|
|
||||||
RECT rectFrom;
|
|
||||||
wxVERIFY(::GetWindowRect(m_hWnd, &rectFrom));
|
|
||||||
wxVERIFY(::DrawAnimatedRects(hWnd, IDANI_CAPTION, &rectFrom, &rectTo));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide our window and show the destination window.
|
|
||||||
Hide();
|
|
||||||
wnd->Show();
|
|
||||||
// ::SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) | WS_VISIBLE);
|
|
||||||
wxVERIFY(::SetForegroundWindow(hWnd));
|
|
||||||
::SetActiveWindow(hWnd);
|
|
||||||
// wxVERIFY(::RedrawWindow(hWnd, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_FRAME | RDW_INVALIDATE | RDW_ERASE));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void wxAppBar::ShowAutoHideAppBar(bool bShow)
|
|
||||||
{
|
|
||||||
RECT rcEnd;
|
|
||||||
bool
|
|
||||||
bFullDragOn,
|
|
||||||
bHidden = GetAutoHidden(),
|
|
||||||
bVisible = ::IsWindowVisible(m_hWnd) ? true : false;
|
|
||||||
|
|
||||||
if (!IsAutoHide() || bHidden != bShow) {
|
|
||||||
// We're not setup for auto-hide or already in the desired state.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get our end window location.
|
|
||||||
GetAutoHideRect(m_state, !bHidden, &rcEnd);
|
|
||||||
|
|
||||||
if (bVisible) {
|
|
||||||
RECT rcStart;
|
|
||||||
|
|
||||||
// Only slide the window if the user has FullDrag turned on.
|
|
||||||
if (!::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &bFullDragOn, 0))
|
|
||||||
bFullDragOn = false;
|
|
||||||
|
|
||||||
// Get our start window location.
|
|
||||||
GetAutoHideRect(m_state, bHidden, &rcStart);
|
|
||||||
|
|
||||||
if (bFullDragOn && (rcStart.left != rcEnd.left || rcStart.top != rcEnd.top || rcStart.right != rcEnd.right || rcStart.bottom != rcEnd.bottom)) {
|
|
||||||
// Get our starting and ending time.
|
|
||||||
DWORD dwTimeStart = ::GetTickCount();
|
|
||||||
DWORD dwTimeElapsed;
|
|
||||||
RECT rcDelta;
|
|
||||||
|
|
||||||
// Calculate difference between ending and starting rectangle.
|
|
||||||
rcDelta.left = rcEnd.left - rcStart.left;
|
|
||||||
rcDelta.top = rcEnd.top - rcStart.top;
|
|
||||||
rcDelta.right = rcEnd.right - rcStart.right;
|
|
||||||
rcDelta.bottom = rcEnd.bottom - rcStart.bottom;
|
|
||||||
|
|
||||||
while ((dwTimeElapsed = ::GetTickCount() - dwTimeStart) < wxABT_AUTOHIDETIME) {
|
|
||||||
// Do the linear interpolation.
|
|
||||||
RECT rect;
|
|
||||||
rect.left = rcStart.left + ::MulDiv(rcDelta.left, dwTimeElapsed, wxABT_AUTOHIDETIME);
|
|
||||||
rect.top = rcStart.top + ::MulDiv(rcDelta.top, dwTimeElapsed, wxABT_AUTOHIDETIME);
|
|
||||||
rect.right = rcStart.right + ::MulDiv(rcDelta.right, dwTimeElapsed, wxABT_AUTOHIDETIME);
|
|
||||||
rect.bottom = rcStart.bottom + ::MulDiv(rcDelta.bottom, dwTimeElapsed, wxABT_AUTOHIDETIME);
|
|
||||||
|
|
||||||
// Show the window at its changed position
|
|
||||||
wxVERIFY(::SetWindowPos(m_hWnd, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE));
|
|
||||||
wxVERIFY(::UpdateWindow(m_hWnd));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bShow)
|
|
||||||
m_flags &= ~wxFLAG_AUTOHIDDEN;
|
|
||||||
else
|
|
||||||
m_flags |= wxFLAG_AUTOHIDDEN;
|
|
||||||
|
|
||||||
if (bVisible) {
|
|
||||||
wxVERIFY(::SetWindowPos(m_hWnd, NULL, rcEnd.left, rcEnd.top, rcEnd.right - rcEnd.left, rcEnd.bottom - rcEnd.top, SWP_NOZORDER | SWP_NOACTIVATE));
|
|
||||||
wxVERIFY(::UpdateWindow(m_hWnd));
|
|
||||||
// Reset auto-hide timer.
|
|
||||||
m_timerID = ::SetTimer(m_hWnd, wxABT_AUTOHIDETIMERID, wxABT_AUTOHIDETIMERINTERVAL, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void wxAppBar::OnChangeState(wxState stateNew)
|
|
||||||
{
|
|
||||||
if (stateNew == wxSTATE_FLOAT) {
|
|
||||||
if (m_flags & wxFLAG_HIDETASKBARTABWHENFLOATING) {
|
|
||||||
// Hide our application bar's entry on the Windows's taskbar.
|
|
||||||
wxModifyStyleEx(m_hWnd, 0, WS_EX_TOOLWINDOW);
|
|
||||||
if (m_taskbarList)
|
|
||||||
wxVERIFY(SUCCEEDED(m_taskbarList->DeleteTab(m_hWnd)));
|
|
||||||
} else if (m_flags & wxFLAG_HIDETASKBARTABWHENDOCKED) {
|
|
||||||
// Show our application bar's entry on the Windows's taskbar.
|
|
||||||
wxModifyStyleEx(m_hWnd, WS_EX_TOOLWINDOW, 0);
|
|
||||||
if (m_taskbarList)
|
|
||||||
wxVERIFY(SUCCEEDED(m_taskbarList->AddTab(m_hWnd)));
|
|
||||||
}
|
|
||||||
} else if (IsDocked(stateNew)) {
|
|
||||||
if (m_flags & wxFLAG_HIDETASKBARTABWHENDOCKED) {
|
|
||||||
// Hide our application bar's entry on the Windows's taskbar.
|
|
||||||
wxModifyStyleEx(m_hWnd, 0, WS_EX_TOOLWINDOW);
|
|
||||||
if (m_taskbarList)
|
|
||||||
wxVERIFY(SUCCEEDED(m_taskbarList->DeleteTab(m_hWnd)));
|
|
||||||
} else if (m_flags & wxFLAG_HIDETASKBARTABWHENFLOATING) {
|
|
||||||
// Show our application bar's entry on the Windows's taskbar.
|
|
||||||
wxModifyStyleEx(m_hWnd, WS_EX_TOOLWINDOW, 0);
|
|
||||||
if (m_taskbarList)
|
|
||||||
wxVERIFY(SUCCEEDED(m_taskbarList->AddTab(m_hWnd)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Unknown state.
|
|
||||||
wxFAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void wxAppBar::OnChangeTaskBarState(UINT_PTR state)
|
|
||||||
{
|
|
||||||
if (state != m_stateTaskBar) {
|
|
||||||
// No change, no fun.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m_flags & wxFLAG_ALWAYSONTOPTASKBAR) &&
|
|
||||||
(m_stateTaskBar & ABS_ALWAYSONTOP) != (state & ABS_ALWAYSONTOP)) {
|
|
||||||
// Always-on-top state of the taskbar changed and we're supposed to mimic it.
|
|
||||||
SetAlwaysOnTop((state & ABS_ALWAYSONTOP) ? true : false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m_flags & wxFLAG_AUTOHIDETASKBAR) &&
|
|
||||||
(m_stateTaskBar & ABS_AUTOHIDE) != (state & ABS_AUTOHIDE)) {
|
|
||||||
// Auto-hide state of the taskbar changed and we're supposed to mimic it.
|
|
||||||
SetAutoHide((state & ABS_AUTOHIDE) ? true : false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remember the state.
|
|
||||||
m_stateTaskBar = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void wxAppBar::OnWindowsArrange(bool WXUNUSED(bBeginning))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void wxAppBar::OnAutoHideDenied()
|
|
||||||
{
|
|
||||||
wxMessageBox(wxT("There is already an auto hidden bar on this edge.\nOnly one auto hidden bar is allowed on each edge.\nAuto-hide feature is now off."), wxT("Warning"), wxOK | wxICON_WARNING, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WXLRESULT wxAppBar::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
|
|
||||||
{
|
|
||||||
switch (message) {
|
|
||||||
case WM_SHOWWINDOW:
|
|
||||||
if (wParam) {
|
|
||||||
// Do the false change of state notification, to allow initialization.
|
|
||||||
OnChangeState(m_state);
|
|
||||||
|
|
||||||
if (IsDocked(m_state)) {
|
|
||||||
if (IsAutoHide()) {
|
|
||||||
// Register auto-hide application bar.
|
|
||||||
RegisterAutoHide(m_state);
|
|
||||||
} else {
|
|
||||||
// Auto-hide failed or wasn't desired at all.
|
|
||||||
DockAppBar(m_state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're all set. Show the window now.
|
|
||||||
return wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
} else {
|
|
||||||
// Hide the window first, to avoid flicker.
|
|
||||||
WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
|
|
||||||
// Clean previous docking/auto-hide settings if required.
|
|
||||||
if (IsDocked(m_state)) {
|
|
||||||
if (IsAutoHide())
|
|
||||||
UnregisterAutoHide(m_state);
|
|
||||||
else
|
|
||||||
UndockAppBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
return lResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_WINDOWPOSCHANGING: {
|
|
||||||
if (m_state != m_stateDesired && IsDocked(m_stateDesired)) {
|
|
||||||
wxASSERT(lParam);
|
|
||||||
LPWINDOWPOS lpwndpos = (LPWINDOWPOS)lParam;
|
|
||||||
|
|
||||||
// When about to get docked, fix position and size to avoid Aero Snap interfering with window size.
|
|
||||||
RECT rect;
|
|
||||||
GetDockedRect(m_stateDesired, &rect);
|
|
||||||
lpwndpos->x = rect.left;
|
|
||||||
lpwndpos->y = rect.top;
|
|
||||||
lpwndpos->cx = rect.right - rect.left;
|
|
||||||
lpwndpos->cy = rect.bottom - rect.top;
|
|
||||||
lpwndpos->flags &= ~(SWP_NOMOVE | SWP_NOSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_WINDOWPOSCHANGED: {
|
|
||||||
WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
|
|
||||||
if (IsDocked(m_state)) {
|
|
||||||
// When our window changes position, tell the Shell so that any
|
|
||||||
// auto-hidden application bar on our edge stays on top of our window making it
|
|
||||||
// always accessible to the user.
|
|
||||||
APPBARDATA abd = { sizeof(abd), m_hWnd };
|
|
||||||
wxVERIFY(::SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd));
|
|
||||||
}
|
|
||||||
|
|
||||||
return lResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_ENTERSIZEMOVE:
|
|
||||||
m_stateDesired = m_state;
|
|
||||||
return wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
|
|
||||||
case WM_EXITSIZEMOVE: {
|
|
||||||
WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
|
|
||||||
// Clean previous docking/auto-hide settings if required.
|
|
||||||
if (IsDocked(m_state) &&
|
|
||||||
(m_stateDesired == wxSTATE_FLOAT || m_stateDesired != m_state && IsDocked(m_stateDesired)))
|
|
||||||
{
|
|
||||||
if (IsAutoHide())
|
|
||||||
UnregisterAutoHide(m_state);
|
|
||||||
else if (m_stateDesired == wxSTATE_FLOAT)
|
|
||||||
UndockAppBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup new docking/auto-hide settings.
|
|
||||||
if (IsDocked(m_stateDesired)) {
|
|
||||||
if (IsAutoHide()) {
|
|
||||||
// Application bar should be auto-hide. Try to setup it as so.
|
|
||||||
// Register auto-hide application bar.
|
|
||||||
RegisterAutoHide(m_stateDesired);
|
|
||||||
} else {
|
|
||||||
// Auto-hide failed or wasn't desired at all.
|
|
||||||
DockAppBar(m_stateDesired);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify about the change of state.
|
|
||||||
OnChangeState(m_stateDesired);
|
|
||||||
m_state = m_stateDesired;
|
|
||||||
m_stateDesired = wxSTATE_UNKNOWN;
|
|
||||||
|
|
||||||
return lResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_MOVING: {
|
|
||||||
WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
|
|
||||||
wxASSERT(lParam);
|
|
||||||
LPRECT lpRect = (LPRECT)lParam;
|
|
||||||
|
|
||||||
// Phase 1. - Determine the desired state (which screen edge or floating) according to the mouse position.
|
|
||||||
|
|
||||||
wxState uStateDesiredPrev = m_stateDesired;
|
|
||||||
DWORD dwPoint = ::GetMessagePos();
|
|
||||||
wxPoint ptMouse(GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint));
|
|
||||||
|
|
||||||
m_stateDesired = wxSTATE_UNKNOWN;
|
|
||||||
|
|
||||||
if ((m_flags & wxFLAG_ALLOWFLOAT) && (::GetKeyState(VK_CONTROL) < 0 || !(m_flags & wxFLAG_ALLOWDOCKANY))) {
|
|
||||||
// The application bar's style allows floating and user is holding down the Ctrl key, or docking is disabled anyway, so we'll force float.
|
|
||||||
m_stateDesired = wxSTATE_FLOAT;
|
|
||||||
} else {
|
|
||||||
RECT rcWorkArea = {};
|
|
||||||
INT iDist, iDistMin = INT_MAX;
|
|
||||||
|
|
||||||
// Get the rectangle that bounds the size of the screen
|
|
||||||
// minus any docked (but not-autohidden) AppBars.
|
|
||||||
wxVERIFY(::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0));
|
|
||||||
|
|
||||||
// Test all four edges, to find the closest one.
|
|
||||||
if ((m_flags & wxFLAG_ALLOWDOCKTOP) && (iDist = ptMouse.y - rcWorkArea.top) < iDistMin) {
|
|
||||||
m_stateDesired = wxSTATE_TOP;
|
|
||||||
iDistMin = iDist;
|
|
||||||
}
|
|
||||||
if ((m_flags & wxFLAG_ALLOWDOCKBOTTOM) && (iDist = rcWorkArea.bottom - ptMouse.y) < iDistMin) {
|
|
||||||
m_stateDesired = wxSTATE_BOTTOM;
|
|
||||||
iDistMin = iDist;
|
|
||||||
}
|
|
||||||
if ((m_flags & wxFLAG_ALLOWDOCKLEFT) && (iDist = ptMouse.x - rcWorkArea.left) < iDistMin) {
|
|
||||||
m_stateDesired = wxSTATE_LEFT;
|
|
||||||
iDistMin = iDist;
|
|
||||||
}
|
|
||||||
if ((m_flags & wxFLAG_ALLOWDOCKRIGHT) && (iDist = rcWorkArea.right - ptMouse.x) < iDistMin) {
|
|
||||||
m_stateDesired = wxSTATE_RIGHT;
|
|
||||||
iDistMin = iDist;
|
|
||||||
}
|
|
||||||
if ((m_flags & wxFLAG_ALLOWFLOAT) && (iDist = wxMax(::GetSystemMetrics(SM_CXVSCROLL), ::GetSystemMetrics(SM_CYHSCROLL))) < iDistMin) {
|
|
||||||
m_stateDesired = wxSTATE_FLOAT;
|
|
||||||
iDistMin = iDist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We must had come up with some useful state.
|
|
||||||
wxASSERT(m_stateDesired != wxSTATE_UNKNOWN);
|
|
||||||
|
|
||||||
// Phase 2. - Calculate the desired rectangle, according to the desired state.
|
|
||||||
|
|
||||||
if (m_stateDesired == wxSTATE_FLOAT) {
|
|
||||||
if (IsDocked(uStateDesiredPrev)) {
|
|
||||||
// We just switched from docked to floating state. Align the window according to the mouse pointer.
|
|
||||||
lpRect->left = ptMouse.x - m_sizeFloat.cx / 2;
|
|
||||||
lpRect->top = ptMouse.y;
|
|
||||||
|
|
||||||
// We also resize back to floating window size.
|
|
||||||
lpRect->right = lpRect->left + m_sizeFloat.cx;
|
|
||||||
lpRect->bottom = lpRect->top + m_sizeFloat.cy;
|
|
||||||
}
|
|
||||||
} else if (IsDocked(m_stateDesired)) {
|
|
||||||
if (IsAutoHide()) {
|
|
||||||
// Calculate auto-hide window rect.
|
|
||||||
GetAutoHideRect(m_stateDesired, false, lpRect);
|
|
||||||
} else {
|
|
||||||
// Calculate docked window rect.
|
|
||||||
GetDockedRect(m_stateDesired, lpRect);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Window is not floating. It's not docked either. Then what?
|
|
||||||
wxFAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_stateDesired != uStateDesiredPrev) {
|
|
||||||
// Notify about the proposed change of state, but don't change the state yet.
|
|
||||||
OnChangeState(m_stateDesired);
|
|
||||||
}
|
|
||||||
|
|
||||||
return lResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_SIZING: {
|
|
||||||
wxASSERT(lParam);
|
|
||||||
LPRECT lpRect = (LPRECT)lParam;
|
|
||||||
|
|
||||||
if (m_stateDesired == wxSTATE_FLOAT) {
|
|
||||||
// Remember the floating window size.
|
|
||||||
m_sizeFloat.cx = lpRect->right - lpRect->left;
|
|
||||||
m_sizeFloat.cy = lpRect->bottom - lpRect->top;
|
|
||||||
} else if (IsDocked(m_stateDesired)) {
|
|
||||||
// Remember the docked window size.
|
|
||||||
if (IsDockedVert(m_stateDesired))
|
|
||||||
m_sizeDocked.cx = lpRect->right - lpRect->left;
|
|
||||||
else
|
|
||||||
m_sizeDocked.cy = lpRect->bottom - lpRect->top;
|
|
||||||
} else {
|
|
||||||
// Unknown state.
|
|
||||||
wxFAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_GETMINMAXINFO: {
|
|
||||||
WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
|
|
||||||
wxASSERT(lParam);
|
|
||||||
LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
|
|
||||||
|
|
||||||
// Convert client size to window size.
|
|
||||||
RECT rectClient = {};
|
|
||||||
wxVERIFY(::GetClientRect(m_hWnd, &rectClient));
|
|
||||||
if (rectClient.right - rectClient.left && rectClient.bottom - rectClient.top) {
|
|
||||||
RECT rectWindow = {};
|
|
||||||
wxVERIFY(::GetWindowRect(m_hWnd, &rectWindow));
|
|
||||||
lpMMI->ptMinTrackSize.x = m_sizeMin.cx + (rectWindow.right - rectWindow.left) - (rectClient.right - rectClient.left);
|
|
||||||
lpMMI->ptMinTrackSize.y = m_sizeMin.cy + (rectWindow.bottom - rectWindow.top ) - (rectClient.bottom - rectClient.top );
|
|
||||||
}
|
|
||||||
|
|
||||||
return lResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_NCMOUSEMOVE:
|
|
||||||
// If we are a docked, auto-hidden application bar, shown us
|
|
||||||
// when the user moves over our non-client area
|
|
||||||
ShowAutoHideAppBar(true);
|
|
||||||
|
|
||||||
return wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
|
|
||||||
case WM_NCHITTEST: {
|
|
||||||
// Find out what the base class thinks is the hit test code.
|
|
||||||
WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
|
|
||||||
if (HTSIZEFIRST <= lResult && lResult <= HTSIZELAST) {
|
|
||||||
if (GetAllowSizing()) {
|
|
||||||
if (IsDocked(m_state)) {
|
|
||||||
// When the application bar is docked, the user can resize only one edge.
|
|
||||||
// This next section determines which edge the user can resize.
|
|
||||||
// To allow resizing, the application bar window must have the WS_THICKFRAME style.
|
|
||||||
|
|
||||||
RECT rcClient = {};
|
|
||||||
wxPoint point(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
|
||||||
|
|
||||||
// Resizing IS allowed for the edge that the application bar is docked on.
|
|
||||||
// Get the location of the appbar's client area in screen coordinates.
|
|
||||||
wxVERIFY(::GetClientRect(m_hWnd, &rcClient));
|
|
||||||
wxVERIFY(::ClientToScreen(m_hWnd, (LPPOINT)&rcClient));
|
|
||||||
wxVERIFY(::ClientToScreen(m_hWnd, ((LPPOINT)&rcClient) + 1));
|
|
||||||
|
|
||||||
// Assume that we can't resize
|
|
||||||
lResult = HTBORDER;
|
|
||||||
|
|
||||||
switch (m_state) {
|
|
||||||
case wxSTATE_LEFT: if (point.x > rcClient.right) lResult = HTRIGHT; break;
|
|
||||||
case wxSTATE_TOP: if (point.y > rcClient.bottom) lResult = HTBOTTOM; break;
|
|
||||||
case wxSTATE_RIGHT: if (point.x < rcClient.left) lResult = HTLEFT; break;
|
|
||||||
case wxSTATE_BOTTOM: if (point.y < rcClient.top) lResult = HTTOP; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// The sizing is locked. Pretend that the mouse is not on a resize border.
|
|
||||||
lResult = HTBORDER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_ACTIVATE: {
|
|
||||||
WXLRESULT lResult = wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
|
|
||||||
if (IsDocked(m_state)) {
|
|
||||||
// When our window changes activation state, tell the Shell so that any
|
|
||||||
// auto-hidden application bar on our edge stays on top of our window making it
|
|
||||||
// always accessible to the user.
|
|
||||||
APPBARDATA abd = { sizeof(abd), m_hWnd };
|
|
||||||
wxVERIFY(::SHAppBarMessage(ABM_ACTIVATE, &abd));
|
|
||||||
|
|
||||||
if (LOWORD(wParam) == WA_INACTIVE && IsAutoHide()) {
|
|
||||||
// Hide the application bar if we are docked and auto-hidden.
|
|
||||||
ShowAutoHideAppBar(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_TIMER:
|
|
||||||
if (wParam == wxABT_AUTOHIDETIMERID) {
|
|
||||||
if (!GetAutoHidden() &&
|
|
||||||
IsDocked(m_state) &&
|
|
||||||
GetActiveWindow() != m_hWnd)
|
|
||||||
{
|
|
||||||
// Get the position of the mouse and the application bar's position
|
|
||||||
// Everything must be in screen coordinates.
|
|
||||||
DWORD dwPoint = ::GetMessagePos();
|
|
||||||
wxPoint pointMouse(GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint));
|
|
||||||
RECT rect = {};
|
|
||||||
wxVERIFY(::GetWindowRect(m_hWnd, &rect));
|
|
||||||
wxRect rectBounds(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
|
|
||||||
|
|
||||||
// Add a little margin around the application bar
|
|
||||||
rectBounds.Inflate(2 * ::GetSystemMetrics(SM_CXDOUBLECLK), 2 * ::GetSystemMetrics(SM_CYDOUBLECLK));
|
|
||||||
if (!rectBounds.Contains(pointMouse)) {
|
|
||||||
// If the mouse is NOT over or near the application bar, hide it.
|
|
||||||
ShowAutoHideAppBar(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} else
|
|
||||||
return wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (message == WM_AB_NOTIFY) {
|
|
||||||
switch (wParam) {
|
|
||||||
case ABN_FULLSCREENAPP:
|
|
||||||
if (lParam)
|
|
||||||
m_flags |= wxFLAG_FULLSCREENAPPOPEN;
|
|
||||||
else
|
|
||||||
m_flags &= ~wxFLAG_FULLSCREENAPPOPEN;
|
|
||||||
OnChangeTaskBarState(GetTaskBarState());
|
|
||||||
|
|
||||||
if (::IsWindowVisible(m_hWnd)) {
|
|
||||||
// Set the Z-order.
|
|
||||||
wxVERIFY(::SetWindowPos(m_hWnd, GetZWnd(m_state, m_flags), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOSENDCHANGING));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ABN_POSCHANGED:
|
|
||||||
if (IsDocked(m_state) && !IsAutoHide())
|
|
||||||
DockAppBar(m_state);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ABN_STATECHANGE:
|
|
||||||
// Taskbar's state changed.
|
|
||||||
OnChangeTaskBarState(GetTaskBarState());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ABN_WINDOWARRANGE:
|
|
||||||
OnWindowsArrange(lParam ? true : false);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Unknown message.
|
|
||||||
wxFAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} else
|
|
||||||
return wxFrame::MSWWindowProc(message, wParam, lParam);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -27,5 +27,3 @@
|
|||||||
#include "../include/wxex/appex.h"
|
#include "../include/wxex/appex.h"
|
||||||
|
|
||||||
#include "../include/wxex/common.h"
|
#include "../include/wxex/common.h"
|
||||||
|
|
||||||
#include <Windowsx.h>
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user