diff --git a/include/nana/gui/detail/native_window_interface.hpp b/include/nana/gui/detail/native_window_interface.hpp index 39cd7c49..66f6ac94 100644 --- a/include/nana/gui/detail/native_window_interface.hpp +++ b/include/nana/gui/detail/native_window_interface.hpp @@ -45,6 +45,8 @@ namespace detail static void enable_dropfiles(native_window_type, bool); static void enable_window(native_window_type, bool); static bool window_icon(native_window_type, const paint::image&); + // (On Windows) The system displays the large icon in the ALT+TAB dialog box, and the small icon in the window caption. + static bool window_icon(native_window_type, const paint::image& big_icon, const paint::image& small_icon); static void activate_owner(native_window_type); static void activate_window(native_window_type); static void close_window(native_window_type); diff --git a/include/nana/gui/detail/window_manager.hpp b/include/nana/gui/detail/window_manager.hpp index c4dfb59e..682c139c 100644 --- a/include/nana/gui/detail/window_manager.hpp +++ b/include/nana/gui/detail/window_manager.hpp @@ -85,7 +85,6 @@ namespace detail void all_handles(std::vector&) const; void event_filter(core_window_t*, bool is_make, event_code); - void default_icon(const nana::paint::image&); bool available(core_window_t*); bool available(core_window_t *, core_window_t*); @@ -107,7 +106,10 @@ namespace detail //@brief: Delete window handle, the handle type must be a root and a frame. void destroy_handle(core_window_t*); + void default_icon(const paint::image&); + void default_icon(const paint::image& big_icon, const paint::image& small_icon); void icon(core_window_t*, const paint::image&); + void icon(core_window_t*, const paint::image& big_icon, const paint::image& small_icon); //show //@brief: show or hide a window diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index 0b66d0f3..6f15f42c 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -113,7 +113,10 @@ namespace API } void window_icon_default(const paint::image&); + void window_icon_default(const paint::image& big_icon, const paint::image& small_icon); void window_icon(window, const paint::image&); + void window_icon(window, const paint::image& big_icon, const paint::image& small_icon); + bool empty_window(window); ///< Determines whether a window is existing. bool is_window(window); ///< Determines whether a window is existing, equal to !empty_window. bool is_destroying(window); ///< Determines whether a window is destroying diff --git a/include/nana/gui/widgets/label.hpp b/include/nana/gui/widgets/label.hpp index 0da88167..bd7d31b4 100644 --- a/include/nana/gui/widgets/label.hpp +++ b/include/nana/gui/widgets/label.hpp @@ -65,6 +65,8 @@ namespace nana label& format(bool); ///< Switches the format mode of the widget. label& add_format_listener(std::function); + void relate(widget& w); // as same as the "for" attribute of a label + /// \briefReturn the size of the text. If *allowed_width_in_pixel* is not zero, returns a /// "corrected" size that changes lines to fit the text into the specified width nana::size measure(unsigned allowed_width_in_pixel) const; diff --git a/include/nana/gui/widgets/skeletons/text_editor.hpp b/include/nana/gui/widgets/skeletons/text_editor.hpp index 2e6e147d..9fc39e69 100644 --- a/include/nana/gui/widgets/skeletons/text_editor.hpp +++ b/include/nana/gui/widgets/skeletons/text_editor.hpp @@ -157,8 +157,8 @@ namespace nana{ namespace widgets void set_accept(std::function); void set_accept(accepts); - bool respond_char(char_type); - bool respond_key(char_type); + bool respond_char(const arg_keyboard& arg); + bool respond_key(const arg_keyboard& arg); void typeface_changed(); @@ -286,6 +286,8 @@ namespace nana{ namespace widgets unsigned _m_char_by_pixels(const nana::char_t*, std::size_t len, unsigned* pxbuf, int str_px, int pixels, bool is_rtl); unsigned _m_pixels_by_char(const nana::string&, std::size_t pos) const; static bool _m_is_right_text(const unicode_bidi::entity&); + void _handle_move_key(const arg_keyboard& arg); + private: std::unique_ptr behavior_; undoable undo_; diff --git a/include/nana/paint/detail/image_impl_interface.hpp b/include/nana/paint/detail/image_impl_interface.hpp index 3d74ce5c..ecd2b6b1 100644 --- a/include/nana/paint/detail/image_impl_interface.hpp +++ b/include/nana/paint/detail/image_impl_interface.hpp @@ -16,6 +16,7 @@ namespace nana{ namespace paint{ typedef nana::paint::graphics& graph_reference; virtual ~image_impl_interface() = 0; //The destructor is defined in ../image.cpp virtual bool open(const nana::char_t* filename) = 0; + virtual bool open(void* buff, size_t sz) = 0; // reads image from memory virtual bool alpha_channel() const = 0; virtual bool empty() const = 0; virtual void close() = 0; diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index aac4712a..e790fc89 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -130,7 +130,7 @@ namespace nana void setsta(); ///< Clears the status if the graphics object had been changed void set_changed(); void release(); - void save_as_file(const char*); + void save_as_file(const char*) const; // saves image as a bitmap file void set_color(const ::nana::color&); void set_text_color(const ::nana::color&); diff --git a/include/nana/paint/image.hpp b/include/nana/paint/image.hpp index 2b127586..2747eee7 100644 --- a/include/nana/paint/image.hpp +++ b/include/nana/paint/image.hpp @@ -37,6 +37,7 @@ namespace paint image& operator=(const image& rhs); image& operator=(image&&); bool open(const nana::string& filename); + bool open_icon(void* buff, size_t sz); // opens a icon from memory bool empty() const; operator unspecified_bool_t() const; void close(); diff --git a/source/gui/detail/native_window_interface.cpp b/source/gui/detail/native_window_interface.cpp index cc6f8802..fa21a0cd 100644 --- a/source/gui/detail/native_window_interface.cpp +++ b/source/gui/detail/native_window_interface.cpp @@ -537,6 +537,30 @@ namespace nana{ return false; } + bool native_interface::window_icon(native_window_type wd, const paint::image& big_icon, const paint::image& small_icon) + { +#if defined(NANA_WINDOWS) + HICON h_big_icon = paint::image_accessor::icon(big_icon); + HICON h_small_icon = paint::image_accessor::icon(small_icon); + if (h_big_icon || h_small_icon) + { + nana::detail::platform_spec::instance().keep_window_icon(wd, (!big_icon.empty() ? big_icon : small_icon)); + if (h_big_icon) { + ::SendMessage(reinterpret_cast(wd), WM_SETICON, ICON_BIG, reinterpret_cast(h_big_icon)); + } + if (h_small_icon) { + ::SendMessage(reinterpret_cast(wd), WM_SETICON, ICON_SMALL, reinterpret_cast(h_small_icon)); + } + return true; + } +#elif defined(NANA_X11) + return window_icon(wd, big_icon); +#endif + return false; + } + + + void native_interface::activate_owner(native_window_type wd) { #if defined(NANA_WINDOWS) diff --git a/source/gui/detail/win32/bedrock.cpp b/source/gui/detail/win32/bedrock.cpp index 9d98f2fe..a0013ba1 100644 --- a/source/gui/detail/win32/bedrock.cpp +++ b/source/gui/detail/win32/bedrock.cpp @@ -1413,6 +1413,7 @@ namespace detail auto tstop_wd = brock.wd_manager.tabstop(msgwnd, is_forward); if (tstop_wd) { + root_runtime->condition.tabstop_focus_changed = true; brock.wd_manager.set_focus(tstop_wd, false); brock.wd_manager.do_lazy_refresh(msgwnd, false); brock.wd_manager.do_lazy_refresh(tstop_wd, true); diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index 3ed2a727..89f1cdf8 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -42,7 +42,8 @@ namespace detail { root_register misc_register; handle_manager wd_register; - paint::image default_icon; + paint::image default_icon_big; + paint::image default_icon_small; }; //end struct wdm_private_impl @@ -182,11 +183,6 @@ namespace detail } } - void window_manager::default_icon(const paint::image& img) - { - impl_->default_icon = img; - } - bool window_manager::available(core_window_t* wd) { return impl_->wd_register.available(wd); @@ -218,7 +214,7 @@ namespace detail if (impl_->wd_register.available(owner)) { native = (owner->other.category == category::frame_tag::value ? - owner->other.attribute.frame->container : owner->root_widget->root); + owner->other.attribute.frame->container : owner->root_widget->root); r.x += owner->pos_root.x; r.y += owner->pos_root.y; } @@ -247,7 +243,7 @@ namespace detail insert_frame(owner, wd); bedrock::inc_window(wd->thread_id); - this->icon(wd, impl_->default_icon); + this->icon(wd, impl_->default_icon_big, impl_->default_icon_small); return wd; } return nullptr; @@ -394,6 +390,18 @@ namespace detail } } + void window_manager::default_icon(const paint::image& img) + { + impl_->default_icon_big = img; + impl_->default_icon_small = img; + } + + void window_manager::default_icon(const nana::paint::image& big, const nana::paint::image& small) + { + impl_->default_icon_big = big; + impl_->default_icon_small = small; + } + void window_manager::icon(core_window_t* wd, const paint::image& img) { if(false == img.empty()) @@ -407,6 +415,19 @@ namespace detail } } + void window_manager::icon(core_window_t* wd, const paint::image& big_icon, const paint::image& small_icon) + { + if(!big_icon.empty() || !small_icon.empty()) + { + std::lock_guard lock(mutex_); + if (impl_->wd_register.available(wd)) + { + if(wd->other.category == category::root_tag::value) + native_interface::window_icon(wd->root, big_icon, small_icon); + } + } + } + //show //@brief: show or hide a window bool window_manager::show(core_window_t* wd, bool visible) diff --git a/source/gui/filebox.cpp b/source/gui/filebox.cpp index 612af33e..441d5682 100644 --- a/source/gui/filebox.cpp +++ b/source/gui/filebox.cpp @@ -1021,6 +1021,7 @@ namespace nana if (!impl_->open_or_save) ofn.Flags = OFN_OVERWRITEPROMPT; //Overwrite prompt if it is save mode + ofn.Flags |= OFN_NOCHANGEDIR; if(FALSE == (impl_->open_or_save ? ::GetOpenFileName(&ofn) : ::GetSaveFileName(&ofn))) return false; diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index 327ffff9..3850c0be 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -359,11 +359,21 @@ namespace API restrict::window_manager.default_icon(img); } + void window_icon_default(const paint::image& big_icon, const paint::image& small_icon) + { + restrict::window_manager.default_icon(big_icon, small_icon); + } + void window_icon(window wd, const paint::image& img) { restrict::window_manager.icon(reinterpret_cast(wd), img); } + void window_icon(window wd, const paint::image& big_icon, const paint::image& small_icon) + { + restrict::window_manager.icon(reinterpret_cast(wd), big_icon, small_icon); + } + bool empty_window(window wd) { return (restrict::window_manager.available(reinterpret_cast(wd)) == false); diff --git a/source/gui/widgets/combox.cpp b/source/gui/widgets/combox.cpp index e088b229..2ddb22f6 100644 --- a/source/gui/widgets/combox.cpp +++ b/source/gui/widgets/combox.cpp @@ -684,7 +684,7 @@ namespace nana { case keyboard::os_arrow_left: case keyboard::os_arrow_right: - drawer_->editor()->respond_key(arg.key); + drawer_->editor()->respond_key(arg); drawer_->editor()->reset_caret(); break; case keyboard::os_arrow_up: @@ -713,14 +713,14 @@ namespace nana } } if (call_other_keys) - drawer_->editor()->respond_key(arg.key); + drawer_->editor()->respond_key(arg); API::lazy_refresh(); } void trigger::key_char(graph_reference graph, const arg_keyboard& arg) { - if (drawer_->editor()->respond_char(arg.key)) + if (drawer_->editor()->respond_char(arg)) API::lazy_refresh(); } //end class trigger diff --git a/source/gui/widgets/label.cpp b/source/gui/widgets/label.cpp index b07bd8fb..675e06e5 100644 --- a/source/gui/widgets/label.cpp +++ b/source/gui/widgets/label.cpp @@ -628,6 +628,8 @@ namespace nana nana::string target; //It indicates which target is tracing. nana::string url; + widget * buddy {nullptr}; + void add_listener(std::function&& fn) { listener_.emplace_back(std::move(fn)); @@ -740,6 +742,10 @@ namespace nana impl_->call_listener(command::click, impl_->target); system::open_url(url); + + if (impl_->buddy) { + impl_->buddy->focus(); + } } void trigger::refresh(graph_reference graph) @@ -821,6 +827,11 @@ namespace nana return *this; } + void label::relate(widget& w) + { + get_drawer_trigger().impl()->buddy = &w; + } + nana::size label::measure(unsigned limited) const { if(empty()) diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 7b256c28..a7afa323 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -461,6 +461,7 @@ namespace nana{ namespace widgets editor_._m_scrollbar(); return (adjusted_cond || adjusted_cond2); } + private: std::size_t _m_textline_from_screen(int y) const { @@ -1349,8 +1350,9 @@ namespace nana{ namespace widgets attributes_.acceptive = acceptive; } - bool text_editor::respond_char(char_type key) //key is a character of ASCII code + bool text_editor::respond_char(const arg_keyboard& arg) //key is a character of ASCII code { + char_type key = arg.key; switch (key) { case keyboard::end_of_text: @@ -1400,14 +1402,28 @@ namespace nana{ namespace widgets return false; } - bool text_editor::respond_key(char_type key) + bool text_editor::respond_key(const arg_keyboard& arg) { + char_type key = arg.key; switch (key) { +#if 0 case keyboard::os_arrow_left: move_left(); break; case keyboard::os_arrow_right: move_right(); break; case keyboard::os_arrow_up: move_ns(true); break; case keyboard::os_arrow_down: move_ns(false); break; +#else + case keyboard::os_arrow_left: + case keyboard::os_arrow_right: + case keyboard::os_arrow_up: + case keyboard::os_arrow_down: + case keyboard::os_home: + case keyboard::os_end: + case keyboard::os_pageup: + case keyboard::os_pagedown: + _handle_move_key(arg); + break; +#endif case keyboard::os_del: if (this->attr().editable) del(); @@ -1605,17 +1621,12 @@ namespace nana{ namespace widgets //Set caret pos by screen point and get the caret pos. auto pos = mouse_caret(scrpos); - if(!hit_select_area(pos)) + if(!select(false)) { - if(!select(false)) - { - select_.a = points_.caret; //Set begin caret - set_end_caret(); - } - select_.mode_selection = selection::mode_mouse_selected; + select_.a = points_.caret; //Set begin caret + set_end_caret(); } - else - select_.mode_selection = selection::mode_no_selected; + select_.mode_selection = selection::mode_mouse_selected; } text_area_.border_renderer(graph_, _m_bgcolor()); @@ -2219,6 +2230,136 @@ namespace nana{ namespace widgets points_.xpos = points_.caret.x; } + void text_editor::_handle_move_key(const arg_keyboard& arg) + { + bool changed = false; + nana::upoint caret = points_.caret; + char_t key = arg.key; + size_t nlines = textbase_.lines(); + if (arg.ctrl) { + switch (key) { + case keyboard::os_arrow_left: + case keyboard::os_arrow_right: + // TODO: move the caret word by word + break; + case keyboard::os_home: + if (caret.y != 0) { + caret.y = 0; + points_.offset.y = 0; + changed = true; + } + break; + case keyboard::os_end: + if (caret.y != nlines - 1) { + caret.y = nlines - 1; + changed = true; + } + break; + } + } + size_t lnsz = textbase_.getline(caret.y).size(); + switch (key) { + case keyboard::os_arrow_left: + if (caret.x != 0) { + --caret.x; + changed = true; + }else { + if (caret.y != 0) { + --caret.y; + caret.x = textbase_.getline(caret.y).size(); + changed = true; + } + } + break; + case keyboard::os_arrow_right: + if (caret.x < lnsz) { + ++caret.x; + changed = true; + }else { + if (caret.y != nlines - 1) { + ++caret.y; + caret.x = 0; + changed = true; + } + } + break; + case keyboard::os_arrow_up: + case keyboard::os_arrow_down: + { + auto screen_pt = behavior_->caret_to_screen(caret); + int offset = line_height(); + if (key == keyboard::os_arrow_up) { + offset = -offset; + } + screen_pt.y += offset; + auto new_caret = behavior_->screen_to_caret(screen_pt); + if (new_caret != caret) { + caret = new_caret; + if (screen_pt.y < 0) { + scroll(true, true); + } + changed = true; + } + } + break; + case keyboard::os_home: + if (caret.x != 0) { + caret.x = 0; + changed = true; + } + break; + case keyboard::os_end: + if (caret.x < lnsz) { + caret.x = lnsz; + changed = true; + } + break; + case keyboard::os_pageup: + if (caret.y >= (int)screen_lines() && points_.offset.y >= (int)screen_lines()) { + points_.offset.y -= screen_lines(); + caret.y -= screen_lines(); + changed = true; + } + break; + case keyboard::os_pagedown: + if (caret.y + screen_lines() <= behavior_->take_lines()) { + points_.offset.y += screen_lines(); + caret.y += screen_lines(); + changed = true; + } + break; + } + if (select_.a != caret || select_.b != caret) { + changed = true; + } + if (changed) { + if (arg.shift) { + switch (key) { + case keyboard::os_arrow_left: + case keyboard::os_arrow_up: + case keyboard::os_home: + case keyboard::os_pageup: + select_.b = caret; + break; + case keyboard::os_arrow_right: + case keyboard::os_arrow_down: + case keyboard::os_end: + case keyboard::os_pagedown: + select_.b = caret; + break; + } + }else { + select_.b = caret; + select_.a = caret; + } + points_.caret = caret; + behavior_->adjust_caret_into_screen(); + render(true); + _m_scrollbar(); + points_.xpos = points_.caret.x; + } + } + nana::upoint text_editor::mouse_caret(const point& scrpos) //From screen position { points_.caret = behavior_->screen_to_caret(scrpos); @@ -2826,6 +2967,8 @@ namespace nana{ namespace widgets if (if_mask && mask_char_) mask_str.reset(new nana::string(str.size(), mask_char_)); + bool focused = API::is_focus_ready(window_); // do this many times is not efficient... + auto & linestr = (if_mask && mask_char_ ? *mask_str : str); unicode_bidi bidi; @@ -2847,7 +2990,7 @@ namespace nana{ namespace widgets graph_.set_color(scheme_->selection.get_color()); //The text is not selected or the whole line text is selected - if ((!_m_get_sort_select_points(a, b)) || (select_.a.y != str_pos.y && select_.b.y != str_pos.y)) + if (!focused || (!_m_get_sort_select_points(a, b)) || (select_.a.y != str_pos.y && select_.b.y != str_pos.y)) { bool selected = (a.y < str_pos.y && str_pos.y < b.y); for (auto & ent : reordered) @@ -2857,7 +3000,7 @@ namespace nana{ namespace widgets if ((text_pos.x + static_cast(str_w) > text_area_.area.x) && (text_pos.x < xend)) { - if (selected) + if (selected && focused) { graph_.set_text_color(scheme_->selection_text.get_color()); graph_.rectangle(::nana::rectangle{ text_pos, { str_w, line_h_pixels } }, true); diff --git a/source/gui/widgets/spinbox.cpp b/source/gui/widgets/spinbox.cpp index 1caaf486..0f22fd4c 100644 --- a/source/gui/widgets/spinbox.cpp +++ b/source/gui/widgets/spinbox.cpp @@ -560,7 +560,7 @@ namespace nana void drawer::key_press(graph_reference, const arg_keyboard& arg) { - if (impl_->editor()->respond_key(arg.key)) + if (impl_->editor()->respond_key(arg)) { impl_->editor()->reset_caret(); impl_->draw_spins(); @@ -570,7 +570,7 @@ namespace nana void drawer::key_char(graph_reference, const arg_keyboard& arg) { - if (impl_->editor()->respond_char(arg.key)) + if (impl_->editor()->respond_char(arg)) { if (!impl_->value(impl_->editor()->text())) impl_->draw_spins(); diff --git a/source/gui/widgets/textbox.cpp b/source/gui/widgets/textbox.cpp index d11ae632..6d7e3380 100644 --- a/source/gui/widgets/textbox.cpp +++ b/source/gui/widgets/textbox.cpp @@ -15,6 +15,9 @@ #include #include +#include +#include + namespace nana { arg_textbox::arg_textbox(textbox& wdg) @@ -89,7 +92,17 @@ namespace drawerbase { void drawer::focus(graph_reference graph, const arg_focus& arg) { refresh(graph); - + if (!editor_->attr().multi_lines && arg.getting) + { + static auto& brock = detail::bedrock::instance(); + auto native_window = reinterpret_cast(arg.receiver); + auto* root_runtime = brock.wd_manager.root_runtime(native_window); + if (root_runtime && root_runtime->condition.tabstop_focus_changed) + { + editor_->select(true); + editor_->move_caret_end(); + } + } editor_->show_caret(arg.getting); editor_->reset_caret(); API::lazy_refresh(); @@ -136,7 +149,7 @@ namespace drawerbase { void drawer::key_press(graph_reference, const arg_keyboard& arg) { - if(editor_->respond_key(arg.key)) + if(editor_->respond_key(arg)) { editor_->reset_caret(); API::lazy_refresh(); @@ -145,7 +158,7 @@ namespace drawerbase { void drawer::key_char(graph_reference, const arg_keyboard& arg) { - if (editor_->respond_char(arg.key)) + if (editor_->respond_char(arg)) API::lazy_refresh(); } diff --git a/source/paint/detail/image_bmp.hpp b/source/paint/detail/image_bmp.hpp index 77f87df2..43643d6d 100644 --- a/source/paint/detail/image_bmp.hpp +++ b/source/paint/detail/image_bmp.hpp @@ -25,24 +25,24 @@ namespace nana{ namespace paint struct bitmap_file_header { unsigned short bfType; - unsigned long bfSize; + unsigned bfSize; unsigned short bfReserved1; unsigned short bfReserved2; - unsigned long bfOffBits; + unsigned bfOffBits; } __attribute__((packed)); struct bitmap_info_header { - unsigned long biSize; - long biWidth; - long biHeight; + unsigned biSize; + int biWidth; + int biHeight; unsigned short biPlanes; unsigned short biBitCount; - unsigned long biCompression; - unsigned long biSizeImage; - long biXPelsPerMeter; - long biYPelsPerMeter; - unsigned long biClrUsed; - unsigned long biClrImportant; + unsigned biCompression; + unsigned biSizeImage; + int biXPelsPerMeter; + int biYPelsPerMeter; + unsigned biClrUsed; + unsigned biClrImportant; }__attribute__((packed)); struct rgb_quad @@ -75,6 +75,12 @@ namespace nana{ namespace paint this->close(); } + bool open(const void* data, std::size_t bytes) + { + // TODO: read a BMP file from memory + return false; + } + bool open(const nana::char_t* filename) override { if(nullptr == filename) return false; diff --git a/source/paint/detail/image_ico.hpp b/source/paint/detail/image_ico.hpp index 37226431..9bc33dea 100644 --- a/source/paint/detail/image_ico.hpp +++ b/source/paint/detail/image_ico.hpp @@ -22,14 +22,15 @@ namespace nana{ namespace paint public: image_ico(bool is_ico); + bool open(const nana::char_t* filename) override; + bool open(const void* data, std::size_t bytes); bool alpha_channel() const override; bool empty() const override; void close() override; nana::size size() const override; virtual void paste(const nana::rectangle& src_r, graph_reference graph, const point& p_dst) const override; virtual void stretch(const nana::rectangle&, graph_reference graph, const nana::rectangle& r) const override; - const ptr_t & ptr() const; private: const bool is_ico_; diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index 343f4c6f..70bba1ef 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -812,7 +812,7 @@ namespace paint size_.width = size_.height = 0; } - void graphics::save_as_file(const char* file) + void graphics::save_as_file(const char* file) const { if(handle_) { diff --git a/source/paint/image.cpp b/source/paint/image.cpp index e2661b44..46bd547a 100644 --- a/source/paint/image.cpp +++ b/source/paint/image.cpp @@ -70,6 +70,31 @@ namespace paint return false; } + bool image_ico::open(void* buff, size_t sz) + { + close(); +#if defined(NANA_WINDOWS) + HICON handle = CreateIconFromResource((PBYTE)buff, sz, TRUE, 0x00030000); + if(handle) + { + ICONINFO info; + if (::GetIconInfo(handle, &info) != 0) + { + HICON * p = new HICON(handle); + ptr_ = std::shared_ptr(p, handle_deleter()); + size_.width = (info.xHotspot << 1); + size_.height = (info.yHotspot << 1); + ::DeleteObject(info.hbmColor); + ::DeleteObject(info.hbmMask); + return true; + } + } +#else + if(is_ico_){} //kill the unused compiler warning in Linux. +#endif + return false; + } + bool image_ico::alpha_channel() const { return false; @@ -236,6 +261,13 @@ namespace paint return false; } + bool image::open_icon(void* buff, size_t sz) + { + image::image_impl_interface * helper = new detail::image_ico(true); + image_ptr_ = std::shared_ptr(helper); + return helper->open(buff, sz); + } + bool image::empty() const { return ((nullptr == image_ptr_) || image_ptr_->empty());