The following writing is part of a series of articles on DWinLib, a semi-simple wrapper for the Windows API. These include:
- DWinLib - An Overview
- Setting up Visual Studio and building a minimal Windows’ wrapper
- Compiling a Minimal DWinLib Program - You are here
- DWinLib - The Guts
- Modal Dialogs - A DWinLib Approach
This article outlines some of the steps required to compile a basic DWinLib program. The previous steps are found in my last writing. For this project, building on my earlier recommendation, I suggest a path to the root project subdirectory similar to “C:\Users\UserDirectory\Documents\Programs\MyProgs\DWinLibExamples\DWinLibBareApp\.” (Or the equivalent on “D” or another drive if you store your data on something other than the Windows partition.)
It takes me about eleven minutes to work through all the steps in the ‘Project Creation’ section. Three to five times more will probably be needed if this is your first time. (This doesn’t include downloading and installing everything.)
You might ask if it is worth the effort of following these directions, as a project file is included in the zip file. If you are new to Visual Studio I believe stepping through this will be an excellent way to get your feet wet, and start to figure out what goes on behind the scenes, and how a Windows program comes together.
For those who are more familiar with Visual Studio this writing may not be so helpful, but the completed project might interest you as it shows everything necessary to create a minimal Windows wrapper. Tearing it apart you will see how to wrap some common controls, how multiple windows interact with each other, how to integrate a DWinLib program with XP themes, how to create a flicker-free docking window system, and many additional items. (The flicker-free mechanism only works in XP classic theme and earlier, as the skinning method MS took in Vista and 7 seems to have made truly flicker-free resizable applications almost impossible to achieve. Even the non-Aero ‘Basic’ theme in Windows 7 has some flicker on the very edges with my approach, although the controls don’t move as they do in Aero.)
Once completed, the program can easily be extended to create your own application.
There are a couple things to do before we are ready to build our executable. First, get Visual Studio set up and running, as outlined in the previous article.
The next action is to copy the DWinLib library files to your system. They are found in a zip file on the DWinLib overview article. Before doing that, though, a suggestion for a subdirectory structure is in order. My recommendation is to create something similar to the following:
If you mirror that structure on your computer you can build the program from the zip file at the beginning of this writing, with the qualification of having version 1.38.0 of the Boost library, of course. (I don’t believe your user name has to be ‘David,’ and D or another drive may be used because relative paths are the important item, not absolute paths.)
To say a little more about this file layout, many iterations of unsatisfaction went into this system. As an example, I initially placed the DWinLib directory inside the project directory, so they were tightly coupled. Each project had its own copy, but I quickly realized I couldn’t keep track of what had changed where. Separating the library from the projects, and chasing the changes made in DWinLib through the projects was FAR easier.
Another benefit of this approach is when setting up programs inside VSE, it isn’t as difficult to track down the locations of the libraries and other components needed; far fewer mouse clicks are required than than in the earlier arrangements I tried out.
There is one more benefit, although in this day of terrabyte+ drives the consideration is almost moot. Each copy of the library consumes approximately half a megabyte. Only keeping one copy will save space.
So extract DWinLib to a location like the above. Next, the application files specific to the bare example need to be placed on your hard drive. These are the ones which will be individually modified for every program created using DWinLib. They are in the zip file at the beginning of this article. It also contains a .vcproj file, as well as a .sln, but for learning purposes I recommend NOT using them. In fact, for now place (or extract, if you wish) the zip file to a temporary location of your chosing. You may just leave it in the Download folder.
Now it’s time to start having fun!
From here on out these instructions are for VSE 2008. I believe the same procedure was used for VSE 2005, and only the setup steps given on the previous page differed for the two programs, but as I said before, I’m not going to reinstall that in order to verify. If you still use the 2005 edition feel free to leave a note in the comments if something important is missing.
So let’s crank up VSE and begin!
First, create an empty project as I outlined in the last article. In other words, ‘File -> New -> Project ...’, then select ‘General’ in the left pane and ‘Empty Project’ in the right. Before finishing, navigate to your equivalent of “C:\Users\David\Documents\Programs\MyProgs\DWinLibExamples” (from the previous illustration), enter ‘DWinLibBareApp’ as the project name, make certain ‘Create directory for solution’ is unchecked, and finally hit ‘OK.’ Something like the following should appear:
Using Explorer to view this on your hard drive, you will find that VSE created a subdirectory named ‘DWinLibBareApp’ and placed several project files inside it.
See those items at the left side of the screen capture? (‘Header Files,’ ‘Resource Files,’ and ‘Source Files.’) They are called ‘Filters’ in Visual-Studio-speak. I like organization, but this default seems a little difficult to use. When I’m looking for a file, whether it is a header or a .cpp, I don’t want to remember to look inside a separate filter. That remembering (and taking action) costs me a few milliseconds of mental processing similar to “Um, I’m now looking for a header file for this .cpp file - that is in what filter, exactly?” And sometimes my dyslexia kicks in and I switch ‘.h’ with ‘.cpp’ in my mind, and go to the wrong filter, only to start cussing when I realize my mistake, and start scrolling back to close trees, and open the right one. Milliseconds multiply by thousands.
On the other hand, if the .cpp and .h files are placed in the same filter they are located together, and I don’t get confused about their location.
This doesn’t mean I don’t use filters. I must still remember something. Here’s how I reorganized them for this project (and other ones). The popup menu which was used to get to this state is also shown:
Now the question simply becomes, “What part of the program am I working on?” Then the type of file comes last, which seems to pop into my mind correctly with this system, but never did with the default.
For grins, press that little green arrow button now and watch what happens. On my setup Visual Studio tried to build something, acted like it did, and gave an error:
Failed to load file... Cool! The computer didn’t lock up and require a hard reboot! (Oh the memories, even though I am not really an old-school programmer who had this occur much more frequently. But I did experience many glitches in my younger years when technology wasn’t as well understood as today.)
Now is the time to start adding files to this project. Every respectable Windows program requires a WinMain (unless you are creating a DLL or (service? - I have no experience with these)), and the file which contains this is DWinLibBareApp.cpp. Using Explorer (or WinZip or the equivalent in older versions of Windows), drag that from the above zip file to the DWinLibBareApp subdirectory on your hard drive. Then drag that file (not the zip file version) onto the ‘Project’ filter in VSE. Of course it helps to have VSE and Explorer non-maximized at this point. You can also use the ‘Filter’ popup menu to add items using the ‘Add -> Existing Item...’ selection, but that is far too time consuming for my tastes.
Try building the project again by pressing the green arrow. This time a new error appears: “
...fatal error C1083: Cannot open include file: 'PrecompiledHeaders.h': No such file or directory.”
To fix this, copy all of the remaining .cpp and .h files from the zip to the DWinLibBareApp subdirectory, then drag them into Solution Explorer’s ‘Project’ filter. Yes, there are a total of 29 of them (28 if ‘DWinLibBareApp.cpp’ isn’t counted). A minimal wrapper is actually a pretty complicated little beast when it does everything those units do. Because they are now in a subdirectory VSE knows something about, a rebuild will result in a new error: “
fatal error C1083: Cannot open include file: 'DwlWinDefines.h': No such file or directory.”
Yay! The issue isn’t with the application files we copied over! It has to do with VSE not knowing about the DWinLib library. To combat the problem, right click on the word ‘DWinLibBareApp’ above our four new filters and select ‘Properties’ at the bottom of the drop-down menu. Once the screen appears, click the ‘Configuration Properties -> C/C++ -> General’ in the left hand side, mosey up to the top next to the word ‘Configuration:’ and select ‘All Configurations,’ click on ‘Additional Include Directories,’ hit the ‘...’ button which appears to the right, select the ‘New Line’ icon (it looks like a file folder), then the newly visible ‘...’ button, and navigate to the equivalent of “C:\Users\David\Documents\Programs\LibsAndUtils\DWinLib_3.01” and press ‘Select Folder.’ Repeat this step for the ‘WinControlWin’ and ‘Utilities’ subdirectories inside the DWinLib subdirectory.
Once again, try building the program. Something amazing happens. VSE actually starts compiling units! But the process is very slow, at least from my perspective.
To fix the problem, hit ‘Ctrl + Break’ (which is ‘Ctrl + Fn + Shift’ on my laptop’s keyboard) to stop the build process. The reason for the lethargy of the compilation process is VSE isn’t taking advantage of precompiled headers even though all the units in the project are designed to. So right click on ‘DWinLibBareApp’ as before, select ‘Configuration Properties -> C/C++ -> Precompiled Headers,’ change to ‘All Configurations’ on the top, modify ‘Create/Use Precompiled Header’ to ‘Use Precompiled Header (/Yu)’, change the line which reads ‘StdAfx.h’ to ‘PrecompiledHeaders.h,’ and press ‘OK.’
Then right click on the ‘DWinLibBareApp.cpp’ file in the ‘Project’ filter. The same screen should reappear, although it is no longer nested as deep on the left side because we are working with the specific properties of that .cpp file, not the entire project. Again, select ‘All configurations’ at the top, and this time change the ‘Create/Use Precompiled Header’ option to ‘Create Precompiled Header (/Yc).’ This tells VSE to create the precompiled header when it compiles the ‘DWinLibBareApp.cpp’ file. (You can use other project files if you wish - feel free to play around on your own in the future and discover what happens.)
A rebuild results in a much faster compilation experience, quickly followed by a bunch of errors beginning with “
error LNK2019: unresolved external symbol "public: __thiscall FlexiCharWrap::~FlexiCharWrap(void).”
Investigating the problem, you will find a
FlexiCharWrap class defined in the DWinLib_3.01\CharArrayWrappers unit. We already added this directory to the project but the code / file is not yet included in the program.
To rectify, the .cpp files need to be manually added to the project. Before doing that let’s add a sub-filter to the DWinLib filter, to mirror the hard drive directory structure. As you did previously (although I didn’t give explicit instructions for the step), right click on the ‘DWinLib’ filter, select ‘Add -> New Filter,’ then change the name to ‘DwlControlWin.’
Navigate in Explorer to the ‘DWinLib_3.01’ subdirectory, select all the .cpp and .h files and drag them to the corresponding filter in VSE. Repeat this process for the files inside ‘DwlControlWin.’ You don’t have to create the subfilters, and can copy everything into the main DWinLib filter if you want to save some time, but if you ever modify the DWinLib files yourself you may appreciate the extra step. While Explorer is open to this location, copy all the files in ‘Utilities’ to the ‘Utilties’ filter we created earlier. (Or you can create a subfilter in the DWinLib filter, and mirror the hard drive organization if doing so pacifies your inner perfectionist.)
I cannot make myself kill the segregation of those subdirectories because they are logically independent items to an extent, and the subdirectories helps me remember how DWinLib works, as well as make finding things a bit easier.
Try to build the program again. This time the first error is “...fatal error C1083: Cannot open include file: 'WinMainO.h'...” The cause behind this is although the WinMainO.h file exists in the main project subdirectory (DWinLibBareApp), VSE doesn’t know it should use this directory on a project-wide basis, and the files outside the directory which include headers inside it are left in the dark. (Design reasons necessitate a bridge between the library and the application files of some sort.)
To fix, repeat the earlier inclusion step (right click on ‘DWinLibBareApp’...) and add the DWinLibBareApp subdirectory to the list, making sure you select ‘All Configurations.’ And press my favorite little green button once more.
This iteration, the first error is “
...error LNK2019: unresolved external symbol __imp__CreateToolbarEx@52 referenced in function "public: __thiscall DwlToolbar::DwlToolbar(class DwlControl *)" (??0DwlToolbar@@QAE@PAVDwlControl@@@Z).” The reason behind this is something new: VSE doesn’t know about the libraries required to build the program. Notice the ‘CreateToolbarEx’ portion of the error? Specifically, VSE doesn’t know to link to the common Windows controls library, which that toolbar (and other items) use.
To correct this, right click on the ‘DWinLibBareApp’ above the filters, select ‘Properties’ at the bottom again, change to ‘All Configurations’ at the top of the window which appears, navigate to ‘Configuration Properties -> Linker -> Input,’ and add “comctl32.lib Shlwapi.lib” to the ‘Additional Dependencies’ line. You can simply click on the line and add them, without having to select the ‘...’ button if you want. Then click on ‘OK,’ and once again rebuild the project. (If you are asking, ‘Shlwapi.lib’ handles a call to ‘PathFileExists’ in the DwlIniFile unit, which is another one of the errors shown.)
something amazing happens, and something drastic. The program actually executes!!!! Then the following error screen appears:
If you take the time to debug this, you will find the problem occurs when trying to add a "FILE_CLOSE" image to an ImageList in the Toolbar constructor. (Initial clues are deceptive because the error seems to occur in a
DwlDockManager::position() call.) Obviously, the previous steps haven’t added any resources to the project. Correct this by finding the ‘DWinLibBareApp.rc’ file, copying it to the project subdirectory, and then dragging it into the ‘Resource Files’ filter. Afterwards, press the mesmerizing little green button.
Pressing the button, a new problem appears. When compiling the resource the first error you will see is
DWinLibBareApp.rc(1) : error RC2135 : file not found: Graphics/Main.ico. All we need to do is copy the ‘Graphics’ subdirectory from the temporary directory (or the zip file) to DWinLibBareApp. While you’re at it, copy ‘Help’ as well.
If everything has been followed properly, you just finished all the required steps! Your screen will contain a new window as a result of all these efforts:
But there is still one more step to complete.
If ‘F1’ is pressed in the program, help doesn’t appear. This is because the directory needs to be copied into the ‘Debug’ directory. (It also needs to be copied into the ‘Release’ directory when you get that far.)
Once that is performed, you may be wondering about spiffifying the program to make the scrollbars and other elements look updated. The simplest way is to change the configuration settings to do a Unicode build. (The option is under ‘Configuration Properties -> General,’ ‘Character Set.’) See ‘DwlWinDefines.h’ for the code behind this.
Once that is done, pat yourself on the back. You have succeeded! Congratulations!
The preceding program’s executable file is located in the ‘Debug’ subdirectory of the ‘DWinLibBareApp’ program. Using VSE 2008, mine is 918 KB.
Don’t send debug versions of your program to customers. They contain information which makes reverse engineering your code much easier. Instead, at the minimum (if you are concerned with this matter), change the Solution Configuration to ‘Release’ rather than ‘Debug.’ The option is located at the top of the screen to the right of the green ‘Run’ button. With this configuration set, the executable size becomes 168 KB.
Another recommended step is to change the runtime library setting. After the above steps, to execute the program you will also need to find the ‘msvc__.dll’ file (if I remember correctly, disregarding the fact I don’t know the underscored characters), and place a copy in your user’s installation directory during the install process.
To get around this, open the project’s properties, navigate to ‘Configuration Properties -> C/C++ -> Code Generation’ and change ‘Runtime Library’ to ‘Multi-threaded (/MT).’ Only do this for the release configuration, not the debug version. After making the change and recompiling DWinLibBareApp, the size increased to 238 KB on my system.
That’s about all there is to the build process, although I should mention one more item in this regard. You may build DWinLib into a static library, eliminating many of the previous steps for including DWinLib in your projects. I have not played with this option because DWinLib has always been in a state of flux, but you should be aware of the possibility.
One potential obstacle of placing DWinLib in a library is DWinLib needs some information about your project. I don’t know if this throws a kink into the process, nor how difficult working around the issue will be, but I believe the bulk of the problem will be integrating ‘PrecompiledHeaders.h,’ which currently touches project and DWinLib files. If you tinker with this and succeed, please leave a comment.
The previous steps have outlined everything necessary to build a minimal DWinLib program from the provided sources. Working through the steps should have given you a greater familiarity with Visual Studio Express, and a little better understanding of what is needed to wrap the Windows API. The next article will explore some of the code in those files, and show one method to create Windows programs in a clean C++ object-oriented fashion.
2/13/2013 - Revised earlier article originally created in 2006 to reflect DWinLib 3.01. Modified to fit into the DWinLib series correctly. As everything is basically redone, and this is a major rewrite, the earlier revisions have been cleared.