diff --git a/Contrib/nsDialogs/Readme.html b/Contrib/nsDialogs/Readme.html index d9c8533cf8..c9e22d9e91 100644 --- a/Contrib/nsDialogs/Readme.html +++ b/Contrib/nsDialogs/Readme.html @@ -796,7 +796,7 @@
${NSD_SetBitmap} control_HWND image_path $output_variable
Loads a bitmap from image_path and displays it on control_HWND created by ${NSD_CreateBitmap}. The image handle is stored in output_variable and should be freed using ${NSD_FreeBitmap} once no longer necessary.
+Loads a BMP, JPG, GIF or PNG image from image_path and displays it on control_HWND created by ${NSD_CreateBitmap}. The image handle is stored in output_variable and should be freed using ${NSD_FreeBitmap} once no longer necessary.
The image must be extracted to the user's computer prior to calling this macro. A good place to extract images is $PLUGINSDIR.
!include nsDialogs.nsh @@ -837,7 +837,7 @@NSD_SetBitmap
NSD_SetStretchedBitmap
-
${NSD_SetStretchedBitmap} control_HWND image_path $output_variableLoads and displays a bitmap just like ${NSD_SetImage} but stretches the image to fit the control.
+Loads and displays a BMP, JPG, GIF or PNG image just like ${NSD_SetImage} but stretches the image to fit the control.
NSD_ClearBitmap
diff --git a/Docs/src/history.but b/Docs/src/history.but index f06f416c3f..55250bc4cf 100644 --- a/Docs/src/history.but +++ b/Docs/src/history.but @@ -6,6 +6,10 @@ Released on ???? ??th, ???? \S1{v3.13-cl} Changelog +\S2{} nsDialogs + +\b Added JPG, GIF and PNG support to NSD_SetImage and NSD_SetStretchedImage + \S2{} Translations \b Updated Italian and Korean diff --git a/Docs/src/ui.but b/Docs/src/ui.but index ba2852e4b9..a4cb1f09ed 100644 --- a/Docs/src/ui.but +++ b/Docs/src/ui.but @@ -75,7 +75,7 @@ If HWND is a window, Gotos jump_if_window, otherwise, Gotos jump_if_not_window ( \c [/EXERESOURCE] [/STRINGID] [/RESIZETOFIT[WIDTH|HEIGHT]] ctrl imagetype lrflags imageid [user_var(imagehandle)] -Loads and sets a image on a static control. \cw{ctrl} is the handle of the control. \cw{imagetype} must 0 for bitmaps and 1 for icons (and the control style must match the image type). \cw{lrflags} should be 0x10 to load from a file or 0 to load from a resource. \cw{imageid} specifies the file path or resource name. Use \cw{/EXERESOURCE} to load a resource from the installer .EXE. Use \cw{/STRINGID} if \cw{imageid} is a string, otherwise it is interpreted as a number. Use \cw{/RESIZETOFIT[WIDTH|HEIGHT]} to resize the image to the dimensions of the control. \cw{imagehandle} can optionally receive the handle of the loaded image. +Loads and sets an image on a static control. \cw{ctrl} is the handle of the control. \cw{imagetype} must be 0 for BMP, JPG, GIF and PNG images, or 1 for icons (and the control style must match the image type). \cw{lrflags} should be 0x10 to load from a file or 0 to load from a resource. \cw{imageid} specifies the file path or resource name. Use \cw{/EXERESOURCE} to load a resource from the installer .EXE. Use \cw{/STRINGID} if \cw{imageid} is a string, otherwise it is interpreted as a number. Use \cw{/RESIZETOFIT[WIDTH|HEIGHT]} to resize the image to the dimensions of the control. \cw{imagehandle} can optionally receive the handle of the loaded image. Images loaded on individual pages should be destroyed to minimize resource leaks. If images are loaded into the same control multiple times, the previous image will only be destroyed if it is a bitmap image. Previous icons and 32-bit ARGB bitmaps must be retrieved with \cw{STM_GETIMAGE} and destroyed. @@ -109,9 +109,9 @@ Overrides the default auto window-closing flag (specified for the installer usin \S2{setbrandingimage} SetBrandingImage -\c [/IMGID=item_id_in_dialog] [/RESIZETOFIT] path_to_bitmap_file.bmp +\c [/IMGID=item_id_in_dialog] [/RESIZETOFIT] path_to_image_file -Sets the current bitmap file displayed as the branding image. If no IMGID is specified, the first image control found will be used, or the image control created by \R{aaddbrandingimage}{AddBrandingImage}. Note that this bitmap must be present on the user's machine. Use \cw{File} first to put it there. If /RESIZETOFIT is specified the image will be automatically resized (very poorly) to the image control size. If you used \R{aaddbrandingimage}{AddBrandingImage} you can get this size by compiling your script and watching for \R{aaddbrandingimage}{AddBrandingImage} output, it will tell you the size. SetBrandingImage will not work when called from .onInit! +Sets the current BMP, JPG, GIF or PNG file displayed as the branding image. If no IMGID is specified, the first image control found will be used, or the image control created by \R{aaddbrandingimage}{AddBrandingImage}. Note that this image must be present on the user's machine. Use \cw{File} first to put it there. If /RESIZETOFIT is specified the image will be automatically resized to the image control size. If you used \R{aaddbrandingimage}{AddBrandingImage} you can get this size by compiling your script and watching for \R{aaddbrandingimage}{AddBrandingImage} output, it will tell you the size. SetBrandingImage will not work when called from .onInit! \S2{setdetailsview} SetDetailsView diff --git a/Source/exehead/SConscript b/Source/exehead/SConscript index f0299ad8c7..c1826bbdc7 100644 --- a/Source/exehead/SConscript +++ b/Source/exehead/SConscript @@ -38,6 +38,7 @@ libs = Split(""" advapi32 shell32 ole32 + oleaut32 comdlg32 comctl32 user32 diff --git a/Source/exehead/exec.c b/Source/exehead/exec.c index bbd4a58b3e..d11a6d513e 100644 --- a/Source/exehead/exec.c +++ b/Source/exehead/exec.c @@ -18,6 +18,7 @@ #include "../Platform.h" #include
${NSD_ClearBitmap} control_HWND+#include #include "fileform.h" #include "util.h" #include "state.h" @@ -62,6 +63,88 @@ HRESULT g_hres; static int NSISCALL ExecuteEntry(entry *entry_); +#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT +// Convert OLE-supported file formats to a caller-owned bitmap compatible with STM_SETIMAGE. +static HBITMAP NSISCALL LoadOLEPictureBitmap(LPCTSTR path, int width, int height) +{ + IPicture *picture = NULL; + IDispatch *dispatch = NULL; + LPOLESTR olepath; + VARIANT filename; + HBITMAP bitmap = NULL; + HDC screen = NULL, target = NULL; + HGDIOBJ old; + OLE_HANDLE picturehandle; + BITMAP source; + LONG picturewidth, pictureheight; + HRESULT hr, init; + DWORD attributes; +#ifndef _UNICODE + WCHAR widepath[NSIS_MAX_STRLEN]; +#endif + + attributes = GetFileAttributes(path); + if (attributes == INVALID_FILE_ATTRIBUTES || (attributes & FILE_ATTRIBUTE_DIRECTORY)) return NULL; +#ifndef _UNICODE + if (!MultiByteToWideChar(CP_ACP, 0, path, -1, widepath, COUNTOF(widepath))) return NULL; + olepath = widepath; +#else + olepath = (LPOLESTR)path; +#endif + + init = OleInitialize(NULL); + VariantInit(&filename); + V_VT(&filename) = VT_BSTR; + V_BSTR(&filename) = SysAllocString(olepath); + if (V_BSTR(&filename)) + { + hr = OleLoadPictureFileEx(filename, 0, 0, LP_DEFAULT, &dispatch); + if (SUCCEEDED(hr)) + hr = dispatch->lpVtbl->QueryInterface(dispatch, &IID_IPicture, (void**)&picture); + } + else + hr = E_OUTOFMEMORY; + VariantClear(&filename); + if (dispatch) dispatch->lpVtbl->Release(dispatch); + if (SUCCEEDED(hr) && + SUCCEEDED(picture->lpVtbl->get_Width(picture, &picturewidth)) && + SUCCEEDED(picture->lpVtbl->get_Height(picture, &pictureheight)) && + SUCCEEDED(picture->lpVtbl->get_Handle(picture, &picturehandle)) && + GetObject((HGDIOBJ)(ULONG_PTR)picturehandle, sizeof(source), &source) && + (screen = GetDC(NULL)) != NULL) + { + if (!width) width = source.bmWidth; + if (!height) height = source.bmHeight; + if (width > 0 && height > 0 && + (target = CreateCompatibleDC(screen)) != NULL && + (bitmap = CreateCompatibleBitmap(screen, width, height)) != NULL) + { + old = SelectObject(target, bitmap); + if (!old || old == HGDI_ERROR) + hr = E_FAIL; + else + { + SetStretchBltMode(target, HALFTONE); + SetBrushOrgEx(target, 0, 0, NULL); + hr = picture->lpVtbl->Render(picture, target, 0, 0, width, height, + 0, pictureheight, picturewidth, -pictureheight, NULL); + SelectObject(target, old); + } + if (FAILED(hr)) + { + DeleteObject(bitmap); + bitmap = NULL; + } + } + } + if (target) DeleteDC(target); + if (screen) ReleaseDC(NULL, screen); + if (picture) picture->lpVtbl->Release(picture); + if (SUCCEEDED(init)) OleUninitialize(); + return bitmap; +} +#endif + /** * If v is negative, then the address to resolve is actually * stored in the global user variables. Convert the value @@ -869,6 +952,8 @@ static int NSISCALL ExecuteEntry(entry *entry_) LPCTSTR imgid = (parm3 & LASIF_STRID) ? GetStringFromParm(0x11) : MAKEINTRESOURCE(parm1); GetClientRect(hCtl, &r); hNewImage=LoadImage(exeres ? g_hInstance : NULL, imgid, it, fitw*r.right, fith*r.bottom, parm3 & LASIM_LR); + if (!hNewImage && IMAGE_BITMAP == it && !exeres && (parm3 & LASIF_LR_LOADFROMFILE)) + hNewImage=LoadOLEPictureBitmap(imgid, fitw*r.right, fith*r.bottom); hPrevImage=(HANDLE)SendMessage(hCtl, STM_SETIMAGE, it, (LPARAM)hNewImage); if (hPrevImage && IMAGE_BITMAP == it) DeleteObject(hPrevImage); // Delete the old bitmap if (parm0 >= 0) iptrtostr(var0, (INT_PTR)hNewImage); // Optional output handle