| 6956 | |
| 6957 | |
| 6958 | ResultType GuiType::ControlLoadPicture(GuiControlType &aControl, LPTSTR aFilename, int aWidth, int aHeight, int aIconNumber) |
| 6959 | { |
| 6960 | // LoadPicture() uses CopyImage() to scale the image, which seems to provide better scaling |
| 6961 | // quality than using MoveWindow() (followed by redrawing the parent window) on the static |
| 6962 | // control that contains the image. |
| 6963 | int image_type; |
| 6964 | HBITMAP new_image = LoadPicture(aFilename, aWidth, aHeight, image_type, aIconNumber |
| 6965 | , aControl.attrib & GUI_CONTROL_ATTRIB_ALTSUBMIT); |
| 6966 | if (!new_image && *aFilename) |
| 6967 | return FAIL; // Caller will report the error. |
| 6968 | |
| 6969 | // In light of the below, it seems best to delete the bitmaps whenever the control changes |
| 6970 | // to a new image or whenever the control is destroyed. Otherwise, if a control or its |
| 6971 | // parent window is destroyed and recreated many times, memory allocation would continue |
| 6972 | // to grow from all of the abandoned bitmaps/icons. |
| 6973 | // MSDN: "When you are finished using a bitmap...loaded without specifying the LR_SHARED flag, |
| 6974 | // you can release its associated memory by calling...DeleteObject." |
| 6975 | // MSDN: "The system automatically deletes these resources when the process that created them |
| 6976 | // terminates, however, calling the appropriate function saves memory and decreases the size |
| 6977 | // of the process's working set." |
| 6978 | // v1.0.40.12: For maintainability, destroy the handle returned by STM_SETIMAGE, even though it |
| 6979 | // should be identical to control.union_hbitmap (due to a call to STM_GETIMAGE in another section). |
| 6980 | // UPDATE: This is now done after LoadPicture() is called to reduce the length of time between |
| 6981 | // the background being erased and the new picture being drawn, which might decrease flicker. |
| 6982 | // It's still done as a separate step to setting the new bitmap due to uncertainty about how |
| 6983 | // the control handles changing the image type, and the notes below about animation. |
| 6984 | if (aControl.union_hbitmap) |
| 6985 | if (aControl.attrib & GUI_CONTROL_ATTRIB_ALTBEHAVIOR) // union_hbitmap is an icon or cursor. |
| 6986 | // The control's image is set to NULL for the following reasons: |
| 6987 | // 1) It turns off the control's animation timer in case the new image is not animated. |
| 6988 | // 2) It feels a little bit safer to destroy the image only after it has been removed |
| 6989 | // from the control. |
| 6990 | // NOTE: IMAGE_ICON or IMAGE_CURSOR must be passed, not IMAGE_BITMAP. Otherwise the |
| 6991 | // animated property of the control (via a timer that the control created) will remain |
| 6992 | // in effect for the next image, even if it isn't animated, which results in a |
| 6993 | // flashing/redrawing effect: |
| 6994 | DestroyIcon((HICON)SendMessage(aControl.hwnd, STM_SETIMAGE, IMAGE_CURSOR, NULL)); |
| 6995 | // DestroyIcon() works on cursors too. See notes in LoadPicture(). |
| 6996 | else // union_hbitmap is a bitmap |
| 6997 | DeleteObject((HGDIOBJ)SendMessage(aControl.hwnd, STM_SETIMAGE, IMAGE_BITMAP, NULL)); |
| 6998 | aControl.union_hbitmap = new_image; |
| 6999 | if (!new_image) |
| 7000 | { |
| 7001 | // By design, no error is reported for a blank aFilename. |
| 7002 | // For simplicity, any existing SS_BITMAP/SS_ICON style bit is not removed. |
| 7003 | return OK; |
| 7004 | } |
| 7005 | if (image_type == IMAGE_ICON && aControl.background_color == CLR_TRANSPARENT) |
| 7006 | { |
| 7007 | // Static controls don't appear to support background transparency with icons, |
| 7008 | // so convert the icon to a bitmap. |
| 7009 | if (HBITMAP hbitmap = IconToBitmap32((HICON)aControl.union_hbitmap, false)) |
| 7010 | { |
| 7011 | DestroyIcon((HICON)aControl.union_hbitmap); |
| 7012 | aControl.union_hbitmap = hbitmap; |
| 7013 | image_type = IMAGE_BITMAP; |
| 7014 | } |
| 7015 | } |
nothing calls this directly
no test coverage detected