Many of you must have faced this obscure problem, it’s because you haven’t called AfxInitRichEdit/AfxInitRichEdit2() function.

Wait! Before you jump onto add this call identify your rich edit control’s class name, if you are working in VC6 then rich edit class name will be RICHEDIT and or if VC7 and above then it will be RichEdit20A. So if the class name is RICHEDIT then call AfxInitRichEdit(), else if the class name is RichEdit20A then call AfxInitRichEdit2().

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
 

I’ve seen in forums numerous times people asking this query: How to change the row height of list control? Answers vary from , owner drawing to adding a fake image list with tall images. :)

Well so I decided to find out a way to do this in a proper way.  So here is a way to do this. This works both ways through a dialog resource and through dynamic creation. Note that this method uses owner drawing “for a moment”. ;)

Here is a screen shot before applying this method…

CListCtrl before changing row height

Well so follow these steps if you are using a dialog resource with a CListCtrl

  1. Add a list control to this resource
  2. Change the style of this list control to “owner draw fixed” style!
  3. Now override OnMeasureItem method of your dialog class, note that this method is not to be overridden in you CListCtrl class, you need not have a derived class of CListCtrl.
    OnMeasureItem prototype:
    afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct);
  4. Now inside OnMeasureItem add this piece of code, this is how mine looks…
    void CDialogGuineaPig::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
    {
       // If this is our list control then increase height
       if( nIDCtl == IDC_ROWLIST )
       {
          // Increase height by 20
          lpMeasureItemStruct->itemHeight += 20;
       }
    }
  5. Now goto OnInitDialog, this is how my OnInitDialog section for implementing this behavior looks…
    BOOL CDialogGuineaPig::OnInitDialog()
    {
        // Insert two columns and two rows...
        m_RowList.InsertColumn( 1, TEXT( "First column" ), LVCFMT_LEFT, 200, 0 );
        m_RowList.InsertColumn( 2, TEXT( "Second column" ), LVCFMT_LEFT, 200, 1 );
        m_RowList.InsertItem( 0, _T( "Row1 Column1" ), 0 );
        m_RowList.SetItemText( 0, 1, _T( "Row1 Column2" ));
        m_RowList.InsertItem( 1, _T( "Row2 Column1" ), 0 );
        m_RowList.SetItemText( 1, 1, _T( "Row2 Column2" ));
    
        // Remove owner drawn style, our job is done,
        // we're tricking the framework into thinking that
        // we wanna owner draw this control so that we get
        // a call to OnMeasureItem.
        m_RowList.ModifyStyle( LVS_OWNERDRAWFIXED, 0, 0 );
    
        // Just to show the change in row height
        m_RowList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES );
    
        return FALSE;  // return TRUE  unless you set the focus to a control
    }
  6. That’s it, we now have a list control with rows having bigger height. Here is a screen shot of the resultant list control…CListCtrl after changing row height

Now with dynamic creation, make sure specify LVS_OWNERDRAWFIXED style while creating so that OnMeasureItem is called by the framework, after the remove this style. Similar to dialog resource method.

So to summarize in one line what we’ve done… we turned on owner drawn style temporarily so that window framework calls OnMeasureItem, so that we can pass our own height value and then we’ve turned off this style so that the windowing framework does the drawing stuff instead of us.

Have fun programming…

Share
 

Converting from CString to char* is conditional, becuase CString is a TCHAR based implementation. TCHAR is defined as a char if _UNICODE is not defined, so if this is the case we can convert to char*, since TCHAR* and char*  are equal, else we’ve got to use function like MultiByteToWideChar/W2A/W2AEX etc.

So from now on for this post I will be using TCHAR version of char. Above explanation would have helped you in understanding what exactly is a TCHAR.

Converting CString to LPCTSTR -

CString has an inbuilt operator which returns a constant pointer to it’s internal data member. It’s called operator LPCTSTR().

So if you write code like this…

CString Str;
LPCTSTR lpctszStr = Str;

The compiler replaces above line with a call to operator LPCTSTR(). So will look somewhat like this…

LPCTSTR lpctszStr = Str.operator LPCTSTR();

This is the reason why we can directly pass CString objects to SDK functions which takes LPCTSTR arguments, for e.g. ::SetWindowText.

Converting CString to LPTSTR -

Converting from CString to LPTSTR is slightly bit more work. We’ve got to call function GetBuffer to get internal data pointer. Don’t forget to call ReleaseBuffer once you are done with the buffer.

LPTSTR lptszStr = Str.GetBuffer(0);
Str.ReleaseBuffer();

A different flavor of this function exists called GetBufferSetLength. Well what’s the use of this function, you can explicitly as CString to give you a larger buffer that the current one. For eg. if you wanna call the SDK version of GetWindowText using a CString object without using a temporary raw TCHAR buffer, you can use GetBufferSetLength function passing the required buffer length as the argument and of course the ReleaseBuffer call should be made too!

Here is a classic example from CWnd::GetWindowText on how to use GetBufferSetLength.

CString rString;
int nLen = ::GetWindowTextLength(m_hWnd);
::GetWindowText(m_hWnd, rString.GetBufferSetLength(nLen),  nLen+1);
rString.ReleaseBuffer();

Converting to and from a unicode string -

http://nibuthomas.wordpress.com/2008/07/02/how-to-convert-a-ansi-string-to-unicode-string-and-vice-versa/

Share
 

I will describe in this post three ways to trim a string of given characters…

  1. Using custom function for std::string
  2. Using CString
  3. Using StrTrim shell API function.

Using custom function for std::string

Its bit strange that std::string doesn’t provide a Trim function :? , but hey since we’ve got head upon our shoulders we’re gonna write one. :P . Here is a simple function which removes white space before and after a string. We’ll call it Trim! :P

void Trim( const std::string& StrToTrim, std::string& TrimmedString )
{
  // Find first non whitespace char in StrToTrim
  std::string::size_type First = StrToTrim.find_first_not_of( ' ' );
  // Check whether something went wrong?
  if( First == std::string::npos )
  {
    First = 0;
  }

  // Find last non whitespace char from StrToTrim
  std::string::size_type Last = StrToTrim.find_last_not_of( ' ' );
  // If something didn't go wrong, Last will be recomputed to get real length of substring
  if( Last != std::string::npos )
  {
    Last = ( Last + 1 ) - First;
  }

  // Copy such a string to TrimmedString
  TrimmedString = StrToTrim.substr( First, Last );
}

int main()
{
  std::string StrToTrim = " 32 Nibu babu thomas 2342 2 23 3 ";
  std::string TrimmedString = "On return will hold trimmed string";
  Trim( StrToTrim, TrimmedString );

  return 0;
}
//Output is: 32 Nibu babu thomas 2342 2 23 3

Using CString

Also CString has a Trim function, if you have the liberty to use CString then that’s another option.

Using StrTrim shell API function

Another option is to use StrTrim shell API function. Here is a demo from MSDN.

#include <windows .h>
#include <iostream .h>
#include "Shlwapi.h"

void main(void)
{
  //String one
  TCHAR buffer[ ] = TEXT("_!ABCDEFG#");
  TCHAR trim[ ] = TEXT("#A!_");

  cout << "The string before calling StrTrim: ";
  cout << buffer;
  cout << "\n";

  StrTrim(buffer, trim);

  cout << "The string after calling StrTrim: ";
  cout << buffer;
  cout << "\n";
}

OUTPUT:
- - - - - -
The string before calling StrTrim: _!ABCDEFG#
The string after calling StrTrim: BCDEFG

Share
 

Call CEdit::SetLimitText or send EM_LIMITTEXT windows message to an edit control. There are some caveats associated with this functionality…

  1. This limitation does not affect the amount of text entered via a call to SetWindowText, or WM_SETTEXT.
  2. This limitation does not hold true for paste operation.
  3. This limitation does not affect text already entered into an edit control.

If above cases are true then the user is allowed to edit the text but not allowed to insert anymore unless the text count falls below allowed count.

Default limit is 32,767 characters.

extern CEdit* pSomeEdit;
pSomeEdit->SetLimitText( 10 );// Only 10 characters can be entered

pSomeEdit->SendMessage(EM_LIMITTEXT, 10, 0); // Using windows message

There is another version called EM_EXLIMITTEXT for rich edit controls which supports lengths above 64k.

Share
 

A topmost window is one which stays on top of other windows even while it’s not in focus. Normally all application popup windows will go to background once they lose focus but a topmost window doesn’t.

Let me explain or show you the code which does this. Everybody knows how to achieve this but still some don’t, so for them here is how we do this and as always in the form of a function.

