From: Robin Dunn Date: Sun, 16 Jul 2006 03:28:23 +0000 (+0000) Subject: Added wxTopLevelWindow::SetTranslucency and CanSetTranslucency, with X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/50f3c41d61bd9ae69f215bad923f562d509e063c?hp=0b850f25d2924ee0e5ea08f93fffaa63f62f9104 Added wxTopLevelWindow::SetTranslucency and CanSetTranslucency, with implementations (so far) for wxMSW and wxMac. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@40112 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/docs/changes.txt b/docs/changes.txt index a06114daed..462bec058a 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -159,6 +159,8 @@ All (GUI): - Fixed problem with zoom setting in print preview. - Moved wxRichTextCtrl from the advanced library to its own. - wxNB_HITTEST_* flags renamed to wxBK_HITTEST_* to serve all book controls. +- Added wxTopLevelWindow::SetTranslucency and CanSetTranslucency, with + implementations (so far) for wxMSW and wxMac. wxMSW: diff --git a/docs/latex/wx/tlw.tex b/docs/latex/wx/tlw.tex index 770b9e34cd..ee1ba586ba 100644 --- a/docs/latex/wx/tlw.tex +++ b/docs/latex/wx/tlw.tex @@ -29,6 +29,16 @@ applicable for the two classes above. \latexignore{\rtfignore{\wxheading{Members}}} +\membersection{wxTopLevelWindow::CanSetTranslucency}\label{wxtoplevelwindowcansettranslucency} + +\func{virtual bool}{CanSetTranslucency}{\void} + +Returns \true if the platform supports making the window translucent. + +\wxheading{See also} + +\helpref{wxTopLevelWindow::SetTranslucency}{wxtoplevelwindowsettranslucency} + \membersection{wxTopLevelWindow::GetIcon}\label{wxtoplevelwindowgeticon} @@ -271,6 +281,22 @@ Sets the window title. \helpref{wxTopLevelWindow::GetTitle}{wxtoplevelwindowgettitle} +\membersection{wxTopLevelWindow::SetTranslucency}\label{wxtoplevelwindowsettranslucency} + +\func{virtual bool}{SetTranslucency}{\param{int }{ alpha}} + +If the platform supports it will set the window to be translucent + +\wxheading{Parameters} + +\docparam{alpha}{Determines how opaque or transparent the window will + be. A value of 0 sets the window to be fully transparent, and a + value of 255 sets the window to be fully opaque.} + +Returns \true if the translucency was successfully changed. + + + \membersection{wxTopLevelWindow::ShouldPreventAppExit}\label{wxtoplevelwindowshouldpreventappexit} \constfunc{virtual bool}{ShouldPreventAppExit}{\void} diff --git a/include/wx/aui/framemanager.h b/include/wx/aui/framemanager.h index 7c4390a5eb..250afd6d91 100644 --- a/include/wx/aui/framemanager.h +++ b/include/wx/aui/framemanager.h @@ -340,7 +340,7 @@ public: wxString caption; // caption displayed on the window wxWindow* window; // window that is in this pane - wxWindow* frame; // floating frame window that holds the pane + wxFrame* frame; // floating frame window that holds the pane unsigned int state; // a combination of wxPaneState values int dock_direction; // dock direction (top, bottom, left, right, center) @@ -527,9 +527,9 @@ protected: wxRect m_last_hint; // last hint rectangle wxPoint m_last_mouse_move; // last mouse move position (see OnMotion) - wxWindow* m_hint_wnd; // transparent hint window (for now, only msw) - wxTimer m_hint_fadetimer; // transparent fade timer (for now, only msw) - int m_hint_fadeamt; // transparent fade amount (for now, only msw) + wxFrame* m_hint_wnd; // transparent hint window, if supported by platform + wxTimer m_hint_fadetimer; // transparent fade timer + int m_hint_fadeamt; // transparent fade amount #ifndef SWIG DECLARE_EVENT_TABLE() diff --git a/include/wx/mac/carbon/toplevel.h b/include/wx/mac/carbon/toplevel.h index 9383af61c6..cdffba933f 100644 --- a/include/wx/mac/carbon/toplevel.h +++ b/include/wx/mac/carbon/toplevel.h @@ -69,6 +69,10 @@ public: virtual bool ShowFullScreen(bool show, long style = wxFULLSCREEN_ALL) ; virtual bool IsFullScreen() const ; + virtual bool SetTranslucency(int alpha); + virtual bool CanSetTranslucency(); + + // implementation from now on // -------------------------- diff --git a/include/wx/msw/missing.h b/include/wx/msw/missing.h index dae3338a0f..a62f97b6c2 100644 --- a/include/wx/msw/missing.h +++ b/include/wx/msw/missing.h @@ -121,6 +121,15 @@ #define TPM_RECURSE 1 #endif + +#ifndef WS_EX_LAYERED +#define WS_EX_LAYERED 0x80000 +#endif + +#ifndef LWA_ALPHA +#define LWA_ALPHA 2 +#endif + // ---------------------------------------------------------------------------- // ListView common control // Needed by listctrl.cpp diff --git a/include/wx/msw/toplevel.h b/include/wx/msw/toplevel.h index 3647a33b9b..f8d064c24b 100644 --- a/include/wx/msw/toplevel.h +++ b/include/wx/msw/toplevel.h @@ -70,6 +70,11 @@ public: // button from the title bar bool EnableCloseButton(bool enable = true); + // Set window transparency if the platform supports it + virtual bool SetTranslucency(int alpha); + virtual bool CanSetTranslucency(); + + // implementation from now on // -------------------------- diff --git a/include/wx/toplevel.h b/include/wx/toplevel.h index 69c5a76ac1..50409bb5ce 100644 --- a/include/wx/toplevel.h +++ b/include/wx/toplevel.h @@ -196,7 +196,11 @@ public: void CentreOnScreen(int dir = wxBOTH) { DoCentre(dir | wxCENTRE_ON_SCREEN); } void CenterOnScreen(int dir = wxBOTH) { CentreOnScreen(dir); } + // Set window transparency if the platform supports it + virtual bool SetTranslucency(int WXUNUSED(alpha)) { return false; } + virtual bool CanSetTranslucency() { return false; } + // implementation only from now on // ------------------------------- diff --git a/src/aui/framemanager.cpp b/src/aui/framemanager.cpp index 27e3bf9416..286df116e5 100644 --- a/src/aui/framemanager.cpp +++ b/src/aui/framemanager.cpp @@ -86,54 +86,6 @@ static void DrawResizeHint(wxDC& dc, const wxRect& rect) } -// on supported windows systems (Win2000 and greater, Mac), this function -// will make a frame window transparent by a certain amount -static void MakeWindowTransparent(wxWindow* wnd, int amount) -{ -#if defined(__WXMSW__) - // this API call is not in all SDKs, only the newer ones, so - // we will runtime bind this - typedef DWORD (WINAPI *PSETLAYEREDWINDOWATTR)(HWND, DWORD, BYTE, DWORD); - static PSETLAYEREDWINDOWATTR pSetLayeredWindowAttributes = NULL; - static HMODULE h = NULL; - HWND hwnd = (HWND)wnd->GetHWND(); - - if (!h) - h = LoadLibrary(_T("user32")); - - if (!pSetLayeredWindowAttributes) - { - pSetLayeredWindowAttributes = - (PSETLAYEREDWINDOWATTR)GetProcAddress(h, -#ifdef __WXWINCE__ - wxT("SetLayeredWindowAttributes") -#else - "SetLayeredWindowAttributes" -#endif - ); - } - - if (pSetLayeredWindowAttributes == NULL) - return; - - LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE); - if (0 == (exstyle & 0x80000) /*WS_EX_LAYERED*/) - SetWindowLong(hwnd, GWL_EXSTYLE, exstyle | 0x80000 /*WS_EX_LAYERED*/); - - pSetLayeredWindowAttributes(hwnd, 0, (BYTE)amount, 2 /*LWA_ALPHA*/); - -#elif defined(__WXMAC__) - - WindowRef handle = GetControlOwner((OpaqueControlRef*)wnd->GetHandle()); - SetWindowAlpha(handle, float(amount)/ 255.0); - -#else - wxUnusedVar(wnd); - wxUnusedVar(amount); -#endif -} - - // CopyDocksAndPanes() - this utility function creates copies of // the dock and pane info. wxDockInfo's usually contain pointers @@ -542,6 +494,40 @@ void wxFrameManager::SetManagedWindow(wxWindow* frame) CenterPane().PaneBorder(false)); } #endif + + // Make a window to use for a translucent hint +#if defined(__WXMSW__) + m_hint_wnd = new wxFrame(m_frame, -1, wxEmptyString, wxDefaultPosition, wxSize(1,1), + wxFRAME_TOOL_WINDOW | + wxFRAME_FLOAT_ON_PARENT | + wxFRAME_NO_TASKBAR | + wxNO_BORDER); + + m_hint_wnd->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION)); + +#elif defined(__WXMAC__) + // Using a miniframe with float and tool styles keeps the parent + // frame activated and highlighted as such... + m_hint_wnd = new wxMiniFrame(m_frame, -1, wxEmptyString, wxDefaultPosition, wxSize(1,1), + wxFRAME_FLOAT_ON_PARENT + | wxFRAME_TOOL_WINDOW + | wxCAPTION ); + + // Can't set the bg colour of a Frame in wxMac + wxPanel* p = new wxPanel(m_hint_wnd); + + // The default wxSYS_COLOUR_ACTIVECAPTION colour is a light silver + // color that is really hard to see, especially transparent. + // Until a better system color is decided upon we'll just use + // blue. + p->SetBackgroundColour(*wxBLUE); +#endif + + if (m_hint_wnd && !m_hint_wnd->CanSetTranslucency()) + { + m_hint_wnd->Close(); + m_hint_wnd = NULL; + } } @@ -1822,7 +1808,7 @@ void wxFrameManager::Update() // window should have this style by default if (m_action == actionDragFloatingPane && (m_flags & wxAUI_MGR_TRANSPARENT_DRAG)) - MakeWindowTransparent(frame, 150); + frame->SetTranslucency(150); frame->SetPaneWindow(p); p.frame = frame; @@ -2450,29 +2436,12 @@ void wxFrameManager::OnHintFadeTimer(wxTimerEvent& WXUNUSED(event)) } m_hint_fadeamt += 5; - MakeWindowTransparent(m_hint_wnd, m_hint_fadeamt); + m_hint_wnd->SetTranslucency(m_hint_fadeamt); } void wxFrameManager::ShowHint(const wxRect& rect) { -#if defined(__WXMSW__) || defined(__WXMAC__) - // First, determine if the operating system can handle transparency. - // Transparency is available on Win2000 and above - - static int os_type = -1; - static int ver_major = -1; - - if (os_type == -1) - os_type = ::wxGetOsVersion(&ver_major); - - // If the transparent flag is set, and the OS supports it, - // go ahead and use a transparent hint - - if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT) != 0 -#ifdef __WXMSW__ - && os_type == wxWINDOWS_NT && ver_major >= 5 -#endif - ) + if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT) != 0 && m_hint_wnd) { if (m_last_hint == rect) return; @@ -2482,50 +2451,18 @@ void wxFrameManager::ShowHint(const wxRect& rect) if (m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE) initial_fade = 0; - if (m_hint_wnd == NULL) - { - wxPoint pt = rect.GetPosition(); - wxSize size = rect.GetSize(); -#if defined(__WXMSW__) - m_hint_wnd = new wxFrame(m_frame, -1, wxEmptyString, pt, size, - wxFRAME_TOOL_WINDOW | - wxFRAME_FLOAT_ON_PARENT | - wxFRAME_NO_TASKBAR | - wxNO_BORDER); - - MakeWindowTransparent(m_hint_wnd, initial_fade); - m_hint_wnd->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION)); -#elif defined(__WXMAC__) - // Using a miniframe with float and tool styles keeps the parent - // frame activated and highlighted as such... - m_hint_wnd = new wxMiniFrame(m_frame, -1, wxEmptyString, pt, size, - wxFRAME_FLOAT_ON_PARENT - | wxFRAME_TOOL_WINDOW - | wxCAPTION ); - - // Can't set the bg colour of a Frame in wxMac - wxPanel* p = new wxPanel(m_hint_wnd); - - // The default wxSYS_COLOUR_ACTIVECAPTION colour is a light silver - // color that is really hard to see, especially transparent. - // Until a better system color is decided upon we'll just use - // blue. - p->SetBackgroundColour(*wxBLUE); -#endif + if (! m_hint_wnd->IsShown()) m_hint_wnd->Show(); - // if we are dragging a floating pane, set the focus - // back to that floating pane (otherwise it becomes unfocused) - if (m_action == actionDragFloatingPane && m_action_window) - m_action_window->SetFocus(); + // if we are dragging a floating pane, set the focus + // back to that floating pane (otherwise it becomes unfocused) + if (m_action == actionDragFloatingPane && m_action_window) + m_action_window->SetFocus(); - } - else - { - MakeWindowTransparent(m_hint_wnd, initial_fade); - m_hint_wnd->SetSize(rect); - m_hint_wnd->Raise(); - } + m_hint_wnd->SetTranslucency(initial_fade); + m_hint_wnd->SetSize(rect); + m_hint_wnd->Raise(); + if (m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE) { @@ -2534,54 +2471,55 @@ void wxFrameManager::ShowHint(const wxRect& rect) m_hint_fadetimer.SetOwner(this, 101); m_hint_fadetimer.Start(5); } - - return; } -#endif - - if (m_last_hint != rect) - { - // remove the last hint rectangle - m_last_hint = rect; - m_frame->Refresh(); - m_frame->Update(); - } - - wxScreenDC screendc; - wxRegion clip(1, 1, 10000, 10000); - // clip all floating windows, so we don't draw over them - int i, pane_count; - for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i) + else // Not using a translucent hint window... { - wxPaneInfo& pane = m_panes.Item(i); + + if (m_last_hint != rect) + { + // remove the last hint rectangle + m_last_hint = rect; + m_frame->Refresh(); + m_frame->Update(); + } + + wxScreenDC screendc; + wxRegion clip(1, 1, 10000, 10000); - if (pane.IsFloating() && - pane.frame->IsShown()) + // clip all floating windows, so we don't draw over them + int i, pane_count; + for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i) { - wxRect rect = pane.frame->GetRect(); - #ifdef __WXGTK__ - // wxGTK returns the client size, not the whole frame size - rect.width += 15; - rect.height += 35; - rect.Inflate(5); - #endif + wxPaneInfo& pane = m_panes.Item(i); - clip.Subtract(rect); + if (pane.IsFloating() && + pane.frame->IsShown()) + { + wxRect rect = pane.frame->GetRect(); +#ifdef __WXGTK__ + // wxGTK returns the client size, not the whole frame size + rect.width += 15; + rect.height += 35; + rect.Inflate(5); +#endif + + clip.Subtract(rect); + } } - } - screendc.SetClippingRegion(clip); + screendc.SetClippingRegion(clip); - wxBitmap stipple = wxPaneCreateStippleBitmap(); - wxBrush brush(stipple); - screendc.SetBrush(brush); - screendc.SetPen(*wxTRANSPARENT_PEN); + wxBitmap stipple = wxPaneCreateStippleBitmap(); + wxBrush brush(stipple); + screendc.SetBrush(brush); + screendc.SetPen(*wxTRANSPARENT_PEN); - screendc.DrawRectangle(rect.x, rect.y, 5, rect.height); - screendc.DrawRectangle(rect.x+5, rect.y, rect.width-10, 5); - screendc.DrawRectangle(rect.x+rect.width-5, rect.y, 5, rect.height); - screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 5); + screendc.DrawRectangle(rect.x, rect.y, 5, rect.height); + screendc.DrawRectangle(rect.x+5, rect.y, rect.width-10, 5); + screendc.DrawRectangle(rect.x+rect.width-5, rect.y, 5, rect.height); + screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 5); + } } void wxFrameManager::HideHint() @@ -2589,7 +2527,7 @@ void wxFrameManager::HideHint() // hides a transparent window hint, if there is one if (m_hint_wnd) { - MakeWindowTransparent(m_hint_wnd, 0); + m_hint_wnd->SetTranslucency(0); m_hint_fadetimer.Stop(); m_last_hint = wxRect(); return; @@ -2696,7 +2634,7 @@ void wxFrameManager::OnFloatingPaneMoveStart(wxWindow* wnd) wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found")); if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG) - MakeWindowTransparent(pane.frame, 150); + pane.frame->SetTranslucency(150); } void wxFrameManager::OnFloatingPaneMoving(wxWindow* wnd) @@ -2782,16 +2720,12 @@ void wxFrameManager::OnFloatingPaneMoved(wxWindow* wnd) // if a key modifier is pressed while dragging the frame, // don't dock the window - if (wxGetKeyState(WXK_CONTROL) || wxGetKeyState(WXK_ALT)) + if (!wxGetKeyState(WXK_CONTROL) && !wxGetKeyState(WXK_ALT)) { - HideHint(); - return; + // do the drop calculation + DoDrop(m_docks, m_panes, pane, client_pt, action_offset); } - - - // do the drop calculation - DoDrop(m_docks, m_panes, pane, client_pt, action_offset); - + // if the pane is still floating, update it's floating // position (that we store) if (pane.IsFloating()) @@ -2799,7 +2733,7 @@ void wxFrameManager::OnFloatingPaneMoved(wxWindow* wnd) pane.floating_pos = pane.frame->GetPosition(); if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG) - MakeWindowTransparent(pane.frame, 255); + pane.frame->SetTranslucency(255); } Update(); diff --git a/src/mac/carbon/toplevel.cpp b/src/mac/carbon/toplevel.cpp index 7c57eeed86..5d77fdc673 100644 --- a/src/mac/carbon/toplevel.cpp +++ b/src/mac/carbon/toplevel.cpp @@ -1431,6 +1431,21 @@ bool wxTopLevelWindowMac::IsFullScreen() const return m_macFullScreenData != NULL ; } + +bool wxTopLevelWindowMac::SetTranslucency(int alpha) +{ + WindowRef handle = GetControlOwner((OpaqueControlRef*)GetHandle()); + OSStatus result = SetWindowAlpha(handle, float(alpha)/255.0); + return result == noErr; +} + + +bool wxTopLevelWindowMac::CanSetTranslucency() +{ + return true; +} + + void wxTopLevelWindowMac::SetExtraStyle(long exStyle) { if ( GetExtraStyle() == exStyle ) diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index 0789747323..e0a489a759 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -1043,6 +1043,55 @@ void wxTopLevelWindowMSW::RequestUserAttention(int flags) } } +// --------------------------------------------------------------------------- + +bool wxTopLevelWindowMSW::SetTranslucency(int alpha) +{ + typedef DWORD (WINAPI *PSETLAYEREDWINDOWATTR)(HWND, DWORD, BYTE, DWORD); + static PSETLAYEREDWINDOWATTR pSetLayeredWindowAttributes = NULL; + + if (alpha < 0) alpha = 0; + if (alpha > 255) alpha = 255; + + if ( pSetLayeredWindowAttributes == NULL ) + { + wxDynamicLibrary dllUser32(_T("user32.dll")); + pSetLayeredWindowAttributes = (PSETLAYEREDWINDOWATTR) + dllUser32.GetSymbol(wxT("SetLayeredWindowAttributes")); + } + if ( pSetLayeredWindowAttributes == NULL ) + return false; + + LONG exstyle = GetWindowLong(GetHwnd(), GWL_EXSTYLE); + + // if setting alpha to fully opaque then turn off the layered style + if (alpha == 255) + { + SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyle & ~WS_EX_LAYERED); + Refresh(); + return true; + } + + // Otherwise, set the layered style if needed and set the alpha value + if ((exstyle & WS_EX_LAYERED) == 0 ) + SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyle | WS_EX_LAYERED); + + return pSetLayeredWindowAttributes(GetHwnd(), 0, (BYTE)alpha, LWA_ALPHA) != 0; +} + +bool wxTopLevelWindowMSW::CanSetTranslucency() +{ + // The API is available on win2k and above + + static int os_type = -1; + static int ver_major = -1; + + if (os_type == -1) + os_type = ::wxGetOsVersion(&ver_major); + + return (os_type == wxWINDOWS_NT && ver_major >= 5); +} + // ---------------------------------------------------------------------------- // wxTopLevelWindow event handling // ---------------------------------------------------------------------------- diff --git a/wxPython/src/_toplvl.i b/wxPython/src/_toplvl.i index e9e6c60fd1..c9aa280142 100644 --- a/wxPython/src/_toplvl.i +++ b/wxPython/src/_toplvl.i @@ -162,6 +162,18 @@ public: void , CenterOnScreen(int dir = wxBOTH), "Center the window on screen", ""); %pythoncode { CentreOnScreen = CenterOnScreen } + +#ifdef __WXMSW__ + bool EnableCloseButton(bool enable = true); +#else + %extend { + bool EnableCloseButton(bool enable = true) { return false; } + } +#endif + + virtual bool SetTranslucency(int alpha); + virtual bool CanSetTranslucency(); + };