There are two functions which helps in capturing mouse input, it’s called SetCapture and ReleaseCapture and a helper function called GetCapture which returns a handle to the capture window associated with the current thread. If no window in the thread has captured the mouse, the return value is NULL.

Why do we need to capture mouse?

An example is when doing rubber band drawing. If mouse goes out of our window we won’t be able to get mouse movement events, but with a call to SetCapture this will be possible as a result our line keeps moving vertically and horizontally according to mouse movement. Ideal flow for drawing rubber band lines should be…

  1. OnLButtonDown – Capture mouse using SetCapture
  2. OnMouseMove – We’ll continue drawing rubber band lines, also clear previous line.
  3. OnLButtonUp – Release mouse using ReleaseCapture
  4. Neatly handle WM_CAPTURECHANGED just in case in someone captures mouse in between the drawing process.

Some points to note…

  1. Only one window at a time can capture mouse input.
  2. Only the foreground window can capture mouse input.
  3. Background windows can capture mouse input but they’ll receive mouse notifications only when mouse moves over their visible region.
  4. Menu hotkeys and accelerators don’t work when mouse is captured.

Don’t forget to handle WM_CAPTURECHANGED message, because if another window calls SetCapture then this message is fired to the window that is losing mouse capture. To release captured mouse call ReleaseCapture.

Share
 

I had a requirement sometime back to make my process have a higher priority at runtime, so went hunting around for an API which does this and found one with an intuitive name, “SetPriorityClass”. So what is process priority? Process priority is the value which determines priority of a process when it’s being scheduled. If there are two processes having normal priority and above normal priority respectively, then the one with above normal priority is given preference. Internally it’s more complicated than what I explained.

We normally set priority through task manager…

Changing process priority through task manager

Changing process priority through task manager

These are the priority classes defined in windows (From MSDN)…

  1. IDLE_PRIORITY_CLASS – Process whose threads run only when the system is idle. The threads of the process are preempted by the threads of any process running in a higher priority class. An example is a screen saver. The idle-priority class is inherited by child processes.
  2. BELOW_NORMAL_PRIORITY_CLASS – Process that has priority above IDLE_PRIORITY_CLASS but below NORMAL_PRIORITY_CLASS.
  3. NORMAL_PRIORITY_CLASS – Process with no special scheduling needs.
  4. ABOVE_NORMAL_PRIORITY_CLASS - Process that has priority above NORMAL_PRIORITY_CLASS but below HIGH_PRIORITY_CLASS.
  5. HIGH_PRIORITY_CLASS - Process that performs time-critical tasks that must be executed immediately. The threads of the process preempt the threads of normal or idle priority class processes. An example is the Task List, which must respond quickly when called by the user, regardless of the load on the operating system. Use extreme care when using the high-priority class, because a high-priority class application can use nearly all available CPU time.
  6. REALTIME_PRIORITY_CLASS -Process that has the highest possible priority. The threads of the process preempt the threads of all other processes, including operating system processes performing important tasks. For example, a real-time process that executes for more than a very brief interval can cause disk caches not to flush or cause the mouse to be unresponsive.

So these are the six priorities supported in windows and here is a small function which changes priority of current process to above normal class.

void ChangeProcessPriority()
{
   HANDLE hProcess = GetCurrentProcess();
   SetPriorityClass( hProcess , ABOVE_NORMAL_PRIORITY_CLASS );
}

Note that for above code to work; the handle given to SetPriorityClass must have PROCESS_SET_INFORMATION right. Use OpenProcessToken function to get a process token and then use AdjustTokenPrivileges function to set new privileges. A demo for changing process priority is given here -> http://nibuthomas.com/2007/06/28/function-for-enabling-privileges-for-your-application/

To retrieve current priority of a process call GetPriorityClass(). Also for this function to work handle given must have PROCESS_QUERY_INFORMATION privilege set.

DWORD GetProcessPriority()
{
   HANDLE hProcess = GetCurrentProcess();
   return GetPriorityClass( hProcess );
}
Share
 

Is there any way to handle child window messages in a parent window? Yes you can use WM_PARENTNOTFIY message or OnParentNotify MFC handler. Note that this message is sent or this function is only called when WS_EX_NOPARENTNOTIFY style is not set. A child controls notifies it’s parent window on…

  • Creation
  • Destruction
  • Mouse button clicks

Please go through following MSDN links for more information…

  1. WM_PARENTNOTIFY
  2. OnParentNotify
  3. A thread in MSDN forums on this topic
