Simple guide to basic Doxygen usage

Make sure to also check out part 2 of this tutorial, “Simple Doxygen templates” for many useful templates and tips.

This is a simple guide to basic use of Doxygen-compliant commenting of source code. The guide is written from my point – C/C++ – but it’s valid for all supported languages, except of Python. See Doxygen documentation for use for Python. Doxygen is very flexible when it comes to the form of how the documentation is written, the layout presented here is simply my preference.

Continue reading

How to Change Print Orientation in MFC

There is no big science to it, but thanks to a “bad choice of title”, the appropriate MSDN-KB-HOWTO article is not easy to find. So, here’s a link:

MSDN KB 126897: How to Change Default Printer Settings in an MFC Application

The above link takes you directly to the code snippet that sets print orientation to landscape; to change the orientation to portrait, you only need to change the DMORIENT_LANDSCAPE to DMORIENT_PORTRAIT; of course, the easiest way is to change the function to allow user to choose the orientation.

Note: The presented code, of course, also changes the orientation of the print preview.

To use the above code, simply surround your printing (or print preview) code with (provided you changed the function to accept bool to choose orientation, and to return previous setting):

CMyApp* app = (CMyApp*) ::AfxGetApp();
bool old_po = app->SetPrintOrientation(*your choice of orientation*);
// printing (or print preview) code comes here
app->SetPrintOrientation(old_po);

Note: So far, I didn’t manage to find a way to change the print orientation for individual pages; seems like you have to print portrait and landscape oriented pages in separate print jobs (?).

How to Find Shell (System) Folders in Win32 from C/C++

It’s possible to refer to e.g. My Documents folder on your own computer by the path you know, and it’ll work. But if you want to distribute your program among users, you cannot expect the fixed path to work. E.g. Windows allow you to save user’s profile folders anywhere on the disk you want; it’s not a rule that all are saved under Documents and Settings; e.g. mine are saved under folder called Profiles, since I wanted to preserve the original Documents and Settings from my previous Windows installation. Also, Windows need not to be installed under C:\Windows; mine are under C:\Windows.1.

But, there is a (quite) simple way to find all the necessary system folders in Windows. All you have to do is be a bit careful.

Continue reading

Visual Assist X – what a tool!

This is my break off work, since yet again I found myself amazed by how the Visual Assist X (VAX) is… no, there is no strong enough superlative to describe it! I just wanted to share this jewel with those people that might not know what VAX is.

VAX is Visual Studio plug-in (all popular versions – VS6, VS2002, VS2003, VS2005 and newly also VS2008 – supported) that saves you nerves, time, and also saves you from quite a few bugs along the way. See more at the official site.

Are you tired of the pointless or totally wrong hints IntelliSense gives you (yes, it got better in VS2005 and VS2008, but still…)? Are you tired of switching between files, trying to find the prototype you need, definition of class, or even just where you were moment ago?

VAX is a program of (almost) infinite possibilities. Except of being “the really intelligent IntelliSense”, it provides many refactoring facilities, for any variable provides you with info about its type, in VAX panel shows you member of variables, provides you with definitions of macros (and knows how to work with them, unlike IntelliSense), speeds up typing (e.g. if you type in MFC dialog class gdi, it right away provides you with GetDlgItem as hint), go to definition and declaration (no need to generate the useless Browse Info anymore!) and much MUCH more…

One thing that might seem totally pointless, but that really made me happy when I found out it’s in VAX – the “go back” function (just like in your web-browser) to get back to where you were before you e.g. skipped to declaration of a function. It sure saves a lot of time and nerves, to fast find where you were moment ago.

Of course, VAX is only a program, and as such has also its little “problems”; for me, main problem (and the only I so far faced!) is its confusion while working with templates; esp. while working on template metaprogram, it’s easier to switch it off. Yet of course, even the best and newest compilers get often confused around templates, not to mention humans… 😉

What more to say? Just go to the official site and check out the trial version!
One warning – price of full version, for individuals, is set at $99; if you don’t want to, or can’t afford to, spend 100 bucks on piece of software, do NOT download the trial! Once you go VAX, there’s no going back… For real, no kidding.

One link to end off the praise – example of refactoring abilities of VAX.

Using NASM in Visual Studio 6 and 2003.NET

Once you’ve obtained the Win32 archive for NASM, nasmw-inst-xxx.exe (where xxx denotes the version number of NASM contained in the archive), install the NASM into its own directory (for example “C:\Program Files\NASM”).

The archive will contain two executable files: the NASM executable files nasmw.exe, and the NDISASM executable files ndisasm.exe and ndisasmw.exe. In each case, the file whose name ends in w is a Win32 executable, designed to run under Windows 95 or Windows NT Intel.

Since 0.95.36, NASM is fully officially compatible with Microsoft Visual Studio 6/2003.NET.

Integration within Microsoft Visual Studio 6

  • In Tools/Options/Directories , select “Show directories for:” into “Executable files”. Add a new path “C:\Program Files\NASM” (or where you have installed NASM).
  • In your project workspace, create a new folder “Assembler Files”.
  • On this folder, right click and select “Settings”.
  • In General, enable “Always use custom build step”.
  • In Custom Build, change the following settings:

Commands:
nasmw.exe -f win32 -Xvc -o "$(IntDir)$\(InputName).obj" $(InputDir)\$(InputName).asm

Outputs:
"$(IntDir)$\(InputName).obj"

Integration within Microsoft Visual 2003.NET

  • In Tools/Options/Projects, Select “VC++ Directories” and “Show directories for:” “Executable files” – should be the default. Press Ctrl+Insert or press the “New Line” icon. Select the path “C:\Program Files\NASM” (or where you have installed NASM).
  • In your project workspace, create a new folder “Assembler Files”.
  • On this folder, right click and select “Settings”.
  • In General, enable “Always use custom build step”.
  • In Custom Build, change the following settings:

