Показать полную графическую версию : Скрипты Inno Setup. Помощь и советы [часть 9]
ivan_rolos
08-04-2022, 19:57
Та я вроде не играю в Павлика Морозова.
четко сказал что нужно в инсталляторе прочитать свойство файла (Описание файла).
Vanadiy777
08-04-2022, 20:55
четко сказал что нужно в инсталляторе прочитать свойство файла (Описание файла). »
ivan_rolos, сценарий инсталлятора дайте, может вместе что и придумаем...
Ну, или сами дальше тогда...
Как можно прочитать свойства файла? »
Вот так (http://forum.oszone.net/post-1643761-1146.html).
Vanadiy777
30-05-2022, 15:19
Коллеги, всем доброго времени суток!
Подскажите пожалуйста, есть ли решение, как заменить иконку в MsgBox вместо mbError, mbInformation, и т.д. на свою, другую иконку, которая будет браться из системных файлов Windows?
Заранее, спасибо.
Vanadiy777,
В WinAPI есть функция MessageBoxIndirect, которая позволяет использовать произвольный значок.
Здесь на форуме есть её реализация (ссылка (http://forum.oszone.net/post-2217348.html#post2217348)), но неполная -- требуется небольшой допилинг для загрузки своего значка.
Vanadiy777
31-05-2022, 18:06
iglezz, спасибо, буду изучать...
Правда не уверен, что получится, для меня сложновато...
Vanadiy777,
Поковырял тот образец, удалось в MessageBoxIndirect отобразить значок из 32/64-бит PE-файла (dll/exe/icl).
ico использовать нельзя.
Пример смогу выложить позже, т.к. код ещё причесать надо.
Vanadiy777
31-05-2022, 20:57
Пример смогу выложить позже, т.к. код ещё причесать надо. »
iglezz, буду Вам очень признателен, если поможете, т.к. сам, видимо, не разберусь...
Мне надо взять два разных значка из одной системной dll, и в зависимости от события вывести этот значок в MsgBox.
В итоге получилать такая матрёшка...
Функция MsgBoxEx (на базе MessageBoxIndirect) может служить полной заменой стандартному MsgBox.
MsgBoxEx('Сообщение', 'Заголовок', 0, ЗНАЧОК, ФЛАГИ) - стандартный значок
MsgBoxEx('Сообщение', 'Заголовок', '', ЗНАЧОК, ФЛАГИ) - значок из установщика
MsgBoxEx('Сообщение', 'Заголовок', 'ФАЙЛ', ЗНАЧОК, ФЛАГИ) - значок из 32/64-бит PE-файла (exe/dll/icl/...)
В константах IDI_SHIELD и IDI_APPLICATION два новых значка.
ЗНАЧОК задаётся константой MB_ICON*, IDI_* либо числом, либо 'строкой' ('MAINICON').
Если файл со значком открыть не удаётся, то устанавливается значок IDI_APPLICATION
Коды возврата, флаги, стандартные значки MB_ICON* соответствуют стандартному месседжбоксу.
#define APPNAME "MessageBoxIndirect test"
[Setup]
AppName={#APPNAME}
AppVersion=0.1
DisableWelcomePage=yes
DefaultDirName={tmp}\{#APPNAME}
OutputDir=.
OutputBaseFilename={#APPNAME}
PrivilegesRequired=lowest
[code]
#include 'WinAPI_MessageBoxIndirect.pas'
procedure initializeWizard();
var
dllname: String;
ret: Integer;
begin
// Standard icons:
MsgBox('std mbInformation', mbInformation, MB_OK);
MsgBoxEx('ex IDI_INFORMATION', '{#APPNAME}', 0, IDI_INFORMATION, MB_OK);
MsgBox('std mbConfirmation', mbConfirmation, MB_OK);
MsgBoxEx('ex IDI_QUESTION', '{#APPNAME}', 0, IDI_QUESTION, MB_OK);
MsgBox('std mbError', mbError, MB_OK);
MsgBoxEx('ex IDI_EXCLAMATION', '{#APPNAME}', 0, IDI_EXCLAMATION, MB_OK);
MsgBox('std mbCriticalError', mbCriticalError, MB_OK);
MsgBoxEx('ex IDI_ERROR', '{#APPNAME}', 0, IDI_ERROR, MB_OK);
MsgBoxEx('ex IDI_SHIELD', '{#APPNAME}', 0, IDI_SHIELD, MB_OK);
MsgBoxEx('ex IDI_APPLICATION', '{#APPNAME}', 0, IDI_APPLICATION, MB_OK);
// Icon from installer
MsgBoxEx('Installer icon', '{#APPNAME}', '', 'MAINICON', MB_OK)
// Icon from exe/dll file
dllname := 'C:\Program Files\Totalcmd\TOTALCMD.EXE'
MsgBoxEx('app icon (text)'#10'from'#10+dllname, '{#APPNAME}', dllname, 'MAINICON', MB_OK)
MsgBoxEx('app icon (num)'#10'from'#10+dllname, '{#APPNAME}', dllname, 6, MB_OK)
// Icon from exe/dll file. failed to load.
MsgBoxEx('LoadLibrary error', '{#APPNAME}', 'x:\notexist', 'MAINICON', MB_OK)
// Return code test loop
dllname := 'C:\Windows\SysWOW64\shell32.dll'
while true do
begin
ret := MsgBoxEx('icon from'#10+dllname, '{#APPNAME}', dllname, 337, MB_YESNOCANCEL or MB_DEFBUTTON2);
case ret of
IDYES:
ret := MsgBoxEx('YES'#10#10'Continue?', '{#APPNAME}', dllname, 16802, MB_YESNO);
IDNO:
ret := MsgBoxEx('NO'#10#10'Continue?', '{#APPNAME}', dllname, 240, MB_YESNO);
IDCANCEL:
ret := MsgBoxEx('CANCEL'#10#10'Continue?', '{#APPNAME}', dllname, 142, MB_YESNO);
end;
if ret = IDNO then break;
end;
Abort;
end;
#ifndef WinAPI_MessageBoxIndirect__pas
#define WinAPI_MessageBoxIndirect__pas
#include 'WinAPI.pas'
#include 'WinAPILoader.pas'
const
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox
MB_CANCELTRYCONTINUE = $00000006;
MB_ICONERROR = $00000010;
MB_ICONSTOP = MB_ICONERROR;
MB_ICONHAND = MB_ICONERROR;
MB_ICONQUESTION = $00000020;
MB_ICONWARNING = $00000030;
MB_ICONEXCLAMATION = MB_ICONWARNING;
MB_ICONINFORMATION = $00000040;
MB_ICONASTERISK = MB_ICONINFORMATION;
MB_USERICON = $00000080;
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadiconw
IDI_APPLICATION = 32512;
IDI_INFORMATION = 32516;
IDI_ASTERISK = IDI_INFORMATION;
IDI_ERROR = 32513;
IDI_HAND = IDI_ERROR;
IDI_WARNING = 32515;
IDI_EXCLAMATION = IDI_WARNING;
IDI_QUESTION = 32514;
IDI_SHIELD = 32518;
IDTRYAGAIN = 10;
IDCONTINUE = 11;
type
// MSGBOXPARAMSW structure
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msgboxparamsw
// lpszIcon - string type
_WinAPI_tagMSGBOXPARAMS_S = record
cbSize: UINT;
hwndOwner: HWND;
hInstance: HINST;
lpszText: String;
lpszCaption: String;
dwStyle: DWORD;
lpszIcon: String;
dwContextHelpId: DWORD_PTR;
lpfnMsgBoxCallback: Pointer;
dwLanguageId: DWORD;
end;
// lpszIcon - numeric type
_WinAPI_tagMSGBOXPARAMS_N = record
cbSize: UINT;
hwndOwner: HWND;
hInstance: HINST;
lpszText: String;
lpszCaption: String;
dwStyle: DWORD;
lpszIcon: DWORD;
dwContextHelpId: DWORD_PTR;
lpfnMsgBoxCallback: Pointer;
dwLanguageId: DWORD;
end;
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxindirectw
function _WinAPI_MessageBoxIndirect_S(const MsgBoxParams: _WinAPI_tagMSGBOXPARAMS_S): Integer; external 'MessageBoxIndirectW@user32.dll stdcall';
function _WinAPI_MessageBoxIndirect_N(const MsgBoxParams: _WinAPI_tagMSGBOXPARAMS_N): Integer; external 'MessageBoxIndirectW@user32.dll stdcall';
function MsgBoxExNI(
const Text: String;
const Caption: String;
const hInstance: HINST;
const IconNumber: DWORD;
const Flags: DWORD
): Integer;
var
mp: _WinAPI_tagMSGBOXPARAMS_N;
begin
mp.cbSize := SizeOf(mp);
mp.hInstance := hInstance;
mp.lpszText := Text;
mp.lpszCaption := Caption;
if (IconNumber < IDI_APPLICATION) and (hInstance = 0) then
mp.dwStyle := Flags or IconNumber
else
begin
mp.dwStyle := Flags or MB_USERICON;
mp.lpszIcon := IconNumber;
end;
Result := _WinAPI_MessageBoxIndirect_N(mp);
end;
function MsgBoxExSI(
const Text: String;
const Caption: String;
const hInstance: HINST;
const IconName: String;
const Flags: DWORD
): Integer;
var
mp: _WinAPI_tagMSGBOXPARAMS_S;
begin
mp.cbSize := SizeOf(mp);
mp.hInstance := hInstance;
mp.lpszText := Text;
mp.lpszCaption := Caption;
mp.dwStyle := Flags or MB_USERICON;
mp.lpszIcon := IconName;
Result := _WinAPI_MessageBoxIndirect_S(mp);
end;
(* function MsgBoxEx
Text: `Messagebox text`
Caption: `Messagebox caption`
IconSource: 0 -- standard icons: MB_ICON*, IDI_*
: '' -- load icon from INSTALLER_EXE
: 'FILE' -- load icon from FILE
IconID: MB_ICON*, IDI_* -- if IconSource = 0
: <icon name/number> if IconSource = '*'
Flags: MB_OK, MB_OKCANCEL, MB_ABORTRETRYIGNORE, MB_YESNOCANCEL, MB_YESNO,
MB_RETRYCANCEL, MB_CANCELTRYCONTINUE,
MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON3, MB_SETFOREGROUND
Return: IDOK, IDCANCEL, IDABORT, IDRETRY, IDIGNORE, IDYES, IDNO, IDTRYAGAIN, IDCONTINUE
*)
function MsgBoxEx(
const Text: String;
const Caption: String;
const IconSource: Variant;
const IconID: Variant;
const Flags: DWORD
): Integer;
var
hInstance: HINST;
UsedIconID: Variant;
begin
hInstance := 0;
UsedIconID := IconID;
if VarType(IconSource) <> varInteger then
begin
if IconSource = '' then
hInstance := _WinAPI_GetModuleHandle('')
else
hInstance := _WinAPI_LoadLibraryEx(IconSource, 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE);
if hInstance = 0 then
UsedIconID := IDI_APPLICATION // fallback to 'defaulticon'
end;
if VarType(UsedIconID) = varInteger then
Result := MsgBoxExNI(Text, Caption, hInstance, UsedIconID, Flags)
else
Result := MsgBoxExSI(Text, Caption, hInstance, UsedIconID, Flags);
if (hInstance > 0) and (IconSource <> '') then _WinAPI_FreeLibrary(hInstance);
end;
#endif
#ifndef WinAPILoader__pas
#define WinAPILoader__pas
#include 'WinAPI.pas'
const
LOAD_LIBRARY_AS_IMAGE_RESOURCE = $20;
LOAD_LIBRARY_AS_DATAFILE = $2;
// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw
function _WinAPI_LoadLibraryEx(const lpLibFileName: String; const Zero: Integer; const dwFlags: DWORD): HINST; external 'LoadLibraryExW@Kernel32.dll stdcall';
// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-freelibrary
function _WinAPI_FreeLibrary(const hLibModule: HINST): Boolean; external 'FreeLibrary@Kernel32.dll stdcall';
// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlew
function _WinAPI_GetModuleHandle(const ModuleName: String): HINST; external 'GetModuleHandleW@Kernel32.dll stdcall';
#endif
#ifndef WinAPI__pas
#define WinAPI__pas
type
Pointer = Longint;
HINST = THandle;
#endif
Пришлось использовать две разные структуры и функции, т.к. мне непонятно как можно числовое значение преобразовать в LPCWSTR.
Vanadiy777
08-06-2022, 00:26
iglezz,
Пример собрал, прикрутил все подключаемые модули. Все отрабатывает как надо.
Попробовал прикрутить к своему скрипту - отрабатывает окно MsgBoxEx, т.е. выскакивает второе окошко, но, ни заголовок окна, ни значок в окне не отображаются.
При этом все флаги отрабатывают. Т.е., функционал весь и работоспособность сохраняются.
Возможно, возникает конфликт с моим, имеющемся кодом...
Буду разбираться...
iglezz, Вам, от всей души, огромное спасибо за предоставленный материал и примеры!
Vanadiy777
10-06-2022, 15:28
iglezz,
Разобрался в чем у меня была ошибка.
Все получилось и замечательно работает!
ico/icl использовать нельзя. »
Свою icl можно тоже использовать, заменив расширение на dll, у меня в таком варианте тоже заработало.
Еще раз - сердечное спасибо Вам! :Beer:
Vanadiy777,
По .icl я ошибся, давно с ними дела не имел.
В общем, icl - это просто исполняемый файл с ресурсами Icon внутри.
32/64-бит PE-файлы (https://en.wikipedia.org/wiki/Portable_Executable) можно использовать, старинные 16-бит NE-файлы (https://en.wikipedia.org/wiki/New_Executable) -- нельзя.
Переименовывать необязательно.
ЗЫ Свои посты выше обновил с учётом этой информации
iglezz
Есть ли в вашем примере возможность менять размер иконки, например с 32х32 на 48х48 или 64х64
ZVSRus,
Нет, такое не предусмотрено.
iglezz
ОК. Всё понял. А жаль.
Vanadiy777
11-06-2022, 14:53
iglezz,
проверил с .icl не изменяя расширение, тоже все нормально отработало.
icl собирал в ArtIcons.
Спасибо Вам, добрый человек!
Скрипт для двух .exe в одном инсталляторе.
Чтобы можно было выбирать какую программу устанавливать.
Может кто подскажет ?
Vanadiy777
05-07-2022, 22:50
serg5,
[Setup]
AppName=My Prog
AppVerName=My Prog
AppVersion=1.5
DefaultDirName={tmp}
OutputBaseFilename=My Setup
Uninstallable=no
DisableProgramGroupPage=True
DisableDirPage=True
DisableReadyPage=True
DisableReadyMemo=True
DisableFinishedPage=True
ShowLanguageDialog=Auto
[Languages]
Name: EN; MessagesFile: compiler:Default.isl
Name: RU; MessagesFile: compiler:Languages\Russian.isl
[Tasks]
Name: "MyProg1"; Description: "Моя программа 1"; Flags: unchecked;
Name: "MyProg2"; Description: "Моя программа 2"; Flags: unchecked;
[Files]
Source: MyProg1.exe; DestDir: {app}; Flags: ignoreversion; Tasks: MyProg1;
Source: MyProg2.exe; DestDir: {app}; Flags: ignoreversion; Tasks: MyProg2;
[Run]
Filename: "{app}\MyProg1.exe.exe"; Parameters: "Сюда добавляете ключи для установки программы"; Flags: waituntilterminated; Tasks: MyProg1;
Filename: "{app}\MyProg2.exe.exe"; Parameters: "Сюда добавляете ключи для установки программы"; Flags: waituntilterminated; Tasks: MyProg2;
Вот простейший пример: »
Если нужны разные пути для установки ?
В "setup" прописывается только один путь..
Vanadiy777
06-07-2022, 12:16
В "setup" прописывается только один путь.. »
serg5,
ну так правильно, прописана временная папка. Оттуда уже запускается установщик той программы, которую Вы выбрали для установки.
Или не это было нужно?
Скрипт для двух .exe в одном инсталляторе.
Чтобы можно было выбирать какую программу устанавливать. »
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.