Using DFL with VisualD

As explained in my previous post (which is from last year… so you can see I am useless at this blogging thing – my apologies!)  my D-Editor at the moment is Visual Studio.NET 2008 Professional with the VisualD plugin (currently on v0.3.33). It is not perfect, but it works ok for me and I am quite productive in it.  I use VS as my standard IDE at work anyway – so this makes it easy for me to switch between D and C++ – which is still the bulk of the work I do.

As I mention in my previous post the main attraction of VisualD for me is the integration with the VS Symbolic Debugger – which makes D debugging pretty much on an par with what I have with VC++. This is the one area where VisualD outperforms other Windows IDE solutions, such as D-IDE, Mono-D and Code Blocks. On the other hand, I believe the semantic analysis / completion of Mono-D is superior to what VisualD currently provides – so you will have to decide which one of these is the”must have” feature for you.

In my previous post I also explained why I am using DFL for GUI development. This of course then implies that I need DFL to play nicely with VisualD – which is does, provided you are aware of some “gotchas”. It is not extremely difficult to sort this out, but there are definitely a few things you need to be aware of!  As this is a topic that regularly seem to re-appear in both the D forum as well as the VisualD forum,  I have decided to do this blog post – to share my experiences on this.

Installation

I am not going to cover D installation since it is well trodden ground (it varies with whichever version you want to use i.e DMD, GDC, etc.), except to note that I am using DMD v2.059 which is installed (on my system at least) to c:\dmd2. Note this is a completely standard DMD installation. But make sure you have the <DMD_INSTALL_PATH>\windows\bin directory in your Path environment variable.

To install VisualD download the latest version from its download page. Make sure VS is closed and runs the downloaded installer. Again the installation should be completely standard – VisualD should detect where DMD is installed as well as which VS version(s) you have. If not, you will be prompted to select the correct path/options. I originally had problems with the VisualD plugin clashing with the VS Qt plugin (but note this was ages ago on v0.3.15 of VisualD), but Rainer Schuetze (the author of VisualD) is amazingly reactive and quickly fixed the issue.

Once VisualD is installed you need to append %DMD_LIB% to the LIB path (see here for reason) in DMD’s sc.ini file (which should be in <DMD_INSTALL_PATH>\windows\bin). Mine reads:

LIB="%@P%\..\lib";\dm\lib;%DMD_LIB%

In the VisualD plugin menu is an option to “Build Phobos Browse Info”. This generates JSON files for code completion purposes, so you would want to do this. Go to VS Tools|Options… menu and select Projects and Solutions|Visual D Directories and make sure JSON paths is set to something like “$(DMDInstallDir)\JSON“. [Edit: Note that version v2.059 of the DMD compiler required you to make an additional change to DMD’s sc.ini file to allow the Phobos browse info to be generated (you had to add “-I%@P%\..\..\src\druntime\src” to the DFLAGS line – the reason is explained here), but this is no longer necessary (in fact it must not be done as it now breaks building of Phobos browse info). At least this is the current state of affairs with DMD v2.062 (I skipped v2.060 & v2.061, so I am not sure about those versions)].

Also make sure the Expansion from JSON browse information option in Tools|Option|Text Editor|D|Intellisense is set. The Phobos JSON files can now be build (or rebuild) from the VisualD menu option.

Installation of DFL is not so straight-forward (read previous blog entry for details). You cannot use the download from the official DFL site, as this will not work with the latest DMD compiler versions. Christopher E. Miller, the creator of DFL, is not active in the community anymore, so you have to use the version from Rayerd/dfl, who is maintaining DFL to keep it compatible with the latest DMD releases. Download the Zip file and unzip to your directory of choice (I recommend something like c:\dmd2\import). Note there are also a  gtk directory in the Zip that you don’t need. You will need to rebuild the DFL static lib file for the following reasons:

  • the Lib itself is not included in the Zip.
  • you can build both Debug and Release versions of the DFL lib.
  • generate JSON info for the DFL library.
  • most importantly – make sure DFL actually builds with your DMD version.

