Deleting IWTreeViewItems causes exception on form release - delphi

On my form I have a IWTreeView and two buttons. One button deletes some IWTreeViewItems, the other releases the form:
procedure TIWForm1.IWButton1Click(Sender: TObject);
begin
IWTreeView1.Items[0].Subitems.Clear;
end;
procedure TIWForm1.IWButton2Click(Sender: TObject);
begin
Release;
end;
Releasing the form after deleting the IWTreeViewItems causes an exception:
Error message raised by the
application: Access violation at
address 004E0D8A in module
'TryTree.exe'. Read of address
00000000
When there is another form active and the application is not terminated by this form release, the error message is:
Error message raised by the
application: List index out of
bounds (-1)
Using IntraWeb 9.0.42 (because of TMS controls and Delphi 2006, as TMS has not tested with 10.0.17 and delphi 2006).
I tried to IWTreeView1.ClearAll in the form destroy, which did not help at all.

Instead of SubItems.Clear I now use
for i := IWTreeView1.Items[0].SubItems.Count-1 downto 0 do begin
TIWTreeViewItem(IWTreeView1.Items[0].SubItems[i]).Free;
end;
This works. Still open for better solutions, maybe not involving a loop through all subitems.

Related

AllocConsole, SetConsoleCtrlHandler prevent terminating

Before thinking this is a duplicate Question, then please read this: Yes this question is around in on SO in different languages at least Delphi, C# and C++ but they all have something in common: They talk about handling a clean shut down not preventing it.
So here we go:
Form a VCL application I open a new Console Window using AllocConsole but when closing that window with the cross in the top right corner my application terminates. That I would like to prevent not handle!
Some code:
function Handler(dwCtrlType: DWORD): Boolean; cdecl;
begin
case dwCtrlType of
CTRL_CLOSE_EVENT, CTRL_C_EVENT, CTRL_BREAK_EVENT:
Exit(True);
else
Exit(false);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
AllocConsole;
SetConsoleCtrlHandler(#Handler, True);
end;
I have read the WinAPI documentation but it doesn't say anything about preventing Application termination.
I have tried adding message handlers for WM_ENDSESSION, WM_QUERYENDSESSION, WM_CLOSE and WM_QUIT on my MainForm but none of them gets called. I've also tried to add a FormCloseQuery event but it doesn't get called either.
I have read and tried out the solution found here but SetConsoleCtrlHandler(nil, True); doesn't provide the application for termination
So in short how to prevent termination.

invalid class typecast in intraweb

I'm porting an old application from delphi7 to delphi xe8
and from intraweb 8 to intraweb XIV
My app was subdivided in a main program and a number of child packages
and it worked perfectly with the old components.
With theese new components, I now get an exception trying to generate and return a page to the server controller, creating such a page from a child package.
If instead I generate the page from the main app, it works.
In the procedure TIWServerController.IWServerControllerBaseGetMainForm
I call a procedure of a my component (packman) that tries to obtain a main window from a child package.
this is the servercontroller function
procedure TIWServerController.IWServerControllerBaseGetMainForm(var vMainForm : TIWBaseForm);
begin
VMainForm := PackMan.MainLoginForm(webApplication);
end;
and this is the packman function:
function tPackMan.MainLoginForm (aOwner:tComponent) : tIwAppForm;
var Proc : tGetMainFormProc;
begin
#Proc := GetProcAddress (LoginPkg,'MainForm');
Result := Proc(aOwner);
end;
this is the definition of the procedural type:
tGetMainFormProc = function (aOwner:tComponent): tIwAppForm;
and this is the MainForm procedure, in the child package (packlogin).
Initially I tried to create the original form, full of components,
after that I've removed all components from original form, without success,
and finally I tried to construct an empty form, as shown in this sample:
function MainForm (aOwner:tComponent): tIWAppForm;
begin
Result := tIWAppForm.Create(aOwner);
end;
exports MainForm;
I've traced the program behaviour using several Outputdebugstring messages (here not shown) and I've come to the following conclusion:
1) the Mainform procedure, in the package, seems to return a valid tIwAppform
2) this Object is correctly returned to the IWServerControllerBaseGetMainForm procedure
and the variable VMainForm is correctly assigned.
3) if I inspect the classname property of this variable, I see it has the value "tIWAppform".
The exception seems to be generated at the procedure return.
I've interceped it in the procedure IWServerControllerBaseException
with the following code :
procedure TIWServerController.IWServerControllerBaseException(
AApplication: TIWApplication; AException: Exception;
var Handled: Boolean);
begin
Dump ('UNEXPECTED EXCEPTION ' + AException.message);
Handled := true;
end;
What am I missing ?
Any suggestion ?
Regards.
Maurizio.

Access violation when open the teechart form at the second time

