Click here to Skip to main content
Licence CPOL
First Posted 6 Feb 2006
Views 42,973
Downloads 340
Bookmarked 19 times

Creating a bare DWinLib program in Visual C++ Express 2005

By | 21 Feb 2006 | Article
An article on setting up Visual C++ Express 2005 for WinAPI and DWinLib programs

Last update

2/21/06 - Updated code in zip file.

DWinLib2BareApp4.jpg

Introduction

The following article will go over the steps to build a basic DWinLib program from the files in the above zip file. The first part will include some basic Visual C++ Express 2005 (VCE) setup steps that make creating pure Win32 API programs easier, and may be helpful even to people not interested in using DWinLib.

The following may appear to be intimidating, as it is a rather long process. It takes me about eleven minutes to accomplish the second portion of the task while following the steps as I have outlined them. I therefore suspect that it will take you three to five times longer than that if this is your first time attempting this task. (And that doesn't include downloading and installing everything.)

You might ask if it is worth your time to follow these steps, as a project file is included in the zip file. If you are new to Visual Studio, I believe the following 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.

If you are familiar with Visual Studio, the following may not be so helpful, but the completed project may be of interest to you, as it will show 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 'fake' a MDI interface in Windows, how to integrate a DWinLib program with XP themes, how to create a flicker-free docking window system, and many other items.

Once completed, the bare application can easily be extended to create your own application.

Preliminaries

The first steps, of course, are downloading and installing VCE and the Platform SDK. The Platform SDK can either be downloaded from the Windows® Server 2003 SP1 Platform SDK Web Install page, or downloaded and installed from the ISO image directly. These links are not guaranteed, and I will not go over installing these items in this article.

I recommend downloading the ISO images for both packages. I believe it is listed as the manual install option on the VCE page. Be warned, as these are rather large downloads.

As this is being written, Microsoft is giving VCE away for free, so it is an incredibly good deal, although Microsoft has stated that this deal will only last until November, 2006. (And yes, the license states that you can create and sell commercial applications made with your free copy.)

In addition to these programs, a bare DWinLib program relies upon part of the boost library, so download and install the newest version of boost. You do not need to go through the extended boost Jam process - DWinLib only relies upon the bare libraries.

Setting up the default linker settings

When you create a console window project in VCE, the project is defaulted to only linking to 'kernel32.lib'. Unless you make some setting changes to VCE itself, you will have to manually add many standard Windows libraries into the dependencies. The following will eliminate this step, although you will still need to link to any non-standard libraries, such as DirectX, yourself.

First, find the 'default.js' file inside 'VC\VCWizards\AppWiz\Generic\Application\scripts\1033' Visual Studio directory. Find the two lines that contain the word 'kernel32'. Insert "user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib" between the 'kernel32.lib' and the '$(NoInherit)' in both lines.

Now open the 'corewin_express.vsprops' files in the 'VC\VCProjectDefaults' Visual Studio directory. Again, find the line with 'kernel32' in it, and insert the same string behind 'kernel32.lib', before the ending quotation mark.

That's it for this step. All your future console projects will automatically list these default libraries in their dependencies.

Setting up the help files inside VCE

Visual Studio has the ability to give context sensitive help based upon the word at the cursor when F1 is pressed. To add the Platform SDK help files to the files that Visual Studio looks in, open Visual Studio and press F1. After the Document Explorer opens, paste the following link into the URL location: ms-help://MS.VSExpressCC.v80/dv_vsexpcc/local/CollectionManagerExpress.htm.

At the bottom of the page that appears, there will be an option to add the Platform SDK help files to the help system. Select that option, and then press OK when it tells you that everything will need to be restarted. Then close the Document Explorer and Visual Studio. Reopen VCE and press F1 again. The Document Explorer will tell you that it is reconfiguring itself with the new help files.

You will note when using the help files that Microsoft is placing more emphasis upon the .Net framework than upon the WinAPI. Many help topics that you would assume should open up as API topics will default to the .Net counterpart. Google will often work better then the help files in these cases. (We can assume that this situation is only going to get worse in the future.)

I have also heard that it is possible to decrease the time it takes for the Document Explorer to open when F1 is pressed. The method that has been given is to click on the 'Tools -> Visual Studio 2005 Command Prompt' menu items, and then navigate to the "C:\Program Files\Common Files\Microsoft Shared\Help 8" directory in the command prompt window that appears, and then type 'for /r %f in (*.dll,*.exe) do ngen "%f"'. The Document Explorer will supposedly open much faster. When I did this I just got a bunch of error messages like the following:

Failed to find dependencies of image C:\Program Files\Common Files\Microsoft Shared\Help 8\dexplmnu.dll because this image or one of its dependencies is not a valid Win32 application.<br />Compiling 1 assembly:<br />Compiling assembly C:\Program Files\Common Files\Microsoft Shared\Help 8\dexplmnu.dll ...<br />Error compiling C:\Program Files\Common Files\Microsoft Shared\Help 8\dexplmnu.dll: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)