Share
 

What I mean is, if we type ‘Start->Run->Cmd.exe’ then command prompt directory is our user directory, for e.g. ‘c:\Documents and settings\Nibu’. So how can we do this through code is the question? Directory that we see when command prompt starts up is called working directory. Every executable in windows has a working directory which is in fact the first location it searches for a file. So using ‘CreateProcess’ it’s possible to set a working directory, since it has a function parameter which corresponds to this feature. So here is a simple dedicated function which sets working directory for command prompt…

void OpenCmdInDir( LPCTSTR lpctszDir )
{
   STARTUPINFO StrInf =  { 0 };
   StrInf.cb = sizeof( StrInf );

   PROCESS_INFORMATION ProcInfo = { 0 };
   VERIFY( CreateProcess( NULL, "C:\\Windows\\system32\\cmd.exe", NULL, NULL, FALSE, 0, 0, lpctszDir, &StrInf, &ProcInfo ));

   // Closing handles since not needed further
   CloseHandle( ProcInfo.hProcess );
   CloseHandle( ProcInfo.hThread );
}

// Usage
OpenCmdInDir( _T( "C:\\Windows\\System32\\Drivers" ));

See screenshot…

Command prompt working directory

Command prompt working directory

Share
 

SHGetFolderPath is the API that we use to retrieve special folder paths.  Some examples of special folders are as follows…

  • My Documents
  • My Pictures
  • Windows directory
  • System directory
  • Program files
  • Internet history directory
  • Cookies directory
  • etc…

So here is a small useful function which retrieves path of any special directory documented for SHGetFolderPath API in MSDN.

CString GetSpecialFolderPath( const DWORD csidl )
{
   HANDLE ProcToken = NULL;
   VERIFY( OpenProcessToken( GetCurrentProcess(), TOKEN_READ, &ProcToken ));

   TCHAR szBuffer[MAX_PATH*2] = { 0 };
   SHGetFolderPath( NULL, csidl, ProcToken, SHGFP_TYPE_CURRENT, szBuffer );
   CString SpecialFolderPath = szBuffer;

   CloseHandle( ProcToken );

   return SpecialFolderPath;
}

// Usage
int main()
{
 // initialize MFC and print and error on failure
 if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
 {
  // TODO: change error code to suit your needs
  cerr << _T("Fatal Error: MFC initialization failed") << endl;
  nRetCode = 1;
 }

 // Get my documents folder path
 const CString MyDocuments = GetSpecialFolderPath( CSIDL_PERSONAL );
 ::MessageBox( NULL, MyDocuments, "MyDocuments Path", MB_OK | MB_ICONINFORMATION );

 // Get Program files path
 const CString ProgramFiles = GetSpecialFolderPath( CSIDL_PROGRAM_FILES );
 ::MessageBox( NULL, ProgramFiles, "Program files", MB_OK | MB_ICONINFORMATION );

 // Get internet history path
 const CString HistoryFolder = GetSpecialFolderPath( CSIDL_HISTORY );
 ::MessageBox( NULL, HistoryFolder, "History folder", MB_OK | MB_ICONINFORMATION );

 return 0;
}

There may be times when a special folder might not be present, so for that case you can combine CSIDL_FLAG_CREATE with other CSIDL flags. For example if you want to create my documents folder if there is no such one present then we’ll call “GetSpecialFolderPath” likewise…

// You can be sure that my documents will be present this way
CString MyDocuments = GetSpecialFolderPath( CSIDL_PERSONAL | CSIDL_FLAG_CREATE );

// Now create a file in this directory
MyDocuments += "/Learning.txt";
// CreateFile 

Above function is extremely easy to use but internally it opens and closes a token handle, so if you want to retrieve multiple entries then you can provide a token handle which may increase performance.

Return values from ShGetFolderPath is interpreted as follows…

S_FALSE -> SHGetFolderPathA only. The CSIDL in nFolder is valid, but the folder does not exist. Note that the failure code is different for the ANSI and Unicode versions of this function.
E_FAIL -> SHGetFolderPathW only. The CSIDL in nFolder is valid, but the folder does not exist. Note that the failure code is different for the ANSI and Unicode versions of this function.
E_INVALIDARG -> The CSIDL in nFolder is not valid.

Share
 

Ever wondered if at all it’s possible to allocate read only chunk of memory. Now you may ask why we would  need to do something like this, well may be just for security reasons. So ideally what happens when we try write to read only memory? We typically get a message box which says…

—————————
Microsoft Visual C++
—————————
Unhandled exception in StaticArray.exe: 0xC0000005: Access Violation.
—————————
OK
—————————

It’s a final good-bye re-worded ;) , unless there is a try/catch statement guarding this particular block!

Aha, This looks great! There are two functions in windows called VirtualAlloc and VirtualProtect. Use VirtualAlloc to allocate read only pages and just in case we wanna write something after we allocate a page but before we protect such a page then we use VirtualProtect.

Here is a sample function which creates a read only memory straightaway…

LPVOID CreateReadOnlyMemory( const DWORD MemSize )
{
   // Take a look at the last parameter to this function
   return VirtualAlloc( NULL, MemSize, MEM_COMMIT, PAGE_READONLY );
}

int main()
{
   LPBYTE pByte = static_cast< LPBYTE >( CreateReadOnlyMemory( MAX_PATH ));
   try
   {
      pByte[0] = 10;
   }
   catch( ... )
   {
      cout < < "\nCaught access violation error!!!";
   }

   cout << "\nYippee! We survived access violation error, Mwhahaha!!!";
   pByte[0] = 20; // This time doomed!
}

To remove a read only protection call VirtualProtect with any suitable access specifier mentioned in MSDN.

Share
 

Easy! call SetConsoleTextAttribute function with appropriate color codes as follows…

// A generic function call to set color for text being output
void SetColor( const int Color )
{
   SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), Color );
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
   // Only change foreground color
   SetColor( FOREGROUND_BLUE );
   cout << "Visit http://nibuthomas.wordpress.com"; <<; endl;

   // This time change background color too
   SetColor( FOREGROUND_BLUE|BACKGROUND_RED|BACKGROUND_INTENSITY)
   cout << "Visit http://nibuthomas.wordpress.com" << endl;

   return 0;
}
Share
 

For this purpose we use _kbhit function included in conio.h file. Please note that conio.h is a non-standard header file so can’t say if _kbhit will be available in other libraries. The purpose of  _kbhit is to check whether a key has been hit and so then we can use this function to wait till a key is pressed. To know which key is pressed we can use _getch or _getche functions immediately after a call to _kbhit. _kbhit returns TRUE if a key is pressed else returns FALSE.

Internally _kbhit used PeekConsoleInput windows console API to check whethere is a KEY_EVENT in input queue. If there is one then it returns TRUE. Note that _kbhit peeks on all events from input queue to check whether there is a KEY_EVENT. Note that extended keys are ignored!

Here are some functions to demonstrate the power of _kbhit

  1. ClearInputBuffer – Clears key events from input buffer using _kbhit
  2. Pause - Much like window’s ‘Pause’ command, except for the animation of ellipses.
#include <conio .h>
#include <iostream>

void ClearInputBuffer()
{
   while( _kbhit() )
   {
      // Read and ignore chars from input buffer resulting in removal from input buffer
      _getch();
   }
}

void Pause( const char* Msg = NULL )
{
   std::cout << ( Msg ? Msg : "Press a key to continue" );

   const int EllipsesCount = 3;
   const char* MoveBackChars[EllipsesCount] = { "\b", "\b\b", "\b\b\b" };
   const char* AllClearText[EllipsesCount] = { " ", "  ", "   " };
   const char* Ellipses[EllipsesCount] = { ".", "..", "..." };

   int ActiveEllipsesIndex = 0;
   while( true )// Animate until a key is pressed
   {
      std::cout << Ellipses[ActiveEllipsesIndex];

      Sleep( 500 );

      if( !_kbhit() )
      {
         std::cout << MoveBackChars[ActiveEllipsesIndex];
         std::cout << AllClearText[ActiveEllipsesIndex];
         std::cout << MoveBackChars[ActiveEllipsesIndex];
      }
      else
      {
         _getch();
         break;
      }

      ActiveEllipsesIndex = (ActiveEllipsesIndex + 1) % EllipsesCount;
   }
}

int main( void )
{
   ClearInputBuffer();
   Pause();

   return 0;
}

Share
 

Recently a colleague of mine asked this question, he added a message map entry for LBN_SELCHANGE but still no notification message arrived and also this list box was dynamically created using CListBox::Create function.

The reason was that he missed out a style id while creating this window. LBS_NOTIFY should be specified when creating a list box if parent window intends to receive notification messages. List box created using resource editor has this option turned on by default.

Some other controls with a similar style id are as follows…

  1. Button control has BS_NOTIFY style which enables a button to send BN_DBLCLK, BN_KILLFOCUS, and BN_SETFOCUS notification messages to its parent window. Note that buttons send the BN_CLICKED notification message regardless of whether it has this style.
  2. Static control has SS_NOTIFY style which enables it to send it’s parent window STN_CLICKED, STN_DBLCLK, STN_DISABLE, and STN_ENABLE notification messages when the user clicks or double-clicks the control.
Share
 

So what are stock objects? “Stock” as the name says means goods in hand, which a shop keeper always has as a backup. In the same way GDI also keep a set of backup of objects which it creates during initialization and these are known as stock objects. Let’s think of a case like this… you are creating a fancy brush but somehow the creation fails, so what will be your backup policy, mine would be to use a stock brush, for e.g. BLACK_BRUSH since these objects are always available. Think of a case where you have to quickly create a black brush, I would go for stock object BLACK_BRUSH.

Following are the stock objects that I know, taken straight out of MSDN

Value Meaning
BLACK_BRUSH Black brush.
DKGRAY_BRUSH Dark gray brush.
DC_BRUSH Windows 2000/XP: Solid color brush. The default color is white. The color can be changed by using the SetDCBrushColor function. For more information, see the Remarks section.
GRAY_BRUSH Gray brush.
HOLLOW_BRUSH Hollow brush (equivalent to NULL_BRUSH).
LTGRAY_BRUSH Light gray brush.
NULL_BRUSH Null brush (equivalent to HOLLOW_BRUSH).
WHITE_BRUSH White brush.
BLACK_PEN Black pen.
DC_PEN Windows 2000/XP: Solid pen color. The default color is white. The color can be changed by using the SetDCPenColor function. For more information, see the Remarks section.
NULL_PEN Empty pen.
WHITE_PEN White pen.
ANSI_FIXED_FONT Windows fixed-pitch (monospace) system font.
ANSI_VAR_FONT Windows variable-pitch (proportional space) system font.
DEVICE_DEFAULT_FONT Windows NT/2000/XP: Device-dependent font.
DEFAULT_GUI_FONT Default font for user interface objects such as menus and dialog boxes. This is MS Sans Serif. Compare this with SYSTEM_FONT.
OEM_FIXED_FONT Original equipment manufacturer (OEM) dependent fixed-pitch (monospace) font.
SYSTEM_FONT System font. By default, the system uses the system font to draw menus, dialog box controls, and text.Windows 95/98 and Windows NT: The system font is MS Sans Serif.Windows 2000/XP: The system font is Tahoma
SYSTEM_FIXED_FONT Fixed-pitch (monospace) system font. This stock object is provided only for compatibility with 16-bit Windows versions earlier than 3.0.
DEFAULT_PALETTE Default palette. This palette consists of the static colors in the system palette.

If you look at above table, we can see that almost all GDI object classes (exceptions are regions and bitmaps) has a backup stock object, mainly to act as a fallback method just in case of a failure IMO.

To use retrieve a stock object we call function GetStockObject. The good thing about working with a stock object is that we don’t have to delete it, since we didn’t create it. Now think how easy it’s to create a black pen, or black brush. No overheads to delete/free them. It’s definitely faster too.

There is a brush called NULL_BRUSH, a pen called NULL_PEN which are quite useful to draw a hollow rectangle without any fill, instead of selecting a brush equivalent to background window color to simulate drawing a rectangle without any fill.

CDC class of MFC has a very easy to use function for stock object. It’s CDC::SelectStockObject. I’m going nuts for this function. ;) Take a look at these calls….

// Select a black brush
CDC ClientDC;
ClientDC.Attach( ::GetDC( m_hWnd ));

const int RestorePoint = ClientDC.SaveDC();

// Select a black brush
ClientDC.SelectStockObject( BLACK_BRUSH );
// Select a black pen
ClientDC.SelectStockObject( BLACK_PEN );
// Select existing font
ClientDC.SelectStockObject( <strong>DEVICE_DEFAULT_FONT</strong> );

ClientDC.RestoreDC( RestorePoint );

See how easy it’s to use these stock objects. No overhead of creating or freeing them, but as I already said these are just for backup action purpose. For fancy stuff you of course have to go for other functions.

So bottom line is stock objects are just to avoid cases were you end up with no brush to paint or no pen to write. :)

Share
© 2012 bits and bytes Suffusion theme by Sayontan Sinha