void SetTopMost( HWND hWnd, const BOOL TopMost )
{
   ASSERT( ::IsWindow( hWnd ));
   HWND hWndInsertAfter = ( TopMost ? HWND_TOPMOST : HWND_NOTOPMOST );
   ::SetWindowPos( hWnd, hWndInsertAfter, 0, 0 , 0 , 0, SWP_NOMOVE | SWP_NOSIZE );
}

The second parameter passed to ::SetWindowPos is the one that does the trick. It’ called hwndInsertAfter, if we specify the after window as HWND_TOPMOST then we get a topmost window, if we specify after window as HWND_NOTOPMOST then topmost setting is unset and our window becomes a normal window.

Equivalent MFC variables for HWND_TOPMOST and HWND_NOTOPMOST are wndTopMost and
wndNoTopMost respectively.

HWND_xxxxx variable are mere #defines just have a look.

#define HWND_TOP        ((HWND)0)
#define HWND_BOTTOM     ((HWND)1)
#define HWND_TOPMOST    ((HWND)-1)
#define HWND_NOTOPMOST  ((HWND)-2)

::SetWindowPos is an interesting function, we can use it

  1. To change the tab order/z-order of a control
  2. To ‘just’ move a control (SWP_MOVE)
  3. To ‘just’ size a control (SWP_SIZE)
  4. To generate ‘just’ nc-paint messages
  5. To generate ‘just’ nc-calcsize messages
  6. To repaint a window

As a homework suggest you to have a look at the flags that are passed to it.

Share
 

Now what’s a hotkey? An easy definition would be a key that remains hot throughout the lifetime of an application. Whenever you press a hotkey it does it’s work no matter where the focus is or where the input is directed to, etc.

Here is a screenshot and a sample application(Right click and save as exe), using this application you can register or unregister any combination of a given key (Here F12). So here when you press Ctrl + Alt + Shift + WinKey + F12 this dialog toggles it’s visibility state.

Screenshot for testing a hotkey

Screenshot for testing a hotkey

So here’s how we go about it.

// Make this a member variable of your class.
UINT m_UniqueIdentifier;

// Creates a unique identifier for your hotkey so that there is no hotkey id clashes.
// Call this probably from OnInitDialog
m_UniqueIdentifier = ::GlobalAddAtom( "Somename" );

::RegisterHotKey( m_hWnd,              /*Your window handle*/
                  m_UniqueIdentifier,  /*Unique identifier to uniquely identify this hotkey*/
                  MOD_ALT|MOD_CONTROL, /*Modifier keys*/
                  VK_F10 );            /*Virtual key code of any key*/

//Add these message map entries
BEGIN_MESSAGE_MAP(..., ...)
   ON_MESSAGE(WM_HOTKEY, HotKeyHandler)
   ON_WM_DESTROY()
END_MESSAGE_MAP()

// Toggle visibility
LRESULT CYourDialog::HotKeyHandler(WPARAM wParam, LPARAM lParam)
{
   if( IsWindowVisible() )
   {
     ShowWindow( SW_HIDE );
   }
   else
   {
     ShowWindow( SW_SHOWNORMAL );
   }// End if
}// End HotKeyHandler

void CYourDialog::OnDestroy()
{
   //if you register you will have to unregister too.
   UnregisterHotKey( m_hWnd, m_UniqueIdentifier );
}

A cleaner approach would be create a wrapper class around this hotkey. So that registration and unregistration can take place smoothly.

Even though unregistering may seem like not required but still IMO we should unregister a hotkey. Just following the rules! :)

Share
 

Have you ever wondered how do people move dialogs by simply clicking anywhere inside the dialog and dragging them. Have you ever wondered how caption-less dialogs can be dragged around. If it is so then let me tell you that you can do the same with just few lines of code…

Here goes the code:

BEGIN_MESSAGE_MAP(CGuineaPigDlg, CDialog)
   //{{AFX_MSG_MAP(CGuineaPigDlg)
   ON_WM_NCHITTEST()
   //}}AFX_MSG_MAP
END_MESSAGE_MAP()

// First add above message entry
UINT CGuineaPigDlg::OnNcHitTest(CPoint point)
{
   const UINT HitArea = CDialog::OnNcHitTest(point);
   if( HitArea == HTCLIENT )
   {
      return HTCAPTION; // Fake caption drag effect
   }
   else
   {
      return HitArea;
   }
}
Share
© 2012 bits and bytes Suffusion theme by Sayontan Sinha