Update of /cvsroot/adobe-source/adobe-source/adobe/future/widgets/sources/win32 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv1031/adobe/future/widgets/sources/win32 Added Files: display.cpp event_dispatcher.cpp metrics.cpp os_utilities.cpp ui_core_implementation.cpp ui_overlay.cpp Log Message: asl 1.0.13 --- NEW FILE: ui_overlay.cpp --- /* Copyright 2005-2006 Adobe Systems Incorporated Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt or a copy at http://opensource.adobe.com/licenses.html) */ /****************************************************************************************************/ #ifndef NDEBUG #define WINDOWS_LEAN_AND_MEAN 1 #include <windows.h> #include "ui_overlay.hpp" #include <adobe/forest.hpp> #include <boost/bind.hpp> /****************************************************************************************************/ namespace { /****************************************************************************************************/ struct overlay_data_t { adobe::point_2d_t origin_m; adobe::extents_t extents_m; }; typedef adobe::forest<overlay_data_t> overlay_forest_t; typedef POINT coord_t; typedef std::vector<coord_t> coord_set_t; /****************************************************************************************************/ overlay_forest_t::iterator unwrap(adobe::ui_overlay_t::position_t& position) { return boost::any_cast<overlay_forest_t::iterator>(position); } /****************************************************************************************************/ adobe::ui_overlay_t::position_t wrap(overlay_forest_t::iterator view) { return adobe::ui_overlay_t::position_t(view); } /****************************************************************************************************/ RECT get_window_client_offset_rect(HWND window) { assert(window); RECT window_rect; RECT client_rect; ::GetWindowRect(window, &window_rect); ::GetClientRect(window, &client_rect); ::ClientToScreen(window, (LPPOINT) &client_rect.left); ::ClientToScreen(window, (LPPOINT) &client_rect.right); RECT result; result.left = std::abs(window_rect.left - client_rect.left); result.top = std::abs(window_rect.top - client_rect.top); result.right = std::abs(window_rect.right - client_rect.right); result.bottom = std::abs(window_rect.bottom - client_rect.bottom); return result; } /****************************************************************************************************/ void draw_line_path(HDC context, coord_set_t& points) { if (points.size() < 2) return; ::Polyline(context, &points[0], static_cast<int>(points.size())); points.erase(points.begin(), points.end()); } /****************************************************************************************************/ } // namespace /****************************************************************************************************/ namespace adobe { /****************************************************************************************************/ struct ui_overlay_t::implementation_t { implementation_t(); ~implementation_t(); struct draw_element_t { enum element_type { element_type_top_left, element_type_top_right, element_type_bottom_left, element_type_bottom_right, element_type_horizontal_poi, element_type_vertical_poi, element_type_count // always be last }; draw_element_t(element_type type, const RECT& rect, const COLORREF& color) : type_m(type), rect_m(rect), color_m(color) { } draw_element_t(const draw_element_t& rhs) : type_m(rhs.type_m), rect_m(rhs.rect_m), color_m(rhs.color_m) { } element_type type_m; RECT rect_m; COLORREF color_m; }; typedef std::vector<draw_element_t> draw_element_set_t; position_t root(HWND& element); position_t insert(position_t parent); void place(position_t node, const point_2d_t& origin, const extents_t& extents); void framing(bool do_framing); overlay_data_t flatten_overlay_data(overlay_forest_t::iterator iter); void tick_extents(const overlay_data_t& overlay_data, HWND main_window, draw_element_set_t& set); void draw_tick(HDC context, const draw_element_set_t::value_type& element); HWND overlay_m; HWND source_m; bool framing_m; overlay_forest_t tree_m; }; /****************************************************************************************************/ ui_overlay_t::ui_overlay_t() : object_m(new implementation_t()) { } ui_overlay_t::~ui_overlay_t() { delete object_m; } template <typename DisplayElement> ui_overlay_t::position_t ui_overlay_t::root(DisplayElement& element) { return ui_overlay_t::position_t(); } template <> ui_overlay_t::position_t ui_overlay_t::root<HWND>(HWND& element) { return object_m->root(element); } ui_overlay_t::position_t ui_overlay_t::insert(position_t parent) { return object_m->insert(parent); } void ui_overlay_t::place(position_t node, const point_2d_t& origin, const extents_t& extents) { return object_m->place(node, origin, extents); } void ui_overlay_t::framing(bool do_framing) { object_m->framing(do_framing); } ui_overlay_t::implementation_t& ui_overlay_t::implementation() { return *object_m; } const ui_overlay_t::implementation_t& ui_overlay_t::implementation() const { return *object_m; } /****************************************************************************************************/ #if 0 #pragma mark - #endif /****************************************************************************************************/ ui_overlay_t::implementation_t::implementation_t() : overlay_m(0), source_m(0), framing_m(false) { } /****************************************************************************************************/ ui_overlay_t::implementation_t::~implementation_t() { if (overlay_m) ::DestroyWindow(overlay_m); overlay_m = 0; } /****************************************************************************************************/ ui_overlay_t::position_t ui_overlay_t::implementation_t::root(HWND& element) { assert(element); source_m = element; return wrap(tree_m.insert(tree_m.begin(), overlay_data_t())); } /****************************************************************************************************/ ui_overlay_t::position_t ui_overlay_t::implementation_t::insert(position_t parent) { overlay_forest_t::iterator position(unwrap(parent)); position.edge() = adobe::forest_trailing_edge; return wrap(tree_m.insert(position, overlay_data_t())); } /****************************************************************************************************/ void ui_overlay_t::implementation_t::place(position_t node, const point_2d_t& origin, const extents_t& extents) { overlay_forest_t::iterator position(unwrap(node)); position->origin_m = origin; position->extents_m = extents; } /****************************************************************************************************/ void ui_overlay_t::implementation_t::framing(bool do_framing) { assert(source_m); framing_m = do_framing; if (!do_framing) { //set_control_invalid(control_m); } else { HWND main_window(source_m);//::GetAncestor(source_m, GA_ROOT)); HDC context(::GetWindowDC(main_window)); draw_element_set_t tick_set; overlay_forest_t::preorder_iterator first(tree_m.begin()); overlay_forest_t::preorder_iterator last(tree_m.end()); ::BringWindowToTop(main_window); for (; first != last; ++first) tick_extents(flatten_overlay_data(first.base()), main_window, tick_set); if (!tick_set.empty()) adobe::for_each(tick_set, boost::bind(&implementation_t::draw_tick, boost::ref(*this), context, _1)); ::ReleaseDC(main_window, context); } } /****************************************************************************************************/ overlay_data_t ui_overlay_t::implementation_t::flatten_overlay_data(overlay_forest_t::iterator iter) { overlay_data_t result; point_2d_t& origin(result.origin_m); overlay_forest_t::iterator last(tree_m.end()); result.extents_m = iter->extents_m; for (; iter != last; iter = find_parent(iter)) { origin.x_m += iter->origin_m.x_m; origin.y_m += iter->origin_m.y_m; } return result; } /****************************************************************************************************/ void ui_overlay_t::implementation_t::tick_extents(const overlay_data_t& overlay_data, HWND main_window, draw_element_set_t& set) { typedef draw_element_t de_t; static const long tick(3); static COLORREF blue(RGB(0, 0, 255)); static COLORREF red(RGB(255, 0, 0)); const point_2d_t& position(overlay_data.origin_m); const extents_t& extents(overlay_data.extents_m); RECT extra(get_window_client_offset_rect(main_window)); long top(position.y_m + extra.top - 1); long left(position.x_m + extra.left); long bottom(top + extents.height() - 1); long right(left + extents.width()); long tick_width(std::min(tick, extents.width())); long tick_height(std::min(tick, extents.height())); long tick_start_right(std::max(right - tick, left)); long tick_start_bottom(std::max(bottom - tick, top)); RECT top_left_rect = { left, top, left + tick_width, top + tick_height }; RECT top_right_rect = { tick_start_right, top, tick_start_right + tick_width, top + tick_height }; RECT bottom_left_rect = { left, tick_start_bottom + 1, left + tick_width + 1, tick_start_bottom + tick_height }; RECT bottom_right_rect = { tick_start_right - 1, tick_start_bottom + 1, tick_start_right + tick_width, tick_start_bottom + tick_height }; set.push_back(de_t(de_t::element_type_top_left, top_left_rect, blue)); set.push_back(de_t(de_t::element_type_top_right, top_right_rect, blue)); set.push_back(de_t(de_t::element_type_bottom_left, bottom_left_rect, blue)); set.push_back(de_t(de_t::element_type_bottom_right, bottom_right_rect, blue)); { guide_set_t::const_iterator iter(extents.horizontal().poi_m.begin()); guide_set_t::const_iterator last(extents.horizontal().poi_m.end()); for (; iter != last; ++iter) { guide_set_t::value_type cur(*iter); long poi(left + cur); RECT top_tick = { poi, top, poi + 1, top + tick_height }; RECT bottom_tick = { poi, bottom - tick_height, poi + 1, bottom }; set.push_back(de_t(de_t::element_type_horizontal_poi, top_tick, red)); set.push_back(de_t(de_t::element_type_horizontal_poi, bottom_tick, red)); } } { guide_set_t::const_iterator iter(extents.vertical().poi_m.begin()); guide_set_t::const_iterator last(extents.vertical().poi_m.end()); for (; iter != last; ++iter) { guide_set_t::value_type cur(*iter); long poi(top + cur); RECT left_tick = { left, poi, left + tick_width, poi + 1 }; RECT right_tick = { right - tick_width, poi, right, poi + 1 }; set.push_back(de_t(de_t::element_type_vertical_poi, left_tick, red)); set.push_back(de_t(de_t::element_type_vertical_poi, right_tick, red)); } } } /****************************************************************************************************/ void ui_overlay_t::implementation_t::draw_tick(HDC context, const draw_element_set_t::value_type& element) { typedef draw_element_set_t::value_type desvt_t; coord_set_t points; long top(element.rect_m.top + 1); long left(element.rect_m.left); long bottom(element.rect_m.bottom + 1); long right(element.rect_m.right - 1); coord_t top_left = { left, top }; coord_t top_right = { right, top }; coord_t bottom_left = { left, bottom }; coord_t bottom_right = { right, bottom }; HPEN pen(::CreatePen(PS_SOLID, 1, element.color_m)); HPEN old_pen((HPEN) SelectObject(context, pen)); if (element.type_m == desvt_t::element_type_top_left) { points.push_back(top_right); points.push_back(top_left); points.push_back(bottom_left); } else if (element.type_m == desvt_t::element_type_top_right) { points.push_back(top_left); points.push_back(top_right); points.push_back(bottom_right); } else if (element.type_m == desvt_t::element_type_bottom_left) { points.push_back(top_left); points.push_back(bottom_left); points.push_back(bottom_right); } else if (element.type_m == desvt_t::element_type_bottom_right) { points.push_back(top_right); points.push_back(bottom_right); points.push_back(bottom_left); } else if (element.type_m == desvt_t::element_type_horizontal_poi) { points.push_back(top_left); points.push_back(bottom_left); } else if (element.type_m == desvt_t::element_type_vertical_poi) { points.push_back(top_left); points.push_back(top_right); } draw_line_path(context, points); // clean up pen work SelectObject(context, old_pen); DeleteObject(pen); } /****************************************************************************************************/ } // namespace adobe /****************************************************************************************************/ #endif /****************************************************************************************************/ --- NEW FILE: ui_core_implementation.cpp --- /* Copyright 2005-2006 Adobe Systems Incorporated Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt or a copy at http://opensource.adobe.com/licenses.html) */ /****************************************************************************************************/ #include "ui_core_implementation.hpp" #include "ui_core_common.hpp" #include "display.hpp" #include "ui_overlay.hpp" #include "metrics.hpp" #include "wincast.hpp" #include <adobe/value.hpp> #include <adobe/array.hpp> [...4400 lines suppressed...] display_t::position_t result; // if (scroll_ref) result = display.insert<HWND>(parent, scroll_ref); // else result = display.insert<HWND>(parent, ref); if (label_ref) display.insert<HWND>(parent, label_ref); if (static_disable_ref) display.insert<HWND>(parent, static_disable_ref); if (popup_static_disable_ref) display.insert<HWND>(parent, popup_static_disable_ref); if (popup_ref) display.insert<HWND>(parent, popup_ref); return result; } /****************************************************************************************************/ } // namespace adobe /****************************************************************************************************/ --- NEW FILE: display.cpp --- /* Copyright 2005-2006 Adobe Systems Incorporated Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt or a copy at http://opensource.adobe.com/licenses.html) */ /****************************************************************************************************/ #define WINDOWS_LEAN_AND_MEAN 1 #include <windows.h> #include "display.hpp" #include <cassert> #include <stdexcept> /****************************************************************************************************/ namespace { /****************************************************************************************************/ struct view_wrap { explicit view_wrap(HWND ref) : ref_m(ref) { } HWND ref_m; }; /****************************************************************************************************/ HWND unwrap(adobe::display_t::position_t& position) { return (boost::any_cast<view_wrap>(position)).ref_m; } /****************************************************************************************************/ adobe::display_t::position_t wrap(HWND view) { return adobe::display_t::position_t(view_wrap(view)); } /****************************************************************************************************/ } // namespace /****************************************************************************************************/ #if 0 #pragma mark - #endif /****************************************************************************************************/ namespace adobe { /****************************************************************************************************/ display_t& get_main_display() { static display_t display_s; return display_s; } /****************************************************************************************************/ struct display_t::implementation_t { void erase(display_t::position_t& position); HWND root_m; }; /****************************************************************************************************/ template <typename DisplayElement> display_t::position_t insert(display_t& display, display_t::position_t& position, DisplayElement& element) { return display.insert(position, element); } /****************************************************************************************************/ template <> HWND unwrap_display_token<HWND, adobe::display_t::position_t>(adobe::display_t::position_t& position) { return (boost::any_cast<view_wrap>(position)).ref_m; } /****************************************************************************************************/ #if 0 #pragma mark - #endif /****************************************************************************************************/ display_t::display_t() : object_m(new implementation_t()) { } display_t::~display_t() { delete object_m; object_m = 0; } display_t::implementation_t& display_t::implementation() { return *object_m; } const display_t::implementation_t& display_t::implementation() const { return *object_m; } template <typename DisplayElement> void display_t::set_root(DisplayElement&) { } template <> void display_t::set_root<HWND>(HWND& root) { object_m->root_m = root; } display_t::position_t display_t::root() { return wrap(object_m->root_m); } void display_t::erase(position_t& position) { return object_m->erase(position); } template <typename DisplayElement> display_t::position_t display_t::insert(position_t& parent, DisplayElement& element) { return insert(parent, adobe::view_for_element<HWND>(element)); } /****************************************************************************************************/ template <> display_t::position_t display_t::insert<HWND>(position_t& parent, HWND& element) { if (parent.type() == typeid(view_wrap)) { HWND parent_view(unwrap(parent)); if (::SetParent(element, parent_view) == 0) throw std::runtime_error("display_t::insert<HWND>"); // ADOBE_REQUIRE_STATUS(::GetLastError()); assert(::GetParent(element) == parent_view); } return wrap(element); } /****************************************************************************************************/ #if 0 #pragma mark - #endif /****************************************************************************************************/ void display_t::implementation_t::erase(display_t::position_t&) { // REVISIT (fbrereto) : What should we do here? // 1) Call DetachSubView on the position? // 2) Call erase recursively for all children of the position? // 3) Invalidate (wipe) the position data? // 4) Invoke some (currently nonexistent) detach() callback for the client? // 4a) With what parameters, considering questions 1, 2, & 3? } /****************************************************************************************************/ } // namespace adobe /****************************************************************************************************/ --- NEW FILE: metrics.cpp --- /* Copyright 2005 Ralph Thomas Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt or a copy at http://opensource.adobe.com/licenses.html) */ /****************************************************************************************************/ // // This is the implementation of the class which looks up widget metrics on // Windows systems. It has two implementations, one uses UxTheme to look up // widget metrics, and the other uses constant values (and is used on systems // where UxTheme is unavailable or Visual Styles are disabled). // /****************************************************************************************************/ #include "metrics.hpp" #include "wincast.hpp" #include <sstream> #include <stdexcept> #include <tchar.h> #include <cstring> #include <boost/static_assert.hpp> #include <uxtheme.h> //Yuck: #include <tmschema.h> #define SCHEME_STRINGS 1 #include <tmschema.h> //End yuck /****************************************************************************************************/ namespace adobe { /****************************************************************************************************/ // /// This implementation of metrics_t uses the Win32 library to lookup font attributes. /// It returns constant values for other metrics. // class metrics_win32_t : public metrics_t { // /// Store the class name of the window which we're currently examining. // std::wstring class_name_m; protected: // /// Return the window class which we are currently returing metrics for. /// /// \return the current window class. // std::wstring get_window_class() const { return class_name_m; } public: // // from metrics_t // bool set_window(HWND window) { WCHAR class_name_buf[50]; if (!GetClassNameW(window, class_name_buf, 50)) return false; class_name_m = class_name_buf; return true; } bool get_font(int widget_type, LOGFONTW& out_font) const { // // On plain windows everything uses DEFAULT_GUI_FONT. // HGDIOBJ font = GetStockObject(DEFAULT_GUI_FONT); if (!font) return false; // // Extract a LOGFONTW from the HFONT. // int rv = GetObject(font, sizeof(out_font), reinterpret_cast<LPVOID>(&out_font)); DeleteObject(font); return (rv != 0); } bool get_font_metrics(int widget_type, TEXTMETRIC& out_metrics) const { // // Try to use the font from get_font before we fall back to DEFAULT_GUI_FONT. // LOGFONTW logical_font = { 0 }; HGDIOBJ font = 0; HDC tmp_dc = GetDC(0); if (get_font(widget_type, logical_font)) { font = (HGDIOBJ)CreateFontIndirectW(&logical_font); } if (!font) font = GetStockObject(DEFAULT_GUI_FONT); // // Get the metrics. // HGDIOBJ oldFont = SelectObject(tmp_dc, font); BOOL have_metrics = GetTextMetrics(tmp_dc, &out_metrics); // // Clean up. // DeleteObject(SelectObject(tmp_dc, oldFont)); ReleaseDC(0, tmp_dc); return hackery::cast<bool>(have_metrics); } bool get_text_extents(int widget_type, std::wstring text, RECT& out_extents) const { // // Create the font and select it into a temporary device context. // HDC tmp_dc = GetDC(0); LOGFONTW logical_font = {0}; HGDIOBJ font = 0; // // Try to use get_font, in case there is another font we're meant // to use. Then fallback on DEFAULT_GUI_FONT. // if (get_font(widget_type, logical_font)) { font = (HGDIOBJ)CreateFontIndirectW(&logical_font); } if (!font) font = GetStockObject(DEFAULT_GUI_FONT); // // Extract the extents. // HGDIOBJ original_font = SelectObject(tmp_dc, font); SIZE out_size = {0, 0}; BOOL have_extents = GetTextExtentPoint32W(tmp_dc, text.c_str(), static_cast<int>(text.size()), &out_size); // // Clean up, and convert the size to a rect. // DeleteObject(SelectObject(tmp_dc, original_font)); ReleaseDC(0, tmp_dc); out_extents.left = 0; out_extents.top = 0; out_extents.right = out_size.cx; out_extents.bottom = out_size.cy; return hackery::cast<bool>(have_extents); } bool get_integer(int widget_type, int measurement, int& out_val) const { if ((widget_type == CP_DROPDOWNBUTTON) && (measurement == TMT_BORDERSIZE) && (class_name_m == L"ComboBox")) { out_val = 1; return true; } if ((widget_type == EP_EDITTEXT) && (measurement == TMT_BORDERSIZE)) { out_val = 1; return true; } out_val = 0; return false; } bool get_size(int widget_type, THEMESIZE measurement, SIZE& out_size) const { if (class_name_m == L"Button") { if ((widget_type == BP_CHECKBOX) || (widget_type == BP_RADIOBUTTON)) { // // Strictly the width of the checkbox widget is 13 pixels. // This adds some padding so that letters don't get clipped. // out_size.cx = 23; out_size.cy = 13; return true; } if (widget_type == BP_GROUPBOX) { out_size.cx = 8; out_size.cy = 8; return true; } out_size.cx = 0; out_size.cy = 0; return true; } out_size.cx = 0; out_size.cy = 0; return false; } bool get_margins(int widget_type, MARGINS& out_margins) const { if ((class_name_m == L"Button") && (widget_type == BP_PUSHBUTTON)) { out_margins.cxLeftWidth = 3; out_margins.cxRightWidth = 3; out_margins.cyTopHeight = 3; out_margins.cyBottomHeight = 3; return true; } return false; } bool get_button_text_margins(int widget_type, RECT& out_margins) const { if ((class_name_m == L"Button") && (widget_type == BP_CHECKBOX)) { out_margins.top = 1; out_margins.left = 1; out_margins.bottom = 1; out_margins.right = 1; return true; } return false; } bool using_styles() const { return false; } void draw_parent_background(HWND window, HDC dc) { // // REVISIT (ralpht): This function doesn't actually get called when visual // styles aren't available, so there's no implementation here. That // may not always be the case, however... // throw std::runtime_error("metrics::draw_parent_background not implemented without visual styles enabled"); } }; /****************************************************************************************************/ const int kState = 1; // /// This implementation of metrics_t uses the UxTheme library to obtain widget metrics. /// It inherits from the plain Win32 implementation because it occasionally falls back /// on the font functions. // class metrics_uxtheme_t : public metrics_win32_t { typedef metrics_win32_t _super; // // Handle to the UxTheme.DLL. // HMODULE theme_dll_m; // // Handle to the theme which we are currently using. // HTHEME theme_m; // // Technically all of these calls are supposed to use a state parameter. We are // only obtaining metrics, rather than drawing, so we don't actually need to // specify any particular state (as metrics should be invariant over all states). // // According to the tmschema.h (in the Platform SDK) a state of 1 should always // work. // // const int kState; // // Because we open UxTheme.DLL dynamically we need to keep function pointers into // the library. These are those. // typedef HTHEME (__stdcall *OpenThemeData_t)(HWND hwnd, LPCWSTR pszClassList); typedef HRESULT (__stdcall *CloseThemeData_t)(HTHEME hTheme); typedef HRESULT (__stdcall *GetThemeMargins_t)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, int iPropId, RECT* prc, MARGINS* pMargins); typedef HRESULT (__stdcall *GetThemePartSize_t)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT* pRect, enum THEMESIZE eSize, SIZE* psz); typedef HRESULT (__stdcall *GetThemeInt_t)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, int* piVal); typedef HRESULT (__stdcall *GetThemeTextExtent_t)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, const RECT* pBoundingRect, RECT* pExtentRect); typedef HRESULT (__stdcall *GetThemeTextMetrics_t)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, TEXTMETRIC* ptm); typedef HRESULT (__stdcall *GetThemeFont_t)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, int iPropId, LOGFONTW* pFont); typedef HRESULT (__stdcall *GetThemeSysFont_t)(HTHEME hTheme, int iFontId, LOGFONTW* pFont); typedef HRESULT (__stdcall *DrawThemeParentBackground_t)(HWND window, HDC dc, LPRECT prc); typedef BOOL (__stdcall *IsThemeActive_t)(void); OpenThemeData_t OpenThemeDataPtr; CloseThemeData_t CloseThemeDataPtr; GetThemeMargins_t GetThemeMarginsPtr; GetThemePartSize_t GetThemePartSizePtr; GetThemeInt_t GetThemeIntPtr; GetThemeTextExtent_t GetThemeTextExtentPtr; GetThemeTextMetrics_t GetThemeTextMetricsPtr; GetThemeFont_t GetThemeFontPtr; GetThemeSysFont_t GetThemeSysFontPtr; IsThemeActive_t IsThemeActivePtr; DrawThemeParentBackground_t DrawThemeParentBackgroundPtr; // // We only ever try to load UxTheme.DLL once, this boolean tells us if we were // successful. // bool loaded_m; // /// The HWND we are currently inspecting. // HWND window_m; public: metrics_uxtheme_t() : theme_dll_m(0), theme_m(0), OpenThemeDataPtr(0), CloseThemeDataPtr(0), GetThemeMarginsPtr(0), GetThemePartSizePtr(0), GetThemeIntPtr(0), GetThemeTextExtentPtr(0), GetThemeTextMetricsPtr(0), GetThemeFontPtr(0), GetThemeSysFontPtr(0), IsThemeActivePtr(0), DrawThemeParentBackgroundPtr(0), loaded_m(false), window_m(0) { // // Try to load the UxTheme library, if we can. // theme_dll_m = LoadLibrary(__T("UxTheme.dll")); if (!theme_dll_m) return; // // Load the addresses of the UxTheme functions. // if (!(OpenThemeDataPtr = (OpenThemeData_t)GetProcAddress(theme_dll_m, "OpenThemeData"))) return; if (!(CloseThemeDataPtr = (CloseThemeData_t)GetProcAddress(theme_dll_m, "CloseThemeData"))) return; if (!(GetThemeMarginsPtr = (GetThemeMargins_t)GetProcAddress(theme_dll_m, "GetThemeMargins"))) return; if (!(GetThemePartSizePtr = (GetThemePartSize_t)GetProcAddress(theme_dll_m, "GetThemePartSize"))) return; if (!(GetThemeIntPtr = (GetThemeInt_t)GetProcAddress(theme_dll_m, "GetThemeInt"))) return; if (!(GetThemeTextExtentPtr = (GetThemeTextExtent_t)GetProcAddress(theme_dll_m, "GetThemeTextExtent"))) return; if (!(GetThemeTextMetricsPtr = (GetThemeTextMetrics_t)GetProcAddress(theme_dll_m, "GetThemeTextMetrics"))) return; if (!(GetThemeFontPtr = (GetThemeFont_t)GetProcAddress(theme_dll_m, "GetThemeFont"))) return; if (!(GetThemeSysFontPtr = (GetThemeSysFont_t)GetProcAddress(theme_dll_m, "GetThemeSysFont"))) return; if (!(IsThemeActivePtr = (IsThemeActive_t)GetProcAddress(theme_dll_m, "IsThemeActive"))) return; if (!(DrawThemeParentBackgroundPtr = (DrawThemeParentBackground_t)GetProcAddress(theme_dll_m, "DrawThemeParentBackground"))) return; // // All loaded! // loaded_m = true; } virtual ~metrics_uxtheme_t() { if (theme_dll_m) FreeLibrary(theme_dll_m); } // /// This function returns true if the theme is active. If the theme /// is not active then the plain win32 metrics object should be used. // bool theme_active() const { if (!loaded_m) return false; return hackery::cast<bool>((*IsThemeActivePtr)()); } // // from metrics_t // bool set_window(HWND win) { if (!_super::set_window(win)) return false; // // Keep this window around. // window_m = win; // // Close any already open theme data, and load up the new // data. // if (theme_m) (*CloseThemeDataPtr)(theme_m); // The next section of code tries to account for the fact that the names required // by OpenThemeData are different from the "class name" used by CreateWindowEx // I am having trouble finding definitive documentation on these names, so I am // not going to clean this up and break it out into a reusable conversion function yet. // MM - 11/15/2005 static const wchar_t* class_names[] = { L"ComboBoxEx32", L"SysTabControl32", L"SysTreeView32", L"msctls_progress32", L"msctls_trackbar32", L"msctls_updown32", L"tooltips_class32", //L"Button", //L"ComboBox", //L"Edit", //L"ListBox", //L"NativeFontCtl", //L"ScrollBar", //L"Static", //L"SysAnimate32", //L"SysDateTimePick32", //L"SysIPAddress32", //L"SysListView32", //L"SysMonthCal32", //L"SysPager", //L"msctls_hotkey32", }; static const wchar_t* theme_names[] = { L"ComboBox", L"Tab", L"TreeView", L"Progress", L"Trackbar", L"Spin", L"Tooltip", //L"Button", //L"Edit", //L"Globals", //L"Header", //L"Menu", //L"Rebar", //L"Scrollbar", //L"Status", //L"Toolbar", //L"Window" }; const std::wstring& class_name = get_window_class(); const wchar_t *theme_name = class_name.c_str(); BOOST_STATIC_ASSERT(sizeof(class_names)==sizeof(theme_names)); const ptrdiff_t names_count = sizeof(class_names)/sizeof(wchar_t*); const wchar_t** i = class_names; while(i != &class_names[names_count] && std::wcscmp(*i, theme_name) != 0) ++i; if(i != &class_names[names_count]) theme_name = theme_names[i - class_names]; theme_m = (*OpenThemeDataPtr)(win, theme_name); return (theme_m != 0); } bool get_font(int widget_type, LOGFONTW& out_font) const { // // We need ensure that we have a handle to the theme before // continuing. // if (!theme_m) return false; if (widget_type != -1) { HDC tmp_dc = GetDC(0); HRESULT hr = (*GetThemeFontPtr)(theme_m, tmp_dc, widget_type, kState, TMT_FONT, &out_font); ReleaseDC(0,tmp_dc); if (hr == S_OK) return true; } // // This widget is a text label, most likely. Give it the // standard message box font. // if (S_OK == (*GetThemeSysFontPtr)(theme_m, TMT_MSGBOXFONT, &out_font)) return true; return false; } // // Previously we had implementations of get_font_metrics and get_text_extents // which used the UXTheme API. We were not getting the values back that we // expected, so we now use the Win32 API for getting those measurements (although // note that we still get the actual widget font with UxTheme). // bool get_integer(int widget_type, int measurement, int& out_val) const { // // We don't fallback from this function. // if ((!theme_m) || (widget_type == -1)) return false; return (S_OK == (*GetThemeIntPtr)(theme_m, widget_type, kState, measurement, &out_val)); } bool get_size(int widget_type, THEMESIZE measurement, SIZE& out_size) const { // // We don't fallback from this function. // if ((!theme_m) || (widget_type == -1)) return false; // // Create a temporary device context and call GetThemePartSize. // HDC tmp_dc = GetDC(0); HRESULT hr = (*GetThemePartSizePtr)(theme_m, tmp_dc, widget_type, kState, 0, measurement, &out_size); ReleaseDC(0, tmp_dc); return (hr == S_OK); } bool get_margins(int widget_type, MARGINS& out_margins) const { // // We don't fall back from this function. // if ((!theme_m) || (widget_type == -1)) return false; // // Use GetThemeMargins call to get the margins for this widget. // return (S_OK == (*GetThemeMarginsPtr)(theme_m, 0, widget_type, kState, TMT_CONTENTMARGINS, 0, &out_margins)); } bool get_button_text_margins(int widget_type, RECT& out_margins) const { // // Fallback if we're not using a theme. // if (!theme_m) return _super::get_button_text_margins(widget_type, out_margins); return hackery::cast<bool>(Button_GetTextMargin(window_m, &out_margins)); } bool using_styles() const { return theme_active(); } void draw_parent_background(HWND window, HDC dc) { if (!loaded_m) return; (*DrawThemeParentBackgroundPtr)(window, dc, 0); } }; /****************************************************************************************************/ metrics_t& metrics_t::get_instance() { static metrics_win32_t win32_instance; static metrics_uxtheme_t uxtheme_instance; if (uxtheme_instance.theme_active()) return uxtheme_instance; return win32_instance; } /****************************************************************************************************/ } /****************************************************************************************************/ --- NEW FILE: event_dispatcher.cpp --- /* Copyright 2005 Ralph Thomas Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt or a copy at http://opensource.adobe.com/licenses.html) */ /****************************************************************************************************/ #include "event_dispatcher.hpp" #include "ui_core_implementation.hpp" #include "wincast.hpp" #include <adobe/future/enum_ops.hpp> #include <sstream> /****************************************************************************************************/ adobe::modifiers_t convert_modifiers(ULONG os_modifiers) { adobe::modifiers_t result(adobe::modifiers_none_s); #define ADOBE_MAPMOD(osmod, adobemod) if (os_modifiers == (osmod)) result = result | (adobemod) // // Note that VK_MENU is the ALT key. // ADOBE_MAPMOD(VK_CAPITAL, adobe::modifiers_caps_lock_s); ADOBE_MAPMOD(VK_CONTROL, adobe::modifiers_any_control_s); ADOBE_MAPMOD(VK_SHIFT, adobe::modifiers_any_shift_s); ADOBE_MAPMOD(VK_MENU, adobe::modifiers_any_option_s); #undef ADOBE_MAPMOD return result; } /****************************************************************************************************/ int get_child_id(UINT message, WPARAM wParam, LPARAM lParam) { if (message == WM_CTLCOLORSTATIC) return hackery::cast<int>(GetWindowLong(hackery::cast<HWND>(lParam), GWL_ID)); return LOWORD(wParam); } /****************************************************************************************************/ namespace adobe { /****************************************************************************************************/ // /// This is the global single instance of the event_dispatcher, and it's /// reference count. // static event_dispatcher* event_singleton_g = 0; static unsigned int event_refcount_g = 0; /****************************************************************************************************/ event_dispatcher::event_dispatcher() : current_id_m(1000) { } /****************************************************************************************************/ LRESULT event_dispatcher::event(UINT message, WPARAM wParam, LPARAM lParam, bool& handled) { handled = false; // // Let's first ensure that we actually have an event_dispatcher to work // on. // if (!event_refcount_g) return 0; // // The child id is usually the low word of the wParam. // control_map_t& cmap(event_singleton_g->control_map_m); control_map_t::iterator control = cmap.find(get_child_id(message, wParam, lParam)); if (control == cmap.end()) return 0; // // We found something to invoke, so we claim that we handled the message // and return the value of the control's event method. // handled = true; return control->second->event(message, wParam, lParam); } /****************************************************************************************************/ void event_dispatcher::keyboard(UINT message, WPARAM wParam) { // // Verify that this is a keyboard message which could contain // modifiers. // if ((message != WM_KEYDOWN) && (message != WM_KEYUP) && (message != WM_SYSKEYDOWN) && (message != WM_SYSKEYUP)) return; // // Ensure that we have an event_dispatcher to work on. // if (!event_refcount_g) return; // // Look up the modifiers which this event translates to. If they // have changed since the last time then we can tell the controls // about it. // static modifiers_t previous_modifiers(modifiers_none_s); // // This is the modifier which corresponds to the key which was // just pressed or released. // modifiers_t the_modifier(convert_modifiers(hackery::cast<ULONG>(wParam))); modifiers_t current_modifiers(previous_modifiers); // // Now we need to either add or remove the current modifier // from the previous modifiers. // if ((message == WM_KEYDOWN) || (message == WM_SYSKEYDOWN)) current_modifiers |= the_modifier; else current_modifiers &= ~the_modifier; // // Only dispatch to all of the children if the currently // pressed modifiers has changed. // if (previous_modifiers != current_modifiers) { // // Iterate through all of the controls and tell them of // the new modifier state. // control_map_t::iterator first = event_singleton_g->control_map_m.begin(); control_map_t::iterator last = event_singleton_g->control_map_m.end(); while (first != last) { first->second->modify(current_modifiers); first++; } } previous_modifiers = current_modifiers; } /****************************************************************************************************/ event_dispatcher::reference::reference() : child_id_m(-1) { // // If the reference count is zero then we have to allocate a new // event dispatcher. // if (!event_refcount_g) event_singleton_g = new event_dispatcher(); event_refcount_g++; } /****************************************************************************************************/ event_dispatcher::reference::~reference() { // // If we subscribed a control then it will be in the map, we // must remove that mapping so that events don't get sent there // any more. // event_dispatcher::control_map_t::iterator us = event_singleton_g->control_map_m.find(child_id_m); if (us != event_singleton_g->control_map_m.end()) event_singleton_g->control_map_m.erase(us); // // Decrease the reference count and delete the event_dispatcher // if there are no remaining references. // event_refcount_g--; if (!event_refcount_g) { delete event_singleton_g; event_singleton_g = 0; } } /****************************************************************************************************/ HMENU event_dispatcher::reference::subscribe(control_t* control) { // // If we're not given a control then we have nothing to subscribe. // if (!control) return 0; // // Store the child ID we're going to use, so that child_id can return it. // child_id_m = event_singleton_g->current_id_m++; event_singleton_g->control_map_m[child_id_m] = control; return child_id(); } /****************************************************************************************************/ HMENU event_dispatcher::reference::child_id() const { return hackery::cast<HMENU>(child_id_m); } /****************************************************************************************************/ } /****************************************************************************************************/ --- NEW FILE: os_utilities.cpp --- /* Copyright 2005-2006 Adobe Systems Incorporated Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt or a copy at http://opensource.adobe.com/licenses.html) */ /****************************************************************************************************/ // This file intentionally left blank /****************************************************************************************************/ |