diff options
| author | Pierre Ossman <ossman@cendio.se> | 2014-06-16 11:39:32 +0000 |
|---|---|---|
| committer | Pierre Ossman <ossman@cendio.se> | 2014-06-16 11:39:32 +0000 |
| commit | f58b1a91b37e5ad758b3d0a3d9be950e8feb5d0c (patch) | |
| tree | ca7ebd90423d4d9267da62703e282f79a9793131 /src/Fl_win32.cxx | |
| parent | 332dc1b7acfedbf80b71cc6f538a14f24d435df3 (diff) | |
Add ability to set custom icons for windows. STR #2816.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10197 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_win32.cxx')
| -rw-r--r-- | src/Fl_win32.cxx | 308 |
1 files changed, 243 insertions, 65 deletions
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index 094edb39d..79b300fb4 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -1820,6 +1820,8 @@ Fl_X* Fl_X::make(Fl_Window* w) { ); if (lab) free(lab); + x->set_icons(); + if (w->fullscreen_active()) { /* We need to make sure that the fullscreen is created on the default monitor, ie the desktop where the shortcut is located @@ -2053,71 +2055,19 @@ void Fl_Window::label(const char *name,const char *iname) { //////////////////////////////////////////////////////////////// -#ifndef IDC_HAND -# define IDC_HAND MAKEINTRESOURCE(32649) -#endif // !IDC_HAND - -int Fl_X::set_cursor(Fl_Cursor c) { - LPSTR n; - HCURSOR new_cursor; - - if (c == FL_CURSOR_NONE) - new_cursor = NULL; - else { - switch (c) { - case FL_CURSOR_ARROW: n = IDC_ARROW; break; - case FL_CURSOR_CROSS: n = IDC_CROSS; break; - case FL_CURSOR_WAIT: n = IDC_WAIT; break; - case FL_CURSOR_INSERT: n = IDC_IBEAM; break; - case FL_CURSOR_HAND: n = IDC_HAND; break; - case FL_CURSOR_HELP: n = IDC_HELP; break; - case FL_CURSOR_MOVE: n = IDC_SIZEALL; break; - case FL_CURSOR_N: - case FL_CURSOR_S: - // FIXME: Should probably have fallbacks for these instead - case FL_CURSOR_NS: n = IDC_SIZENS; break; - case FL_CURSOR_NE: - case FL_CURSOR_SW: - // FIXME: Dito. - case FL_CURSOR_NESW: n = IDC_SIZENESW; break; - case FL_CURSOR_E: - case FL_CURSOR_W: - // FIXME: Dito. - case FL_CURSOR_WE: n = IDC_SIZEWE; break; - case FL_CURSOR_SE: - case FL_CURSOR_NW: - // FIXME: Dito. - case FL_CURSOR_NWSE: n = IDC_SIZENWSE; break; - default: - return 0; - } - - new_cursor = LoadCursor(NULL, n); - if (new_cursor == NULL) - return 0; - } - - if ((cursor != NULL) && custom_cursor) - DestroyIcon(cursor); - - cursor = new_cursor; - custom_cursor = 0; - - SetCursor(cursor); - - return 1; -} - -int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) { +static HICON image_to_icon(const Fl_RGB_Image *image, bool is_icon, + int hotx, int hoty) { BITMAPV5HEADER bi; HBITMAP bitmap, mask; DWORD *bits; - HCURSOR new_cursor; + HICON icon; - if ((hotx < 0) || (hotx >= image->w())) - return 0; - if ((hoty < 0) || (hoty >= image->h())) - return 0; + if (!is_icon) { + if ((hotx < 0) || (hotx >= image->w())) + return NULL; + if ((hoty < 0) || (hoty >= image->h())) + return NULL; + } memset(&bi, 0, sizeof(BITMAPV5HEADER)); @@ -2139,7 +2089,7 @@ int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) { ReleaseDC(NULL, hdc); if (bits == NULL) - return 0; + return NULL; const uchar *i = (const uchar*)*image->data(); for (int y = 0;y < image->h();y++) { @@ -2168,22 +2118,250 @@ int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) { mask = CreateBitmap(image->w(),image->h(),1,1,NULL); if (mask == NULL) { DeleteObject(bitmap); - return 0; + return NULL; } ICONINFO ii; - ii.fIcon = FALSE; + ii.fIcon = is_icon; ii.xHotspot = hotx; ii.yHotspot = hoty; ii.hbmMask = mask; ii.hbmColor = bitmap; - new_cursor = CreateIconIndirect(&ii); + icon = CreateIconIndirect(&ii); DeleteObject(bitmap); DeleteObject(mask); + if (icon == NULL) + return NULL; + + return icon; +} + +//////////////////////////////////////////////////////////////// + +static HICON default_big_icon = NULL; +static HICON default_small_icon = NULL; + +static const Fl_RGB_Image *find_best_icon(int ideal_width, + const Fl_RGB_Image *icons[], + int count) { + const Fl_RGB_Image *best; + + best = NULL; + + for (int i = 0;i < count;i++) { + if (best == NULL) + best = icons[i]; + else { + if (best->w() < ideal_width) { + if (icons[i]->w() > best->w()) + best = icons[i]; + } else { + if ((icons[i]->w() >= ideal_width) && + (icons[i]->w() < best->w())) + best = icons[i]; + } + } + } + + return best; +} + +void Fl_X::set_default_icons(const Fl_RGB_Image *icons[], int count) { + const Fl_RGB_Image *best_big, *best_small; + + if (default_big_icon != NULL) + DestroyIcon(default_big_icon); + if (default_small_icon != NULL) + DestroyIcon(default_small_icon); + + default_big_icon = NULL; + default_small_icon = NULL; + + best_big = find_best_icon(GetSystemMetrics(SM_CXICON), icons, count); + best_small = find_best_icon(GetSystemMetrics(SM_CXSMICON), icons, count); + + if (best_big != NULL) + default_big_icon = image_to_icon(best_big, true, 0, 0); + + if (best_small != NULL) + default_small_icon = image_to_icon(best_small, true, 0, 0); +} + +void Fl_X::set_default_icons(HICON big_icon, HICON small_icon) { + if (default_big_icon != NULL) + DestroyIcon(default_big_icon); + if (default_small_icon != NULL) + DestroyIcon(default_small_icon); + + default_big_icon = NULL; + default_small_icon = NULL; + + if (big_icon != NULL) + default_big_icon = CopyIcon(big_icon); + if (small_icon != NULL) + default_small_icon = CopyIcon(small_icon); +} + +void Fl_X::set_icons() { + HICON big_icon, small_icon; + + // Windows doesn't copy the icons, so we have to "leak" them when + // setting, and clean up when we change to some other icons. + big_icon = (HICON)SendMessage(xid, WM_GETICON, ICON_BIG, 0); + if ((big_icon != NULL) && (big_icon != default_big_icon)) + DestroyIcon(big_icon); + small_icon = (HICON)SendMessage(xid, WM_GETICON, ICON_SMALL, 0); + if ((small_icon != NULL) && (small_icon != default_small_icon)) + DestroyIcon(small_icon); + + big_icon = NULL; + small_icon = NULL; + + if (w->icon_->count) { + const Fl_RGB_Image *best_big, *best_small; + + best_big = find_best_icon(GetSystemMetrics(SM_CXICON), + (const Fl_RGB_Image **)w->icon_->icons, + w->icon_->count); + best_small = find_best_icon(GetSystemMetrics(SM_CXSMICON), + (const Fl_RGB_Image **)w->icon_->icons, + w->icon_->count); + + if (best_big != NULL) + big_icon = image_to_icon(best_big, true, 0, 0); + if (best_small != NULL) + small_icon = image_to_icon(best_small, true, 0, 0); + } else { + if ((w->icon_->big_icon != NULL) || (w->icon_->small_icon != NULL)) { + big_icon = w->icon_->big_icon; + small_icon = w->icon_->small_icon; + } else { + big_icon = default_big_icon; + small_icon = default_small_icon; + } + } + + SendMessage(xid, WM_SETICON, ICON_BIG, (LPARAM)big_icon); + SendMessage(xid, WM_SETICON, ICON_SMALL, (LPARAM)small_icon); +} + +/** Sets the default window icons. + + Convenience function to set the default icons using Windows' + native HICON icon handles. + + The given icons are copied. You can free the icons immediately after + this call. + + \param[in] big_icon default large icon for all windows + subsequently created + \param[in] small_icon default small icon for all windows + subsequently created + + \see Fl_Window::default_icon(const Fl_RGB_Image *) + \see Fl_Window::default_icons(const Fl_RGB_Image *[], int) + \see Fl_Window::icon(const Fl_RGB_Image *) + \see Fl_Window::icons(const Fl_RGB_Image *[], int) + \see Fl_Window::icons(HICON, HICON) + */ +void Fl_Window::default_icons(HICON big_icon, HICON small_icon) { + Fl_X::set_default_icons(big_icon, small_icon); +} + +/** Sets the window icons. + + Convenience function to set this window's icons using Windows' + native HICON icon handles. + + The given icons are copied. You can free the icons immediately after + this call. + + \param[in] big_icon large icon for this window + \param[in] small_icon small icon for this windows + + \see Fl_Window::default_icon(const Fl_RGB_Image *) + \see Fl_Window::default_icons(const Fl_RGB_Image *[], int) + \see Fl_Window::default_icons(HICON, HICON) + \see Fl_Window::icon(const Fl_RGB_Image *) + \see Fl_Window::icons(const Fl_RGB_Image *[], int) + */ +void Fl_Window::icons(HICON big_icon, HICON small_icon) { + free_icons(); + + if (big_icon != NULL) + icon_->big_icon = CopyIcon(big_icon); + if (small_icon != NULL) + icon_->small_icon = CopyIcon(small_icon); + + if (i) + i->set_icons(); +} + +//////////////////////////////////////////////////////////////// + +#ifndef IDC_HAND +# define IDC_HAND MAKEINTRESOURCE(32649) +#endif // !IDC_HAND + +int Fl_X::set_cursor(Fl_Cursor c) { + LPSTR n; + HCURSOR new_cursor; + + if (c == FL_CURSOR_NONE) + new_cursor = NULL; + else { + switch (c) { + case FL_CURSOR_ARROW: n = IDC_ARROW; break; + case FL_CURSOR_CROSS: n = IDC_CROSS; break; + case FL_CURSOR_WAIT: n = IDC_WAIT; break; + case FL_CURSOR_INSERT: n = IDC_IBEAM; break; + case FL_CURSOR_HAND: n = IDC_HAND; break; + case FL_CURSOR_HELP: n = IDC_HELP; break; + case FL_CURSOR_MOVE: n = IDC_SIZEALL; break; + case FL_CURSOR_N: + case FL_CURSOR_S: + // FIXME: Should probably have fallbacks for these instead + case FL_CURSOR_NS: n = IDC_SIZENS; break; + case FL_CURSOR_NE: + case FL_CURSOR_SW: + // FIXME: Dito. + case FL_CURSOR_NESW: n = IDC_SIZENESW; break; + case FL_CURSOR_E: + case FL_CURSOR_W: + // FIXME: Dito. + case FL_CURSOR_WE: n = IDC_SIZEWE; break; + case FL_CURSOR_SE: + case FL_CURSOR_NW: + // FIXME: Dito. + case FL_CURSOR_NWSE: n = IDC_SIZENWSE; break; + default: + return 0; + } + + new_cursor = LoadCursor(NULL, n); + if (new_cursor == NULL) + return 0; + } + + if ((cursor != NULL) && custom_cursor) + DestroyIcon(cursor); + + cursor = new_cursor; + custom_cursor = 0; + + SetCursor(cursor); + + return 1; +} + +int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) { + HCURSOR new_cursor; + + new_cursor = image_to_icon(image, false, hotx, hoty); if (new_cursor == NULL) return 0; |
