I like to introduce a crash in Delphi7 Application. I like to do this to experiment the crash dump and getting to the same where I introduced the faulty code.
Below is the code which run when a button is clicked on the Form:
procedure TForm1.Button1Click(Sender: TObject);
var
x : Integer;
y : Integer;
begin
//Try Crashing the WebLink Dll (For a Reserach)
x:=0;
y:=0;
y:= x div y;
end;
end.
When I execute the above code in debugger or double clicking the exe, I am getting the below message. But, application is not crashing. Mean, after clicking OK to the dialog, I can click the 'button 1' once again. I do not have any exception handling code. But, how process is not removed from Operating System? What is code I have to write in delphi-7 so that the application will terminate after displaying the crash message
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I managed to hide my winforms application taskbar button using
ShowWindow(GetParent(Form1.Handle),SW_HIDE);
This i call on timer 1 second after the form is created. The taskbar button remain hidden through out the application usage, but until I click a button on the form to show another form, with the Form1 as the owner.
I try to use the same code to hide the second form but not able to work.
Edit: Adding more codes:
Codes in Form1:
// this fires every 1 second and works well.
procedure TForm1.scanTimerTimer(Sender: TObject);
begin
ShowWindow(GetParent(Form1.Handle),SW_HIDE);
end;
// when a user press Settings button on the Form1
// I open another form.
procedure TForm1.SettingsBtnClick(Sender: TObject);
var
settings: TSettingsForm;
begin
settings := TSettingsForm.Create(Form1);
settings.Show;
end;
Codes in SettingsForm
// this fires every 1 second and DOESNT WORK!
procedure TSettingsForm.scanTimerTimer(Sender: TObject);
begin
ShowWindow(GetParent(SettingsForm.Handle),SW_HIDE);
end;
That's all there is for the codes. So when I open SettingsForm, immediately the taskbar button reappears and never disappears anymore. I want taskbar to remain hidden no matter how many other forms I open from the main form.
I tried a "OS specific API" for windows which is
ShowWindow(GetParent(Form1.Handle),SW_HIDE);
Which works after FormCreate, but after the main window opens a secondary window,
the taskbar button reappears. So if your app just have one window, you can use this. But for multiple windows/forms app, it will not work!
Also I tried Non OS Specific API:
SettingsForm.ShowInTaskBar := stNever;
Tried putting this in FormCreate, and also just before Show in Caller form, but still it doesn't work. The taskbar button still appears.
Finally I found in lazarus forum the answer using a OS Specific API:
You need to add 2 imports:
InterfaceBase, Win32Int
And put this is FormCreate:
procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
EXStyle: Long;
AppHandle: THandle;
begin
AppHandle := TWin32WidgetSet(WidgetSet).AppHandle;
EXStyle:= GetWindowLong(AppHandle, GWL_EXSTYLE);
SetWindowLong(AppHandle, GWL_EXSTYLE, EXStyle or WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW);
end;
I've built a custom control that I'm trying to send input to. It will accept mouse input and report MouseDown, MouseMove and MouseUp correctly, but for whatever reason, it won't accept keyboard input. When I click on it, it doesn't receive focus, and any keys I press get interpreted by whatever control had the focus already.
This is probably something really simple. The first place I thought to look was in the ControlStyle property, but the only thing I can see in the helpfile about keyboard input is csNoStdEvents, which disables it, and my control doesn't have that. So what do I need to do to make it so my control can receive input focus?
A few things to try:
On MouseDown, call Windows.SetFocus(Handle). In my experience, the WinAPI function SetFocus often works better than the VCL's SetFocus method.
In response to the WM_GETDLGCODE message, reply with Message.Result := Message.Result or DLGC_WANTCHARS or DLGC_WANTARROWS or DLGC_WANTTAB or DLGC_WANTALLKEYS;
Could it be as simple as calling SetFocus on mouse down?
procedure TYourCustomControl.MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer);
begin
inherited;
if CanFocus then
SetFocus;
end;
Do you have WS_TABSTOP set? You don't have input focus without that, I believe. But this is based on a recollection from nearly 10 years ago, when I was writing my own syntax-highlighting code editor, for which I have long since lost the source.
{TWinControl.}TabStop := True; ought to do. A quick test app with a do-nothing component derived from TWinControl and displaying a dialog for key events seems to show that it makes all the difference.
I've checked the code for my control and I can't see anything that might stop this working. Are you calling "inherited" in the Create procedure?
I do handle the following, but nothing special:
procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
Is the keystroke available at form level? That is, is KeyPreview turned on, and can you see the keystroke in the form's OnKeypress event? You can follow it from there in the debugger. Is the control (as Dan indicated) suitable for keyboard input? For instance, a TLabel, although it displays text, is a graphical control.
My application has an option for the users to run it only in the system tray, and not in the task bar. This worked fine when my application was built by Delphi 6. After switching to Delphi XE2 it no longer functions.
I've messed with it some, and I have this working for Windows 7, but when running on Windows XP I still have a problem. The application correctly hides from the task bar, and shows in the system tray. But when I create and show any additional form, the icon shows up in Windows XP.
procedure TfrmAppointment.HideWindowFromTaskbar;
var
TaskbarList: ITaskbarList;
begin
Application.MainFormOnTaskBar := False;
// Windows 7 seems to behave differently. This seems to fix it.
if (CheckWin32Version(6, 1)) then
begin
// We are in Win7, and we requested the tray.
TaskbarList := CreateComObject(CLSID_TaskbarList) as ITaskbarList;
TaskbarList.HrInit;
TaskbarList.DeleteTab(Application.Handle);
end
else
begin
// Previous code from D6 days
ShowWindow(Application.Handle, SW_HIDE);
SetWindowLong(Application.Handle, GWL_EXSTYLE, GetWindowLong(Application.Handle, GWL_EXSTYLE) or WS_EX_TOOLWINDOW);
ShowWindow(Application.Handle, SW_SHOWNOACTIVATE);
end;
end;
That code is ran if the user chooses the option to show the application in the system tray. It works fine on all versions of Windows I've tested on. On Windows XP, however, when I show any child form, the application instantly shows up in the taskbar. In Windows 7 all is fine.
Any ideas what I'm missing?
I should add that I know this is likely the same question as Hide the Main Form in a Delphi 2009 Application, however I already have the MainFormOnTaskBar being set, so that answer does not seem to apply.
[EDIT:] To be more specific, I'm adding additional information here. This application has two modes: Show in task bar, and show in system tray.
The first mode is the same as any normal application. The application exists only in the task bar. It minimizes to the task bar. It restores from the task bar.
The second mode behaves exactly the same, BUT that task bar icon instead exists in the system tray only. So, when a user minimizes the application, I intercept that message, grab the TRect for 'Shell_TrayWnd'/'TrayNotifyWnd', and call DrawAnimatedRects() to simulate the minimize to the tray. Then I hide the main form. On message from the system tray I draw the same animation rects in reverse, and make it visible again. While the form is visible it does not show in the task bar.
This all works perfectly fine in all Windows versions.
The specific issue I am having is that when any other form gets shown, Windows XP is creating the application icon in the task bar. Windows 7 does not do this. So if a Windows XP user only uses the application main form, no problems arise and both viewing modes work fine. If they open another window, the application icon appears, and stays there even after that window closes. Windows 7 does not do this, and the icon stays gone.
You should set
Application.MainFormOnTaskBar := True;
in your .dpr file and then never modify that setting.
Then, when you want to remove the main form from the taskbar you simply write
MainForm.Hide;
When you need to bring the main form out of hiding again write
MainForm.Show;
And that's it.
Naturally you'll want to show and hide your notification area icon in concert with hiding and showing the main form.
The code in HideWindowFromTaskbar is not necessary and you should remove it. When you application is in MainFormOnTaskBar equals True mode, the main form is an un-owned top-level window. And so it appears on the taskbar whenever it is visible. So you can remove the main form from the taskbar simply my hiding it.
The other forms in your application will be owned top-level windows. Typically they will be owned by your main form. By virtue of being owner, they will not appear on the taskbar.
By and large you should try hard to avoid fiddling with window styles. You can usually make your application behave the way you need without doing so. What's more, if ever you have to adjust window styles, you must do it in CreateParams. That way the window style will persist when the window gets re-created. But I re-iterate, avoid modifying window styles where you can.
The key MSDN references are:
Window Features.
The Taskbar.
Here's the smallest program I can produce that proves the point:
program MainFormHiding;
uses
Forms, StdCtrls;
var
MainForm, OtherForm: TForm;
Button: TButton;
type
TEventHandlerClass = class
class procedure ToggleMainFormVisible(Sender: TObject);
end;
class procedure TEventHandlerClass.ToggleMainFormVisible(Sender: TObject);
begin
MainForm.Visible := not MainForm.Visible;
end;
begin
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm, MainForm);
OtherForm := TForm.Create(Application);
MainForm.Caption := 'Main Form';
OtherForm.Visible := True;
OtherForm.Caption := 'Other Form';
Button := TButton.Create(OtherForm);
Button.Caption := 'Toggle';
Button.Parent := OtherForm;
Button.OnClick := TEventHandlerClass.ToggleMainFormVisible;
Application.Run;
end.
In the comments you make it clear that you want to be able to hide the taskbar window without hiding the main form. In that case I suggest that you set MainFormOnTaskbar to False. That will mean that Application.Handle will be the window associated with the taskbar button. You can then hide that window to remove it from the taskbar.
You will now need to explicitly set PopupParent for any auxiliary forms. If you want those windows to be owned by the main form, then you can set it up.
Here's my example adjusted for this scenario:
program MainFormHiding;
uses
Forms, StdCtrls, Windows;
var
MainForm, OtherForm: TForm;
Button: TButton;
type
TEventHandlerClass = class
class procedure ToggleTaskbarButton(Sender: TObject);
end;
class procedure TEventHandlerClass.ToggleTaskbarButton(Sender: TObject);
begin
if IsWindowVisible(Application.Handle) then
ShowWindow(Application.Handle, SW_HIDE)
else
ShowWindow(Application.Handle, SW_SHOW);
end;
begin
Application.MainFormOnTaskbar := False;
Application.CreateForm(TForm, MainForm);
OtherForm := TForm.Create(Application);
OtherForm.PopupParent := MainForm;
MainForm.Caption := 'Main Form';
Application.Title := MainForm.Caption;
OtherForm.Visible := True;
OtherForm.Caption := 'Other Form';
Button := TButton.Create(OtherForm);
Button.Caption := 'Toggle';
Button.Parent := OtherForm;
Button.OnClick := TEventHandlerClass.ToggleTaskbarButton;
Application.Run;
end.
Run this program and click on the toggle button. Now you will see main form and other form showing. And nothing in the taskbar. I included the toggle button to show that you can switch between your two modes of operation whilst the program is running. No need to restart it.
The key here is to make a window other than your visible forms be the window associated with the taskbar. Once you do that you can once again control taskbar presence by showing and hiding that window. In this case that window is the application window, Application.Handle. Because that's the window on the taskbar, you need to set its Title property to control its text.
I stress finally, once again, that interaction with the taskbar is best controlled with window owner and visibility. Always search for solutions using those methods rather than ITaskbarList, extended window styles etc.
Update
Hopefully the last word on the subject. As you have noticed, the code directly above has poor behaviour when the main form is minimised. When that happens, the application window is made visible again and so appears once more in the taskbar.
I'm not so sure of myself when it comes to suppressing this behaviour. The behaviour comes about because of the code in TApplication.Minimize which shows the application handle when the main form is minimized. The best solution that I have is to convert a main form minimize into a hide.
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
....
procedure TMainForm.WMSysCommand(var Msg: TWMSysCommand);
begin
if (Msg.CmdType and $FFF0)=SC_MINIMIZE then
begin
Hide;
exit;
end;
inherited;
end;
Or another way would be to suppress the application window show by means of an OnMinimize event handler for TApplication.
class procedure TEventHandlerClass.ApplicationMinimize(Sender: TObject);
begin
ShowWindow(Application.Handle, SW_HIDE);
end;
David's answer is correct. There were a couple minor issues with it, but I ran with it and got everything working. He posted his last update while I was figuring this out. I am posting some additional code samples here, and accepted his answer. First I assigned:
Application.OnMessage := AppMessage;
Then the procedure is as follows:
procedure TfrmAppointment.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
// This first check decides if we are minimizing via the upper right button OR
// The context menu in the upper left hand corner of the window.
// Minimizing twice restores, so this can be a restore as well.
if ((((Msg.message = WM_NCLBUTTONDOWN) and (Msg.wParam = HTMINBUTTON)) or
((Msg.message = WM_SYSCOMMAND) and (Msg.wParam = SC_MINIMIZE))) and
(Screen.ActiveForm = Self)) then
begin
// This function is defined as (bool, bool) where the variables are:
// Param1: Mimimizing (true), Restoring (false)
// Param2: Draw animation rectangles for doing this or not
Handled := MinimizeOrRestore(Self.WindowState <> wsMinimized, True);
end
else if ((Msg.message = WM_SYSCOMMAND) and
(Msg.wParam = SC_RESTORE) and
(Screen.ActiveForm = Self)) then
begin
// Specifically, restore has been asked for
Handled := MinimizeOrRestore(False, True); // Minimize with animation
end
else if ((Msg.message = WM_SYSCOMMAND) and (Msg.wParam = SC_CLOSE)) then
begin
// The user just used the system menu to close the application
ApplicationIsClosing := True; // see below for this
end
end;
Then in my FormCloseQuery, I check for "ApplicationIsClosing" to be true. If it's FALSE, then I know the user hit the X, and I simply minimize the application calling the other function referenced here. If it's true, I allow the close.
Finally, MinimizeOnRestore grabs the TRect for the form itself, as well as the system tray and then executes DrawAnimatedRects. This doesn't work always on Vista or higher, but it doesn't error either. Next, it hides the main application window or makes it visible. It always returns true unless it encounters an error. Then it returns false.
i have a window that i want to minimize (to the taskbar), so i call ShowWindow:
ShowWindow(Handle, SW_MINIMIZE);
Except that rather than minimizing itself (to the taskbar), the window is iconified:
The window is unparented:
How do i minimize a window to the taskbar?
Update:
Following some advice from 2002, i try setting the WS_EX_APPWINDOW window style and/or ensuring the window has no owner:
Unfortunately, that changes the behavior of my (Delphi) application because there is now two taskbar icons for my application, rather than one:
This, of course, is an artifact of Delphi (5); and because i was trying to solve another issue.
But that shouldn't affect this question. i'm calling the ShowWindow(..., SW_MINIMIZE) API, and rather than minimize the window Windows is iconifying the application.
How do i minimize a window to the taskbar?
That icon on the taskbar is the icon of the Application (Handle) rather than that of the MainForm.
Use:
Application.Minimize;
Edit: But out of both your links, I understand you knew that already...duh ;)
This works for the MainForm:
TForm1 = class(TForm)
private
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
protected
procedure CreateParams(var Params: TCreateParams); override;
...
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
begin
ExStyle := ExStyle or WS_EX_APPWINDOW;
WndParent := GetDesktopWindow;
end;
end;
procedure TForm1.WMSysCommand(var Msg: TWMSysCommand);
begin
if Msg.CmdType = SC_MINIMIZE then
ShowWindow(Handle, SW_MINIMIZE)
else
inherited;
end;
And to hide Application.Handle from the taskbar (to only have a taskbar icon for the MainForm): set the Visible property of this Form to True and hide the Application in the project file:
Application.Initialize;
Application.CreateForm(TForm1, Form1);
ShowWindow(Application.Handle, SW_HIDE);
Application.Run;
For this form, ShowWindow(Handle, SW_MINIMIZE); shóuld work. It also provides for the default zooming-feature of Windows when minimizing or restoring.
(Tested with D5 & D7 on XP and W7)
A super simple solution is to disable the minimize icon on the FORM
[Object inspector]-[Form properties]-[Border icons]-[biMinimize]
The application can still be minimized and restore by clicking on the APPLICATION icon at the taskbar
How do you make a form appear on the taskbar in Delphi? In Firefox, for example, when you open a page in a new window, it creates another window on the taskbar without creating a new process. At the moment my Delphi application opens a new form when a button is clicked, but there is still only one thing on the task bar, so you can't alt-tab between the main form and the form that is created when the button is clicked. How do I change it so that the new form appears with a new taskbar button? My current code looks like this:
procedure Form1ButtonClick(Sender: TObject);
begin
Form2.Show;
end;
I have been messing around with CreateWindowEx, but ideally I would like to find a simpler solution than directly using the Windows API.
If I understand what you want correctly, you can show your secondary forms on the task bar by overriding it's CreateParams procedure, as explained in Minimize child forms independent of the main form delphi.about.com article, like this:
interface
type
TMyForm = class(TForm)
...
protected
procedure CreateParams(var Params: TCreateParams) ; override;
...
implementation
procedure TMyForm.CreateParams(var Params: TCreateParams) ;
begin
inherited;
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
Params.WndParent := 0;
end;
if not using of this line is better in form order :
Params.WndParent := 0;