There seems to be a problem with TFileOpenDialog's preview pane setting, when selecting certain images the app crashes. Is there a fix for this?
Test image
Demo source:
procedure TForm1.Button1Click(Sender: TObject);
begin
FileOpenDialog1.Execute;
end;
object FileOpenDialog1: TFileOpenDialog
FavoriteLinks = <>
FileTypes = <>
Options = [fdoForcePreviewPaneOn]
Left = 200
Top = 32
end
Edit: it seems to happen only in Windows10 (AN. update), works normally in Win7. Some debug:
callstack crc : $6ac33669, $66c06792, $66c06792
exception number : 1
exception class : EInvalidOp
exception message : Invalid floating point operation.
main thread ($ae0):
6ac33669 +000 PhotoMetadataHandler.dll
71f6447f +09f PROPSYS.dll PSCreateDelayedMultiplexPropertyStore
773ef71a +00a combase.dll PropVariantClear
74d317c2 +082 KERNELBASE.dll QISearch
71f4f677 +097 PROPSYS.dll #424
71f4f829 +249 PROPSYS.dll #424
6c5f1bba +11a DUI70.dll ?_PreSourceChange@Element@DirectUI@@AAEJPBUPropertyInfo@2@HPAVValue@2@1@Z
6c5ee3a6 +246 DUI70.dll ?_SetValue@Element@DirectUI@@IAEJPBUPropertyInfo@2@HPAVValue@2@_N@Z
6c5ee46e +30e DUI70.dll ?_SetValue@Element@DirectUI@@IAEJPBUPropertyInfo@2@HPAVValue@2@_N@Z
6c5ecf15 +025 DUI70.dll ?SetContentAlign@Element@DirectUI@@QAEJH@Z
6c5e6813 +033 DUI70.dll ?_BroadcastEventWorker@Element@DirectUI@@AAEXPAUEvent@2@@Z
6c5e6867 +087 DUI70.dll ?_BroadcastEventWorker@Element@DirectUI@@AAEXPAUEvent@2@@Z
6c5e68a2 +012 DUI70.dll ?BroadcastEvent@Element@DirectUI@@QAEXPAUEvent@2@@Z
6c5e6813 +033 DUI70.dll ?_BroadcastEventWorker@Element@DirectUI@@AAEXPAUEvent@2@@Z
6c5e6867 +087 DUI70.dll ?_BroadcastEventWorker@Element@DirectUI@@AAEXPAUEvent@2@@Z
6c5e68a2 +012 DUI70.dll ?BroadcastEvent@Element@DirectUI@@QAEXPAUEvent@2@@Z
6c54d590 +0b0 DUser.dll DUserSendEvent
6c5e68ef +03f DUI70.dll ?FireEvent@Element@DirectUI@@QAEXPAUEvent@2@_N1@Z
7529df12 +092 user32.dll CallWindowProcW
752ac53c +0fc user32.dll IsDialogMessageW
752abd8d +02d user32.dll DialogBoxIndirectParamAorW
752abd46 +016 user32.dll DialogBoxIndirectParamW
005af784 +370 Project1.exe Vcl.Dialogs TCustomFileDialog.Execute
005af3f9 +045 Project1.exe Vcl.Dialogs TCustomFileDialog.Execute
006375ec +008 Project1.exe Unit1 29 +0 TForm1.Button1Click
005880d3 +073 Project1.exe Vcl.Controls TControl.Click
0059f1d2 +01e Project1.exe Vcl.StdCtrls TCustomButton.Click
0059fce0 +010 Project1.exe Vcl.StdCtrls TCustomButton.CNCommand
00587b65 +2bd Project1.exe Vcl.Controls TControl.WndProc
0058c6a5 +5e9 Project1.exe Vcl.Controls TWinControl.WndProc
0059ee7c +06c Project1.exe Vcl.StdCtrls TButtonControl.WndProc
005877a0 +024 Project1.exe Vcl.Controls TControl.Perform
0058c80b +023 Project1.exe Vcl.Controls DoControlMsg
0058d293 +00b Project1.exe Vcl.Controls TWinControl.WMCommand
00627ed9 +045 Project1.exe Vcl.Forms TCustomForm.WMCommand
00587b65 +2bd Project1.exe Vcl.Controls TControl.WndProc
0058c6a5 +5e9 Project1.exe Vcl.Controls TWinControl.WndProc
00624d08 +62c Project1.exe Vcl.Forms TCustomForm.WndProc
0058bcc4 +02c Project1.exe Vcl.Controls TWinControl.MainWndProc
0052f48c +014 Project1.exe System.Classes StdWndProc
77630004 +034 ntdll.dll KiUserCallbackDispatcher
752a0bfb +13b user32.dll SendMessageW
7529df12 +092 user32.dll CallWindowProcW
0058c7b6 +0e6 Project1.exe Vcl.Controls TWinControl.DefaultHandler
00588528 +010 Project1.exe Vcl.Controls TControl.WMLButtonUp
00587b65 +2bd Project1.exe Vcl.Controls TControl.WndProc
0058c6a5 +5e9 Project1.exe Vcl.Controls TWinControl.WndProc
0059ee7c +06c Project1.exe Vcl.StdCtrls TButtonControl.WndProc
0058bcc4 +02c Project1.exe Vcl.Controls TWinControl.MainWndProc
0052f48c +014 Project1.exe System.Classes StdWndProc
7529df9b +00b user32.dll DispatchMessageW
0062e363 +0f3 Project1.exe Vcl.Forms TApplication.ProcessMessage
0062e3a6 +00a Project1.exe Vcl.Forms TApplication.HandleMessage
0062e6d9 +0c9 Project1.exe Vcl.Forms TApplication.Run
00640801 +049 Project1.exe Project1 18 +4 initialization
74fa62c2 +022 KERNEL32.DLL BaseThreadInitThunk
disassembling:
006375e4 public Unit1.TForm1.Button1Click: ; function entry point
006375e4 29 mov eax, [eax+$3c4]
006375ea mov edx, [eax]
006375ec > call dword ptr [edx+$4c]
006375ef 30 ret
You are seeing an FPU exception that originates from PhotoMetadataHandler.dll, The reason why it is crashing is unknown but it seems that some JPG files can cause floating point exceptions. For instance Total Commander (which is written in Delphi) has been hit with the same problem a number of times. The fix is quite simple, disable all exceptions before executing the dialog and reenable them afterwards:
procedure TForm1.Button1Click(Sender: TObject);
var
OrgMask : TArithmeticExceptionMask;
begin
OrgMask := GetExceptionMask;
// disable all exceptions
SetExceptioNMask([exInvalidOp,exDenormalized, exZeroDivide, exOverflow,
exUnderflow, exPrecision]);
FileOpenDialog1.Execute;
SetExceptionMask(OrgMask);
end;
EDIT
based on the comment of Craig Young, I would implement an interface to make sure that we always restore the original exception mask.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Math;
type
ICatchAllFPUExceptions = interface
['{7F429ECA-B458-4F39-832B-429839A8E948}']
end;
TCatchAllFPUExceptions = class(TInterfacedObject, ICatchAllFPUExceptions)
private
OrgExceptionMask : TArithmeticExceptionMask;
public
class function Activate : ICatchAllFPUExceptions; static;
constructor Create;
destructor Destroy; override;
end;
TForm1 = class(TForm)
FileOpenDialog1: TFileOpenDialog;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TCatchAllFPUExceptions }
class function TCatchAllFPUExceptions.Activate: ICatchAllFPUExceptions;
begin
Result := TCatchAllFPUExceptions.Create;
end;
constructor TCatchAllFPUExceptions.Create;
begin
inherited;
OrgExceptionMask := GetExceptionMask;
SetExceptioNMask([exInvalidOp,exDenormalized, exZeroDivide,
exOverflow, exUnderflow, exPrecision]);
end;
destructor TCatchAllFPUExceptions.Destroy;
begin
SetExceptioNMask(OrgExceptionMask);
inherited;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// disable all exceptions
TCatchAllFPUExceptions.Activate;
FileOpenDialog1.Execute;
// mask will be restored here due to internal function variable going out of scope
end;
end.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With