Setup Programs created using Inno Setup Compiler doesn't display Minimize Animation - inno-setup

My Problem is why Inno Setup Compiler (Unicode or ANSI) and any Setups made by it don't minimize showing a nice Minimizing Animation like in Other Windows Programs?
It displays a very basic Minimize Animation..........Why that?
I know Borland Delphi as Inno Setup Compiler's Compiler, but Borland Delphi doesn't have such a bad Minimize Animation...........It minimizes normally as Windows System Windows minimize (such as Explorer, Computer, Control Panel).................
I also noticed that the Windows Installer Creater Nullsoft Scriptable Install System - NSIS and Setups made using it are also minimizing well like I said.
How can I resolve this problem?
UPDATED QUESTION
I also added a code to play that nice Zooming Minimize / Restore Animation can be seen in Many Windows Applications on Inno Setup's WizardForm, But when I click the WizardForm's Minimize Button after adding this code to Inno Setup Compiler's Source Code, the Nice Zooming animation not plays and it never can be minimized using it, it only can be minimized using Taskbar button after adding this code. So it means this code not working or anything else wrong...........Why this is not working???
The Code I Added to unit WizardForm:
interface
uses
Windows;
type
TTrayZoom = class(TObject)
private
class function GetTrayRect: TRect;
class procedure DoZoom(const Wnd: HWND; const Src, Dest: TRect);
public
class procedure ZoomToTray(const Wnd: HWND);
class procedure ZoomFromTray(const Wnd: HWND);
end;
implementation
class procedure TTrayZoom.DoZoom(const Wnd: HWND; const Src, Dest: TRect);
begin
DrawAnimatedRects(Wnd, IDANI_CAPTION, Src, Dest);
end;
class function TTrayZoom.GetTrayRect: TRect;
var
TaskbarWnd, TrayWnd: HWND;
begin
TaskbarWnd := FindWindow('Shell_TrayWnd', nil);
TrayWnd := FindWindowEx(TaskbarWnd, 0, 'TrayNotifyWnd', nil);
GetWindowRect(TrayWnd, Result);
end;
class procedure TTrayZoom.ZoomFromTray(const Wnd: HWND);
var
WndRect: TRect;
begin
GetWindowRect(Wnd, WndRect);
DoZoom(Wnd, GetTrayRect, WndRect);
end;
class procedure TTrayZoom.ZoomToTray(const Wnd: HWND);
var
WndRect: TRect;
begin
GetWindowRect(Wnd, WndRect);
DoZoom(Wnd, WndRect, GetTrayRect);
end;
And I called TTrayZoom.ZoomToTray from if WMSysCommand..... = SCMINIMIZE and called TTrayZoom.ZoomFromTray from if WMSysCommand..... = SCRESTORE with the setting HWND parameter to WizardForm.Handle.
But those codes never works, I even don't know if they're get called or not. :(
What is the problem playing this Zooming Animation in this WizardForm?

I'd say there are two issues.
The animation is shown for windows that have a task bar button. The wizard form does not have a task bar button.
The task bar button of the installer belongs to a hidden main window.
Historically the installers had full screen background gradient blue windows. Even Inno Setup supported that.
While that background window is no longer enabled by default (the WindowVisible directive defaults to No in modern versions of Inno Setup), it still exists and owns the task bar button.
Inno Setup is built using an ancient version of Delphi that likely does not play nicely with the minimize feature.
Generally, I'd say you should file a feature request/bug report to get this fixed.

Related

Loading resources at design time?

Is it possible to load a resource at design time?
I am making a speed button component, and I want to automatically load a new image from the resource whenever the button size changes. It already works properly at run time, but at design time, after I set the resource name property, it does not show any icon.
I can draw a default rectangle in place of the icon if it is not possible, but it would have been nice to display my icons at design time as well.
function TPngSpeedButton.LoadIcon(ResName: String): Boolean;
var hI: HICON;
Ico: TIcon;
ISize: Integer;
Png: TPngImage;
begin
Result:= False;
if ResName = '' then Exit;
ISize:= Height - 7 - Round(Height * 0.15);
Png:= TPngImage.Create; Ico:= TIcon.Create;
try
if LoadIconWithScaleDown(HInstance, PChar(ResName), ISize, ISize, hI) = S_OK then begin
Ico.Handle:= hI;
ConvertToPng(Ico, Png);
SetPngImage(Png);
Result:= True;
end;
finally
Png.Free; Ico.Free;
end;
end;
You can not load icons at design-time from your application resource, since at that time the application executable doesn't even exist as you haven't compiled it yet.
Now, what you might be able to do is create a resource-based dynamic link library (resource DLL) which you compile separately. This way, you would be able to access the DLL resources even at design-time, similar to how the Delphi IDE is already accessing some system resources.
If you don't want to deal with additional DLLs, then put your icons into one or more ImageLists, since images from ImageLists are available both at run-time as well at design-time.

How to know console background and text colors?

* NOT A DUPLICATE * as it refers to C++ and Windows only.
(Currently for Windows, but a solution also for Linux is preferred.)
I have an application that uses TextColor and/or TextBackground to highlight some text. Because a user may alter the console defaults, I would like to be able to read those colors so I can adjust the color of my highlights to not blend with the user's colors.
For example, if the user has selected yellow text, I don't want my highlight to also be yellow, or if the user's background is red I don't want the highlight to be red and disappear.
I checked the RTL.PDF and couldn't find anything. But that manual is really long (2K+ pages), and I may have missed it.
My question: Are there equivalent functions to TextColor and TextBackground that instead of setting the colors, return the currently set values? (Or, if not specific functions, maybe some other method like getting all console parameters that also contains this color information.)
UPDATE:
After being 'pushed' to deal with C++, and go study the Windows API, I went and did all that :)
Luckily, I found an unrelated FreePascal example of a console Windows API call in the Lazarus forum, and putting all this together, I came up with this which I post as I'm sure it will be useful to others:
{$mode fpc}
Unit Console;
Interface
uses Windows, SysUtils;
function GetTextColor: Byte;
function GetTextBackground: Byte;
Implementation
////////////////////////////////////////////////////////////////////////////////
function GetColors: Byte;
var
vHandle :THandle;
vScreenBufInfo :TConsoleScreenBufferInfo;
begin
vHandle := GetStdHandle(STD_OUTPUT_HANDLE);
if vHandle = INVALID_HANDLE_VALUE then RaiseLastOSError;
GetConsoleScreenBufferInfo(vHandle,vScreenBufInfo);
GetColors := vScreenBufInfo.wAttributes;
end;
////////////////////////////////////////////////////////////////////////////////
function GetTextColor: Byte;
begin
GetTextColor := GetColors and $0F;
end;
////////////////////////////////////////////////////////////////////////////////
function GetTextBackground: Byte;
begin
GetTextBackground := GetColors shr 4 and $0F;
end;
////////////////////////////////////////////////////////////////////////////////
begin
//Writeln('TextColor : ',GetTextColor);
//Writeln('BackgroundColor: ',GetTextBackground);
end.
I'm still looking for a Linux solution, however. Anyone?