If you want to use DFL making use of its visual form designer called Entice Designer (which I recommend!), you should not use the officially released version, but instead use this testing version. If you have already installed the “official” version, you can simply update it from the “testing version’s” Zip file.

Building DFL

Navigate to <DFL_INSTALL_DIR>\win32\dfl directory where <DFL_INSTALL_DIR> would typically be something like c:\dmd2\import. DFL makes use of a batch file (go.bat) that calls another batch file (makelib.bat) to build the DFL Lib files. Edit makelib.bat as follows (make a backup copy 1st if you prefer):

Edit line 16 from:

set dmd_path=c:\dmd

To (or the equivalent for your DMD installation):

set dmd_path=c:\dmd2

If you (like me) do not want to “allow deprecated features”, remove the ‘-d’ compiler option as follows:

Edit Line 48 from:

set _dfl_flags=%dfl_flags% -d -wi

To:

set _dfl_flags=%dfl_flags% -wi

You need to add the necessary compiler switch (-X) to generate JSON information (DFL predates JSON generation, so the JSON option is not used by default).

Edit Line 111 from:

%dmd_path_windows%\bin\dmd -c %dfl_release_flags% %_dfl_flags% %dfl_options% -I.. %dfl_files%

To:

%dmd_path_windows%\bin\dmd -c -X %dfl_release_flags% %_dfl_flags% %dfl_options% -I.. %dfl_files%

Lastly I recommend copying the generated DFL JSON file to the standard JSON folder (as discussed earlier). To do this you need to edit go.bat:

Insert at Line 32:

@echo About to move DFL JSON file to %dmd_path_windows%\JSON (Close window or Ctrl+C to stop)
@pause

@copy all.json %dmd_path%\JSON\dfl.json
@if errorlevel 1 goto fail

At this stage you can rebuild the DFL Libs. In my case (DMD v2.059 with Rayerd-dfl-f39bb32.zip) there were still some functions declared as nothrow which the compiler complains about (it may be fixed by now). Simply remove the nothrow specifier and everything should build fine at this stage (remember, you have to run “go.bat“, not “makelib.bat“!). You should see something like this now:

Compiling debug DFL...

C:\dmd2\import\win32\dfl>c:\dmd2\windows\bin\dmd -c -debug -g  -wi  -I.. all.d b
ase.d application.d internal/dlib.d internal/clib.d internal/utf.d internal/com.
d control.d clippingform.d form.d registry.d drawing.d menu.d notifyicon.d commo
ndialog.d filedialog.d folderdialog.d panel.d textbox.d richtextbox.d picturebox
.d listbox.d groupbox.d splitter.d usercontrol.d button.d label.d collections.d
internal/winapi.d internal/wincom.d event.d socket.d timer.d environment.d messa
gebox.d tooltip.d combobox.d treeview.d tabcontrol.d colordialog.d listview.d da
ta.d clipboard.d fontdialog.d progressbar.d resources.d statusbar.d imagelist.d
toolbar.d

Making debug lib...

C:\dmd2\import\win32\dfl>c:\dm\bin\lib -c -n -p64 dfl_debug.lib c:\dm\lib\gdi32.
lib c:\dm\lib\comctl32.lib c:\dm\lib\advapi32.lib c:\dm\lib\comdlg32.lib c:\dm\l
ib\ole32.lib c:\dm\lib\uuid.lib c:\dmd2\windows\lib\ws2_32.lib user32_dfl.lib sh
ell32_dfl.lib olepro32_dfl.lib all.obj base.obj application.obj dlib.obj clib.ob
j utf.obj com.obj control.obj clippingform.obj form.obj registry.obj drawing.obj
 menu.obj notifyicon.obj commondialog.obj filedialog.obj folderdialog.obj panel.
obj textbox.obj richtextbox.obj picturebox.obj listbox.obj groupbox.obj splitter
.obj usercontrol.obj button.obj label.obj collections.obj winapi.obj wincom.obj
event.obj socket.obj timer.obj environment.obj messagebox.obj tooltip.obj combob
ox.obj treeview.obj tabcontrol.obj colordialog.obj listview.obj data.obj clipboa
rd.obj fontdialog.obj progressbar.obj resources.obj statusbar.obj imagelist.obj
toolbar.obj
Digital Mars Librarian Version 8.02n
Copyright (C) Digital Mars 2000-2007 All Rights Reserved

http://www.digitalmars.com/ctg/lib.html

Digital Mars Librarian complete.

Compiling release DFL...

C:\dmd2\import\win32\dfl>c:\dmd2\windows\bin\dmd -c -X -O -inline -release  -wi
 -I.. all.d base.d application.d internal/dlib.d internal/clib.d internal/utf.d
internal/com.d control.d clippingform.d form.d registry.d drawing.d menu.d notif
yicon.d commondialog.d filedialog.d folderdialog.d panel.d textbox.d richtextbox
.d picturebox.d listbox.d groupbox.d splitter.d usercontrol.d button.d label.d c
ollections.d internal/winapi.d internal/wincom.d event.d socket.d timer.d enviro
nment.d messagebox.d tooltip.d combobox.d treeview.d tabcontrol.d colordialog.d
listview.d data.d clipboard.d fontdialog.d progressbar.d resources.d statusbar.d
 imagelist.d toolbar.d

Making release lib...

C:\dmd2\import\win32\dfl>c:\dm\bin\lib -c -n -p64 dfl.lib c:\dm\lib\gdi32.lib c:
\dm\lib\comctl32.lib c:\dm\lib\advapi32.lib c:\dm\lib\comdlg32.lib c:\dm\lib\ole
32.lib c:\dm\lib\uuid.lib c:\dmd2\windows\lib\ws2_32.lib user32_dfl.lib shell32_
dfl.lib olepro32_dfl.lib all.obj base.obj application.obj dlib.obj clib.obj utf.
obj com.obj control.obj clippingform.obj form.obj registry.obj drawing.obj menu.
obj notifyicon.obj commondialog.obj filedialog.obj folderdialog.obj panel.obj te
xtbox.obj richtextbox.obj picturebox.obj listbox.obj groupbox.obj splitter.obj u
sercontrol.obj button.obj label.obj collections.obj winapi.obj wincom.obj event.
obj socket.obj timer.obj environment.obj messagebox.obj tooltip.obj combobox.obj
 treeview.obj tabcontrol.obj colordialog.obj listview.obj data.obj clipboard.obj
 fontdialog.obj progressbar.obj resources.obj statusbar.obj imagelist.obj toolba
r.obj
Digital Mars Librarian Version 8.02n
Copyright (C) Digital Mars 2000-2007 All Rights Reserved

http://www.digitalmars.com/ctg/lib.html

Digital Mars Librarian complete.

Making build lib...

C:\dmd2\import\win32\dfl>c:\dm\bin\lib -c -n dfl_build.lib user32_dfl.lib shell3
2_dfl.lib olepro32_dfl.lib
Digital Mars Librarian Version 8.02n
Copyright (C) Digital Mars 2000-2007 All Rights Reserved

http://www.digitalmars.com/ctg/lib.html

Digital Mars Librarian complete.

Done.

About to move DFL lib files to c:\dmd2\windows\lib (Close window or Ctrl+C to st
op)
Press any key to continue . . .
C:\dmd2\import\win32\dfl\dfl.lib
C:\dmd2\import\win32\dfl\dfl_build.lib
C:\dmd2\import\win32\dfl\dfl_debug.lib
About to move DFL JSON file to c:\dmd2\windows\JSON (Close window or Ctrl+C to s
top)
Press any key to continue . . .
        1 file(s) copied.
Done.

You will possibly note that there are in fact 3 DFL Lib files that are generated:

  • dfl_debug.lib – static lib containing debug info / symbols
  • dfl.lib – release static lib without debug info / symbols
  • dfl_build.lib – link lib to a small number of functions from the shell32.dll, user32.dll, olepro32.dll (all Windows System dlls).

Using DFL

Since you will be linking to the DFL Libs, you should confirm that your Library paths option in Tools|Option|Projects and Solutions|Visual D Directories  is set to “$(DMDInstallDir)windows\lib“.

To start a new DFL based Windows GUI application you would normally follow a 2-step approach. First, create a new project using VisualD and VS:

  • Select File|New|Project…|Other Languages|D|Windows Application.
  • Edit Name and Location as required.

VisualD will create a new project with a single winmain.d file containing 2 functions:

  • WinMain(…)
  • myWinMain(…)

Secondly, switch to Entice Designer and chose File|New. This will open Dialog showing some options. For your main DFL window, you can choose Main Form or, simply, Form. The only difference between the two is that Entice will add a main() function to the Main Form, but not the Form. But since VisualD already handles the main (well, in fact WinMain) function, it is not necessary to use Main Form – ever! Either option will create a Form in the Designer. Controls can now be placed on the Form – and properties edited as required. You can switch between “form view” and “code view“.  Note that Entice uses special comments to mark blocks of code that it uses like this:

	private void initializeMyForm()
	{
		// Do not manually modify this function.
		//~Entice Designer 0.8.6pre4 code begins here.
		//~DFL Form
		text = "My Form";
		clientSize = dfl.all.Size(536, 368);
		//~DFL dfl.button.Button=button1
		button1 = new dfl.button.Button();
		button1.name = "button1";
		button1.text = "Close";
		button1.bounds = dfl.all.Rect(360, 312, 128, 32);
		button1.parent = this;
		//~Entice Designer 0.8.6pre4 code ends here.
	}

You can, if you prefer, edit the code directly in Entice Designer. You can even build the code directly in Entice Designer (you specify the compile/build command in Project|Compile Command…) , but for that you also need to build dflexe.exe since this is what Entice uses (dflexe’s source code is included in the Zip for DFL). I have only tried once to build dflexe.exe, but ran into issues. I gave up very quickly as as there is frankly no point to build in Entice if you cannot debug in Entice. Entice also cannot do conditional compilation (this is not a major problem as DMD compiles blindingly fast but still…). So, even though I sometimes do a little bit of code editing in Entice, I always do most of my editing as well as compiling or building in VisualD.

The final Entice step is to save the form’s D file to the same directory as where the winmain.d is that VisualD created. Add the Entice generated D module to the project (for example mymainform.d). Edit the Project options as follows:

  • Add dfl_debug.lib to the Library Files field in Project|Properties|Configuration Properties|Linker|General for the Project’s Debug Configuration. Repeat using dfl.lib for the Release Configuration.
  • Add -L/SUBSYSTEM:WINDOWS to Additional options field in Project|Properties|Configuration Properties|Command line for the Project’s Debug Configuration. Repeat using -L/SUBSYSTEM:WINDOWS:4.0 for the Release configuration.

At the bottom of mymainform.d may be a redundant main() function (inserted by Entice if you chose Main Form instead of Form) which can be removed (note that the WinMain(..) function provided by VisualD is the correct way to do it). All that is still required is to  import the necessary modules:

Add to winmain.d:

import dfl.all;
import mymainform;

Also edit the myWinMain(..) function in winmain.d as follows:

int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    int result = 0;

    try
    {
        Application.enableVisualStyles();

        //@  Other application initialization code here.

        Application.run(new MyForm());
    }
    catch(DflException o)
    {
        msgBox(o.toString(), "Fatal DFL Error", MsgBoxButtons.OK, MsgBoxIcon.ERROR);

        result = 1;
    }

    return result;
}

This simply instantiates a Main Form object and passes it to the Application object. As you can see this is boilerplate code where the only thing that will be different in your future winmain.d implementations is the “MyForm”  class name and the import name of the main form module.

At this stage your DFL application should build without problems. You can set breakpoints and break in the Debug version. Then step, evaluate variables,  etc. Pretty much anything you can do in VC++.You can change to Release mode and build the release version.

The next logical step is to add event or message handlers for all your controls (or new forms.. with more controls… etc.) . But that is not really part of this blog post (you can see the DFL website for more details), maybe next time I will post some specific hints/tips on DFL itself. So till next time… happy coding with DFL & VisualD!

About these ads
This entry was posted in D programming and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s