It also failed to load any faster. (The Document Explorer takes about thirty seconds to open after VCE is first opened and F1 is pressed on my system. Future openings occur almost instantaneously, until VCE is closed.)

Setting up the default directory settings

It is necessary to point VCE to the 'Include' and 'Lib' directories that were installed in the platform SDK installation step. To do so, open VCE and select the 'Tools -> Options' menu items. Then select the 'Projects and Solutions -> VC++ Directories' item in the left frame, and select the 'Show directories for: drop-down combo box. Select 'Include files', and select the 'New Line (Ctrl-Insert)' icon. Then select the '...' button at the right of the new line, and navigate to the 'Include' directory that the Platform SDK installation installed. Select 'Open' in the directory selection window, and then change the 'Show directories for:' dropdown combo box to 'Library files', and repeat the process, this time selecting the 'Lib' directory off the Platform SDK installation directory. When finished, press the 'OK' button in the options window.

This step only needs to be performed once. All future projects will use this setting.

While you are in the Options window, you might want to enable Build Timing, so VCE will notify you how long your build takes. That option is in the 'Projects and Solutions -> VC++ Project Settings' section.

Creating and setting up your project

Creating

The next thing to do is to create a blank project. We will drag pre-existing files into this project, so we won't have to create the code from scratch.

