How can I restore the default picture of a TImage? - lazarus

When I build my app, I have a pre-loaded TImage showing; the file I assigned to TImage's Picture property.
The user has the choice to load a different external image file with Image.Picture.LoadFromFile, and this works well.
But if I want to restore the pre-loaded image (the one assigned during form design), how do I do this without loading it from a separate file?
I see in the corresponding FORM.LFM file that my pre-loaded image is in
object Image: TImage
...
Picture.Data = { 0A544A7065674... }
However, Picture.Data does not seem to be accessible from my code.
Is there some method to load the original image (built in the EXE file) back?
I tried Image.Picture.LoadFromLazarusResource(...) but not sure what to put as string (tried the filename) or if this is even the right method to call.
Any ideas?

The below solution (a variation of which I tried successfully) was given to me on Lazarus Forum, and I repeat here for completeness:
In the Form's OnCreate event, save the current (design-time) TImage.Picture to a separate TPicture object, and then you can Assign() that back to the TImage.Picture when needed.
private
OriginalPicture: TPicture;
procedure TMyForm.FormCreate(Sender: TObject);
begin
OriginalPicture := TPicture.Create;
OriginalPicture.Assign(Image.Picture);
end;
procedure TMyForm.FormDestroy(Sender: TObject);
begin
OriginalPicture.Free;
end;
procedure TMyForm.RestoreImage;
begin
Image.Picture.Assign(OriginalPicture);
end;

Related

Global TAction with shorcut key BkSp

I have TAction with ShortCut key set to BkSp (backspace). I'm trying implementing Back button like in web browser so I need TAction is called in any control except Edit controls (TMemo, TEdit etc.).
All works as expected, but Backspace key is not sent to Edit controls (so user can't delete char).
OnExecute look's like:
if (Screen.ActiveControl is TCustomMemo) or (Screen.ActiveControl is TCustomEdit) then exit;
DoBack;
Any idea to past BkSp key trought TAction to edit control (fo all platforms Win,Mac,Linux)?
Solution is simple, based on Andreas Rejbrand comment and same as in Delphi.
On OnUpdate for action:
procedure TForm1.aBackUpdate(Sender: TObject);
begin
aBack.Enabled := not (Screen.ActiveControl is TCustomEdit);
end;
And OnExecute for action:
procedure TForm1.aBackExecute(Sender: TObject);
begin
DoBack;
end;

Delphi Application Main Form temporarly flicking to the front

We have a Delphi 2007 application and have recently enabled MainFormOnTaskBar for better support of Windows Aero. However because the main form would not come to the top of all child forms when clicked we added the following code.
procedure TBaseForm.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
Params.WndParent := 0;
end;
One side effect of this is that when pressing an Alt + key hotkey on a child form that does not handle that particular hot key the main form flicks to the front and then back again. If the hot key is handled then this behavior does not occur, probably because the hotkey is swallowed.
Has anyone else experienced this behavior and can advise a workaround.
Thanks
The observed behavior is the result of VCL's accelerator support for a possible main menu on the main form, so that you can select menu items from the main form's menu even when another form is active.
The activation of the main form takes place by a SetFocus call on the main form's handle while the "Application" is handling the CM_APPSYSCOMMAND message which is sent from the WM_SYSCOMMAND handler of a "WinControl" (secondary form) when command type is SC_KEYMENU (window menu activation - Alt key).
Note that this behavior is not a side effect of using MainFormOnTaskBar and then overriding CreateParams to have forms that can be brought to front. The same behavior occurs regardless of the setting of MainFormOnTaskBar. The only difference is that the activated main form cannot come in front of secondary forms when it is set, but the main form is activated all the same.
You can intercept to modify the behavior in a number of places, like a WM_SYSKEYDOWN handler on the secondary form, or in OnKeyDown of the secondary form. Semantically more correct override, IMO, should be done on the IsShortCut of the secondary form. As you have found out, when the secondary form handles a key combination, the processing of the system key terminates. You can, then, tell the VCL that your form requires the key:
type
TSecondaryForm = class(TForm)
..
public
function IsShortCut(var Message: TWMKey): Boolean; override;
...
function TSecondaryForm.IsShortCut(var Message: TWMKey): Boolean;
begin
Result := True;
end;
Of course you can fine tune to conditionally return true depending on the parameter.

TListView event OnSelectItem holds the wrong TListItem instance?

The TListItem returned in OnSelectItem event of the TListView holds the previously selected item instead of the latest (current) one. Is It a bug? Tested in Linux Mint 17.2, Lazarus 1.4.4, FPC 2.6.4
Feed a TListView with some items first...
procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
begin
Form1.Caption := Item.Caption;
end;
I had to use the selected parameter. The event gets called multiple times, with the old item and selected=False, and the actual item with Selected=ON.
When coming from Delphi, it happens.

Assign start button for each file instead of whole queued batch

Most of the Fine Uploader documentation seems to only use a single button to begin uploading ALL files which have been added to the queue. Is there a method which can begin uploading a single file from the queue?
I would like users to be able to add a few files which would be added into a row, and then at the end of each file's row, the user would click a button to begin uploading that individual file.
Any advice would be appreciated. Thanks!
The best solution to your situation is simply to construct multiple Fine Uploader instances: one for each row. At the end of a row, you can have a button that calls the uploadStoredFiles method on the corresponding Fine Uploader instance.

Hide form when application is minimized

I have a main form and a status form that I display when work is going on in my application. If the work is finished I just call Hide on the status form and the status form disappears.
My problem occurs when I minimize the main form whilst the wait form is visible. Then both forms are hidden which is what I want. However, if the work finishes whilst the main form is minimized then when I restore it, the status form is also restored, even though Hide has been called on it whilst minimized.
Visible seems to be False for the status form when the application is minimized and therefore calling Hide seems to have no effect (the help says it just sets Visible to False).
Are that observations correct? How is the form visibility restored when the application gets focus again? How can I hide my form while the application is minimized?
Visible of the display form is indeed false and calling Hide does nothing when the application is minimized, because it is hidden by the application as part of the minimization mechanism.
Code calls ShowOwnedPopups with first 'False' as 'bShow' while the application is minimizing, and then with 'True' as 'bShow' while the application is restoring. Since the function shows all windows which was hidden by a previous call, changing visibility of a form
in between has no effect.
Now, see this quote from the remarks section of the documentation of the function,
if a pop-up window is hidden by using
the ShowWindow function, subsequently
calling ShowOwnedPopups with the fShow
parameter set to TRUE does not cause
the window to be shown
So, one solution can be to hide the form before the application hides it, so it won't get shown while restoring. But then we have to know if the display form is actually to be hidden or shown when we restore. This can be achieved by putting a property on the display form or with a global variable perhaps. In the below, 'ShouldBeVisible' is a hypothetical property that would return true if we are to display information:
type
TForm1 = class(TForm)
..
private
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
...
procedure TForm1.WMSysCommand(var Msg: TWMSysCommand);
begin
if (Msg.CmdType = SC_MINIMIZE) and Assigned(Form2) and Form2.Visible then
Form2.Hide;
inherited;
if (Msg.CmdType = SC_RESTORE) and Assigned(Form2) and Form2.ShouldBeVisible then
Form2.Show;
end;
I now use the following solution which works for me:
In Application.OnRestore restore event handler I call StatusForm.NotifyRestored. Status form is explicitly hidden if it should not be visible.
In my status form I keep track of visibility in a boolean field FShouldDisplay. This is set in methods ShowStatusForm and HideStatusForm.
procedure TMainForm.OnApplicationRestore(Sender : TObject);
begin
StatusForm.NotifyRestored;
end;
procedure TStatusForm.NotifyRestored;
begin
if not FShouldDisplay then
ShowWindow(Handle, SW_HIDE);
end;
procedure TStatusForm.ShowStatusForm;
begin
FShouldDisplay := True;
Show;
end;
procedure TStatusForm.HideStatusForm;
begin
FShouldDisplay := False;
Hide;
end;
Warning: I am not 100 % sure that the following approach is safe.
If you don't need the same form object to be alive for the duration of the application's life (which you most likely do not), then you could try to disable the automatic creation of the popup form (Project/Options) and then create and show it by
Application.CreateForm(TForm2, Form2);
Form2.Show;
and then free it by
Form2.Release;
This way the form cannot possibly be restored together with the main form.

Resources