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.
Related
In my vb6 project, I created my own msgbox using a form, due to difficulties in changing
the font/language of in-built msgbox. A search with google gave the idea of own msg-
box rather than trying msgbox of VB. Now the problem is : - when the user exits the
program, 3 options are given: to close, to restart and to cancel exit. The user need not
again go through the process of giving password etc in restart option. If I give cancel =
true in the QueryUnload event, then 2nd option does not work, 3rd option works. If
cancel = true is not given, 2nd option works, but 3rd option does not. It appears that
the main form does not get unloaded if cancel = true. Unless & until the main form
unloads, the program will not work with the fresh data to be given by the user in the
initial Form. Since the code after "msgbox.show" depends on options, it is not possible
to write that code in the same sub, not even in the same form code. Is there any way
to stop the subsequent code after "msgbox.show" and continue the same after getting
option? (like in the in-built msgbox of VB.) I am not an expert in VB, so please correct
if I made some mistake; also help with advice/suggestions.
EDIT:- [Extended explanation]
The 3 forms in my project:
Initial form for password, data etc. This is input Form for user.
Main Form. This Form shows the results after process of input.
frmMsgBox. This is a custom msgbox created using a form.
Main Form code portion. Code for closing the program:
Private Sub Form_QueryUnload(Cancel as.......)
cancel = True
frmMsgBox.Label1.caption = Do you wish to 1.Exit 2.Restart
3.Cancel the exit?
frmMsgBox.Show
End sub
(The above msgbox is almost like an in-built msgbox in VB with
vbYesNoCancel buttons) The message is in regional language,
which was the main reason forced me to use my own msgbox.
After MsgBox appears, the user selects one of the above options
using 3 commandButtons placed in that Form. The code after
clicking these buttons is written in the code portion of frmMsgBox:
Command1_Click 'This is for Exit from the Program.
All Forms.unload, All forms set to nothing, end.
Command2_click 'This is for restarting the Program.
Unload Main Form, set to nothing
Load Initial Form
Initial Fom.show
frmMsgBox.Hide
Command3_Click 'This is for cancelling the exit request.
Main Form.Show
frmMsgBox.Hide
With the above code, I have no problem with options 1 & 3,
i.e; to exit from the program or to start. The frmMsgBox hides,
the initial form shows - these are OK, but the main form does
not unload nor it is removed from memory. Because of this,
whatever new data is given by the user in the initial form now
is not being processed, the main form is struck with the old results.
If cancel = true is removed from the code above, Options 1 & 2
are OK, but option 3 does not work. Then the Main Form loses
all its results (all labels, texts etc in that Form turn blank.)
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;
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;
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.
Greetings to you dear colleagues!
Prompt.
I have here a situation - there is a component RadWindows RadButton button on it by pressing a button in the RadGrid RadWindows component is set to Visible = true; But after PostBack and shape RadWindows disappears. But going into the RadWindows everything remains as it was changed to reboot.
Question: How to prevent reload the page.
Who does not know what are the components of Rad Teleric.
The source code can throw if it helps.
Thank you, Regards!
Set DestroyOnClose="true" to prevent the window from reopening after close or postback. It sounds like you may be setting the Visible property to true using server-side code. This is bad practice which leads to issues like you describe. RadWindows should be opened via the client-side methods.
On the server side use this code to open a window from the client side using the RadWindow.Show client-side method while having DestoryOnClose set to true. You can customize the script string should you want to use the RadWindow.Open() method to pass a url to the window.
private void ShowWindow()
{
string script = "function f(){$find(\"" + YourRadWindow.ClientID + "\").show(); Sys.Application.remove_load(f);}Sys.Application.add_load(f);";
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "key", script, true);
}
Consider opening it with JavaScript, this will let you stop using these unnecessary postbacks: http://www.telerik.com/help/aspnet-ajax/window-programming-opening.html.
Use OnClientClicking of the RadButton: http://blogs.telerik.com/aspnet-ajax/posts/12-08-10/migrating-onclientclick-handlers-from-asp-button-to-telerik-s-asp-net-ajax-button.aspx.
You can also use AJAX to prevent full postbacks that will dispose (and thus, hide) the RadWindow: http://www.telerik.com/help/aspnet-ajax/radwindow-ajaxifying.html.
Read this sticky to see how to open it from the server if you need to. If you set VisibleOnPageLoad to true it will re-show after postbacks, so you will only need to take care of setting the property back to false when you need to: http://www.telerik.com/community/forums/aspnet-ajax/window/opening-radwindow-from-the-server.aspx.