First, extract the contents of the above zip file to your hard drive. Keep this close to the DWinLib subdirectory created during the unzipping of the 'DWinLib.zip' file on the DWinLib: An Overview page. (I am not going to place that file on more than one of these tutorial pages, as I don't want to have to remember to update multiple items in the future, and that page makes the best home.)

I recommend a subdirectory structure something like this, and the zip file will reflect it:

DWinLib2BareApp1.gif

You might be tempted to place the 'DWinLib' subdirectory in the 'DWinLibBareApp' directory. It will work that way, but a lot of experience has taught me not to do it. That method ties the 'DWinLib' contents to the DWinLibBareApp project, which is fine when you will only use the DWinLib files in the DWinLibBareApp project. But I found that when I used DWinLib in many projects, and I started making changes to DWinLib in some of those projects, I started losing my changes as I switched between projects. It was much easier to work from one common DWinLib directory and chase the changes through all the projects. Doing so will also save more than 400 Kb of hard drive space per project, although in with the ample hard drives of today, that is not an issue.

Next, create a blank C++ project in VCE. Select the 'File -> New Project' menu items, and then select the 'General' project type in the left pane, and select 'Empty Project' in the right pane. (This is easier than selecting 'Win32' in the left pane for several reasons I won't discuss.)

VCE makes part of this step a little perplexing. You must enter a name in the 'Name:' portion of the New Project dialog. VCE also prompts you to create a new subdirectory for the solution. We will not use that option, so uncheck that menu item. The 'Solution:' box will become inactive, but VCE will STILL create a subdirectory off of wherever you have browsed to in the location box in order to place this 'solution' you are creating.

Therefore, if you want to create your project (or solution, or whatever you want to call it) in 'D:\Programs\DWinLibExamples\DWinLibBareApp', and that directory already exists, you must browse to 'D:\Programs\DWinLibExamples', press the 'Open' button, and then type 'DWinLibBareApp' into the 'Name:' box of the New Project dialog box. If you want the solution to have a different name than the subdirectory containing it, you will have to rename the solution after it is created, and this can only be done by clicking on the 'Solution 'DWinLibBareApp'' line in the Solution Explorer to highlight it, and then selecting the 'File -> Save DWinLibBareApp.sln As...' menu items, as far as I can tell.

The next recommended step is to add some filters to the Solution Explorer, in order to keep the files better organized. (VCE calls them 'Filter's, but they look more like files.) Right-click on the 'Source Files' filter in the Solution Explorer, and select the 'Add -> New Filter' menu items. As shown below, I usually add 'aaa', 'DWinLib', and 'utilities' filters. 'aaa' is used simply to keep the main source files separated from the DWinLib files, and at the top of the filter list.

DWinLib2BareApp2.jpg

We are now ready to drag the appropriate files into this project. If you don't already have Windows Explorer (or your own preferred equivalent to this program) open, open it. (I always set up my machine so that Explorer opens when Windows opens. It is probably the most used of all Windows programs.) Navigate to the 'D:\Programs\DWinLibExamples\DWinLibBareApp' directory (or whatever you have extracted it to), and then drag all of the files that are not VCE files into the 'aaa' filter. (The VCE files are the .suo file, .vcproj file, .ncb file, .user file, and the .sln file.)

Then in the Solution Explorer, drag the 'HelpFileConstants.h', 'IncludeAccelerator.h', 'PrecompiledHeaders.h', and 'ProgramHeaders.h' files into the 'Header Files' filter. Lastly, drag the 'BareApp.rc' file into the 'Resource files' filter. The Solution explorer should now look like this:

DWinLib2BareApp3.jpg

With that, we are finally ready to start modifying the solution properties for this project.

Setup

Double-click on any .cpp file in the 'Source Files' 'filter' to bring up the file in the editor. Then click anywhere on the editor. You can now open the Project Properties window by clicking on the 'Project -> [ProjectName] Properties... Alt+F7' menu items (or just press 'Alt+F7', but it is not a keystroke that sticks with my mind).

Change to 'All Configurations' - Click on the 'Configuration Properties' section in the left side of the window. Then select 'All Configurations' in the 'Configurations' dropdown box near the top of the window. This will make the following changes apply to both the Debug and Release versions of your program.

Unicode - Double-check to make sure that the 'Configuration Properties -> General', 'Character Set' is set to 'Not Set'. If you want to use Unicode, uncomment the '#define UNICODE' and '#define _UNICODE' lines in the 'ProgramHeaders.h file, rather than changing anything in this section.

Additional libraries - Go to 'Configuration Properties -> C/C++ -> General' section, click on 'Additional Include Directories' at the top of the right pane, and click on the '...' button that appears at the right of the entry area. Click the 'New Item' icon, and then press the '...' button that will appear. Navigate to the top of the boost library hierarchy on your hard drive (ie - to inside the 'boost_1_33_0' or whatever your installation was), and press 'OK'. (You can include any other directories at this point, and as we will see in a bit, there are a few more that need to be included at this point, but it will be informative to see what happens when they are left out.)

Debug Information Format - Go to the 'Debug Information Format' topic in the 'Configuration Properties -> C/C++ -> General' section. Change it to 'Program Database (/Zi)'. This is one of the items that allows you to place breakpoints in your code, and perform proper debugging of your program.

Disable 64 bit Portability Issues - You may also want to disable the 'Detect 64-bit Portability Issues' item if you don't plan on creating 64 bit executables. To disable 64 bit checks, in the 'Configuration Properties -> C/C++ ->General' section from the last step, change the 'Detect 64-bit Portability Issues' to 'No'. (This may already be set to 'No'.).

DWinLib has been revised so it should properly build a 64-bit executable. This has not been tested, because I have not needed it, but if you do create a 64-bit application, and have to modify a 64-bit portion of DWinLib, please notify me of the updates, so I can modify the zip file.

You will note that there are some #pragma warning (disable XXXX) lines in DWinLib to disable some 64-bit warnings. These were necessitated by the fact that Microsoft's PSDK headers still cannot tell whether you are building a 64-bit application or not, and using Get/SetWindowLongPtr will leave you with warnings that cannot be worked around any other way than disabling the warnings. For more on this, Google on the following: SetWindowLongPtr "'LONG' to 'WNDPROC'".

For more on creating 64 bit executables within VCE, see this link. (Thanks go to James Gardiner for pointing that link out.)

Precompiled Headers - DWinLib uses a 'PrecompiledHeaders.h' file that is used where Microsoft uses 'stdafx.h'. Change this in the 'Configuration Properties -> C/C++ -> Precompiled Headers', 'Create/Use PCH Through File' option. The 'Create/Use Precompiled Header' option must also be set to 'Create Precompiled Header (/Yc)', but that is usually the default.

Manifest - It does not appear that the default manifest VCE embeds adds any size overhead to your application. It also does not appear to do anything for XP theming. So it does not appear to be worth changing the default manifest embedding, unless you want to save two seconds on your compile times. If you do, you can change it in the 'Configuration Properties -> Linker -> Manifest File' section.

As I write this, I have only tested once to see whether this option will enable you to embed a manifest of your own creation into an application. My test was not successful, but I may have missed something simple. I have yet to see any good information on this topic, although I haven't looked for it. The only way I have gotten XP manifest theming compliancy is by adding an '[AppName].exe.manifest' file to the directory in which your application resides.

Debugging - If you want debugging information to be created for both Debug and Release versions, go to 'Configuration Properties -> Linker -> Debugging', 'Generate Debug Info', and change it to 'Yes (/DEBUG)'. If you only want debugging information for the Debug version, change this setting at the same time as the below 'Change Debug DLL' section. (There is a reminder in that section for you.)

Windows Subsystem - Go to 'Configuration Properties -> Linker ->System' page. Then choose 'SubSystem' on the right pane, and select 'Windows (/SUBSYSTEM:WINDOWS)'.

Code Generation - If you don't want to redistribute MSVCR80.dll (480 kb) with your application, you will have to change the default multithreading libraries VCE compiles your app with to enable users without the newest DLLs to run your app. First, tell VCE to accept the changes you have already made by pressing the 'Apply' button in the lower right of the Properties Pages window. After that:

  • Change Debug DLL - Change the Configuration to 'Debug'. Then change the 'Configuration Properties -> C/C++ -> Code Generation' setting to 'Multi-threaded Debug (/MTd)'. Here is a good place to check the 'Generate Debug Info' for the Debug version, as mentioned above, if you want debugging information for only the Debug version. I have seen VCE set this to both 'Yes' and 'No' for blank projects. After checking and changing if necessary, press the 'Apply' button.
  • Change Release DLL - Change the Configuration to 'Release'. Then change the 'Configuration Properties -> C/C++ -> Code Generation' setting to 'Multi-threaded (MT)'. (This setting has also been set correctly sometimes.) Press 'OK' to drop back to VCE.

Set Precompiled Header File - It is now necessary to select one file which, when compiled, will make VCE compile the precompiled header. I do not know if it makes any difference which file you select, but I usually use the main project file (the one that contains WinMain). So right-click on the BareApp.cpp file in the Solution Explorer, select 'Properties', change the configuration selection to 'All Configurations', go to the 'Configuration Properties -> C/C++ -> Precompiled Headers' page, and change the 'Create/Use Precompiled Header' option to 'Create Precompiled Header (/Yc)'. You are done with this part of the setup, but here are some FYIs for you.

There is a '#pragma warning (disable:4996)' line in the 'ProgramHeaders.h' file that DWinLib uses. This pragma does the same thing as the preprocessor directive "_CRT_SECURE_NO_DEPRECATE". This quiets the compiler warnings about a bunch of functions that Microsoft has decided to deprecate, even though the C++ standardization committee has not done so. As long as you use the functions correctly, you will not incur any buffer overruns. As far as I know, using the new functions will tie your application to the MSVCR80.dll, although this may not be an issue if you don't dynamically link to the multithreaded libraries. (I have not tested this in any way. Theoretically, statically linking should overcome this issue, but there may be other issues involved I am not aware of, and have not tested.)

You may be tempted to toss "_CRT_SECURE_NO_DEPRECATE" into the 'Configuration Properties -> C/C++ -> Preprocessor ->Preprocessor Definitions', 'All Configurations' section. Unfortunately, this will kill the standard 'Debug' and 'Release' preprocessor strings, and the easiest work-around I have found is to use the ProgramHeaders.h file as I have. (You could also insert this directive directly into both the Release and Debug sections independently if you so desired, and that would overcome this annoyance.) If you do play with this, and lose your original settings, they were: 'Debug: WIN32;_DEBUG;_CONSOLE', and 'Release: WIN32;NDEBUG;_CONSOLE'.

A general FYI about the 'All Configurations' usage is that it is often best to not add a common setting by using the 'All Configurations' option, as it is confusing. Instead of adding the options selected in 'All Configurations' into the Release and Debug configurations, the settings selected in 'All Configurations' will replace the existing settings in the Debug and Release configurations. This is not often what you want.

Adding files and other stuff

So far, the only files we have are the bare application specific files. We don't have the necessary DWinLib files, nor the utility files that DWinLib needs for some functions.

Build the solution - What I do at this stage is to press the 'Build -> Build Solution F7' menu items to build the project as it stands, and then solve each error message that comes up. Doing so, the first error message is:

...PrecompiledHeaders.h(5) : fatal error C1083: Cannot open include file: 'DWinLib.h'...

Fix the 'Additional Include Directories' - This is because the compiler is looking for the DWinLib.h file, which simply contains a list of the DWinLib header units that are completed, and can be added to the precompiled header (PCH). The files we added earlier include that file through the #include "PrecompiledHeaders.h" line at the top of them, but we haven't told the compiler where to find DWinLib.h. The way to tell the compiler that information is to repeat the 'Additional libraries' step above, making sure to again set it to 'All Configurations', and then add the DWinLib directory to the list.

If you continue to attack these problems one at a time, the string in the Additional Include Directories will eventually look something like the following: D:\Programs\DWinLibExamples\BareApp; D:\Programs\DWinLib\WinControlWin; D:\Programs\utilities; D:\Programs\DWinLib; D:\Programs\utilities\boost\boost_1_33_0. You can simply paste the previous line into the edit box that already contains the path to the boost libraries, and then modify each item appropriately for your system. (I have also placed spaces between each ';' and the next 'D', compared to the exact string in the edit box, in order to wrap this article. A test shows that it is OK to leave the spaces, but as always, there are no guarantees.)

Rebuild the solution - Press the 'Build -> Build Solution F7' menu items again, and you will be happy to see the compiler do a lot of work, and actually attempt to link the program. Hooray! - We are getting there. But you will then get many link errors. The first one I got was Application.obj : error LNK2019: unresolved external symbol "public: void __thiscall WinAppKeeper::removeApp(class Application *)" (?removeApp@WinAppKeeper@@QAEXPAVApplication@@@Z) referenced in function "public: __thiscall Application::~Application(void)" (??1Application@@QAE@XZ).

Add DWinLib files - This is due to the fact that even though we have told the compiler where to find the header files, we have not told the compiler what files to include. To overcome this, you can either drag all of the files from the 'DWinLib' and 'DWinLib\WinControlWin' directories into the 'Source Files -> DWinLib' filter in the Solution Explorer, or we can drag only the files that the linker complains about. I usually go the second route, as the compiler won't have to rebuild the files that aren't really necessary for the project to compile when a complete rebuild is triggered. This will save you time in the long run.

(Of course, you could also create a library file, and just add the library file to your project. I won't go into how to do that here.)

For this example, I recommend going the first route, and dragging all the files from the Windows Explorer 'DWinLib' and 'DWinLib\WinControlWin' subdirectories into the 'DWinLib' Solution Explorer filter. When you create a project for yourself, I recommend the second route. Going the first route is a somewhat time-consuming task.

Rebuild the solution - After you do so, then press the 'Build -> Build Solution F7' menu items again, and you will be happy to see only a handful of linker errors left. (Twenty-three on my machine.) These items boil down to two issues.

Add final file dependencies - The first issue is that the program also relies upon the 'CharArrayWrappers' unit, the 'RMW_Utilities.cpp' unit and the 'VisualStylesXP.cpp' unit in the 'utilities' subdirectory. To fix that, drag those files from the 'D:\Programs\utilities' directory (or wherever you placed it) into the 'Source Files -> utilities' Solution Explorer filter. (I usually drag the header files as well, so I can double-click them in the Solution Explorer to open them up.)

Add 'comctl32.lib' - The second issue is the fact that the project relies upon the comctl32.lib library. Select the 'Project -> DWinLibBareApp Properties... Alt+F7' menu items, change to 'All Configurations', navigate to the 'Configuration Properties -> Linker -> Input' section, and paste comctl32.lib into the 'Additional Dependencies' edit box.

Build the solution and run the executable - Press the 'Build -> Build Solution F7' menu items (or just press F7). If you have followed the above steps correctly (and if I haven't missed anything), the 'Output' window will show everything get compiled and linked, and at last you will get a 'Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped' message. At that point, you can press F5 to run the program, and you are done. Congratulations!

Conclusion

We have seen that a minimal windows wrapper is comprised of many items, and putting them together inside VCE takes some doing. I hope that the above has not been too intimidating, and that it proves useful in your programming toolkit. If you use another framework, I hope that this exposition has given you a better appreciation of some of what that framework does.

And in case you are asking yourself, "Why did we have to include so many files for such a minimal wrapper?," I encourage you to tear into some of the units you question, and see the dependencies for yourself, and why DWinLib is designed the way it is. The more you dig, the more I believe you will appreciate everything that is needed for a minimal application.

History

2/14/2006 - Added 'Setting up the default directory settings' section. Also pointed to information on creating 64 bit executables in VCE in the 'Disable 64 bit Portability Issues' topic. Thanks go to James Gardiner for pointing out that I had missed that step, as well as the 64 bit creation information. James also pointed to this page for enabling ATL and WTL within VCE, and that may be helpful to some of you. He indicated that with some thunking, it appears to be possible to use ATL and WTL in 64 bit code, although no details were given.

2/19/2006 - Modified 'Disable 64 bit Portability Issues' section to reflect that DWinLib has been updated so it should build 64-bit applications cleanly.

2/21/2006 - Updated code in zip file so window list menu worked in a more standard manner. Also modified window list menu so that when a child window is maximized and a non-maximized window is selected through the window list, the selected window would become maximized.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

RandomMonkey

Web Developer

United States United States

Member

Just another hardworking guy who also went by the name of David O'Neil once.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralResource Editor in VCE PinmemberLysy9521:53 21 Feb '06  
GeneralRe: Resource Editor in VCE PinmemberRandomMonkey1:27 22 Feb '06  
GeneralRe: Resource Editor in VCE PinmemberLysy9520:46 22 Feb '06  
GeneralRe: Resource Editor in VCE PinmemberRandomMonkey19:01 23 Feb '06  
GeneralWindows® Server 2003 SP1 Platform SDK Pinmemberemilio_grv23:57 14 Feb '06  
GeneralRe: Windows® Server 2003 SP1 Platform SDK PinmemberRandomMonkey2:58 15 Feb '06  
GeneralRe: Windows® Server 2003 SP1 Platform SDK PinmemberBassam Abdul-Baki17:34 20 Feb '06  
I ran the SDK installer a dozen times, and redownloaded it a couple of times. It finally worked today for some reason.
 
"If only one person knows the truth, it is still the truth." - Mahatma Gandhi Web - Blog - RSS - Math

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web03 | 2.5.120528.1 | Last Updated 21 Feb 2006
Article Copyright 2006 by RandomMonkey
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid