How To Get The Screen Resolution In Pixels

January 7, 2009

The function GetWindowRect(), defined in WinUser.h, is able to give the current screen resolution. The declaration of GetWindowRect() is


BOOL
WINAPI
GetWindowRect(
    __in HWND hWnd,
    __out LPRECT lpRect);

We can give a handle to the current desktop window to the above function as input. A sample implementation for getting the current screen resolution is given below.

#include “wtypes.h”
#include
using namespace std;

// Get the horizontal and vertical screen sizes in pixel
void GetDesktopResolution(int& horizontal, int& vertical)
{
   RECT desktop;
   // Get a handle to the desktop window
   const HWND hDesktop = GetDesktopWindow();
   // Get the size of screen to the variable desktop
   GetWindowRect(hDesktop, &desktop);
   // The top left corner will have coordinates (0,0)
   // and the bottom right corner will have coordinates
   // (horizontal, vertical)
   horizontal = desktop.right;
   vertical = desktop.bottom;
}

int main()
{       
   int horizontal = 0;
   int vertical = 0;
   GetDesktopResolution(horizontal, vertical);
   cout << horizontal << '\n' << vertical << '\n';    return 0; } [/sourcecode]


How To Get All CD Drives

November 19, 2008

In the last post, I described how to open/close cd tray. Some of you might have raised your eye brows as there is no description how to find the drive letter of cd drive. Here is a sample program which prints all cd drive letters in a system.

#include
#include
#include “wtypes.h”
#include “basetsd.h”
#include “winbase.h”
using namespace std;

int main()

   // Iterate through all the 26 drives possible  
   for (char Drive = ‘a’; Drive <= 'z'; ++Drive)    {       // Format drive like "c:\"       string StrDrive = "";       StrDrive.push_back(Drive);       StrDrive.append(":\\");       // Print the drive letter if it is a cd drive       if (DRIVE_CDROM == GetDriveType(StrDrive.c_str()))       {          cout << Drive << '\n';       }    }    return 0; } [/sourcecode]

Some Background Info

The GetDriveType() function can give the type of a drive. The possible values are given below.

  • DRIVE_UNKNOWN = 0 : The drive type can not be determined.
  • DRIVE_NO_ROOT_DIR = 1 :The root path is invalid; for example, there is no volume is mounted at the path.
  • DRIVE_REMOVABLE = 2 : The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader.
  • DRIVE_FIXED = 3 : The drive has fixed media; for example, a hard drive or flash drive.
  • DRIVE_REMOTE = 4 : The drive is a remote (network) drive.
  • DRIVE_CDROM = 5 : The drive is a CD-ROM drive.
  • DRIVE_RAMDISK = 6 : The drive is a RAM disk.

The GetDriveType() function expects an argument of type LPCTSTR, which can specify the root path of the drive with a trailing slash (as in c:\). if the argument is NULL, it will take the root of the current directory.

GetDriveType() will be expanded to GetDriveTypeW (for UNIODE) and GetDriveTypeA (for ANSI). The macro _T() can automatically expand the argument to multibyte character string if unicode is defined.


How To Get Files in a Directory

September 17, 2008

VC++ provides two API’s FindFirstFile and FindNextFile to get files in a directory. You can specify the file name(s) to be searched in terms of wild cards as well to match your criteria. See the following example.

#include
#include
#include
using namespace std;

int main()
{  
   HANDLE FindHandle = INVALID_HANDLE_VALUE;
   WIN32_FIND_DATA FindData;
   string FileName = “.\\*.*”;   // . specifies the current directory
   FindHandle = FindFirstFile(FileName.c_str(), &FindData);
   if (INVALID_HANDLE_VALUE != FindHandle)
   {
      do
      {
         cout << FindData.cFileName << '\n';               } while (FindNextFile(FindHandle, &FindData) != 0);       FindClose(FindHandle);    }    return 0; } [/sourcecode] You can call the GetLastError() function to see why the while loop has finished. If the result of GetLastError() is ERROR_NO_MORE_FILES, there is no more file matching the criteria in the specified directory and hence it is not an unexpected error.


Getters and Setters for a class using a Macro

September 4, 2008

Fed up of wriing getters and setters for all the variables in a class? Here is a one step solution using a macro (generously contributed by my friend Jibin Raju). See the following code segment.


#define GETSET(type, var) \

private: \

   type _##var; \

public: \

   type Get##var() \

   {\

      return _##var; \

   }\

   void Set##var(type val) \

   {\

      _##var = val; \

   }

The above macro GETSET will automatically expand any variable defined using var to two public functions.

1. void Setvar(type val) and

2. type Getvar()

For example, if I declare GETSET(int, MyInt), in the class it will be expanded as


public:

   int GetMyInt() {return _MyInt;}

   void SetMyInt(int val) {_MyInt = val;}

private:

   int _MyInt;

An example using the above macro is given below.

#include

#include

using namespace std;

class CMyClass

{

   GETSET(int,MyInt)   

   GETSET(float,MyFloat)

   GETSET(string,MyString)

};

 

int main()

{

   CMyClass MyClass;

   MyClass.SetMyInt(10);

   MyClass.SetMyFloat(23.35f);

   MyClass.SetMyString(“This is my string”);

   cout << MyClass.GetMyInt() << '\n';    cout << MyClass.GetMyFloat() << '\n';    cout << MyClass.GetMyString() << '\n';    return 0;    } [/sourcecode]


When using dynamic_cast in Visual C++ 6.0

June 27, 2008

Dynamic cast is normally used to cast an object of derived type to the base type when the classes are polymorphic type (they contain virtual functions and method over riding).

#include <assert.h>

class CBase

{

public:

virtual ~CBase();

virtual void MyFunction() { cout<<“Base”; }

};

class CDerived : public CBase

{

public:

~CDerived();

void MyFunction() { cout<<“Derived”; }

};

int main()

{

CBase* Base = new CDerived();

CDerived* Derived = dynamic_cast<CDerived*>(Base);

assert(Derived);

delete Base;

return 0;

}

Although the code is perfectly legal, in VS 6.0, the compiler will throw a warning

“dynamic_cast’ used on polymorphic type ‘class CBase’ with /GR-; unpredictable behavior may result”.

And if you ignore the warning and run the program, you will get an exception thrown at the line of dynamic cast.

This is because the VC++ 6.0 compiler is not using the feature of Runtime type Information (RTTI).
To enable RTTI, go to Project–>Settings–>C/C++ and in the Category combo box, select C++ Language. Now enable the check box “Enable Runtime type Information (RTTI)”.

Now compile the program and run it.

If you call Base->Myunction() and Derived->MyFunction(), you will get result as “Derived” and it is quite expected.

If you try to dynamic cast a base class to derived class, with the above option, the compiler won’t show any warning, but the result will be NULL. (Note the assert statement in the code). So be careful to cast only the right type.

Instead, if you use the following code snippet,

CBase* Base = new CBase();

CDerived* Derived = static_cast<CDerived*>(Base);

assert(Derived);

Base->MyFunction();

Derived->MyFunction();

delete Base;

the code will compile and run successfully. But the result will be “Base” for both calls.

static_cast does not employ any kind of run time type checking.

dynamic_cast has that overhead, but it is safer.


How To Use Dynamic Cast

March 31, 2008

Eventhough I would suggest avoiding any type of casting, there are not many situations in C++ where you can omit them. Among the casts, dynamic cast can be very handy and is a normally used one. It is used to convert objects of one type to another related (as a result of inheritance) type.

Eg:

class CMyClass

{

virtual void Foo()

{

}

};

class CMyDerivedClass : public CMyClass

{

void Foo()

{

}

} ;

// Declare a variable of

CMyDerivedClass* myDerivedClassObject = new CMyDerivedClass();

// Call Foo() of derived class

myDerivedClassObject->Foo();

// Call Foo() of the base class

CMyClass* myClass = dynamic_cast<CMyClass*>(myDerivedClassObject);

// Make sure that our program won’t crash

assert(myClass);

myClass->Foo(); // Calls the Foo() in the base class

Note the assert statement. It is always a good practice to use assert just after the dynamic cast, to make sure that you are not going to access an uninitialized object.


ASSERT and VERIFY in VC++

March 31, 2008

Both these are used to make sure that an expression or statement in VC++ is executed properly.

In the debug version, both have no difference at all. But if you compile these statements in the release version, the one with ASSERT won’t be executed at all, but the one with VERIFY will work normally.

Eg:

CString StrMyString(“This is my string”);

ASSERT ( StrMyString.Erase(0,2));

will not cause the first two characters to be erased, if compiled in the release version.

But

VERIFY (StrMyString.Erase(0,2)) ;

will cause the first two characters to be erased.