Why won't the BitmapImage for WizardStyle=modern resize in Inno Setup? [duplicate] - resize

Bitmap for Inno Setup WizardImageFile (and WizardSmallImageFile) looks terrible because when Windows 7 has the large system fonts enabled, the Wizard is bigger than usual, but the images are scaled terrible wrong.
Is there a fix?
There is no similar issue if I add own picture somewhere like this:
BitmapImage1.AutoSize := True;
BitmapImage1.Align := alClient;
BitmapImage1.Left := 0;
BitmapImage1.Top := 0;
BitmapImage1.stretch := True;
BitmapImage1.Parent := Splash;

These are bitmap images, they naturally scale badly. You are just lucky that your own images do not look that bad when scaled.
You have to prepare your own set of images for common scaling factors.
Common scaling factors used nowadays are 100%, 125%, 150% and 200%. So you should have four sizes for the images, like:
WizardImage 100.bmp
WizardImage 125.bmp
WizardImage 150.bmp
WizardImage 200.bmp
WizardSmallImage 100.bmp
WizardSmallImage 125.bmp
WizardSmallImage 150.bmp
WizardSmallImage 200.bmp
Inno Setup can automatically select the best version of the image since 5.6.
Just list your versions of the images in the WizardImageFile and WizardSmallImageFile. You can use wildcards:
[Setup]
WizardImageFile=WizardImage *.bmp
WizardImageFile=WizardSmallImage *.bmp
On older versions of Inno Setup (or if your need to customize the selection algorithm or when you have additional custom images in the wizard), you would have to select the images programatically.
The following example does more or less the same what Inno Setup 5.6:
[Setup]
; Use 100% images by default
WizardImageFile=WizardImage 100.bmp
WizardSmallImageFile=WizardSmallImage 100.bmp
[Files]
; Embed all other sizes to the installer
Source: "WizardImage *.bmp"; Excludes: "* 100.bmp"; Flags: dontcopy
Source: "WizardSmallImage *.bmp"; Excludes: "* 100.bmp"; Flags: dontcopy
[Code]
function GetScalingFactor: Integer;
begin
if WizardForm.Font.PixelsPerInch >= 192 then Result := 200
else
if WizardForm.Font.PixelsPerInch >= 144 then Result := 150
else
if WizardForm.Font.PixelsPerInch >= 120 then Result := 125
else Result := 100;
end;
procedure LoadEmbededScaledImage(Image: TBitmapImage; NameBase: string);
var
Name: String;
FileName: String;
begin
Name := Format('%s %d.bmp', [NameBase, GetScalingFactor]);
ExtractTemporaryFile(Name);
FileName := ExpandConstant('{tmp}\' + Name);
Image.Bitmap.LoadFromFile(FileName);
DeleteFile(FileName);
end;
procedure InitializeWizard;
begin
{ If using larger scaling, load the correct size of images }
if GetScalingFactor > 100 then
begin
LoadEmbededScaledImage(WizardForm.WizardBitmapImage, 'WizardImage');
LoadEmbededScaledImage(WizardForm.WizardBitmapImage2, 'WizardImage');
LoadEmbededScaledImage(WizardForm.WizardSmallBitmapImage, 'WizardSmallImage');
end;
end;
You might want to do the same for the SelectDirBitmapImage, the SelectGroupBitmapImage and the PreparingErrorBitmapImage.
See also:
How to detect and "fix" DPI settings with Inno Setup?
Inno Setup Placing image/control on custom page

Related

Notification and indication - BLE, Glucose service

I'm trying to get glucose measurements from glucose device (Contour One Plus) with Bluetooth LE, using the TBluetoothLE component in Delphi. I can:
- connect to device
- discover GATT services
- discover GATT characteristics
and now Im trying to set notification for Glucose Measurement Characteristic and indication to Record Access Control Point Characteristic.
I wrote two procedures for enabling:
notification for Glucose Measurement:
procedure TForm6.enableGlucoseMeasurementNotification(
const ACharacteristic: TBluetoothGattCharacteristic);
var
ADescriptor: TBluetoothGattDescriptor;
AValues : TBytes;
begin
BluetoothLE1.DiscoveredDevices[0].SetCharacteristicNotification(FGlucoseMeasurementGattCharact, true);
ADescriptor := FGlucoseMeasurementGattCharact.Descriptors[0]; // czy aby na pewno [0]... ?
SetLength(AValues, 2);
AValues[0] := $01;
AValues[1] := $00;
ADescriptor.SetValue(AValues);
BluetoothLE1.DiscoveredDevices[0].WriteDescriptor(ADescriptor);
end;
indication for Record Access Control Point:
procedure TForm6.enableRecordAccessControlPointIndication(
const ACharacteristic: TBluetoothGattCharacteristic);
var
ADescriptor: TBluetoothGattDescriptor;
AValues: TBytes;
begin
BluetoothLE1.DiscoveredDevices[0].SetCharacteristicNotification(FRecordAccessControlPoint, true);
ADescriptor := FRecordAccessControlPoint.Descriptors[0];
SetLength(AValues, 2);
AValues[0] := $02;
AValues[1] := $00;
ADescriptor.SetValue(AValues);
BluetoothLE1.DiscoveredDevices[0].WriteDescriptor(ADescriptor);
end;
I am based on nRF Connect but I dont understand few things.
My question is, where I should run these two procedures? In OnServicesDiscovered?
Are my procedures correct?
And what is the next step to get values from RACP? I should just write byte value (for example 0x01) to RACP?

Delphi 10.2: Using Local SQL with Firedac Memory Tables

How can I use Firedac LocalSQL with FDMemtable? Is there any working example available?
According to the Embarcadero DocWiki I set up a local connection (using SQLite driver), a LocalSQL component and connected some Firedac memory tables to it. Then I connected a FDQuery and try to query the memory tables. But the query always returns "table xyz not known" even if I set an explicit dataset name for the memory table in the localSQL dataset collection.
I suspect that I miss something fundamental that is not contained in the Embarcadero docs. If anyone has ever got this up and running I would be grateful for some tips.
Here is some code I wrote for an answer here a while ago, which is a self-contained example of using LocalSQL, tested in D10.2 (Seattle). It should suffice to get you going. Istr that the key to getting it working was a comment somewhere in the EMBA docs that FD's LocalSQL is based on Sqlite, as you've noted.
procedure TForm3.CopyData2;
begin
DataSource2.DataSet := FDQuery1;
FDConnection1.DriverName := 'SQLite';
FDConnection1.Connected := True;
FDLocalSQL1.Connection := FDConnection1;
FDLocalSQL1.DataSets.Add(FDMemTable1);
FDLocalSQL1.Active := True;
FDQuery1.SQL.Text := 'select * from FDMemTable1 order by ID limit 5';
FDQuery1.Active := True;
FDMemTable1.Close;
FDMemTable1.Data := FDQuery1.Data;
end;
procedure TForm3.FormCreate(Sender: TObject);
var
i : integer;
MS : TMemoryStream;
begin
FDMemTable1.CreateDataSet;
for i := 1 to 10 do
FDMemTable1.InsertRecord([i, 'Row:' + IntToStr(i), 10000 - i]);
FDMemTable1.First;
// Following is to try to reproduce problem loading from stream
// noted by the OP, but works fine
MS := TMemoryStream.Create;
try
FDMemTable1.SaveToStream(MS, sfBinary);
MS.Position := 0;
FDMemTable1.LoadFromStream(MS, sfBinary);
finally
MS.Free;
end;
end;
As you can see, you can refer in the SQL to an existing FireDAC dataset simply by using its component name.

Is it possible to use adodb stream for large files using pre-allocated chunks?

I'm currently using comobject adodb.stream to grab very large files (multiple gb) from archive.org as an authenticated user and consequently receiving an out of memory error at allocation time. Is there a way to use adodb.stream to set the chunk size and append/concatenate to the output file?
Alternative solutions are welcome.
Here I am using AHKscript:
file_save_location := save
Overwrite := True
get_site := "https://archive.org/download/file.zip" ;;multi-gb file
post_site :="https://archive.org/account/login.php"
post_data :="username=" username_str "&password=" password_str "&remember=CHECKED&referer=https://archive.org&action=login&submit=Log in"
WebRequest := ComObjCreate( "WinHttp.WinHttpRequest.5.1" )
WebRequest.Open("POST", post_site)
WebRequest.SetRequestHeader("Content-Type", "application / zip, application / octet - stream""application / zip, application / octet - stream")
WebRequest.SetRequestHeader("Cookie", "test-cookie=1")
WebRequest.SetRequestHeader("Accept-Encoding","gzip,deflate,sdch")
WebRequest.Send(post_data)
WebRequest.Open("HEAD",get_site)
WebRequest.Send()
WebRequest.Open("GET",get_site)
WebRequest.Send()
ADODBObj := ComObjCreate( "ADODB.Stream" )
ADODBObj.Type := 1
ADODBObj.Open()
;;ADODBObj.Position := 0 ;;getting warm
ADODBObj.Write( WebRequest.ResponseBody )
ADODBObj.SaveToFile(file_save_location, Overwrite ? 2:1)
ADODBObj.Close()
ADODBObj:=""
WebRequest:=""

Go agouti testing fill textarea with PhantomJS perfomance issue

I am using agouti with gomega and ginkgo in Go to test an upload form of our application consisting of an textarea which we fill.
This Code works fine for 1500 rows:
upload_externalData := page.Find("#upload_externalData")
buf := bytes.NewBuffer(nil)
f, err := os.Open("./files/external.log")
io.Copy(buf, f)
externalData := string(buf.Bytes())
Expect(upload_externalData.Fill(string(externalData))).Should(Succeed())
When increasing the imported data to the normal 25000 rows, PhantomJS blocks one CPU Core at 100% and nothing else happens.
Is there a way to achieve this?

Is it possible to set user defined session/connection flag for use in trigger?

Consider a trigger that sets an id-column to an Oracle-sequence (next-)value on-insert. Now I want to extend it with some extra debugging actions. But they should be only active for certain connection/sessions (i.e. debugging ones).
Pseudo-Code on client side:
Open connection to oracle database
set mydebugflag=yes for that connection only
insert some stuff
close connection
Pseudo-Code on server-side (inside the trigger):
set id = someseq.next_val
if mydebugflag=yes then { do_some_extra_sanity_checks(); diagnostics();}
else: finished
How to implement such logic for an Oracle database?
Which Oracle features should I use for this?
There are a couple of ways to do this.
One is to create a package, create a package global variable (which will have session scope) in the package, and then have your client set the package variable and your trigger read it. Something like
CREATE OR REPLACE PACKAGE pkg_debug_mode
AS
PROCEDURE set_debug_mode( p_debug_mode IN NUMBER );
FUNCTION get_debug_mode
RETURN NUMBER;
DEBUG_MODE_ON constant number := 1;
DEBUG_MODE_OFF constant number := 2;
END;
CREATE OR REPLACE PACKAGE BODY pkg_debug_mode
AS
g_debug_mode NUMBER := DEBUG_MODE_ON;
PROCEDURE set_debug_mode( p_debug_mode IN NUMBER )
AS
BEGIN
g_debug_mode := p_debug_mode;
END;
FUNCTION get_debug_mode
RETURN NUMBER
IS
BEGIN
RETURN g_debug_mode;
END;
END;
The client calls pkg_debug_mode.set_debug_mode to set the debug mode and the trigger calls pkg_debug_mode.get_debug_mode to determine the current debug mode for the session.
create or replace context my_ctx using pkg_debug_mode;
CREATE OR REPLACE PACKAGE BODY pkg_debug_mode
AS
PROCEDURE set_debug_mode( p_debug_mode IN NUMBER )
AS
BEGIN
dbms_session.set_context( 'MY_CTX', 'DEBUG_MODE', p_debug_mode );
END;
FUNCTION get_debug_mode
RETURN NUMBER
IS
BEGIN
RETURN SYS_CONTEXT( 'MY_CTX', 'DEBUG_MODE' );
END;
END;
Your trigger can either call the get_debug_mode function or it can directly reference the context by putting the SYS_CONTEXT call in the trigger.