Commands:
nasmw.exe -f win32 -Xvc -o "$(IntDir)\$(InputName).obj" $(InputDir)\$(InputName).asm

Outputs:
"$(IntDir)\$(InputName).obj"

Using Inline Assembler in C/C++ Code

.asm file:

[bits 32]
[section .bss align=16]
[section .data align=16]
[section .text align=16]
[global _myFunction]
_myFunction:
push ebp
mov ebp,esp
mov eax, [ebp + 8] ; your code goes here, instead of this line...
pop ebp
ret
END

in .c/.cpp file call the function:

under MSVS:

int cdecl myFunction(int parameter);

under GCC you’d call the function with ‘_’ prefix:

int _myFunction(int parameter);

For more information see NASM Documentation, chapter 8.

Get IP of local (host) computer

Often when programming simple TCP/IP server (for monitoring of services and other non-GUI-based applications, etc.) we need to know IP of the host computer so that clients can connect to it; to retrieve this IP from within the server-side program, use the following snippet:

WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 0);

if (WSAStartup(wVersionRequested, &wsaData ) != 0)
{
    printf("WSAStartup() failed!n");
    return 0;
}

// Get the local host information
hostent* localHost = gethostbyname("");
char* localIP = inet_ntoa(*(struct in_addr *)*localHost->h_addr_list);

printf("Local host IP is: %sn", localIP);

WSACleanup();

Includes
WinSock2.h, Ws2tcpip.h

Link libraries
ws2_32.lib

Once I get some time on my hands, I’ll clean up and post the code of my WinSock-based TCP/IP library for simple development of both server and client side.

How to create table in MSSQL only if it does not exist

Often you wanna make sure some tables in database exist, but you want to avoid getting the error message “There is already an object named ‘yourtable’ in the database.”, that you would get by simply issuing the CREATE TABLE command.

For these cases, MSSQL offers keyword EXISTS (most SQL engines provide similar facilities; e.g. MySQL C API allows you to directly check for the existance of database and/or table).

All you have to do in MSSQL is make sure the table is not yet registered in the sysobjects table, using the following SQL command:

IF NOT EXISTS (SELECT * FROM sysobjects WHERE id = object_id(N'[dbo].[tablename]')
AND OBJECTPROPERTY(id, N'IsUserTable') = 1)
CREATE TABLE [dbo].[tablename] ( columns specification );

where “tablename” is name of table you want to create, and “columns specification” is the usual definition of table’s columns. Feel free to extend the table definition to your liking.

Or you might want to DROP the table before re-creating it:

IF EXISTS (SELECT * FROM sysobjects WHERE id = object_id(N'[dbo].[tablename]')
AND OBJECTPROPERTY(id, N'IsUserTable') = 1)
DROP TABLE [dbo].[tablename];
CREATE TABLE [dbo].[tablename] ( columns specification );

Yes, that’s all. Good luck!

Precise time measuring on Win32

Windows provide means for a more precise time measurement than just the standard C-function clock().

The basic definitions and declarations are as follows (typedef is for readability):

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

typedef LARGE_INTEGER timeStamp;

void getCurrentTimeStamp(timeStamp& _time);
timeStamp getCurrentTimeStamp();
double getTimeMili(const timeStamp& start, const timeStamp& end);
double getTimeSecs(const timeStamp& start, const timeStamp& end);

Notes:
* LARGE_INTEGER is 8B big, so it’s faster to use reference than direct copy, but this may vary compiler to compiler – test before using!
* Value stored in LARGE_INTEGER variable is by itself useless – it’s something of the sort “number of ticks since the computer booted”; but two of them define interval with quite a useable resolution. (check MSDN for more info)

Usage is trivial – to measure intervals, simply use one of getCurrentTimeStamp() functions to get current “timestamp” of beginning and end of interval, and then use getTimeMili() go get interval’s length in miliseconds, or getTimeSecs() for length in seconds.

Implementation pretty much just uses what’s readily available (both versions of getCurrentTimeStamp() are obvious candidates for inline‘s):

void getCurrentTimeStamp(timeStamp& _time)
{
    QueryPerformanceCounter(&_time);
}

timeStamp getCurrentTimeStamp()
{
    timeStamp tmp;
    QueryPerformanceCounter(&tmp);
    return tmp;
}

double getTimeMili(const timeStamp& start, const timeStamp& end)
{
    timeStamp dwFreq;
    QueryPerformanceFrequency(&dwFreq);
    return double(end.QuadPart - start.QuadPart) /
        double(dwFreq.QuadPart) * 1000;
}

double getTimeSecs(const timeStamp& start, const timeStamp& end)
{
    timeStamp dwFreq;
    QueryPerformanceFrequency(&dwFreq);
    return double(end.QuadPart - start.QuadPart) / double(dwFreq.QuadPart);
}

Note:
* The QueryPerformanceFrequency(&dwFreq); in getTimeMili() returns the same value on each call – storing this value at the start of the program might be a good idea. (most probably – on multiprocessor computers this might be false!)

How to prevent dialog from closing on Enter/Escape in MFC

Implicit behaviour of dialogs in MFC is, that the dialog closes when user presses <Enter> (equivalent to pressing “OK” button) or <Escape> (“Cancel” button).

To prevent this, you have to override dialog class’ PreTranslateMessage() function, and use the following code to “translate” the <Enter> and <Escape> keys to <Tab> key:

BOOL CMyDialog::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->message == WM_KEYDOWN)
    {
        if ((pMsg->wParam == VK_RETURN) || (pMsg->wParam == VK_ESCAPE))
            pMsg->wParam = VK_TAB;
    }
    return CDialog::PreTranslateMessage(pMsg);
}