Why do I need Sharemem in my Delphi dll which only exposes a function with WideString parameters?

I have a dll and a test application written in Delphi. The test application uses multiple threads to call the function exported by the dll. The exported function has a trivial thread safe implementation. When running the test application various errors (access violation, invalid pointer operation, stack overflow etc) happens or the application freezes. In some cases the application finishes without errors.
Note that these errors only happen (surface) when using multiple threads. When calling the function from the main thread only then everything works fine.
I have found that adding ShareMem to both the dll and the application stops all these kind of errors. But I don't understand why. To my knowledge ShareMem is only needed when passing long strings between the dll and the application. As far as I know WideString is not a long string.
Also according to this post ShareMem should not be required:
Why can Delphi DLLs use WideString without using ShareMem?
Here is the source of the dll:
library External;
uses
Winapi.Windows;
type
TMyType = class
private
FText: string;
end;
function DoSomething(input: WideString; out output: WideString): Bool; stdcall;
var
x: TObject;
begin
x := TMyType.Create;
try
output := x.ClassName;
finally
x.Free;
end;
Result := True;
end;
exports
DoSomething;
begin
end.
Here is the test application:
program ConsoleTest;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
Winapi.Windows,
OtlParallel;
function DoSomething(input: WideString; out output: WideString): Bool; stdcall; external 'External.dll' name 'DoSomething';
var
sResult: WideString;
begin
try
Parallel.&For(0, 500).Execute(procedure(value: Integer)
var
sResult: WideString;
begin
DoSomething('hhh', sResult);
end);
WriteLn('Done');
ReadLn;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Why ShareMem makes the bugs go away and is there another way to fix these bugs?
I am using Delphi XE2 and OmniThread 3.07.5.
Update
- Same issue when run from a VCL application's button's on click event handler
- If DoSomething uses a critical section inside then runs fine
- If FText field is removed from TMyClass then no errors are reported but the application randomly freezes
For the standard memory manager (FastMM) to support multi threading, you need to set the IsMultiThread flag.
When you use RTL for threading, this flag is automatically set. As revealed in the comments to the question, OTL also use RTL to start its threads. So the memory manager in your executable is aware of threading, but the distinct memory manager in the dll causes errors. When you use "sharemem", there is only one memory manager which is aware of threading because of OTL, so you encounter no errors.
An alternative solution, apart from using a shared memory manager, would be to set the flag also for the memory manager in the dll.

Inno Setup: Modify icon and title of specific error message

I have a program that should only be installed on 64-bit architectures. So I added:
ArchitecturesAllowed = x64
In my Inno Setup file to prevent this.
The problem is that the message displayed is a bit too "violent". It displays "error" in title and a big red cross.
I've found that I can change content of this message (with OnlyOnTheseArchitectures message), but no way to modify icon and title without impacting other error message.
And I do not see what step can match...
Is there a way to make it like an information box?
There's no generic way to modify any standard Inno Setup message box.
You generally have to re-implement the function on your own. What is not always possible.
For your specific case, you are lucky, as you can easily implement your own custom check for 64-bit system using the IsWin64 function from the InitializeSetup event function.
And display your own custom message box using the MsgBox function.
function InitializeSetup(): Boolean;
begin
Result := True;
if not IsWin64 then
begin
MsgBox('This cannot be installed on 32-bit system.', mbInformation, MB_OK);
Result := False;
end;
end;

Delphi IDE hangs when I create a thread

I have a problem that Delphi (2010) IDE and the program both hang during debugging when I run a thread.
Both windows do not respond. When I kill the program, IDE works again.
It took time, I had to delete pieces of my program and I found the problem.
It is caused by VirtualStringTree.
So if I put just empty VirtualStringTree (v. 5.5.3) on form, one button to execute TThread with just "Sleep(2000)" in Execute procedure and run such program under debugger, it hangs (usually at first click). When I remove the VST, it works.
I have also noticed that Windows Reporting Service is started but I haven't found anything in the Windows event log.
Does anyone have any idea how this is possible?
Full source here
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, VirtualTrees, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
VirtualStringTree1: TVirtualStringTree;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
TTestThread = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TTestThread }
procedure TTestThread.Execute;
begin
FreeOnTerminate:=True;
Sleep(2000);
end;
{ TForm }
procedure TForm1.Button1Click(Sender: TObject);
begin
TTestThread.Create(False);
end;
end.
EDIT:
I have also tried to debug Delphi process. I attached from second to first IDE. When I click the button to start the thread, both IDEs hang. So I have tried with Delphi 7 which I also have installed. That worked. It stays in a loop somewhere in ntdll.NtWaitForMultipleObjects, KERNELBASE.WaitForMultipleObjectsEx, USER32.MsgWaitForMultipleObjects.
I have completely reinstalled Delphi, no change. It may also be related to this line in VirtualStringTree source: "WaitForSingleObject(WorkEvent, INFINITE);". When I remove it, it does not freeze. But I think it is necessary there.
Finally I installed Delphi XE and that works correctly. It is mysterious.
TTestThread is a descendant of TThread in your code but it still needs a variable declaration and a proper constructor call.
var
MyThread: TTestThread;
The proper call to instantiate it would be
MyThread := TTestThread.Create(False);
rather than trying to invoke the constructor as you have in the button click event.
Good luck and have fun.
RP

Resources