Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Contrib/nsDialogs/Readme.html
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ <h3><a name="mref-dategetdatefields">NSD_Date_GetDateFields</a></h3>

<h3><a name="mref-setbitmap"></a><a name="mref-setimage"></a>NSD_SetBitmap</h3>
<p><code>${NSD_SetBitmap} <i>control_HWND</i> <i>image_path</i> <i>$output_variable</i></code></p>
<p>Loads a bitmap from <i>image_path</i> and displays it on <i>control_HWND</i> created by <a href="#mref-create">${NSD_CreateBitmap}</a>. The image handle is stored in <i>output_variable</i> and should be freed using <a href="#mref-freebitmap">${NSD_FreeBitmap}</a> once no longer necessary.</p>
<p>Loads a BMP, JPG, GIF or PNG image from <i>image_path</i> and displays it on <i>control_HWND</i> created by <a href="#mref-create">${NSD_CreateBitmap}</a>. The image handle is stored in <i>output_variable</i> and should be freed using <a href="#mref-freebitmap">${NSD_FreeBitmap}</a> once no longer necessary.</p>
<p>The image must be extracted to the user's computer prior to calling this macro. A good place to extract images is $PLUGINSDIR.</p>
<blockquote><pre>!include nsDialogs.nsh

Expand Down Expand Up @@ -837,7 +837,7 @@ <h3><a name="mref-setbitmap"></a><a name="mref-setimage"></a>NSD_SetBitmap</h3>

<h3><a name="mref-setsbitmap"></a><a name="mref-setsimage"></a>NSD_SetStretchedBitmap</h3>
<p><code>${NSD_SetStretchedBitmap} <i>control_HWND</i> <i>image_path</i> <i>$output_variable</i></code></p>
<p>Loads and displays a bitmap just like <a href="#mref-setbitmap">${NSD_SetImage}</a> but stretches the image to fit the control.</p>
<p>Loads and displays a BMP, JPG, GIF or PNG image just like <a href="#mref-setbitmap">${NSD_SetImage}</a> but stretches the image to fit the control.</p>

<h3><a name="mref-clearbitmap"></a><a name="mref-clearimage"></a>NSD_ClearBitmap</h3>
<p><code>${NSD_ClearBitmap} <i>control_HWND</i></code></p>
Expand Down
4 changes: 4 additions & 0 deletions Docs/src/history.but
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions Docs/src/ui.but
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions Source/exehead/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ libs = Split("""
advapi32
shell32
ole32
oleaut32
comdlg32
comctl32
user32
Expand Down
85 changes: 85 additions & 0 deletions Source/exehead/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "../Platform.h"
#include <shlobj.h>
#include <olectl.h>
#include "fileform.h"
#include "util.h"
#include "state.h"
Expand Down Expand Up @@ -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);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unclear which Windows versions support this. It should be present on Windows XP according this this:
https://github.com/DeDf/winxp_source/blob/a2f6d7c93aa4f11efc51147566d5961c59a8ef89/Source/XPSP1/NT/base/win32/fusion/oleaut32/whistler/oleaut32.src#L485

If needed, I can change this to use GetProcAddress.

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
Expand Down Expand Up @@ -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
Expand Down
Loading