We're migrating our XE projects to XE5, however, we encountered the access violation exception about teechart during the test.
I've created a test application to recreate the issue. With the test app, it works fine when open the first teechart form but will get the access violation exception when open it second time or open a new form.
Please refer to the attached test app from the following QC (embarcadero).
http://qc.embarcadero.com/wc/qcmain.aspx?d=122729
When debug it with DCUs. The exception happened when notifying TDBChart's OnStateChange event.
procedure TDataSet.DataEvent(Event: TDataEvent; Info: NativeInt);
begin
...
if NotifyDataSources then
begin
for I := 0 to FDataSources.Count - 1 do
FDataSources[I].DataEvent(Event, Info); // <<---- Access Violation
if FDesigner <> nil then FDesigner.DataEvent(Event, Info);
end;
end;
As David Berneda said at Quality Central:
Its related to using an internal TObjectList generic collection inside
DBChart. The code has been improved so the error is fixed now (a new
code takes care of destroying the ObjectList items correctly).
As a workaround, you can add this code at your form's OnClose event:
type
TChartAccess=class(TDBChart);
procedure TOutcomesGraphFm.bbtnCloseClick(Sender: TObject);
begin
TChartAccess(dbcBar).RemovedDataSource(bsTestScores,bsTestScores.DataSource);
Close;
end;

Why doesn't my form receive WM_DropFiles when files are dropped on it?

I am using Embarcadero RAD Studio XE to develop an application. I am trying catch the file(s) drag and drop to the application with the following code
TMainForm = class(TForm)
public:
procedure WMDropFiles(var Msg: TWMDropFiles); message WM_DROPFILES;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
DragAcceptFiles(Self.Handle, True);
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
DragAcceptFiles(Self.Handle, False);
end;
procedure TMainForm.WMDropFiles(var Msg: TWMDropFiles);
begin
inherited;
showmessage('catch here');
// some code to handle the drop files here
Msg.Result := 0;
end;
This code complied without problem. Also, when I drag and drop files, the cursor show that the status changed to drag and drop but after things dropped, nothing happen (no message shown too). Is that anything wrong with that?
In a plain vanilla application, the code in the question results in WMDropFiles executing when an object is dropped on the form. So, clearly there's something else happening to stop it working. The most obvious potential causes are:
The main form's window handle is re-created after the initial call to DragAcceptFiles.
Your process is running at a higher integrity level than the process that is dropping files on it. For example, are you running your process as administrator. Note that running the Delphi IDE as administrator would lead to your process running as administrator when started from the IDE.
Something else in your process is interfering with drag/drop. Without knowing what's in your app, it's hard to guess what this could be. Start removing portions of your app until there's nothing left but the code in the question.
Option 2 seems quite plausible. To learn more see: Q: Why Doesn’t Drag-and-Drop work when my Application is Running Elevated? – A: Mandatory Integrity Control and UIPI
in TForm.Create use two lines
ChangeWindowMessageFilter (WM_DROPFILES, MSGFLT_ADD);
ChangeWindowMessageFilter (WM_COPYGLOBALDATA, MSGFLT_ADD);
that's all

error in Delphi loadlibrary()

i have given a chance to my software user to select dll from openfile dialog.(so my user can download dlls form my website and use it with the main project ). everything is working fine and it can even find that dlls is provided by me or selected an invalid dll.but the problem raises if the user selects a renamed file(eg : apple.txt file renamed to apple.dll ). i typed the code like this
try
dllHandle := LoadLibrary( pwidechar(openfiledialog1.filename)) ;
catch
{ showmessage if it is not a dll (but it can be any dll, it checks this is my dll or 3rd party later )}
end;
error message shown by delphi is 'bad library image selected'
but try catch is not working if the user selects invalid dll it is showing its own error message and struck up.
can anyone help me,i am using delphi 2009
There's no exception to catch because an exception is not raised when LoadLibrary fails; it just returns '0'.
You should check if 'dllHandle' is 0 or not, if it is, show the error information to the user by using GetLastError as documented. Alternatively you can use the Win32Check function in the RTL which will raise an exception with the appropriate error message:
(edit: Documentation of 'LoadLibrary' states that: To enable or disable error messages displayed by the loader during DLL loads, use the SetErrorMode function. So if you don't want the OS to show an additional dialog you'd set the error mode before calling LoadLibrary.)
var
dllHandle: HMODULE;
ErrorMode: UINT;
begin
if OpenDialog1.Execute then begin
ErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS); // disable OS error messages
try
dllHandle := LoadLibrary(PChar(OpenDialog1.FileName));
finally
SetErrorMode(ErrorMode);
end;
if Win32Check(Bool(dllHandle)) then begin // exception raised if false
// use the libary
end;
end;
end;

Resources