note description: "[ Objects that permit graphical drawing operations to be performed which respect the theming state of Windows XP. ]" legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class EV_XP_THEME_DRAWER_IMP inherit EV_THEME_DRAWER_IMP WEL_THEME_PART_CONSTANTS export {NONE} all end feature -- Basic operations open_theme_data (item: POINTER; a_class_name: READABLE_STRING_GENERAL): POINTER -- Open theme data for WEL_WINDOW represented by `item' -- with type of theme `class_name'. See "Parts and States" of MSDN -- for a list of valid class names. do Result := cwin_open_theme_data (item, unicode_string (a_class_name).item) end close_theme_data (item: POINTER) -- Close theme data for WEL_WINDOW represented by `item'. do cwin_close_theme_data (item) end get_window_theme (item: POINTER): POINTER -- Retrieve a theme handle for WEL_WINDOW `item'. do Result := cwin_get_window_theme (item) end draw_theme_background (theme: POINTER; a_hdc: WEL_DC; a_part_id, a_state_id: INTEGER; a_rect: WEL_RECT; a_clip_rect: detachable WEL_RECT; background_brush: WEL_BRUSH) -- Draw a background theme using `theme' into `a_hdc'. `a_part_id' represents the part type to draw and `a_state_id' represents -- the item state. Drawing is performed into `a_rect' and clipped to `a_clip_rect'. `background_brush' is not used for this themed version. require else theme_exists: theme /= default_pointer local l_clip_rect: POINTER do if a_clip_rect /= Void then l_clip_rect := a_clip_rect.item end cwin_draw_theme_background (theme, a_hdc.item, a_part_id, a_state_id, a_rect.item, l_clip_rect) end get_notebook_parent (a_widget: EV_WIDGET_IMP): detachable EV_NOTEBOOK_IMP -- Return the first notebook parent of `Current' in the widget structure -- unless a widget with a background color or a container with a background pixmap -- is found. require a_widget_not_void: a_widget /= Void local l_parent: detachable EV_CONTAINER_IMP colored_container_found: BOOLEAN do if a_widget.background_color_imp = Void then l_parent ?= a_widget if l_parent = Void or else l_parent /= Void and then l_parent.background_pixmap_imp = Void then from l_parent := a_widget.parent_imp until l_parent = Void or Result /= Void or colored_container_found loop Result ?= l_parent if Result = Void and (l_parent.background_color_imp /= Void or l_parent.background_pixmap_imp /= Void) then colored_container_found := True end l_parent := l_parent.parent_imp end end end end draw_widget_background_gdip (a_widget: EV_WIDGET_IMP; a_hdc: WEL_DC; a_rect: WEL_RECT; a_background_brush: WEL_GDIP_BRUSH; a_background: WEL_COLOR_REF): BOOLEAN -- <Precursor> local notebook_parent: detachable EV_NOTEBOOK_IMP container_widget: detachable EV_CONTAINER_IMP l_x, l_y, l_width, l_height: INTEGER l_gdip_graphics: WEL_GDIP_GRAPHICS l_background_color: WEL_GDIP_COLOR do notebook_parent ?= get_notebook_parent (a_widget) if notebook_parent = Void then container_widget ?= a_widget if container_widget /= Void and then container_widget.background_pixmap_imp /= Void then l_x := a_rect.x l_y := a_rect.y l_width := a_rect.width l_height := a_rect.height create l_gdip_graphics.make_from_dc (a_hdc) create l_background_color.make_from_argb (255, a_background.red, a_background.green, a_background.blue) l_gdip_graphics.clear (l_background_color) l_gdip_graphics.fill_rectangle (a_background_brush, create {WEL_GDIP_RECT}.make_with_size (l_x, l_y, l_width, l_height)) l_gdip_graphics.destroy_item Result := True end end end draw_widget_background (a_widget: EV_WIDGET_IMP; a_hdc: WEL_DC; a_rect: WEL_RECT; background_brush: WEL_BRUSH) -- Draw the background for `a_widget' onto `a_hdc' restricted to `a_rect'. If `a_widget' is contained at some level within -- a notebook then apply the theming of the notebook background to `a_widget', otherwise draw the background using `background_brush'. -- The theming is ignored if `a_widget' has had a background color specifically set or if one of the containers `a_widget' is contained in -- between itself and the notebook have a background color specifically set. local notebook_parent: detachable EV_NOTEBOOK_IMP l_rect: WEL_RECT container_widget: detachable EV_CONTAINER_IMP do notebook_parent ?= get_notebook_parent (a_widget) if notebook_parent = Void then container_widget ?= a_widget a_hdc.fill_rect (a_rect, background_brush) else -- The rect is made with the correct offset from `a_widget' to `notebook_parent' so that the -- texture of the theming can be applied correctly. This ensures that the background is seamless with the notebook. create l_rect.make ( notebook_parent.absolute_x - a_widget.absolute_x, notebook_parent.absolute_y - a_widget.absolute_y, notebook_parent.width + notebook_parent.absolute_x - a_widget.absolute_x , notebook_parent.height + notebook_parent.absolute_y - a_widget.absolute_y) draw_theme_background (notebook_parent.open_theme, a_hdc, tabp_body, 0, l_rect, a_rect, background_brush) end end draw_notebook_background (notebook: EV_NOTEBOOK_IMP; a_hdc: WEL_DC; a_rect: WEL_RECT; background_brush: WEL_BRUSH) -- Draw the background of `notebook'. Does nothing as on XP, the background is drawn automatically. do -- Does nothing on Windows XP as with styles enabled it appears that the background of a notebook is -- automatically drawn correctly. This does not happen with the classic look and feel. end draw_theme_parent_background (wel_item: POINTER; a_hdc: WEL_DC; a_rect: WEL_RECT; background_brush: detachable WEL_BRUSH) -- For the WEL_WINDOW represented by `wel_item', copy the background of it's parent into `a_hdc' bounded by -- `a_rect'. `background_brush' is not used. Warning. If this is used recursively in nested widget structures, -- it appears to slow things down a great deal. do -- Need to first clear the area to the background color of `parent_imp' cwin_draw_theme_parent_background (wel_item, a_hdc.item, a_rect.item) end draw_button_edge (memory_dc: WEL_DC; a_state_id: INTEGER; a_rect: WEL_RECT) -- Draw the edge of a button into `memory_dc' using `a_state_id' to give the current -- button state. `a_rect' gives the boundaries of the drawing. do -- Nothing to do here as themed buttons automatically draw their frame as part of the background. end update_button_text_rect_for_state (wel_item: pointer; a_state_is: INTEGER; a_rect: WEL_RECT) -- Update `a_rect' to reflect new position for text drawn on a button with state `a_state'. do -- Nothing to do here as themed buttons do not offset their text when pressed as per classic buttons. end update_button_pixmap_coordinates_for_state (open_theme: POINTER; a_state: INTEGER; coordinate: EV_COORDINATE) -- Update `coordinate' to reflect new coordinates for a pixmap drawn on a button with state `a_state'. do -- Nothing to do here as themed buttons do not offset their text when pressed as per classic buttons. end draw_text (theme: POINTER; a_hdc: WEL_DC; a_part_id, a_state_id: INTEGER; text: READABLE_STRING_GENERAL; dw_text_flags: INTEGER; is_sensitive: BOOLEAN; a_content_rect: WEL_RECT; foreground_color: EV_COLOR_IMP) -- Draw `text' using theme `theme' on `a_hdc' within `a_content_rect' corresponding to part `a_part_id', `a_state_id'. Respect state of `is_sensitive' local wel_string: WEL_STRING do wel_string := unicode_string (text) -- We must check that a color has not been set. If one has, then the classic drawing routine must -- be called to override the theme drawing color. -- `cwin_draw_theme_text' can't draw grey disabled text. `cwin_dtt_grayed' not work. Set state_id to disabled state not work. -- They all draw normal black text. So when not `is_sensitive' we use classic drawing routine. if foreground_color.attached_interface.is_equal ((create {EV_STOCK_COLORS}).default_foreground_color) and is_sensitive then cwin_draw_theme_text (theme, a_hdc.item, a_part_id, a_state_id, wel_string.item, wel_string.count, dw_text_flags, 0, a_content_rect.item) else classic_drawer.draw_text (theme, a_hdc, a_part_id, a_state_id, text, dw_text_flags, is_sensitive, a_content_rect, foreground_color) end end feature -- Query theme_color (a_theme: POINTER; a_color_id: INTEGER): EV_COLOR -- Theme color -- a_color_id is one value from EV_THEME_COLOR_CONTANTS local l_wel_color: WEL_COLOR_REF l_wel_err: detachable WEL_ERROR l_int: INTEGER do debug ("VISION2_WINDOWS") create l_wel_err l_wel_err.reset_last_error_code end l_int := cwin_get_theme_sys_color (a_theme, a_color_id) debug ("VISION2_WINDOWS") check l_wel_err /= Void then end if l_wel_err.last_error_code /= 0 then l_wel_err.display_last_error end end create l_wel_color.make_by_color (l_int) create Result.make_with_8_bit_rgb (l_wel_color.red, l_wel_color.green, l_wel_color.blue) end feature {NONE} -- Implementation classic_drawer: EV_CLASSIC_THEME_DRAWER_IMP -- Once access to the classic drawer for use in situations where -- `Current' determines that it must use the classic implementation -- as a property is set which overrides the theme drawer. once create Result end unicode_string (string: READABLE_STRING_GENERAL): WEL_STRING -- Convert `string' into a Unicode string, require string_not_void: string /= Void do create Result.make (string) ensure result_not_void: Result /= Void end cwin_open_theme_data (a_item, a_class_name: POINTER): POINTER -- SDK's OpenThemeData external "dllwin %"uxtheme.dll%" signature (HWND, LPCWSTR): EIF_POINTER use <windows.h>" alias "OpenThemeData" end cwin_close_theme_data (a_item: POINTER) -- SDK's CloseThemeData external "dllwin %"uxtheme.dll%" signature (HWND) use <windows.h>" alias "CloseThemeData" end cwin_draw_theme_parent_background (hwnd, a_hdc: POINTER; a_content_rect: POINTER) -- SDK's DrawThemeText external "dllwin %"uxtheme.dll%" signature (HWND, HDC, RECT *) use <windows.h>" alias "DrawThemeParentBackground" end cwin_draw_theme_background (a_theme, a_hdc: POINTER; a_part_id, a_state_id: INTEGER; a_rect, a_clip_rect: POINTER) -- SDK's DrawThemeBackground external "dllwin %"uxtheme.dll%" signature (EIF_POINTER, HDC, int, int, RECT *, RECT *) use <windows.h>" alias "DrawThemeBackground" end cwin_draw_theme_text (a_theme, a_hdc: POINTER; a_part_id, a_state_id: INTEGER; psz_text: POINTER; i_char_count, dw_text_flags, dw_text_flags2: INTEGER; a_content_rect: POINTER) -- SDK's DrawThemeText external "dllwin %"uxtheme.dll%" signature (EIF_POINTER, HDC, int, int, LPCWSTR, int, DWORD, DWORD, RECT *) use <windows.h>" alias "DrawThemeText" end cwin_draw_theme_edge (a_theme, a_hdc: POINTER; a_part_id, a_state_id: INTEGER; a_rect: POINTER; a_edge, a_flags: INTEGER; a_content_rect: POINTER) -- SDK's DrawThemeBackground external "dllwin %"uxtheme.dll%" signature (EIF_POINTER, HDC, int, int, RECT *, UINT, UINT, RECT *) use <windows.h>" alias "DrawThemeEdge" end cwin_get_window_theme (hwnd: POINTER): POINTER -- SDK's GetWindowTheme external "dllwin %"uxtheme.dll%" signature (EIF_POINTER): EIF_POINTER use <windows.h>" alias "GetWindowTheme" end cwin_dtt_grayed: INTEGER = 1; -- SDK's DTT_GRAYED cwin_get_theme_sys_color (a_theme: POINTER; a_color_id: INTEGER): INTEGER -- SDK's GetThemeSysColor external "dllwin %"uxtheme.dll%" signature (EIF_POINTER, int): COLORREF use <windows.h>" alias "GetThemeSysColor" end note copyright: "Copyright (c) 1984-2013, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end