Sunteți pe pagina 1din 75

VC++ Tips

How do I extract programmatically, the path of the directory where the program
currently running is situated?
Ans: Use GetModuleFileName( ) function. In Windows an '.EXE' or '.DLL' is called module.
The GetModuleFileName( ) function takes three parameters, a handle to the module
which in case of an '.EXE' would be NULL. The second and third parameters specify the
address of buffer that stores the path and the size of the buffer respectively. Following code
snippet demonstrates the use of this function.
void CGetmodnameDlg :: OnGetname( )
{
char buffer[MAX_PATH] ;
if ( GetModuleFileName ( NULL, buffer, MAX_PATH ) != 0 )
* ( strrchr ( buffer, '\\' ) + 1 ) = '\0' ;
MessageBox ( buffer ) ;
}
Here, we have called strrchr( ) function to eliminate the filename from the full path.

How do I retrieve the current font settings of a menu of a window,


programmatically?
Ans: We can use the NONCLIENTMETRICS structure to retrieve information about font
settings of a menu of a window. Not only that, but the NONCLIENTMETRICS structure can
also give us information about the settings like width of scrollbar or window border, font of
caption bar etc. Actually, these are the scalar metrics associated with the non-client area of
a non-minimized window. The following code snippet demonstrates how to use this structure
in a program.
void CChildView::OnPaint( )
{
CPaintDC dc ( this ) ;
NONCLIENTMETRICS nc ;
nc.cbSize = sizeof ( nc ) ;
SystemParametersInfo ( SPI_GETNONCLIENTMETRICS, 0, &nc, 0 ) ;
CString temp ;
CString str = "MenuFont : " ;
str += nc.lfMenuFont.lfFaceName ;
str += "\n" ;
LOGFONT lf = nc.lfMenuFont ;
str += "FontHeight : " ;
temp.Format ( "%d", lf.lfHeight ) ;
str += temp ;
str += "\n" ;
str += "Italics : " ;
lf.lfItalic ? str += "True" : str += "False" ;
str += "\n" ;

str += "StrikeOut : " ;


lf.lfStrikeOut ? str += "True" : str += "False" ;
str += "\n" ;
str += "Underline : " ;
lf.lfUnderline ? str += "True" : str += "False" ;
str += "\n" ;
str += "Bold : " ;
lf.lfWeight ? str += "True" : str += "False" ;
str += "\n" ;
}

MessageBox ( str ) ;

We have used an API function SystemParametersInfo( ) that would fill the nc structure
with the corresponding information. The parameter SPI_GETNONCLIENTMETRICS specifies
the system parameter about which we want to get the information.

How do I turn off the tool bar and status bar programmatically?
Ans: Write following code in a member function of CMainFrame class, and call this function
through a handler or any other function when you want to turn off toolbar and status bar.
void CMainFrame::fun( )
{
if ( m_wndToolBar.IsWindowVisible( ) )
SendMessage ( WM_COMMAND, AFX_IDW_TOOLBAR, 0L ) ;
if ( m_wndStatusBar.IsWindowVisible( ) )
SendMessage ( WM_COMMAND, AFX_IDW_STATUS_BAR, 0L ) ;
}

How to create a multidimensional array in VC++?


Ans: Java programmers are familiar with the concept of multidimensional array. It is an
array where each row can contain different number of columns. We can create such an array
even in VC++. Following program shows how...
int main ( int argc, TCHAR* argv[ ], TCHAR* envp[ ] )
{
CUIntArray a[2] ;
a[0].SetSize ( 4 ) ;
a[1].SetSize ( 3 ) ;
for ( int i = 0 ; i < 2 ; i++ )
{
for ( int j = 0 ; j < a[i].GetSize( ) ; j++ )
a[i][j] = j ;
}
for ( i = 0 ; i < 2 ; i++ )
{
for ( int j = 0 ; j < a[i].GetSize( ) ; j++ )
cout << a[i][j] << " " ;
cout << endl ;

Since an object of the CUIntArray collection class is a 1D array, a [ 2 ] becomes the 2D


array of ints. The zeroeth row of array a contains 4 elements and the first row contains 3
elements.

How do I write code, so that if connection fails, then using same socket object
connection for other server should get established?
Ans: This is shown in following code fragement.
void CClientDlg :: OnConnect( )
{
UpdateData ( TRUE ) ;
m_commsocket.Create( ) ;
BOOL result = m_commsocket.Connect( "User17", 100 ) ;
if ( !result )
{
MessageBox ( "Server not found! Try again..." ) ;
m_commsocket.Close( ) ;
m_commsocket.Connect( "User100", 100 ) ;
}
}
Here, m_commsocket is an object of class (derived from CSocket) that handles socket
related operations like, accept request, receive messages, etc. The values User17 or
User100 are the machine names on which the server application is supposed to be running.
Calling Close( ) closes the socket. As a result, same socket object can be reused to
establish connection with the server.

How do I remove the window caption 'Untitled' that gets added to the window of
an SDI application created with Doc/View support?
Ans: Write following statement to the PreCreateWindow( ) function of the CMainFrame
class.
BOOL CMainFrame :: PreCreateWindow ( CREATESTRUCT& cs )
{
cs.style &= ~FWS_ADDTOTITLE ;
//AppWizard generated code
}
Here, we have removed FWS_ADDTOTITLE style from the window. FWS_ADDTOTITLE is an
MFC-specific style that instructs the framework to add the document title to the windows
caption.

SendMessage versus PostMessage...


The SendMessage sends a message to another window immediately by calling that
window's procedure and waiting for it to return, whereas PostMessage queues the
message in an MSG (Message) structure and returns immediately without waiting.
With SendMessage, the receiving application processes the message immediately, rather

than at some later time, by fetching it from its message queue. On the contrary,
PostMessage doesn't call the window procedure. Instead it adds a MSG structure to the
message queue of the thread or process of the application window (to whom the message
has to be passed) and returns. The thread or application processes the message when it
gets around to it.
We should use SendMessage to send messages to an application window to perform some
action that must be done immediately. Whereas, use Postmessage for messages that are
not urgent.

How do I write code, to display a toolbar at the left edge of the window, moreover,
the buttons on the toolbar should get arranged in multiple rows and should work
like check box?
Ans: This is shown in following code fragement.
int CMainFrame :: OnCreate ( LPCREATESTRUCT lpCreateStruct )
{
// AppWizard generated code
// Create tool bar with styles
m_tool.CreateEx ( this, TBSTYLE_BUTTON | TBSTYLE_WRAPABLE, WS_CHILD |
WS_VISIBLE | CBRS_SIZE_FIXED | CBRS_ALIGN_LEFT, CRect ( 0, 0, 5, 5 ), 1 ) ;
m_tool.SetWindowText ( "Tool" ) ;
// Create imgaelist & set it
// IDB_BITMAP1 is ID of bitmap holding images of toolbar buttons, & created in
resource
CImageList img ;
img.Create ( IDB_BITMAP1, 22, 0, RGB ( 255, 0, 255 ) ) ;
m_tool.GetToolBarCtrl( ).SetImageList ( &img ) ;
img.Detach( ) ;
// Add button information
m_tool.SetButtons ( NULL, 6 ) ;
// ID_B1 to ID_B6 are #define macros added for buttons
m_tool.SetButtonInfo ( 0, ID_B1, TBSTYLE_GROUP | TBSTYLE_CHECKGROUP, 0 ) ;
m_tool.SetButtonInfo ( 1, ID_B2, TBSTYLE_CHECKGROUP, 1 ) ;
m_tool.SetButtonInfo ( 2, ID_B3, TBSTYLE_CHECKGROUP, 2 ) ;
m_tool.SetButtonInfo ( 3, ID_B4, TBSTYLE_CHECKGROUP, 3 ) ;
m_tool.SetButtonInfo ( 4, ID_B5, TBSTYLE_CHECKGROUP, 4 ) ;
m_tool.SetButtonInfo ( 5, ID_B6, TBSTYLE_CHECKGROUP, 5 ) ;
// Set Toolbar size
CRect toolrect,r ;
m_tool.GetItemRect ( 0, &toolrect ) ;
m_tool.SetSizes ( toolrect.Size( ), CSize ( 22, 20 ) ) ;
// Set number of rows
m_tool.GetToolBarCtrl( ).SetRows ( 3, TRUE, &r ) ;
// Code to dock toolbar
m_tool.EnableDocking ( CBRS_ALIGN_ANY ) ;
EnableDocking ( CBRS_ALIGN_ANY ) ;
DockControlBar ( &m_tool ) ;

return 0 ;
}
Here, we have created a toolbar with style as TBSTYLE_BUTTON and TBSTYLE_WRAPABLE.
These two styles indicate that the toolbar contains buttons and can have multiple rows of
buttons respectively. The SetRows( ) function is used to set the number of rows for
buttons.

How do I speed up loading of a workspace containing multiple projects?


Ans: While creating a professional application, a team often require to add multiple projects
in one workspace. But not everyone in the team requires all the projects added to the
workspace. For example, suppose a workspace has 20 projects. One team member may
need only 5 of them while other may require only 10. At such a time, time is wasted in
loading the workspace. We can speed up loading the workspace by unloading unwanted
projects. To unload a project right-click on the project name in the 'File View' tab and select
the 'Unload Project' option. The next time we load the workspace this project remains
unloaded. We can load it again by double clicking on it.

How do I detect whether the screen resolution is 640x480 or 600x800?


Ans: We can use the function GetSystemMetrics( ) to get the all sorts of global
dimensions, like the size of an icon, height of a window caption, no of mouse buttons if any
mouse is attached etc. The following code snippet shows how to get the screen resolution.
void CChildView::OnPaint( )
{
CPaintDC dc ( this ) ;
int cx = GetSystemMetrics ( SM_CXSCREEN ) ;
int cy = GetSystemMetrics ( SM_CYSCREEN ) ;
CString str ;
str.Format ( "x = %d y = %d", cx, cy ) ;
MessageBox ( str ) ;
}

How do I get the text in resources like menu, toolbar etc, in some different
language like German?
Ans: While creating project, in Step 1, AppWizard displays a combo-box under the name
"What language would you like your resources in?" From this combo-box select the
language that you want. This would add text for the resources in the language that you
have selected.

How do I create a pen so that the joins of the shapes appear round?
Ans: Create a pen as shown in the following code snippet:
CChildView :: OnPaint( )
{
LOGBRUSH lb ;
lb.lbStyle = BS_SOLID ;

lb.lbColor = RGB ( 255, 255, 0 ) ;


CPen mypen ( PS_SOLID | PS_GEOMETRIC | PS_ENDCAP_ROUND, 15, &lb ) ;
CPen *old = dc.SelectObject ( &mypen ) ;
dc.Rectangle ( 10, 10, 100, 100 ) ;
dc.SelectObject ( old ) ;
}

How do I implement a 'Close All Documents' menu command?


The 'Close All Documents' is a menu command that closes all the open documents and their
views. This feature can be implemented by using two functions
CWinApp::CloseAllDocuments( ) and SaveAllModified( ). The CloseAllDocuments( )
function destroys the currently active document objects without saving them. So we must
first call SaveAllModified( ) function to save the documents. Following code shows how to
implement this feature.
if ( AfxGetApp( ) -> SaveAllModified( ) )
AfxGetApp( ) -> CloseAllDocuments ( FALSE ) ;

How do I write code to check whether or not a directory exists?


Ans: The following code illustrates how this can be done.
void CMyDlg :: OnCheckdir( )
{
CString m_path = "C:\\MyProg\\First" ;
int l = m_path.GetLength( ) ;
int pos = m_path.ReverseFind ( '\\' ) ;
CString path = m_path.Left ( pos + 1 ) ;
CFileFind f ;
BOOL found = f.FindFile ( path + "*.*" ) ;
int flag = 0 ;
while ( found )
{
found = f.FindNextFile( ) ;
CString fname = f.GetFilePath( ) ;
fname.MakeUpper( ) ;
m_path.MakeUpper( ) ;

if ( f.IsDots( ) )
continue ;
if ( fname == m_path && f.IsDirectory( ) )
{
MessageBox ( "Directory exists..." ) ;
flag = 1 ;
break ;
}

if ( !flag )
MessageBox ( "Directory does not exist..." ) ;

How do I associate multiple file extensions with the same document class?
Ans: In applications like Notepad and MS-Word we can open files with different file
extensions. For example, in Notepad we can open a '.txt' file as well as '.htm' file. We can
also implement this feature in our MDI application. For this create a document template
object for each file extension that you want to use in your application. Here, we intend to
create two objects, one associated with '.txt' extension and the other with '.ini' extension.
Modify the InitInstance( ) function as shown below:
BOOL CMultiextApp::InitInstance( )
{
// AppWizard added code
CMultiDocTemplate* pDocTemplate ;
pDocTemplate = new CMultiDocTemplate ( IDR_MULTIETYPE, RUNTIME_CLASS
( CMultiextDoc ), RUNTIME_CLASS ( CChildFrame ), RUNTIME_CLASS
( CMultiextView ) ) ;
AddDocTemplate ( pDocTemplate ) ;
CMultiDocTemplate* pDocTemplate1 ;
pDocTemplate1 = new CMultiDocTemplate ( IDR_TEXTTYPE,
RUNTIME_CLASS(CMultiextDoc), RUNTIME_CLASS ( CChildFrame ), RUNTIME_CLASS
( CMultiextView ) ) ;
AddDocTemplate ( pDocTemplate1 ) ;
// AppWizard added code
return TRUE;
}
For each object all the parameters except the resource ID must be same. We have kept the
default resource ID for '.ini' file. Create a resource string having ID IDR_TEXTTYPE for the
'.txt' file. Also add the icon and menu having ID IDR_TEXTTYPE. Modify the string so that it
contains suitable filterName and filterExt substrings. Now you can create or open both the
text files and ini files.

How do I make an application remember the last active document and


automatically reopen it?
Ans: This involves two steps, first is to save the last active document when the frame
window is about to close and second is to reopen it the next time application is started.
Perform the first step in OnClose( ) handler of main frame class as shown below:
CString docstr = "" ;
CMDIChildWnd *pchild = MDIGetActive( ) ;
if ( pchild )
{
CDocument *pdoc = pchild->GetActiveDocument( ) ;
if ( pdoc )
{
docstr = pdoc -> GetPathName( ) ;
}
}
AfxGetApp( )->WriteProfileString ( "Settings", "LastDocName", docstr ) ;
The second step, i.e to open the document when the application is executed next time, write
the following code in the InitInstance( ) function.

if ( cmdInfo.m_nShellCommand == CCommandLineInfo::FileNew
|| cmdInfo.m_nShellCommand == CCommandLineInfo::FileNothing )
{
CString docname = GetProfileString ( "Settings", "LastDocName", "" ) ;
if ( !docname.IsEmpty( ) )
OpenDocumentFile ( docname ) ;
}

Accessing Objects from Multiple Threads...


MFC objects are thread-safe at the class level but not at the object level, due to size or the
performance reasons. This means that we can have two separate threads manipulating two
different CString objects, but not two threads manipulating the same CString object.
However, if we want to have multiple threads manipulating the same object, protect such
access with appropriate Win32 synchronization mechanisms, such as critical sections.

Does every window has its own message loop?


Ans: No, not every window created by an application has a message loop. Only the
application has message loop.
This is evident from the example of a Doc/View application. In a Doc/View application, it
doesn't matter in which class we write the menu handlers. If a menu item is clicked it is
checked in which class the handlers for that message are defined and the message is then
sent to the appropriate window. This mechanism is called 'message routing'. Had there been
separate message loop for the frame window and view window it would have become
compulsory for us to write the menu handlers in the frame class.

Data Type Conversions...


1. From CString to BSTR
CString str = "Alice In Wonder Land" ;
BSTR bs = str.AllocSyString( ) ;
2. From char* to BSTR
char *s = "KICIT,Nagpur" ;
bstr_t b = s ;
3. From string to double, long, integer
char *s = "567.45" ;
double d = atof ( s ) ;
s = "54678" ;
long l = atol ( s ) ;
s = "345" ;
int i = atoi ( s ) ;

Why should we restore the device context by selecting the old GDI object once we
have used it?
Ans: If we select a new pane or brush in the device context after its use is over we must
restore the old brush in the device context. Following code snippet shows how to do this:
CPen mypen ( PS_SOLID, 1, RGB ( 255, 0, 0 ) ) ;
CClientDC dc ( this ) ;
CPen *oldpen = dc.SelectObject ( &mypen ) ;

// Use pen
mypen.DeleteObject( ) ;
dc.SelectObject ( &oldpen ) ;
When we select a GDI object, pen in this case, by calling SelectObject( ) function, address
of the pen gets stored in the device context structure. When we call DeleteObject( )
function, the pen gets deleted but its address remains stored in the device context
structure. That pointer points to such a location which does not exist at all. Such a pointer is
called as dangling pointer. Hence after deleting our pen it is necessary to restore the
address of the old pen previously selected.

What is the name of the new version of Visual C++?


Ans: The new version of Visual C++ is 'Visual C++ .NET'. You can have Visual C++ .NET on
a computer that is using Visual C++ 6.0 and use both. You can also easily recompile your
Visual C++ 6.0 projects However, in few cases, improvements have been made in MFC and
ATL libraries. You can refer the Visual Studio .NET online help for more information on
potentially code-breaking changes.

How to display MS-Excel like gridlines in list control?


Ans: The MFC class CListCtrl provides a member function SetExtendedStyle( ) using
which we can set number of extended styles for the list control. Following call to the
SetExtendedStyle( ) function shows how to display the gridlines in the list control.
m_listctrl.SetExtendedStyle ( LVS_EX_GRIDLINES ) ;

VC++ .NET Or VC++ 7.0...


VC++ .NET comes along with .NET Visual Studio. It is also called as VC++ 7.0, next version
of VC++ 6.0. In VC++ 7.0, we can write two types of code - Managed code, or Unmanaged
code. Unmanaged code is the code that makes use of MFC, ATL, COM and Win32 API
provided by VC++ 6.0. VC++ 7.0 provides better improved wizards to develop MFC or ATL
based applications as compared to those used in version 6.0. Unmanaged code development
is for those who do not want to change their current applications to become a part of .NET.
Managed Code is the code that makes use of .NET library.
In VC++ 7.0 we can even mix code types, i.e. we can write code in both managed and
unmanaged ways and then mix this code to work as a full application.

How to get command line arguments in VC++?


Ans: Some times execution of a VC++ program depends on the command line arguments
provided by the user. Or, sometimes we may run an executable from another program and
pass to it few arguments. These command line arguments can be collected by calling an API
function GetCommandLine( ).

How to use .NET base classes in VC++.NET?


Ans: Irrespective of the rich collection of classes provided by MFC we may wish to use .NET

base classes in our VC++ application. For this, open VC++ project in VC++.NET
environment. In the Solution Explorer window, right click on the name of project and select
'Properties' option. In C/C++ tab, in the 'General' link, change the 'Compile As Managed'
option to 'Assembly Support (/clr)'.
Following code shows how to use .NET collection classes.
#pragma push_macro("new")
#undef new
#using <mscorlib.dll>
#using <System.dll>
using namespace System ;
using namespace System::Collections ;
void CbaseclassView::display( )
{
ArrayList *a = new ArrayList ( 5 ) ;
// Add items in list

String *s ;
CClientDC d ( this ) ;
IEnumerator *e = a -> GetEnumerator( ) ;
int y = 30 ;
while ( e -> MoveNext( ) )
{
s = ( e -> Current ) -> ToString( ) ;
d.TextOut ( 10, y+=50, s ) ;
}

#pragma pop_macro("new")

How would you detect in your application that the system settings have been
changed?
Ans: Whenever the system settings such as folder options, active desktop settings, desktop
style, etc. change, Windows sends WM_SETTINGCHANGE message to all the top-level
windows. We can handle this message in our application and detect that the settings have
changed. The OnSettingChange( ) handler is shown below:
void CMainFrame::OnSettingChange ( UINT uFlags, LPCTSTR lpszSection )
{
MessageBox ( "Settings are changing" ) ;
CFrameWnd::OnSettingChange ( uFlags, lpszSection ) ;
}

How do I write code that displays a button on status bar and clicking the button
displays a bitmap besides the button on the status bar?
Ans: Follow the steps listed below:

10

1. Create an SDI application.


2. To the CMainFrame class add two member variables say m_button and
m_bitmap of type CButton and Cbitmap respectively.
3. Add a bitmap using Resource Editor.
4. Open OnCreate( ) function of CMainFrame class and add code to it as shown
below.
int CMainFrame :: OnCreate ( LPCREATESTRUCT lpCreateStruct )
{
// AppWizard generated code
// create button
m_button.Create ( "&My Button", WS_CHILD | WS_VISIBLE, CRect ( 45, 0, 125,
20 ), &m_wndStatusBar, 100 ) ;
return 0;
}
5. Add a member function say ShowBitmap( ) to CMainFrame class and add
following code to it.
void CMainFrame :: ShowBitmap( )
{
m_bitmap.LoadBitmap ( IDB_BITMAP1 ) ;
CDC *pDC, memdc ;
pDC = m_wndStatusBar.GetDC( ) ;
memdc.CreateCompatibleDC ( pDC ) ;
memdc.SelectObject ( &m_bitmap ) ;
pDC -> BitBlt ( 130, 0, 25, 20, &memdc, 0, 0, SRCCOPY ) ;
}

6. Add following entry to the message map so that on clicking the button the
ShowBitmap( ) function gets executed.
ON_COMMAND ( 100, ShowBitmap )

How does the CDC member functions like DrawText( ) and TextOut( ) receives
both a char* as well as a CString?
Ans: DrawText( ) and TextOut( ) are overloaded to receive char* and CString. Its not
that char* is converted to CString while receiving. This has been done so because CString
is accepted by the overloaded function as a reference. This saves copying overhead. Had it
received a CString by value there would have been no need for overloading.
------------------------------------------------------------------------------------------------------What happens if we pass a CString to a function that expects LPCSTR or viceversa?
Ans: If you pass a CString to a function that expects LPCSTR, then because CString has a
conversion operator, CString::operator LPCSTR, that converts the CString to an LPCSTR.
All the compiler needs to know is that there's this member function called operator
LPCSTR (operator const char*) that returns LPCSTR.
Now, if you pass a LPCSTR to a function that expects a CString, then again one of the
functions defined for CString as CString::CString(LPCSTR), gets called. This is a
constructor that creates a CString from an LPCSTR.

11

When we create a modeless dialog we allocate memory dynamically for the object
of the desired dialog class. How do I write code to display only one instance of the
modeless dialog and to de-allocate memory?
Ans: The memory allocated dynamically for the dialog class would not get de-allocated
unless we call delete operator. Suppose a modeless dialog of class mydialog has to be
displayed by calling a function of CChildView class, then follow the steps given below:
1. Add a pointer to an object of the mydialog class as a private data member to
CChildView class.
2. Initialize this data member to NULL in the constructor of CChildView class.
3. Add code shown below to the function that displays modeless dialog.
void CChildView :: OnModelessdlg( )
{
if ( d== NULL )
{
d = new mydialog ( this ) ; // where mydialog is a class
d -> Create ( IDD_DIALOG1 ) ; // where IDD_DIALOG1 is an ID of the dialog
created in resource editor
d -> ShowWindow ( 1 ) ;
}
else
d -> SetFocus( ) ; // to activate the dialog which is already created
}
Here, first we have ascertained whether the pointer d is NULL. If it is, then we have
allocated memory dynamically, passed the address of parent window (i.e. CChildView
class) to the constructor of mydialog class. Then we have created dialog and displayed it. If
the pointer d is not NULL then we have activated the dialog by calling SetFocus( ) so that
the same dialog would get activated.
4. Add a pointer to CWnd class as a data member to dialog class and collect the parent
address received by constructor in it.
5. Add handlers for 'OK' and 'Cancel' button to the mydialog class. A modeless dialog never
gets dismissed by calling EndDialog( ) hence, delete the base class handlers called in
OnOK( ) or OnCancel( ), and call DestroyWindwo( ) function in each of them.
6. Override PostNcDestroy( ) (a virtual function) in the mydialog class and call a user
defined function say delptr( ) of CChildView class as shown below:
void mydialog::PostNcDestroy( )
{
( CChildView * ) p ) -> delptr( ) ;
CDialog::PostNcDestroy( );
}
7. Add a function delptr( ) to CChildView class and enter following code to it.
voif CChildView :: delptr( )
{
delete d ;
d = NULL ;
}

12

How can we retrieve icon of an exe file?


Ans: The executable files of Paint Brush, Notepad, PowerPoint etc. have their own icons. If
you want to use icon of one of these executables for your window use ExtractIcon( ) API
function as shown below.
HICON hicon ;
hicon = ::ExtractIcon ( AfxGetApp( ) -> m_hInstance, "C:\\Windows\\pbrush.exe", 0 ) ;
SetIcon ( hicon, FALSE ) ;
This code snippet shows how to set icon of Paint application to our window.

What is Message Reflection?


Ans: Windows controls frequently send notification messages to their parent windows. For
instance, many controls send a control color notification message (WM_CTLCOLOR) to their
parent to allow the parent to supply a brush for painting the background of the control. The
parent window, often a dialog box, is responsible for handling these messages. This means
that the code for handling the message needs to be in the parent window's class and that it
has to be duplicated in every class that needs to handle that message. In such case, every
dialog box that wanted controls with custom backgrounds would have to handle the control
color notification message. It would be much easier to reuse code if a class for a control
could be written that would handle its own background color. MFC facilitates reuse by
providing a feature called "message reflection" that allows these notification messages to be
handled in either the control window or the parent window, or in both. In the example,
where background of a control has to be colored, you can now write a control class that sets
its own background color by handling the reflected WM_CTLCOLOR message-all without
relying on the parent.
If you have supplied a handler for a specific message in your parent window's class, it will
override reflected message handlers for the same message, provided you don't call the base
class handler function in the handler that you have supplied. For example, if you handle
WM_CTLCOLOR in your dialog box class, your handling will override any reflected message
handlers.
If, in your parent window class, you supply a handler for a specific WM_NOTIFY message,
your handler will be called only if the child control sending those messages does not have a
reflected message handler called through ON_NOTIFY_REFLECT( ).
The message-map macro for reflected messages is slightly different than the one used for
regular notifications. It has _REFLECT appended to its usual name. For instance, to handle a
WM_NOTIFY message in the parent, you use the macro ON_NOTIFY in the message map of
parent window's class. To handle the reflected message in the child control, use
ON_NOTIFY_REFLECT macro in the child control's message map.

How do I write code that would restrict user from entering any digits in an edit
control?
Ans: Follow the steps given below:
1.
2.
3.
4.

Create a dialog-based application.


Add an edit control to the dialog template.
Add a new class say myedit derived from CEdit class to the application.
Add a message handler WM_CHAR to this class and write following code to it.

13

void myedit::OnChar ( UINT nChar, UINT nRepCnt, UINT nFlags )


{
if ( ! ( isdigit ( nChar ) ) )
CEdit::OnChar ( nChar, nRepCnt, nFlags ) ;
}
5. Add an object say dlgedit of myedit class to the dialog class.
6. Open OnInitDialog( ) function of the dialog class and enter following code to it.
BOOL CEditDlg::OnInitDialog( )
{
dlgedit.SubclassDlgItem ( IDC_EDIT1, this ) ;
CDialog::OnInitDialog( ) ;
}

// AppWizardGenerated code

Setting the Timer...


The timers in an application are handled usually by generating WM_TIMER messages. What
programmers prefer is to set a timer by configuring a timer to call a callback function inside
an application. It is assumed that the timer callbacks are processed more expediently than
the timer messages, since callbacks are called directly by the Operating System whereas
WM_TIMER messages are placed in the message queue. This is a mere misconception.
In reality, timer callbacks and timer messages are handled identically up to the point at
which ::DispatchMessage is called. When a timer fires, Windows sets a flag in the
message queue to indicate that a timer message or callback is waiting to be processed. If
::GetMessage finds that the message queue is empty and that no windows need
repainting, it checks the timer flag. If the flag is set, ::GetMessage builds a WM_TIMER
message that is subsequently dispatched by ::DispatchMessage. If the timer that
generated the message is of WM_TIMER variety, the message is dispatched to the window
procedure. But if a callback function is registered instead, ::DispatchMessage calls the
callback function. Therefore callback timers enjoy virtually no performance advantage over
message timers. Callbacks are subject to slightly less overhead than messages because
neither a message map nor a Windows procedure is involved, thus the difference is all but
immeasurable.

How can I create an edit window of the size same as the size of frame window and
resize automatically when size of frame window is changed?
Ans: By giving AFX_IDW_PANE_FIRST as an id while creating an edit window.
For example:
edit.Create ( WS_CHILD | WS_VISIBLE | ES_MULTILINE, rectDefault, this,
AFX_IDW_PANE_FIRST ) ;
where edit is an object of CEdit class.

We can get the memory information of the machine like total virtual memory, memory in
use, etc using an API function GlobalMemoryStatus( ) as shown below:
void mydialog::OnButton1( )
{
DWORD var ;

14

MEMORYSTATUS memorystatus = { 0 } ;
memorystatus.dwLength = sizeof ( MEMORYSTATUS ) ;
GlobalMemoryStatus ( &memorystatus ) ;
CString m_memused ;
m_memused.Format ( "Memory used %ld",
memorystatus.dwMemoryLoad ) ;
var = memorystatus.dwTotalPhys / 1024 ;
CString m_meminstalled ;
m_meminstalled.Format ( "Memory installed %ld", var ) ;
m_meminstalled += " KB" ;
var = memorystatus.dwAvailPhys / 1024 ;
CString m_memavailable ;
m_memavailable.Format ( "Memory available %ld", var ) ;
m_memavailable += " KB" ;
var = memorystatus.dwTotalVirtual / 1024 ;
CString m_memvirtual ;
m_memvirtual.Format ( "Total virtual memory %ld", var ) ;
m_memvirtual += " KB" ;
CString meminfo ;
meminfo = m_memused ;
meminfo += "\n" ;
meminfo += m_meminstalled ;
meminfo += "\n" ;
meminfo += m_memavailable ;
meminfo += "\n" ;
meminfo += m_memvirtual ;
MessageBox ( meminfo ) ;
}

How do I set a system wide cursor?


Ans: If we change the cursor using SetCursor( ) function, the new cursor gets displayed as
long as cursor is in our application window. As soon as it goes outside the window, system
cursor gets restored. If we want to change the cursor system wide then we can use a
function SetSystemCursor( ). Following code snippet shows how to use this function.
HCURSOR h1 = AfxGetApp( ) -> LoadCursor ( IDC_CURSOR1 ) ;
HCURSOR h2 = CopyCursor ( h1 ) ;
SetSystemCursor ( h2, OCR_NORMAL ) ;
If we obtain handle to the new cursor using LoadCursor( ) function DestroyCursor( )
function automatically gets called to destroy the handle. So, we have copied the handle
using CopyCursor( ) function. OCR_NORMAL is a macro defined for "Normal" arrow cursor.
For every cursor used by the system there is a corresponding macro. These macros are
#defined only if a macro OEMRESOURCE is defined. So, we must add the following
statement in 'stdafx.h' before the #include statements.
#define OEMRESOURCE

15

How to obtain dependencies of an executable file?


Ans: We can use a tool called 'Depends' that is shipped with Visual C++ 6.0 to get the
names of various DLLs used by any application, ActiveX control, device drivers, screen
savers, etc. We can run this tool by selecting 'Depends' from 'Start | Programs | Microsoft
Visual C++ 6.0 | Microsoft Visual C++ 6.0 Tools'. The tool shows information like the DLLs,
functions available in the DLLs, ordinal numbers of the functions in DLL, etc.

How a dialog box works?


DoModal( ) function creates and displays the dialog box. Just after creation of the dialog
box and before displaying it Windows sends the dialog box WM_INITDIALOG message. This
message activates OnInitDialog( ) handler. In this handler we should call base class's
OnInitDialog( ) because it calls CWnd::UpdateData( ) function with a FALSE parameter.
UpdateData( ) in turn creates a CDataExchange object and calls dialog class's
DoDataExchange( ), passing it a pointer to CDataExchange object. In this function
macros like DDX_Text( ), DDX_Check( ) etc. are used to initialize a control to the value
of the dialog box when it is displayed.
If we wish to extract data from the controls or validate the data we must override OnOK( )
handler. In our implementation we must call CDialog's OnOK( ) function. When the user
clicks OK, OnOK( ) handler calls UpdateData( ) with TRUE parameter. So when
DoDataExchange( ) is called values entered in the controls get collected in the associated
variables. OnOK( ) calls EndDialog( ) functions to dismiss the dialog box.

How do I create a custom control?


Ans: Follow the steps given below, to create a custom control.
1. Create a simple MFC Application containing Dialog resource.
2. Select the custom control from the control bar.
3. Drag and place the custom control on the Dialog resource.
4. Select Class Wizard by right-clicking on the custom control.
5. Click 'Add Class' button, and add a new class. Select appropriate base class.
6. Add a function called RegisterWndClass( ) and add code to it to register the Custom
Window class.
7. Call this function through the constructor of the custom class.
8. Set the custom controls class to the registered window class name. To do so right click on
the control (in resource editor) and select 'Properties'. Specify the name of the registered
class in edit control labelled with 'Class'
9. Add the member variable for the control to the dialog, using 'Add Member variable...'
option.
10. Add code to DoDataExchange( ) so that data can be exchanged from variable to
control (i.e. custom control) and vice versa.
11. The program can now be compiled and executed. If required then we can add windows
messages to the Custom controls'

How do I set background image for a List view control?


Ans: To set the background image for a list view control write following code in the
OnInitDialog( ) function.
BOOL CListimageDlg::OnInitDialog( )
{

16

// AppWizard generated code


CoInitialize ( NULL ) ;
m_list.SetBkImage ( "C:\\Windows\\Bubbles.bmp" ) ;
}

return TRUE ; // return TRUE unless you set the focus to a control

The SetBkImage( ) function makes use of OLE COM functionality. Hence we have called
CoInitialize( ) to initialise the COM libraries.

In an MDI application that supports multiple document types, how does a view
identify its document?
Ans: A document object can have any number of views associated with it, but a view always
belongs to just one document. The framework stores a pointer to the associated document
object in a view's m_pDocument data member and exposes that pointer through the
view's GetDocument( ) member function. The way document object can identify its views
using GetFirstViewPosition( ) and GetNextView( ), a view can identify its document by
calling the GetDocument( ) function.

Whenever a software created in VC++ is to be distributed one should distribute it in Release


version rather than in Debug version. Release version does not contain debug information
and so the size of an exe file reduces to a great extent. It also results in increase in the
speed of execution.

How do I write code that sets desktop wallpaper using IActiveDesktop interface?
Ans: Create a dialog based application, and #include following header files in 'StdAfx.h'
file. Note that the following files should get #included after 'afxwin.h'
#include <comdef.h>
#include <wininet.h>
#include <atlbase.h>
Then add a private variable to the dialog class as shown below:
CComQIPtr<IActiveDesktop> pad ;
To get interface pointer add following code to OnInitDialog( ).
BOOL CSetwpDlg :: OnInitDialog( )
{
// AppWizard generated code
CoInitialize ( NULL ) ;
HRESULT hr = CoCreateInstance ( CLSID_ActiveDesktop, NULL,
CLSCTX_INPROC_SERVER, IID_IActiveDesktop, ( void** ) &pad ) ;
return TRUE ;
}
To set wallpaper add following code to the button handler.
void CSetwpDlg::OnSetwallpaper( )
{
COMPONENTSOPT comopt ;
WALLPAPEROPT wpopt ;
comopt.dwSize = sizeof ( comopt ) ;

17

comopt.fActiveDesktop = TRUE ;
comopt.fEnableComponents = TRUE ;
wpopt.dwSize = sizeof ( WALLPAPEROPT ) ;
wpopt.dwStyle = WPSTYLE_TILE ;
pad -> SetDesktopItemOptions ( &comopt, 0 ) ;
pad -> SetWallpaperOptions ( &wpopt, 0 ) ;
USES_CONVERSION ;
CString str = "C:\\Winnt\\Soap Bubbles.bmp" ;
pad -> SetWallpaper ( T2CW ( str ), 0 ) ;
pad -> SetWallpaperOptions ( &wpopt, 0 ) ;
pad -> ApplyChanges ( AD_APPLY_ALL ) ;
}

How do I display a bitmap in a static control?


Ans: A static control can display an image if its style is set to SS_BITMAP. But, we cannot
set this style through properties window when we add a static control to a dialog template.
We need to change the style programmatically. This is shown in following code snippet.
BOOL mydialog::OnInitDialog( )
{
//AppWizard generated code
m_sctrl.ModifyStyle ( 0, SS_BITMAP ) ; // where m_sctrl is a control variable of
static control
HBITMAP h = ( HBITMAP ) ::LoadImage ( NULL, "C:\\Windows\\bubbles.bmp",
IMAGE_BITMAP, LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_LOADFROMFILE ) ;
m_sctrl.SetBitmap ( h ) ;
return TRUE ;
}

How to register a document type with an OS shell?


Ans: Registering an application with OS shell, involves writing a series of entries to the
HKEY_CLASSES_ROOT branch of the registry that identify each document type with its file
name extension and the command used to open and print files of that type. An MFC
application makes simple function calls and registers every document type it supports.
BOOL CMyApp::InitInstance( )
{
// AppWizard generated code
CSingleDocTemplate* pDocTemplate ;
pDocTemplate = new CSingleDocTemplate ( IDR_MAINFRAME, RUNTIME_CLASS
( CMyDoc ), RUNTIME_CLASS ( CMainFrame ), // main SDI frame window
RUNTIME_CLASS ( CMyView ) ) ;
AddDocTemplate ( pDocTemplate ) ;
// Enable DDE Execute open
EnableShellOpen( ) ;
RegisterShellFileTypes ( TRUE ) ;
// AppWizard generated code

18

return TRUE ;

The function CWinApp::AddDocTemplate( ) adds a document template to the list of


available document templates that the application maintains. Then the function
CWinApp::RegisterShellFileTypes ( TRUE ) registers an applications document types
with the Windows. The function CWinApp::EnableShellOpen( ), allows the user to open a
file created by an application by double-clicking it.

How to change the color of a progress bar in a progress bar control?


Ans: Call SendMessage( ) function as follows:
m_progress.SendMessage ( PBM_SETBARCOLOR, 0, RGB ( 255, 0, 0 ) ) ;
Where m_progress is an object of CProgressCtrl class.

The WM_NOTIFY message...


Unlike the classic controls, which send notifications to their parents using WM_COMMAND
messages, most common controls, send their notifications in WM_NOTIFY mesages.
virtual BOOL OnNotify ( WPARAM wParam, LPARAM lParam, LRESULT* pResult ) ;
The parameter wParam, holds the child window ID of the control that sent the message,
and lParam holds a pointer to an NMHDR structure. NMHDR is defined as follows.
typedef struct tagNMHDR
{
HWND hwndFrom ;
UINT idFrom ;
UINT code ;
} NMHDR ;
hwndFrom holds the control's window handle, idFrom holds the control ID (the same
value that is passed in wParam), and code specifies the notification code. The notification
code identifies the notifications like left mouse button is clicked or double clicked, enter key
is pressed etc.

How to ensure that at a time only one instance of an application runs in the
memory?
Ans: Some applications like MS-Power Point allow only one instance of the application to run
in the memory. It means that if PowerPoint application is already loaded and if we try to
open another '.ppt' file the file gets opened in the same instance of PowerPoint. We can also
achieve this using the following code.
In the frame window class write a function as shown below:
int CMainFrame::oncheck( )
{
return 0xA1B2C3D4 ;
}
Nothing special about the number 0xA1B2C3D4. We can give any unique number.
Make the following entry in message map of frame window class.
ON_MESSAGE ( WM_USER, oncheck )
BOOL CMyApp::InitInstance( )
{

19

CWnd *check = CWnd::FindWindow ( 0, "Hello World" ) ;


if ( check && check -> SendMessage ( WM_USER ) == 0xA1B2C3D4 )
{
check -> SetForegroundWindow( ) ;
check -> ShowWindow ( SW_SHOWNORMAL ) ;
}
else
{
// Code added by AppWizard
m_pMainWnd -> ShowWindow ( SW_SHOW ) ;
m_pMainWnd -> UpdateWindow( ) ;
return TRUE ;
}
return 0 ;
}
In the above code "Hello World" must be the title of the window.

How do I write code so that when focus is set on edit control, its background and
foreground color changes and when the focus is not on the edit control, it should
change back to normal?
Ans: To change color of edit control when focus is set on it and bring it back to normal when
focus goes on some other control, create a class derived from CEdit and handle
EN_SETFOCUS and EN_KILLFOCUS events in it. Besides this also handle WM_CTLCOLOR
message in this class. Add code to the event handlers as shown below:
HBRUSH MyEdit :: CtlColor ( CDC* pDC, UINT nCtlColor )
{
if ( CWnd :: GetFocus( ) == this )
{
static CBrush mybrush ( RGB ( 255, 0, 0 ) ) ;
pDC -> SetBkColor ( RGB ( 0, 255, 0 ) ) ;
pDC -> SetTextColor ( RGB ( 0, 0, 255 ) ) ;
return mybrush ;
}
return NULL ;
}
void MyEdit :: OnSetfocus( )
{
Invalidate( ) ;
UpdateWindow( ) ;
}
void MyEdit :: OnKillfocus( )
{
Invalidate( ) ;
UpdateWindow( ) ;
}
Now add a member variable of MyEdit class to the dialog class of your dialog-based
application. Also add an edit control on to the dialog template. To subclass this control add
code to OnInitDialog( ) as shown below:
BOOL CMyDlg :: OnInitDialog( )
{

20

m_edit.SubclassDlgItem ( IDC_EDIT1, this ) ; // Where m_edit is a variable of MyEdit


CDialog :: OnInitDialog( ) ;
// AppWizard generated code
}

How do I get an IP address of a local machine?


Ans: Follow the steps given below
1. Create an application with 'Windows Socket' support.
2. Add following code to the handler that is meant to return an IP address.
void mydialog::getIPaddress( )
{
CString hostname ; // stores local host name
CString IPAddress ; // stores IP address
char hname[256] ;
int nRetCode = gethostname ( hname, sizeof ( hname ) ) ;
if ( nRetCode != 0)
{
MessageBox ( "Host name not available" ) ;
return ;
}
else
hostname = hname ;
hostent FAR *lpHostEnt = gethostbyname ( hostname ) ;
if ( lpHostEnt == NULL )
{
MessageBox ( "IPAddress not available" ) ;
retrun ;
}
LPSTR lpAddr = lpHostEnt -> h_addr_list[0] ;
if ( lpAddr )
{
in_addr inAddr ;
memmove ( &inAddr, lpAddr, 4 ) ;
IPAddress = inet_ntoa ( inAddr ) ;
if ( IPAddress.IsEmpty( ) )
MessageBox ( "IPAddress not available" ) ;
}
}
To get an IP address of the local machine, we need to know the host name. Hence, we have
called the Windows Socket's function gethostname( ) . This function returns the host
name for the local machine. The function gethostbyname( ) called next retrieves the host
information about the given host name. It returns a pointer to the hostent structure. This
structure contains an IP address. To retrieve an IP address from this structure first we have
copied first 4 bytes from lpAddr to inAddr. Then by calling inet_ntoa( ) function (again a
windows socket function) we have retrieved an IP address.

DeleteContents( )...

21

In case of an SDI application, when a new document is created or opened, the framework
calls the virtual function DeleteContents( ) to delete the document's existing data. Thus,
we can override CDocument::DeleteContents( ) and take the opportunity to free any
resources allocated to the document and perform other necessary cleanup procedures, in
order to reuse the document object.

Collection Classes
Ans: MFC provides collection classes of three categories. The classes under each category
and what the object of these classes can store are given below:
MFC Array Classes
CByteArray - 8-bit bytes (BYTEs)
CWordArray - 16-bit words (WORDs)
CUIntArray - Unsigned integers (UINTs)
CStringArray - CStrings
CPtrArray - void pointers
CObArray - CObject pointers
MFC List Classes
CObList - CObject pointers
CPtrList - void pointers
CStringList - CStrings
MFC Map Classes
CMapWordToPtr - Stores void pointers keyed by WORDs
CMapPtrToWord - Stores WORDs keyed by void pointers
CMapPtrToPtr - Stores void pointers keyed by other void pointers
CMapWordToOb - Stores CObject pointers keyed by WORDs
CMapStringToOb - Stores CObject pointers keyed by strings
CMapStringToPtr - Stores void pointer keyed by strings
CMapStringToString - Stores strings keyed by other strings

When does the update-command handler get called?


Ans: MFC sets up an object of CCmdUI class for every menu item, toolbar button, and
status bar pane in an application, then calls CCmdUI::DoUpdate( ) for each one.
CCmdUI::DoUpdate( ) checks message maps looking for ON_UPDATE_COMMAND_UI
handlers with IDs that match the ID of the menu item, toolbar button, or status bar pane.
Thus, when we select a menu (either using hot keys or by pressing mouse button) all
update-command handlers added for the menu items of the selected menu gets called and
then the menu gets displayed. The update-command handler receives address of the
CCmdUI object associated with the item.

How do I enumerate windows of currently running applications?


Ans: Follow the steps given below.
1. Create a dialog-based application.
2. Add a button and a list box control to the dialog template.
3. Add control variable say m_list for the list box to the dialog class.
4. Add following code to the button handler.
void CDlgDlg::OnGetwindow( )
{

22

HWND hlb = ( HWND ) m_list ;


CWnd *h = GetDesktopWindow( ) ;
WindowsHandle ( h -> m_hWnd, ( LPARAM ) hlb ) ;
EnumWindows ( WindowsHandle, ( LPARAM ) hlb ) ;
}
Here, h stores the address of desktop window. A handle to the desktop window and a list
box control is then passed to a callback function WindowsHandle( ). This function
retrieves the title of the window and adds it to the list box. The function EnumWindows( )
called next enumerates all top-level windows on the screen by passing the handle to each
window, in turn, to WindowsHandle( ) function. EnumWindows continues until the last
top-level window is enumerated or the callback function returns FALSE. The code to the
WindowsHandle( ) function is as shown below.
BOOL CALLBACK WindowsHandle ( HWND hwnd, LPARAM lParam )
{
CWnd *h = CWnd::FromHandle ( hwnd ) ;
CString hand ;
hand.Format ( "%p ", hwnd ) ;
CString title ;
h -> GetWindowText ( title ) ;
if ( title == "" )
title += "\"\" " ;
else
title = "\"" + title + "\" " ;
char cname[50] ;
GetClassName ( hwnd, cname, 50 ) ;

HWND hcb = ( HWND ) lParam ;


CWnd *pcombo = CWnd::FromHandle ( hcb ) ;
( ( CListBox * ) pcombo ) -> AddString ( hand + title + cname ) ;
return TRUE ;

RUNTIME_CLASS ( )...
The RUNTIME_CLASS macro surrounding the class names returns a pointer to a
CRuntimeClass structure for the specified class. This enables the framework to create
objects of that class at run time. This is what is a dynamic creation mechanism a feature of
Doc/View.

How would you display a list box having a check box in front of each item?
Ans: We come across a list box having check boxes many times while installing softwares
like Microsoft Visual C++, MS-office etc. We can also implement such a list box and give a
professional look to our application. This is how it can be done...

Derive a class, say, mycheckbox from CCheckListBox class.

Create an object of mycheckbox and call Create( ) function.

Add strings using CCheckListBox::AddString( ) function.

Run the application and you will see the list control with check boxes. You can
interact with the control using member functions of CCheckListBox.

23

How do I write code to know whether or not a thread is alive?


Ans: Use GetExitCodeThread( ) function. To this function, we need to pass a handle to
the thread (whose status has to be checked) and address of a DWORD variable. Following
code snippet shows how this can be achieved.
void OnStatus( )
{
DWORD d ;
GetExitCodeThread ( pthread -> m_hThread, &d ) ;
if ( d == STILL_ACTIVE )
MessageBox ( "thread is active" ) ;
LPVOID lpMsgBuf ;
FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError( ), MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT), //
Default language (LPTSTR) &lpMsgBuf, 0, NULL ) ;
MessageBox ( ( LPCTSTR ) lpMsgBuf ) ;
LocalFree ( lpMsgBuf ) ;
}
Here, pthread is a pointer to the thread object. If the thread is still alive then the
GetExitCodeThread( ) will be successful. If this function fails, then using
FormatMessage( ) function we can retrieve an error message as shown in code snippet.

Error with EOF while using ADO


When we #include 'afxwin.h' file number of other header files also get #included. In one
of these files the macro EOF stands defined with -1. While using ADO we have to #import
'msado15.dll'. When the #import statement is compiled 'msado15.tlh' file gets created. In
this file EOF is again defined as a property of Recordset class. Here EOF is defined as
VARIANT_BOOL EOF ;
VARIANT_BOOL is typedefed as short. Hence, when the above line is parsed it becomes
short -1 ;
-1 is not a valid variable name. Hence while using ADO we have to rename EOF to some
other name as given below:
rename ( "EOF", "ADOEOF" ) ;

How to extract red, green and blue elements from a RGB value without using API
functions?
Ans: Following code retrieves red, green and blue elements from a COLORREF object rgb.
COLORREF rgb = RGB ( 100, 50, 75 ) ;
int r, g, b ;
r = ( ( rgb ) & 0xff ) ;
g = ( ( ( rgb ) >> 8 ) & 0xff ) ;
b = ( ( ( rgb ) >> 16 ) & 0xff ) ;

Suppose there are 6 pairs of controls, each having a slider control and an edit
control. If slider of a particular slider control is moved then the value
corresponding to its position should get displayed in an edit control placed besides
it. How do I write code to achieve this?

24

Ans: Override OnNotify( ) virtual function. This function notifies the parent window of a
control that an event has occurred in the control. Add code to it as shown below:
BOOL CMyDlg :: OnNotify ( WPARAM wParam, LPARAM lParam, LRESULT* pResult )
{
NMHDR *n = ( NMHDR * ) lParam ;
switch ( n -> idFrom )
{
case IDC_SLIDER1 :
m_val1 = m_slider1.GetPos( ) ;
break ;
// where m_val1 is a value var. of edit ctrl.
// & m_slider1 is a ctrl var. of slider ctrl.
case IDC_SLIDER2 :
m_val2 = m_slider2.GetPos( ) ;
break ;
case IDC_SLIDER3 :
m_val3 = m_slider3.GetPos( ) ;
break ;
case IDC_SLIDER4 :
m_val4 = m_slider4.GetPos( ) ;
break ;
case IDC_SLIDER5 :
m_val5 = m_slider5.GetPos( ) ;
break ;
case IDC_SLIDER6 :
m_val6 = m_slider6.GetPos( ) ;
break ;
}
UpdateData ( FALSE ) ;
return CDialog :: OnNotify ( wParam, lParam, pResult ) ;
}

How do I write code so that if I delete a file, then instead of getting the file
deleted permanently it should go to the Recycle bin?
Ans: Use a shell API function called SHFileOperation( ). This function takes one argument
which is a pointer to the SHFILEOPSTRUCT structure. This structure tells Windows what
operation to perform, which files to delete, and other important information.
SHFileOperation( ) also lets us copy, move, or rename one or several files. The following
code snippet shows how to use this function.
void CRecycleDlg::OnDelete()
{
static SHFILEOPSTRUCT fp ;
char buff[] = "C:\\file1.txt\0\0" ;
fp.wFunc = FO_DELETE ;
fp.pFrom = ( LPCSTR ) buff ;
fp.fFlags = FOF_ALLOWUNDO ;
}

SHFileOperation ( &fp ) ;

25

When we use FO_DELETE operation to delete a file, SHFileOperation( ) attempts to place


the deleted file in the Recycle Bin. Note that to send file to recycle bin we must set fFlags
to FOF_ALLOWUNDO.

If I add a new class, say myview, for example derived from CListView, the
ClassWizard generates a class but uses DECLARE_DYNCREATE(...) and declares
constructor as protected. Now, if I try to create an instance of the class, I get the
compiler error as "cannot access protected member declared in class 'myview'?
Why does ClassWizard makes the constructor protected?
Ans: The ClassWizard makes the constructor of class as protected, this is because the
framework normally creates an object. If this is a CView derived class, normally the
CDocumentTemplate instantiates the view during the default OnFileNew( ) or when you
call OpenDocumentFile( ). The framework does this so that it will give you an error
message if you accidentally try to instantiate it yourself. If you really need to do
instantiation outside of the CDocTemplate framework, simply change the constructor to be
public.

Can we have drag-drop functionality for a CListBox control? If yes then how do I
get the name(s) of file(s) that I drag-drop on a CListBox control?
Ans: The CListBox control can have a drag-drop functionality. Follow the steps given below
to get the names of files dropped on a list box.
1. Create a dialog-based application. Add a list box control to the dialog template.
2. Check 'Accept Files' property of the 'Extended Styles' tab for the list box control, so that if
a user drops a file on this control, WM_DROPFILES message will be sent to the control.
3. Add a new class say list derived from CListBox class to the application.
4. Add WM_CREATE and WM_DROPFILES message handlers to the list class and enter code
given below to these handlers.
int list :: OnCreate ( LPCREATESTRUCT lpCreateStruct )
{
//AppWizard generated code
DragAcceptFiles ( TRUE ) ;
return 0 ;
}
void list :: OnDropFiles ( HDROP hDropInfo )
{
char buff[255] ;
int c = DragQueryFile ( hDropInfo, 0xFFFFFFFF, ( LPTSTR ) buff, sizeof ( buff ) ) ;
for ( int i = 0 ; i < c ; i++ )
{
int c = DragQueryFile ( hDropInfo, i, ( LPTSTR ) buff, sizeof ( buff ) ) ;
AddString ( ( LPCTSTR ) buff ) ;
}
}

CListBox :: OnDropFiles ( hDropInfo ) ;


The DragAcceptFiles( ) function with parameter TRUE enables to process the
WM_DROPFILES message. Then in

26

OnDropFiles( ) handler we have used DragQueryFile( ) function which retrieves the


file name(s) of dropped file(s). The first call to DragQueryFile( ) function returns the
number of files dropped. Then through a loop we have called DragQueryFile( ) function
again to extract the file name(s). The name thus retrieved is then added to the list box
by calling AddString( ) function.
5. Add a member variable say m_list of class list to the dialog class and add following code
to the OnInitDialog( ) function.
BOOL CDragdropDlg::OnInitDialog( )
{
m_list.SubclassDlgItem ( IDC_LIST1, this ) ; // where IDC_LIST1 is an id of list box
control
CDialog :: OnInitDialog( ) ;

// AppWizard generated code


return TRUE ;

How do I move start button on the taskbar?


Ans: Create a dialog based application and add following variables to the dialog class.
int m_maxX ;
CWnd* m_pWndStart,*m_parent ;
CRect rect ;
The Start button on the task bar is a control, and a control is nothing but a window. The
start button belongs to the Window class Shell_TrayWnd.
BOOL CMyDialog::OnInitDialog( )
{
//AppWizard generated code
m_parent = FindWindow ( "Shell_TrayWnd", "" ) ;
if ( m_parent )
{
m_pWndStart = m_parent -> GetWindow ( GW_CHILD ) ;
}
if ( m_pWndStart == NULL )
PostMessage ( WM_CLOSE ) ;
else
{
m_pWndStart -> GetWindowRect ( &rect ) ;
m_parent -> ScreenToClient ( &rect ) ;
SetTimer ( 1, 0, NULL ) ;
}

m_maxX = ::GetSystemMetrics ( SM_CXSCREEN ) ;


return TRUE ;

The function CWnd::FindWindow( ) identifies the window with the class Shell_TrayWnd.
Then to get the pointer to the window we have called function CWnd::GetWindow( ).

27

Next, to move the button, we require to know the screen coordinates of the upper-left and
lower-right corners of the start button. This is achieved by calling
CWnd::GetWindowRect( ) function. These coordinates are then converted to the client
coordinate as they are required to place the start button at new place. Then to move start
button we should know the maximum width (in terms of pixels) of the display monitor. The
function GetSystemMetrics( ) would give us the width of the screen. Then we have called
a timer, that would move the start button
CMyDialog::OnTimer ( UINT nIDEvent )
{
rect.OffsetRect ( 1, 0 ) ;
if ( rect.left >= m_maxX )
rect.left = 2 ;
m_pWndStart -> SetWindowPos ( &wndTop, rect.left, rect.top, 0, 0, SWP_NOSIZE |
SWP_SHOWWINDOW | SWP_FRAMECHANGED ) ;
}
The function CRect::OffsetRect( ) would move the Start button by one unit to the right (of
start button on the taskbar). CWnd::SetWindowPos( ) would change the position of the
window.

How to create a colored or animated cursor?


Ans: We cannot create a colored cursor in Resource Editor. To create it we need an editor
called Image Editor which comes as a sample in VC++ 5.0 CD. It provides all the drawing
tools and color palette using which we can draw the cursor. Save it as '.cur' file. Now, we
can import it in our application by selecting Insert | Resource | Cursor and then selecting
the '.cur' file. Load it using LoadCursor( ) and display it using AfxRegisterWndClass( ).
To create animated cursor we need an editor called 'aniedit' which is given in VC++ 5.0 CD.
Create different frames in the editor and save these frames in an '.ani' file. Load the cursor
using ::LoadCursorFromFile( ) and pass the handle returned by this function to
AfxRegisterWndClass( ) function.

How do I write code to size a view?


Ans: The view window is a child of frame window and is housed in frame window. We can
change the size of a window by calling CWnd::MoveWindow( ) function. To change the
size of the view window, we need to get a pointer to the frame window of the view. This can
be done by calling CWnd::GetParentFrame( ) function. Once we get pointer to frame
window, call MoveWindow( ) to change the size of the parent. When the parent frame
window changes size, it automatically changes the size of the view window to fit in the
parent frame. The following code snippet shows how this can be achieved.
#include "Mainfrm.h"
// OnChange( ) is a handler for menu item
void CMyView :: OnChange( )
{
CMainFrame *w = ( CMainFrame * ) GetParentFrame( ) ;
w -> MoveWindow( 0, 0, 300, 300 ) ;
}
How do I change the system colors programmatically?
Ans: An API function SetSysColors( ) is used to change the color of various display

28

elements like caption bar, menu, desktop, etc of a window. This function takes the number
of elements whose color has to be changed, a pointer to an array of integers which
represents the display elements, and an array containing new RGB values for the elements
whose color has to be changed. The following code snippet demonstrates the use of this
function, where we have changed the color of caption bar of active window, menu and a
window.
void CSyscolorDlg::OnSetColor( )
{
int color_array[] = { COLOR_ACTIVECAPTION, COLOR_MENU, COLOR_WINDOW } ;
COLORREF rgbvalues[] = { RGB ( 255, 0, 0 ) , RGB ( 255, 255, 0 ), RGB ( 0, 255,
255 ) } ;
SetSysColors ( 3, color_array, rgbvalues ) ;
}

How do I create a dropdown toolbutton on a toolbar?


Ans : The DropDown toolbutton acts like a menu item. To get this effect we will have to
create a toolbar, with an extended style as TBSTYLE_EX_DRAWDDARROWS. Then set
dropdown style to the button for which you want a dropdown control.
int CMainFrame::OnCreate ( LPCREATESTRUCT lpCreateStruct )
{
//AppWizard generated code
m_rebar.Create ( this ) ; // m_rebar a private variable of class CReBar
m_toolbar.CreateEx ( this ) ; // m_toolbar a private variable of CToolBar
// set dropdown arrow style for the toolbar
m_toolbar.GetToolBarCtrl( ).SetExtendedStyle ( TBSTYLE_EX_DRAWDDARROWS ) ;
m_toolbar.SetButtons ( NULL, 1 ) ;
// set dropdown style to the button for which you want a dropdown control
m_toolbar.SetButtonInfo ( 0, ID_MY_BUTTON, TBSTYLE_DROPDOWN, 0 ) ;
CRect toolrect ;
m_toolbar.GetItemRect ( 0, &toolrect ) ;
m_toolbar.SetSizes( toolrect.Size( ), CSize ( 16, 15 ) ) ;
m_rebar.AddBar ( &m_toolbar ) ;
}
Add following two lines to the 'MainFrm.cpp' file of the application.
#define lpnm ( ( LPNMHDR ) lParam )
#define lpnmTB ( ( LPNMTOOLBAR ) lParam )
Then add a WM_NOTIFY message to the CMainFrame class and enter following code to it.
BOOL CMainFrame::OnNotify ( WPARAM wParam, LPARAM lParam, LRESULT* pResult )
{
CMenu menu ;
CPoint p ;
CRect r ;
m_toolbar.GetWindowRect ( &r ) ;
p.x = r.top+70 ; // specify coordinates for the dropdown menu to be displayed
p.y = r.bottom ;
switch ( lpnm -> code ) // check for the drop down event
{
case TBN_DROPDOWN : //drop down button was hit handle appropriately

29

// check if the toolbutton for whom the drop dwon menu has to be displayed is
selected
if ( lpnmTB -> iItem == ID_MY_BUTTON )
{
if ( menu.m_hMenu != NULL )
menu.DestroyMenu( ) ;
menu.LoadMenu ( IDR_MENU1 ) ;
CMenu* pPopup = menu.GetSubMenu ( 0 ) ;
p.x = r.top ;
p.y = r.bottom ;
pPopup -> TrackPopupMenu ( TPM_RIGHTALIGN | TPM_RIGHTBUTTON, p.x, p.y,
this ) ;
return FALSE ; //indicates the TBN_DROPDOWN notification was handled.
}
}

How to disable Ctrl+Alt+Del key?


Ans: Disabling Ctrl+Alt+Del keys is an easy job. Just call SystemParametersInfo( )
function as follows:
SystemParametersInfo ( SPI_SETSCREENSAVERRUNNING, TRUE, NULL, 0 ) ;
To enable the keys again call SystemParametersInfo( ) as given below:
SystemParametersInfo ( SPI_SETSCREENSAVERRUNNING, TRUE, NULL, 0 ) ;

How do I write code that sets different icon for all the modeless dialogs of my
application?
Ans: To set a different icon for a modal/modeless dialog, call SetIcon( ) in
OnInitDialog( ) of each of the dialog class for which an icon has to be set. This is shown in
the code snippet given below:
BOOL modeless :: OnInitDialog( )
{
CDialog :: OnInitDialog( ) ;
SetIcon ( AfxGetApp( ) -> LoadIcon ( IDI_ICON1 ),FALSE ) ;
}

return TRUE ;

How do I check programmatically, whether an Internet connection is available on


my system?
Ans: The function InternetGetConnectedState( ) is used to find if an Internet connection
is available on the system. This function returns true if an Internet connection is available. It
also tells how the connection is available, i.e. whether the system uses modem, proxy or
LAN to connect to the Internet. To make use of this function we need to #include
'wininet.h' file and link 'wininet.lib' file through 'Project | Settings | Link '. The following code
snippet shows how we can use this function.
void CNetdlgDlg::OnCheckNet( )
{

30

DWORD flag ;
CString str = "" ;
if ( InternetGetConnectedState ( &flag, NULL ) )
str += "Internet connection is present\n" ;
else
str += "No Internet connection\n" ;

if ( flag & INTERNET_CONNECTION_LAN )


str += "The system uses a local area network to connect to the Internet" ;
if ( flag & INTERNET_CONNECTION_MODEM )
str += "The system uses a modem to connect to the Internet" ;
if ( flag & INTERNET_CONNECTION_PROXY )
str += "The system uses a proxy server to connect to the Internet\n" ;
MessageBox ( str ) ;

CreateCompatibleDC( )...
To draw a bitmap in a window, first we have to create a special type of device context called
memory device context and then select the bitmap into the memory device context.
CDC::CreateCompatibleDC( ) creates a memory DC that is compatible with the specified
device context whose address you pass in is usually a screen DC.
Once a bitmap is selected into a memory device context, we can draw to the memory device
context using the same CDC member functions you use to draw to a screen or printer
device context. Drawing to a memory device context first and then transferring them to a
screen device context can be useful for replicating the same image on the screen several
times. Rather than draw the image a new each time, you can draw it once in a memory
device context and then transfer it to a screen device context as many times as you want.

How to display processes running on the system?


Ans: Many a times we need to see whether a particular application is running in the
memory. We can get the information of processes running in the memory by using API
functions Process32First( ) and Process32Next( ) as shown below.
PROCESSENTRY32 pr ;
HANDLE h = CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS, 0 ) ;
Process32First ( h, &pr ) ;
do
{
///Write your code///
} while ( Process32Next ( h, &pr ) ) ;

The width and height of a widow of an SDI application is fixed so that it cannot be
changed at runtime. However, if I move cursor on the left or right border of the
window, it still displays the left/right size arrows. How do I write code to prevent
the size arrows from getting displayed?
Ans: To prevent displaying of size arrows for a window whose size has been fixed override
WM_NCHITTEST message in your application as shown below:
UINT CMainFrame :: OnNcHitTest ( CPoint point )
{

31

UINT hittest = CFrameWnd :: OnNcHitTest ( point ) ;


switch ( hittest )
{
case HTLEFT :
case HTRIGHT :
case HTBOTTOMLEFT :
case HTBOTTOMRIGHT :
case HTTOPLEFT :
case HTTOPRIGHT :
return HTBORDER ;

default :
return hittest ;

}
The OnNcHitTest( ) function returns an enumerated value. For example a value such as
HTBORDER indicates that the mouse is on the broder of the window.
Here, we have checked the value returned by the CFrameWnd::OnNcHitTest( ) function.
If the value is any from
HTLEFT/HTTOPLEFT/HTBOTTOMLEFT/HTRIGHT/HTTOPRIGH/HTBOTTOMRIGHT (which
require size arrow cursor) then we are returning HTBORDER that indicates no sizing border,
hence cursor will not get changed.

How do I create a bitmapped button on a dialog box?


Ans: Follow the steps given below to create a bitmapped button on a dialog box.
1. Create a dialog-based application.
2. Add a button control on the dialog template.
3. Set the style of the button control to 'Owner draw' in the 'Styles' tab of the
properties window.
4. Create 4 bitmaps for 4 different states of a button like up, down, focus and disabled.
5. Give each of the images created for the button an ID constructed by appending one
of the letters 'U', 'D', 'F', or 'X to the string used for the button caption. For example,
for the button with caption 'MyButton' IDs would be 'MyButtonU', 'MyButtonD',
'MyButtonF', and 'MyButtonX'. You must specify the ID of the bitmaps within double
quotes. Otherwise the resource editor will assign an integer to the resource and MFC
will fail when loading the image.
6. Now, add a data member say m_bmpbutton of type CBitmapButton to the dialog
class.
7. Add following code to the OnInitDialog( ) function of the dialog class.
BOOL CBitmapbtDlg::OnInitDialog( )
{
// AppWizard generated code
m_bmp.AutoLoad ( IDC_MYBUTTON, this ) ;
}

return FALSE ; // return TRUE unless you set the focus to a control
The AutoLoad( ) function internally loads the bitmap images and attaches them to
the button control.

32

What do you mean by registering a window class?


Ans: An application must specify a window class when it creates a window, and a class must
be registered before it can be used. The window class defines the characteristics of the
window such as the address of its Window procedure, background color, icon, cursor etc.
These attributes are placed in the structure called WNDCLASS. The function
AfxRegisterWndClass( ) called in PreCreateWindow( ) fills the WNDCLASS structure
and registers the application window.
If you use ::RegisterClass( ) or MFC's AfxRegisterClass( ) to register a WNDCLASS, then
you will have to initialize every field in the WNDCLASS structure. But
AfxRegisterWndClass( ) fills most of the fields for you, leaving you to specify for just four
values like class style, cursor, background color and icon, that MFC applications are
concerned with.

How to display standard Properties dialog box?


Ans: If we right click on a file in Windows Explorer and select Properties from the popup
menu it displays a dialog box showing all the properties of that file. We can display the
Properties dialog box programmatically. Following code snippet will show Properties dialog
box of abc.doc file which is in C drive.
SHELLEXECUTEINFO sh = { 0 } ;
sh.cbSize = sizeof ( sh ) ;
sh.fMask = SEE_MASK_INVOKEIDLIST ;
sh.lpVerb = "properties" ;
sh.lpFile = "C:\\abc.doc" ;
ShellExecuteEx ( &sh ) ;

Why do we get strange and misleading errors while running the program involving
typeid on VC++ 6.0 compiler?
Ans: The errors occur because we may not have enabled the RTTI option. To overcome
these errors we need to perform the following steps.
1. Select Settings from the Project menu and click the C/C++ tab
2. From the category listbox, select C++ language
3. Click the checkbox named Enable Run-time Type Information

How do I provide a utility of formatting drives in an application?


Ans: A function called SHFormatDrive( ) can be used to format a drive programmatically.
This function displays a dialog that allows the user to format a drive. Write following code in
the menu-handler or a button-handler that is defined to perform job of formatting.
void CmyDlg::OnFormat( )
{
typedef DWORD ( SHFORMATDRIVE ) ( HWND, UINT, UINT, UINT ) ;
SHFORMATDRIVE WINAPI *pfunc ;
HINSTANCE m_hinst = ::LoadLibrary ( "shell32.dll" ) ;
pfunc = ( SHFORMATDRIVE * ) ::GetProcAddress ( ( HMODULE ) m_hinst,
"SHFormatDrive" ) ;
( *pfunc ) ( m_hWnd, 0, 0, 0 ) ;

33

}
Here, we have declared pfunc as a pointer to the SHFormatDrive( ) function. This
function takes 4 parameters - a handle of the dialog's (dialog that gets displayed by
SHFormatDrive( ) function) parent window, the drive number (0 for A:, 1 for B:, etc.), the
size of the formatted disk, a type indicating format type as quick or full format. Next, we
have loaded 'shell32.dll' file by calling the ::LoadLibrary( ) function and stored its return
value in the m_hinst object. We have then obtained the address of the SHFormatDrive( )
function by calling the ::GetProcAddress( ) function. We have then called the
SHFormatDrive( ) function using pfunc. On execution, this function will format A drive.

Are MFC classes thread safe?


Ans: No! MFC classes are not thread safe on object level. That means if we use same object
in two threads, data may not be safe. For example, if we use a CFile object in two classes,
we must use some synchronization scheme to make sure that the data is safe or use two
separate objects.

How do I write code to remove a toolbar button programmatically?


Ans: This is shown in following code snippet.
void CMainFrame::OnDelete( )
{
m_wndToolBar.SendMessage ( TB_DELETEBUTTON, ( WPARAM ) 0 ) ;
}
Here, we have called SendMessage( ) function and passed it the message
TB_DELETEBUTTON, as we want a toolbar button to be deleted and a zero-based index of
the button to be deleted.

If CFile class is used to work on a file, then how to read a file till its end of file is
encountered (EOF)?
Ans: To check for end-of-file, we will have to check whether the number of bytes actually
read is less than the number of bytes requested. This is shown in the following code snippet.
CFile f ;
f.Open( ) ;
char buf[254] ;
UINT nread ;
do ( nread = f.read ( buf, 254 ) )
{
...
// process nread bytes
} while ( nread = 254 ) ;

How to create a user defined message?


Ans: In Windows programming the sequence of execution depends on the events or
messages received by the window. We use number of messages in our program like
WM_CREATE, WM_LBUTTONDOWN etc. We too can create a message and send it to the

34

window whenever a particular event occurs. For this, firstly #define a message as shown
below:
#define WM_MYMSG (WM_USER + 1)
Add a message map entry as shown below:
WM_MESSAGE ( WM_MYMSG, OnMyMsg )
OnMyMsg( ) is a user-defined function that will get called whenever the message
WM_MYMSG is sent to our window. Define this function as given below:
int CMessageDlg::OnMyMsg( )
{
MessageBox ( "Message Received" ) ;
}

return 0 ;

To send the WM_MYMSG message call SendMessage( ) function as shown below:


void CMessageDlg::OnButton1( )
{
SendMessage ( WM_MYMSG, NULL, NULL ) ;
}

Is there any way by which I can increase/decrease the limit of amount of text an
edit control can hold?
Ans: The CEdit and CEditView classes have limits on the amount of text they can contain.
But, these limits are operating-system dependent. To adjust the limit we can use
CEdit::SetLimitText( ) function. We can also use CEdit::LimitText( ) function to limit the
length of the text that the user may enter into an edit control.
Windows 95 has a limit of 64 KB on edit controls and it cannot be increased. Windows NT
has a machine-dependent limit on edit controls. If you need to use a control that is
expected to contain near or over 64 KB of data, use CRichEditCtrl or CRichEditView.
These classes wrap the rich edit Windows control.

How do I change color of the status bar?


Ans: To change the color of status bar, we must access the status bar control lying under
the status bar and call the SetBkColor( ) member function of the CStatusBarCtrl class.
m_wndStatusbar.GetStatusBarCtrl( ).SetBkColor ( RGB ( 255, 255, 0 ) ) ;

How do I set the wallpaper as the background of a dialog box?


Ans : Create a dialog based application. Add code to the OnPaint( ) handler of the dialog
class as given below.
void CDlgDlg::OnPaint( )
{

35

CPaintDC dc ( this ) ; // device context for painting


SendMessage ( WM_ICONERASEBKGND, ( WPARAM ) dc.GetSafeHdc( ), 0 ) ;
HDC hdc ;
if ( IsIconic( ) )
{
// Center icon in client rectangle
int cxIcon = GetSystemMetrics ( SM_CXICON ) ;
int cyIcon = GetSystemMetrics ( SM_CYICON ) ;
CRect rect ;
GetClientRect ( &rect ) ;
int x = ( rect.Width( ) - cxIcon + 1 ) / 2 ;
int y = ( rect.Height( ) - cyIcon + 1 ) / 2 ;
// Draw the icon
dc.DrawIcon ( x, y, m_hIcon ) ;
}
else
{

hdc = dc.GetSafeHdc( ) ;
::SetBkColor( hdc , RGB ( 255, 0, 100 ) ) ;
CDialog::OnPaint( ) ;

How to obtain the drives present on the hard disk?


Ans: Many times while creating an application in we wish to know the number, name and
type of the drives present on the hard disk. For example, we may create a Windows
Explorer like application in VC++ or an application that lets user select a path to copy files,
etc. We can obtain the information about the drives by calling API function
GetDriveType( ). By checking the return value of the GetDriveType( ) function we can
determine the type of the drive like root, remote, fixed, removable, etc. Following code
snippet displays all the drives on the hard disk in a message box.
char ch ;
CString dr ;
for ( ch = 'A' ; ch <= 'Z' ; ch++ )
{
dr = ch ;
dr += ":\\" ;
if ( GetDriveType( ) != DRIVE_NO_ROOT_DIR )
MessageBox ( dr ) ;
}

How do I write code to right justify the entries displayed in columns of list
control?
Ans: To right justify the text in columns of list control use CListCtrl::InsertColumn( )
function as shown below:
m_list.InsertColumn ( 0, "Name", LVCFMT_RIGHT, 100 ) ; // where m_list is a control var. of
list control

36

Working Of Queued Messages...


Windows NT maintains a single system-message queue and any number of thread-message
queues, one for each thread. Whenever the user moves the mouse, clicks the mouse
buttons, or types at the keyboard, the device driver for the mouse or keyboard converts the
input into messages and places them in the system-message queue. Windows removes the
messages, one at a time, from the system-message queue, examines them to determine
the destination window, and then posts them to the message queue of the thread that
created the destination window. A thread's message queue receives all mouse and keyboard
messages for the windows created by the thread. The thread removes messages from its
queue and directs Windows NT to send them to the appropriate window procedure for
processing. The system posts a message to a thread's message queue by filling an MSG
structure and then copying it to the message queue. Information in the MSG structure
includes the handle of the window for which the message is intended, the message
identifier, the two message parameters, the message time, and the mouse-cursor position.
A thread can post a message to its own message queue or to the queue of another thread
by using the PostMessage( ) or PostThreadMessage( ) function.

How do I change the color of the status bar?


Ans : Create an SDI application. Open the OnCreate( ) function of the CMainFrame class
and add following lines to this function.
int CMainFrame::OnCreate ( LPCREATESTRUCT lpCreateStruct )
{
// Appwizard generated code
CStatusBarCtrl &pStatusBarCtrl = m_wndStatusBar.GetStatusBarCtrl( ) ;
pStatusBarCtrl.SetBkColor ( RGB ( 141, 251, 251 ) ) ;
return 0 ;
}

In a Doc/View application, how the resources get loaded by specifying only one
ID, IDR_MAINFRAME?
Ans: The LoadFrame( ) function is called to create and load the frame window. The
LoadFrame( ) function calls the functions LoadMenu( ), LoadString( ), LoadIcon( ),
etc. and pass them the ID IDR_MAINFRAME. These functions search the resources having
ID IDR_MAINFRAME and a corresponding tag. For example, LoadMenu( ) function searches
for the resource IDR_MAINFRAME having tag MENU, the LoadIcon( ) function searches for
the resource IDR_MAINFRAME having tag ICON and so on. Under each tag the information
of that particular resource is stored. Using this information the resource is then loaded on
the frame window. You can open the '.rc' file and see the tags written in front of
IDR_MAINFRAME.

How to retrieve resources from a .dll or .exe file?


Ans: We can obtain the resources like menu, toolbar, bitmap, icon, etc. from any DLL or
executable file by first loading it and then calling a set of API and callback functions. The
EnumResourceTypes( ) function searches all the resources and pass the resource type to
the callback function passed to it as second parameter. Then we can call the
EnumResourceNames( ) function that searches the module for each resource of the
specified type. This function returns the ID of the resource found. We can use this ID in our
program.

37

How do I set the output directory for the project files?


Ans :
1.
2.
3.

After creating a project, perform following steps.


Select 'Project | Settings' menu option.
In the 'Settings For' pane select the item for which you want to set the directories.
Select 'General' tab. Type the name of the directory in the 'Output Files' text box.
The output files would get created in this directory.
To place all intermediate files in some other directory, type the name of the directory in the
'Intermediate Files' text box.

What is the difference between worker thread and user interface thread?
Ans: A worker thread is mainly created to perform background work. It doesn't have a user
interface.
A UI thread provides user interface and is created to interact with the user. You might use
UI threads in an application that creates several independent windows, each of which
occasionally needs to do extensive processing.
A worker thread is created by calling AfxBeginThread( ).
To create a UI thread you must derive a class from CWinThread and override its
InitInstance( ) function to create a window.
A worker thread does not have its own message loop.
A UI thread has its own message loop.
A worker thread executes for once and then terminates.
A UI thread terminates when it receives WM_QUIT message.

How to create scrolling tabs in a property sheet?


Ans: By default, if a property sheet has more tabs than will fit in a single row in the width
of the property sheet, the tabs will stack in multiple rows. To use scrolling tabs instead of
stacking tabs, we can call the EnableStackedTabs( ) function passing to it FALSE before
calling DoModal( ) or Create( ) functions.

How to make sure that the application automatically opens the document that is at
the top of the recent file list?
Ans: #include the 'afxadv.h' file in the application class's source file. This file is required
for CRecentFileList class's definition. Add the following code in InitInstance( ) to open
the first file in MRU list.
BOOL CMRUApp::InitInstance( )
{
// AppWizard generated code
if ( cmdInfo.m_nShellCommand == CCommandLineInfo::FileNew ||
cmdInfo.m_nShellCommand == CCommandLineInfo::FileNothing )
{
if ( m_pRecentFileList != NULL )
{

38

CString strmru = ( *m_pRecentFileList )[0] ;


if ( !strmru.IsEmpty( ) )
OpenDocumentFile ( strmru ) ;

}
}
else
if ( !ProcessShellCommand ( cmdInfo ) )
return FALSE ;
}

How do I write code to display bitmap in column header of a list control?


Ans: The column names in a list control are displayed on a header control. We can obtain
the pointer to the header control and set an image list on it. Following code shows how to
do this.
CImageList m_img ;
m_img.Create ( IDB_BITMAP1, 16, 0, ILC_COLOR16 ) ;
CHeaderCtrl *h = m_l.GetHeaderCtrl( ) ; // where m_l is a control variable of list control
h -> SetImageList ( &m_img ) ;
m_l.InsertColumn ( 0, "A", LVCFMT_LEFT, 100 ) ;
m_l.InsertColumn ( 1, "B", LVCFMT_LEFT, 100 ) ;
HDITEM hitem ;
h -> GetItem ( 0, &hitem ) ;
hitem.mask = HDI_IMAGE | HDI_FORMAT ;
hitem.iImage = 0 ;
hitem.fmt = HDF_LEFT | HDF_IMAGE | HDF_STRING ;
h -> SetItem(0, &hitem);
m_img.Detach( ) ;
This code snippet displays a bitmap on the left side of zeroth column name.

What are Custom AppWizards?


Ans : The MFC Appwizard allows us to create new programs, that are based on the most
common types of programs like SDI / MDI application, Dialog-based application etc. It
generates the starter files that are needed for these common applications. But, sometimes
we need to create applications that contain features which MFC Appwizard can not provide.
We often need to create such applications. Here comes the use of a custom Appwizard.
Custom AppWizards are useful for creating generic programs that can generate programs
for specific features and functionality. Like the standard MFC AppWizard, a custom
AppWizard presents the user with choices, tracks the users decisions, and uses those
decisions to generate the code, resources, and project files that the build tools require to
build a working starter application

What is a Hook?
Ans: A C programmer is often very excited when he creates his first TSR. A TSR is a
'Terminate but Stay Resident program' which continues to remain in memory even if the
program is terminated. One can use a TSR for number of purposes like displaying a clock on
output screen, keeping track of user's actions, etc. However, TSRs cannot run in Windows.
In Windows a TSR like activity is performed by Hook. A hook is a mechanism by which a

39

function can intercept events (messages, mouse actions, keystrokes) before they reach an
application. Following code snippet shows how to create a hook that intercepts the keyboard
events. Whenever a keyboard event occurs we set the status of the Caps Lock to off. As a
result, once this program is executed, there onwards any attempt to put on the Caps Lock
on would fail. This is because an attempt to put it on would result into transfer of control to
our filter function. And this function would put the Caps Lock off.
Declare a variable of type HHOOK as shown below:
HHOOK hookdata ;
Declare a global function which is called as a 'filter function'.
LRESULT CALLBACK KeyboardProc ( int code, WPARAM w, LPARAM l ) ;
In OnCreate( ) handler call the following statement.
int CMainFrame::OnCreate( )
{
// AppWizard added code
hookdata = SetWindowsHookEx ( WH_KEYBOARD, KeyboardProc, NULL, 0 ) ;
}

return 0 ;

SetWindowsHookEx( ) maintains the specified filter functions. Define the global filter
function as shown below:
LRESULT CALLBACK KeyboardProc ( int code, WPARAM w, LPARAM l )
{
if ( code < 0 )
return CallNextHookEx ( hookdata, code, w, l ) ;
unsigned char state [256] ;
if ( w == VK_CAPITAL )
{
GetKeyboardState ( state ) ;
if ( state [VK_CAPITAL] == 1 )
state [VK_CAPITAL] = 0 ;
SetKeyboardState ( state ) ;

}
return CallNextHookEx ( hookdata, code, w,1 ) ;

In case of COM, what is meant by aggregation and how do I get an interface of the
aggregated object?
Ans: Aggregation is the reuse mechanism, in which the outer object exposes interfaces
from the inner object as if they were implemented on the outer object itself. This is useful
when the outer object would always delegate every call to one of its interfaces to the same
interface in the inner object.
Aggregation is actually a specialized case of containment/delegation, and is available as a
convenience to avoid extra implementation overhead in the outer object. We can get a

40

pointer to the interface, by calling QueryInterface( ) of the outer object with IID of the
inner interface.

Can we get the name of the current DLL where an exported function lives?
Ans: The function GetModuleFileName( ) gives the name of a module (which is a DLL or
an EXE). This function takes two arguments, a handle to the instance of the module
HINSTANCE, and a buffer to store the name of the module. If we call the
GetModuleFileName( ) function with a NULL as an instance handle, it would return the
name of the module running, which is an EXE, not the DLL. To get the name of DLL an
instance handle is required.
To get an instance handle we can use AfxGetAPP( ) function. This function returns a
pointer to the current global application object. Then pass m_hInstance a member of
CWinApp class, to the GetModuleFileName( ) function. Follow the steps given below.
1. Create an application to form '.dll' file.
2. Override the InitInstance( ) function in the application class of the module, that
creates '.dll'. Enter following code to the InitInstance( ) function.
BOOL CFontdllApp::InitInstance()
{
// Appwizard generated code
char str[ 100 ] ;
::GetModuleFileName ( AfxGetApp( ) ->m_hInstance , str, sizeof ( str ) ) ;
AfxMessageBox ( str ) ;
return CWinApp::InitInstance( ) ;
}
If you run the application in which the above given '.dll' file is getting used, then a message
box would get displayed with the full name of the '.dll' file being used.

Many a times we create a control and need to reuse it in number of other applications.
Instead of creating the class having the same functionality or copying the already created
classes we can add the created control to the in-built gallery of controls. We can then add
this control to the project as and when necessary. Following steps show how to achieve this.

Create a dialog-based application 'mycontrol' and insert a class 'charedit' in it derived


from CEdit.
Override OnChar( ) handler and add following code in it to accept only the
characters.
void charedit::OnChar ( UINT nChar, UINT nRepCnt, UINT nFlags )
{
if ( nChar >= 48 && nChar <= 57 )
;
else
CEdit::OnChar ( nChar, nRepCnt, nFlags ) ;
}
Right click on charedit in the class view tab and select 'Add to Gallery' menu item.
'Add to Gallery' creates and places a user-defined component (.OGX file) in the new
folder. The .OGX file allows other applications to share the class you added to the
Gallery.
The 'charedit.ogx' would get created in the Gallery located in:
C:\Program Files\Microsoft Visual Studio\Common\MSDEV98\Gallery\mycontrol.
Now to use the charedit control create another dialog-based application.

41

Add the control by selecting 'Project | Add to Project | Component and Control |
mycontrol'. Select 'charedit.ogx' from there.
The 'charedit.h' and 'charedit.cpp' would get added to your project. Create the edit
control by calling charedit::Create( ) function.

How do I write code to get the index of the first selected item of a list control?
Ans: Use CListCtrl::GetNextItem( ) function as shown below:
void CMyDlg :: OnSelect( )
{
int iItem = m_list.GetNextItem ( -1, LVNI_SELECTED ) ;
if ( iItem == -1 )
MessageBox ( "No item selected..." ) ;
else
{
CString s ;
s.Format ( "Index of the first selected item is %d", iItem ) ;
MessageBox ( s ) ;
}
}

How do I ensure that on running an application a new document doesn't get


created at startup?
Ans: To prevent creation of a new document at startup add the statement given below to
InitInstance( ) function just before a call to ProcessShellCommand( ) function.
BOOL MyApp::InitInstance()
{
// AppWizard generated code
// prevent creartion of new document at startup
cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing ;
// Dispatch commands specified on the command line
if ( ! ProcessShellCommand ( cmdInfo ) )
return FALSE ;
// AppWizard generated code
return TRUE ;
}
Here, cmdInfo is an object of CCommandLineInfo class and m_nShellCommand is its
data member. It indicates the shell command to be processed. We have specified the shell
command to be processed as CCommandLineInfo::FileNothing. This turns off the display
of a new document on startup.

How to get the path of an executable file of a given file?


Ans: Sometimes we need to find out on double clicking a file in which application would it
get opened. For example, there might be more than one browser like IE, Netscape, etc.
installed on a machine. We may want to find out the default browser in which our .htm file
will get opened. We can find this out using a function FindExecutable( ) as shown below:
char buff [MAX_PATH] ;
FindExecutable ( "C:\\credits.htm", NULL, buff ) ;

42

The path of executable file in which 'credits.htm' would get opened is returned in the last
parameter.

How do I write code to get the item of the list control that has focus?
Ans: To get the item that has focus use CListCtrl::GetNextItem( ) function as shown in
following code snippet.
void MyDlg :: OnSelect( )
{
int iItem = m_list.GetNextItem ( -1, LVNI_FOCUSED ) ; // where m_list is control
var. of list control
}

How do I write code to add a resizable status bar on a resizable dialog box?
Ans: Follow the steps given below:
1. Create a dialog-based application
2. Add a pointer to CStatusBar class as a data member to the dialog class
3. Open OnInitDialog( ) function and add code shown below to it.
BOOL CDlgstatDlg::OnInitDialog( )
{
// AppWizard generated code
// Create the status bar.
HWND h = CreateWindowEx ( 0, STATUSCLASSNAME,
(LPCTSTR) NULL, SBARS_SIZEGRIP | WS_CHILD,
0, 0, 0, 0, m_hWnd, 0, AfxGetApp( ) -> m_hInstance,
NULL ) ;
// Get the coordinates of the parent window's client area.
CRect r ;
GetClientRect ( &r ) ;
// allocate memory for the panes of status bar
int nopanes = 5 ;
int *indicators = new int[nopanes] ;
// set width for the panes
int width = r.right / nopanes ;
for ( int i = 0; i < nopanes ; i++ )
{
indicators[i] = width ; width += width ;
}
// Collect address in pointer to CStatusBar and call functions to set style
m_st = ( CStatusBar * ) CStatusBar::FromHandle ( h ) ;
m_st -> SendMessage ( SB_SETPARTS, (WPARAM) nopanes, (LPARAM) indicators) ;
m_st -> SendMessage ( SB_SETTEXT, (WPARAM) 0 | SBT_POPOUT, (LPARAM)
"Ready" ) ;
m_st -> ShowWindow ( 1 ) ;
return TRUE ;

43

}
4. To set pane text add a virtual function PreTranslateMessage( ) and enter code shown
below to it.
BOOL CDlgstatDlg::PreTranslateMessage(MSG* pMsg)
{
if ( pMsg->message == WM_KEYDOWN )
{
switch ( pMsg -> wParam )
{
case VK_CAPITAL :
m_st -> SendMessage ( SB_SETTEXT, (WPARAM) 1 | SBT_RTLREADING, (LPARAM)
"CAP" ) ;
break ;
}
}
return CDialog::PreTranslateMessage ( pMsg ) ;
}
5. To size the status bar when the dialog box resizes add handler for WM_SIZE message and
code shown below to it.
void CDlgstatDlg::OnSize ( UINT nType, int cx, int cy )
{
CDialog::OnSize ( nType, cx, cy ) ;
CRect r ;
m_st -> GetWindowRect ( &r ) ;
r.right += cx ;
r.bottom += cy ;
m_st -> SetWindowPos ( &wndTop, r.left, r.top, r.Width( ),
r.Height( ), SWP_SHOWWINDOW ) ;
}

What do you mean by serialization?


Ans: Reading or storing of data in binary form is known as serialization. CArchive class
enables the job of serialization. When you write a serializable class, MFC uses the schema
number that you assign to achieve a rough form of version control. MFC tags instances of
the class with the schema number when it writes them to the archive, and when it reads
them back, it compares the schema number recorded in the archive to the schema number
of the objects of that type in use within the application. If the two numbers do not match ,
MFC throws an exception.

How to display a round splash screen?


Ans: Before starting any professional software it displays a splash screen displaying the
product info, etc. We can also display the splash screen for our application by using a ready
made component. We can insert this component by selecting 'Project | Add To Project |
Components and Controls | Visual C++ Components | Splash Screen'. After inserting the
component a bitmap having ID IDB_BITMAP and a class CSplashWnd gets added to the
project. This bitmap is displayed as the splash screen. By default the splash screen is
displayed as rectangular window. For a change, we can display this screen as a round
window. For this, add a variable m_rgn of type CRgn to the CSplashWnd class. In
CSplashWnd::OnCreate( ) add the following code:

44

m_rgn.CreateEllipticRgn ( 0, 0, 372, 270 ) ;


SetWindowRgn ( m_rgn.operator HRGN( ), FALSE ) ;
The parameters passed to the CreateEllipticRgn( ) are the coordinates of the bitmap.

How do I convert an existing dialog box to a property page?


Ans: Select the dialog box that you desire to change to the property page. Then from within
Visual C++s dialog editor, do the following...
Choose the style as 'Child' and border as 'Thin' from the 'styles' tab.
Similarly check the 'Title bar' property from the same 'styles' tab.
Check the 'Disabled' property from the 'More Styles' tab
You can also change the caption of the dialog if desired.
Now Change the base class of your dialog class from CDialog to CPropertyPage and
modify the constructor for your dialog class to call CPropertyPages constructor as show
below.
the old constructor for dialog class would be
mydialog::mydialog ( CWnd* pParent /*=NULL*/ ) : CDialog ( mydialog::IDD, pParent )
{
//AppWizard generated code
}
The modified constructor would be
mydialog::mydialog( ) : CPropertyPage ( mydialog::IDD )
{
//AppWizard generated code
}
Also make the changes in the declaration of the constructor in header file of your dialog
class.

SetModifiedFlag( )...
SetModifiedFlag( ) should get called whenever the document's data is modified. This
function sets a flag inside the document object, that tells MFC that the document contains
unsaved data. This helps MFC to prompt the user before closing a document that contains
unsaved changes.

How do I fix the minimal as well maximum size of a resizable window?


Ans: To fix the minimal and maximum size of a resizable window, add a handler for
WM_GETMINMAXINFO message and write following code to it.
void CMainFrame :: OnGetMinMaxInfo ( MINMAXINFO FAR* lpMMI )
{
lpMMI -> ptMinTrackSize.x = 300 ; // width
lpMMI -> ptMinTrackSize.y = 200 ; // height
lpMMI -> ptMaxTrackSize.x = 400 ; // width
lpMMI -> ptMaxTrackSize.y = 400 ; // height
CFrameWnd :: OnGetMinMaxInfo ( lpMMI ) ;
}
The OnGetMinMaxInfo( ) function gets called whenever Windows needs to know the the
minimum or maximum tracking size, or maximized position or dimensions of window. The
maximum and minimum tracking size of the window is the largest and the smallest window
size a window can have when we resize the window using the borders, respectively.

45

How do I display .gif or .jpg images in an SDI application?


Ans: Create an SDI application with a Doc/View support. Add a data member *p as a
pointer to the IPicture interface, to the view class. Add following line to the '.cpp' file of the
view class.
#include <afxpriv2.h>
Then add a member function as loadimage( ) to the view class and enter code to it as
shown below.
void CImageView :: loadimage ( CArchive &ar )
{
CArchiveStream as ( &ar ) ;
IStream *s = &as ;
OleLoadPicture ( s, 0, FALSE,IID_IPicture, ( void** ) &p ) ;
}
Add following code to the OnDraw( ) function of the view class.
void CImageView::OnDraw ( CDC *pDC )
{
CImageDoc *pDoc = GetDocument( ) ;
if ( p != NULL )
{
CRect rc ;
long w, h ;
p -> get_Width ( &w ) ;
p -> get_Height ( &h ) ;
CSize sz ( w, h ) ;
pDC -> HIMETRICtoDP ( &sz ) ;
rc.right = sz.cx;
rc.bottom = sz.cy;
p -> Render ( *pDC, 0, 0, rc.right, rc.bottom,0, h, w, -h, NULL ) ;
}
}
Then add following code to the Serialize( ) function of the document class.
void CImageDoc::Serialize ( CArchive& ar )
{
if ( ar.IsLoading( ) )
{
POSITION pos = GetFirstViewPosition( ) ;
CImageView *pView = ( CImageView* ) GetNextView ( pos ) ;
pView -> load ( ar ) ;
pView -> Invalidate( ) ;
pView -> UpdateWindow( ) ;
}
}

How do I invoke the file 'Properties' dialog box?


Ans: We can invoke the file 'Properties' dialog box for a file by calling Shell API function
ShellExecuteEx( ). The ShellExecuteEx( ) function performs an action on a file. It takes
one argument which is nothing but the address of a variable of type SHELLEXECUTEINFO
structure. In the SHELLEXECUTEINFO structure, set the SEE_MASK_INVOKEIDLIST flag and
the "properties" verb as given in following code snippet.

46

void CFileprDlg::OnShow( )
{
SHELLEXECUTEINFO sh ;
ZeroMemory ( &sh, sizeof ( sh ) ) ;
sh.cbSize = sizeof ( sh ) ;
sh.lpFile = "C:\\myfile.txt" ; // path of file for which 'Properties' dialog is to be
displayed
sh.lpVerb = "properties" ;
sh.fMask = SEE_MASK_INVOKEIDLIST ;
ShellExecuteEx ( &sh ) ;
}

How do I write code to keep the bottom line in a multiple-line edit control visible?
Ans: To keep the bottom line in a multiple-line edit control visible, we need to know the
total number of text lines added to the control. Once we get this number we can call
LineScroll( ) function of CEdit class to scroll text of a multiple-line edit control.
BOOL CMuleditDlg :: OnInitDialog( )
{
// AppWizard generated code
int c = 0 ;
CString str1, str2 ;
CStdioFile f ( "Readme.txt", CFile::modeRead ) ;
while ( f.ReadString ( str1 ) != FALSE )
{
str2 += str1 + "\r\n" ;
c++ ;
}
m_edit.SetWindowText ( str2 ) ; // where m_edit is a control variable for edit control
m_edit.LineScroll ( c ) ;
return TRUE ;
}
Here, through a while loop we have read the contents of 'Readme.txt' file and copied it to
the CString object str2. We have also counted the number of text lines read. Then after
adding the text into the edit control we have called LineScroll( ) function to scroll text
lines. Note that for the edit control added to the dialog template we must enable 'Auto
HScroll' and 'Auto VScroll' properties

MFC provides number of macros to us such as RGB, DECLARE_MESSAGE_MAP,


BEGIN_MESSAGE_MAP etc. If we want to see what goes inside these macros we can see the
expanded code of our program. For this, Select Project menu | Settings | Link tabs. In the
'Project Options' edit box delete all the options and type /EP in it. Now compile the file. You
will see the expanded code in the output window.

String Conversion Macros...


In string conversion macros, letters like A, W, T, etc. are used, where A stands for LPSTR,
W stands for LPWSTR and T stands for LPTSTR. Following are string conversion macros.

47

1. A2W ( LPSTR l ) : Converts an LPSTR to an LPWSTR.


2. A2BSTR ( LPSTR l ) : Converts an LPSTR to BSTR.
3. A2COLE ( LPSTR l ) : Converts an LPSTR to a const LPOLESTR.
4. A2CT ( LPSTR l ) : Converts an LPSTR to a const LPTSTR.
5. A2CW ( LPSTR l ) : Converts an LPSTR to a const LPWSTR.
6. A2OLE ( LPSTR l ) : Converts an LPSTR to an LPOLESTR.
7. A2T ( LPSTR l ) : Converts an LPSTR to an LPTSTR.

How do I write code to add multiple values for a key?


Ans: Following code snippet shows how we can achieve this.
void fun( )
{
CStringList s, *get ;
s.AddTail ( "Cord" ) ;
s.AddTail ( "Filament" ) ;
s.AddTail ( "Rope" ) ;
s.AddTail ( "Thread" ) ;
CMapStringToOb p ;
p["String"]= ( CObject * ) &s ;
POSITION pos ;
p.Lookup ( "String", ( CObject *& ) get ) ;
pos = get -> GetHeadPosition( ) ;
cout << "\nA String means: " ;
while ( pos != NULL )
{
CString str = get -> GetNext ( pos ) ;
cout << (LPCTSTR) str << " " ;
}
cout << endl ;

}
Here, first we have added some strings (which are meanings of word 'String') to an object s
of CStringList class. Then we have created an object p of class CMapStringToOb.
CMapStringToOb is an MFC collection class which maps unique CString objects to
CObject pointers. Thus through the statement p["String"] = ( CObject * ) &s ; we have
mapped the address of s as a value to the key value 'string'. The Lookup( ) function called
next returns a reference to a CObject pointer (mapped with key 'String') which we have
collected in get. Lastly, to display the strings we have retrieved the position of first string by
calling GetHeadPosition( ) and then through a loop we have displayed the strings.

We can display a bitmap or a picture in our window using CDC's member functions. However
once a bitmap is displayed we cannot change its size like we do in MS-Word or MSPowerPoint. If you want that when user clicks the picture resize handles should appear and
on dragging the handle picture's size should change then use the functionality of

48

CRectTracker class. CRectTracker class provides functions to display resize handles


around the picture and to change the size of the picture if handle is dragged.

How do I write code, to display a toolbar at the left edge of the window, moreover,
the buttons on the toolbar should get arranged in multiple rows and should work
like check box?
Ans: This is shown in following code fragement.
int CMainFrame :: OnCreate ( LPCREATESTRUCT lpCreateStruct )
{
// AppWizard generated code
// Create tool bar with styles
m_tool.CreateEx ( this, TBSTYLE_BUTTON | TBSTYLE_WRAPABLE, WS_CHILD |
WS_VISIBLE | CBRS_SIZE_FIXED |
CBRS_ALIGN_LEFT, CRect ( 0, 0, 5, 5 ), 1 ) ;
m_tool.SetWindowText ( "Tool" ) ;
// Create imgaelist & set it
// IDB_BITMAP1 is ID of bitmap holding images of toolbar buttons, & created in
resource
CImageList img ;
img.Create ( IDB_BITMAP1, 22, 0, RGB ( 255, 0, 255 ) ) ;
m_tool.GetToolBarCtrl( ).SetImageList ( &img ) ;
img.Detach( ) ;
// Add button information
m_tool.SetButtons ( NULL, 6 ) ;
// ID_B1 to ID_B6 are #define macros added for buttons
m_tool.SetButtonInfo ( 0, ID_B1, TBSTYLE_GROUP | TBSTYLE_CHECKGROUP, 0 ) ;
m_tool.SetButtonInfo ( 1, ID_B2, TBSTYLE_CHECKGROUP, 1 ) ;
m_tool.SetButtonInfo ( 2, ID_B3, TBSTYLE_CHECKGROUP, 2 ) ;
m_tool.SetButtonInfo ( 3, ID_B4, TBSTYLE_CHECKGROUP, 3 ) ;
m_tool.SetButtonInfo ( 4, ID_B5, TBSTYLE_CHECKGROUP, 4 ) ;
m_tool.SetButtonInfo ( 5, ID_B6, TBSTYLE_CHECKGROUP, 5 ) ;
// Set Toolbar size
CRect toolrect,r ;
m_tool.GetItemRect ( 0, &toolrect ) ;
m_tool.SetSizes ( toolrect.Size( ), CSize ( 22, 20 ) ) ;
// Set number of rows
m_tool.GetToolBarCtrl( ).SetRows ( 3, TRUE, &r ) ;
// Code to dock toolbar
m_tool.EnableDocking ( CBRS_ALIGN_ANY ) ;
EnableDocking ( CBRS_ALIGN_ANY ) ;
DockControlBar ( &m_tool ) ;
return 0 ;
}
Here, we have created a toolbar with style as TBSTYLE_BUTTON and TBSTYLE_WRAPABLE.
These two styles indicate that the toolbar contains buttons and can have multiple rows of
buttons respectively. The SetRows( ) function is used to set the number of rows for
buttons.

49

The OnCmdMsg( ) Function...


This is a virtual function of CCmdTarget class and gets called by the framework. AppWizard
adds this function to framewindow class. If we create any new class derived from
CFrameWnd then we need to override this function in it. It routes the messages to the
child window. The commands that this function receives, dispatches them to the child.
However, if the messages are not handled then it itself handles them by calling base class
function i.e. of CCmdTarget.
The function receives ID of the command, the notification code of the command and
additional information. The code that AppWizard adds to this function is given below:
BOOL CMainFrame :: OnCmdMsg ( UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo )
{
// let the view have first crack at the command
if ( m_wndView.OnCmdMsg ( nID, nCode, pExtra, pHandlerInfo ) )
return TRUE ;
// otherwise, do default handling
return CFrameWnd :: OnCmdMsg ( nID, nCode, pExtra, pHandlerInfo ) ;
}
How to display the system information?
The most easy way to display system information is to add a ready made component
'System Info For About Dlg' provided with VC++. This component displays system
information in the 'About' dialog box. This component can be added to our project from
Project | Add To Project | Components and Controls. Inserting the component in our project
adds few lines of code in CAboutDlg::OnInitDialog( ) function. Changes must be made in
the 'About' dialog according to that code.

A Few Tips About CComBSTR...


If strings in two CComBSTR are to be compared, then never use != expression, as it simply
compares the underlying BSTR pointers and does not perform string comparison. Instead
use ! ( == ) as shown below:
CComBSTR bs1, bs2 ;
if ( ! ( bs1 == bs2 ) )
{
// code
}
Similarly, ? operator doesn't work with CComBSTR. For example, consider following code
snippet
CComBSTR cb ;
BSTR bs1, bs2 ;
bs1 = L"Ai" ;
bs2 = cb.Length( ) ? cb : bs1 ;
cout << ( LPCSTR ) bs2 ;
This code would end up calling CComBSTR ( bs2 ), causing bs2 to be assigned to a
temporary object that is deleted whenever the compiler feels like it. Instead, use
cb.Length( ) ? cb : bs1.
SendMessage...

50

The SendMessage( ) is an API function, which sends a message immediately to your


window or another window by calling the window's message procedure and returns when
the message has been processed. It is used to perform some action that must be done
immediately because the subsequent lines of code depend on the result. SendMessage( )
is typically used to communicate between parent/child windows. SendMessage( ) would
get blocked if the the target thread is different from the one through which it has been
called, hence be careful while sending messages to other windows in other threads.

How to change the tab order of controls placed in a dialog box?


Sometimes, specially when we are using spin button controls or radio buttons, the order in
which we are creating controls is very important. Spin button controls considers the control
created just before it as its buddy whereas radio buttons to be grouped must have ids in
sequence. Any small mistake in creating controls may result in unpredictable results.
However, we can correct this mistake by changing tab order of controls in Resource Editor.
For this, open dialog in Resource Editor, select 'Tab order' menu item from 'Layout' menu. It
will display number in blue box for every control which is the tab order of controls. Now, if
you click a control that will become first in the tab order, clicking another control will make it
second and so on.

How do I write code to retrieve the text from column items of a list control?
Ans: Add a handler for NM_CLICK notification, that occurs when an item in the list control is
clicked with the left mouse button. Write code to this handler as shown below:
void MyDlg :: OnClickList1 ( NMHDR* pNMHDR, LRESULT* pResult )
{
NMLISTVIEW* nmitem = ( NMLISTVIEW* ) pNMHDR ;
LVHITTESTINFO lvhti ;
lvhti.pt = nmitem -> ptAction ;
lvhti.flags = LVHT_ONITEMLABEL ;
m_list.SubItemHitTest ( &lvhti ) ; // where m_list is a control var. for list control
CString m_text = m_list.GetItemText ( lvhti.iItem, lvhti.iSubItem ) ;
MessageBox ( m_text ) ;
}
The NMLISTVIEW structure used here contains information about the notification message
as well as about the item/subitem of the list control. The LVHITTESTINFO structure contains
information about a hit test. The member ptAction of NMLISTVIEW indicates the location at
which the event occurred. It contains the coordinates of the point at which the click
occurred. This point we have stored in pt, a data member of LVHITTESTINFO. Next, we
have set the flag of LVHITTESTINFO structure to LVHT_ONITEMLABEL which indicates that
the position is over a list-view item's text. Lastly, we have called SubItemHitTest( )
function which determines which list view item, if any, is at a given position. The parameter
that is to be passed to this function is a pointer to the LVHITTESTINFO structure. Then we
have retrieved the text by using the GetItemText( ) function.

How do I implement a 'Close All Documents' menu command?


The 'Close All Documents' is a menu command that closes all the open documents and their
views. This feature can be implemented by using two functions
CWinApp::CloseAllDocuments( ) and SaveAllModified( ). The CloseAllDocuments( )
function destroys the currently active document objects without saving them. So we must
first call SaveAllModified( ) function to save the documents. Following code shows how to
implement this feature.

51

if ( AfxGetApp( ) -> SaveAllModified( ) )


AfxGetApp( ) -> CloseAllDocuments ( FALSE ) ;
How to display Control Panel applets?
We can execute a Control Panel applet by double clicking it. If we want to execute it through
a program then the simplest way to do so is to use the ShellExecute( ) API function. The
following call to ShellExecute( ) function will execute the Mouse applet.
ShellExecute ( NULL, "open", "control.exe", "Mouse", NULL, SW_NORMAL ) ;
Here, we have executed 'control.exe' (which starts Control Panel application) and passed to
it 'Mouse' as the parameter.

How do I write code to obtain a list of fonts available on the system?


Ans: Suppose while programming a situation comes where one needs all the fonts available
in the system to be listed in a list control. In this situation we can't display the standard
'Font' dialog box. To get all the fonts we can call an API function EnumFontFamilies( ) as
shown in following statement.
EnumFontFamilies ( dc.m_hDC, NULL, ( FONTENUMPROC ) callbackfunc, ( LPARAM ) this ) ;
This function enumerates the system fonts and with every font it enumerates, it calls the
callback function specified as the third parameter. The callback function must be defined as
given below:
int CALLBACK callbackfunc ( ENUMLOGFONT FAR *p, NEWTEXTMETRIC FAR *tm, int type,
LPARAM par )
{
// take the font name using p -> elfLogFont.lfFaceName
return 1 ;
}

How to fix the error "unexpected end of file while looking for precompiled header
directive" that occurs when compiling?
Ans: By default, the Visual C++ project wizard sets up a project to use 'Stdafx.h' as the
precompiled header file for every file in a project. All header files that are #included in
'StdAfx.h' are precompiled into a file named as 'projectname.pch' and 'stdafx.obj' so that
once compiled, they do not have to be compiled again. Appwizard #includes 'StdAfx.h' in
the CPP files that it generates and inside 'StdAfx.h', it adds #includes for MFC header files
such as 'AfxWin.h'. If a file however does not contain "#include <stdafx.h>", this message
is generated. To fix the problem, make sure that every '.cpp' of the project has #included
'StdAfx.h' header file.

How would you set an indicator in the caption bar indicating that the document is
dirty and needs to be saved?
Ans: While working in a VC++ source editor if you observe carefully, you would see that if
you make any changes in a file an indicator in the form of an asterisk ( '*' ) is shown in the
title bar indicating that the file is modified. If you save the file the indicator disappears. We
can also display such an indicator and remove it if user saves the document, by simply
overriding a virtual function SetModifiedFlag( ) in the document class as shown below:
void CTitleDoc::SetModifiedFlag ( BOOL bmodified )
{
CString title = GetTitle( ) ;
CString indicator = " *" ;
if ( !IsModified( ) && bmodified )
SetTitle ( title + indicator ) ;

52

else
{
if ( IsModified( ) && !bmodified )
{
title = title.Left ( title.GetLength( ) - indicator.GetLength( ) ) ;
SetTitle ( title ) ;
}
}
CDocument::SetModifiedFlag ( bmodified ) ;

}
Note that you must manually override the SetModifiedFlag( ) function without the help of
ClassWizard because although SetModifiedFlag( ) is a virtual function it is not mentioned
in the online help and if you right click the document class in ClassView tab and select 'Add
Virtual function' you would not see this function in the list of virtual functions.

How do I write code that displays button in various shapes which we select?
Ans: Derive a class say MyButton from CButton class and override DrawItem( ). This is
shown in the following code snippet:
void MyButton :: DrawItem ( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
CRect r = lpDrawItemStruct -> rcItem ;
CDC* dc = CDC::FromHandle ( lpDrawItemStruct -> hDC ) ;
UINT state = lpDrawItemStruct -> itemState ;
UINT nStyle = GetStyle( ) ;
int nSavedDC = dc -> SaveDC( ) ;
//make the rect a square
r.bottom = r.right = min ( r.bottom, r.right ) ;
//Draw button
switch ( sh )
{
case 1:
dc -> Ellipse ( r.left, r.top, r.right, r.bottom ) ;
break ;
case 2 :
dc -> MoveTo ( r.left, r.top ) ;
dc -> LineTo ( r.right, r.top ) ;
dc -> MoveTo ( r.right, r.top ) ;
dc -> LineTo ( r.right, r.bottom ) ;
dc -> MoveTo ( r.right, r.bottom ) ;
dc -> LineTo ( r.left, r.top ) ;
break ;
case 3 :
dc -> Rectangle ( r.left, r.top, r.right, r.bottom ) ;
break ;
}
}
Here sh is a member variable of MyButton class of type int. Then add a button control
onto the dialog template and set its 'Style' to 'Owner draw' & 'Flat'. Also add 3 radio buttons

53

labelled as 'Circle', 'Triangle' and 'Square' respectively. Now add code to OnInitDialog( ) of
the dialog class (of application) as shown below:
BOOL CButtonDlg :: OnInitDialog( )
{
m_bt.SubclassDlgItem ( IDC_BUTTON1, this ) ;
CDialog :: OnInitDialog( ) ;
// AppWizard generated code
}
Also add handlers for BN_CLICKED event for radio buttons and add code to them as shown
below:
void CButtonDlg :: OnRadio1( )
{
m_bt.sh = 1 ; // setting flag for shape
m_bt.Invalidate( ) ;
}
Similar code should go to the handlers for other two radio buttons.

How do I change title of 'Open' button in the standard File Open dialog box?
Ans: Follow the steps given below:
a) Derive a class from the CFileDialog class.
b) Add OnInitDialog( ) handler in the derived class and write the following code in it.
CWnd *p = GetParent( ) ;
CButton *b = ( CButton* ) p -> GetDlgItem ( IDOK ) ;
b -> SetWindowText ( "Delete" ) ;
The 'Open' button on the dialog box has an ID IDOK. We have passed this ID to the
GetDlgItem( ) to obtain the pointer to the 'Open' button. Using this pointer we have
changed the title.
Now, create an object of the derived class by passing appropriate parameters and call
DoModal( ). You will see the title of 'Open' button changed to 'Delete'.

How do I add a toolbar to the child window of an MDI application?


Ans: Follow the steps given below to add a toolbar in the child window of an MDI
application.
Create an MDI application with a Doc/View support.
Add a data member m_wndtoolbar of the class CToolBar to the CChildFrame
class.
Create a new toolbar IDR_MAINFRAME1 in the resource editor.
Add OnCreate( ) handler to the CChildFrame class and enter following code to this
handler.
int CChildFrame::OnCreate ( LPCREATESTRUCT lpCreateStruct )
{
//AppWizard generated code
m_wndtoolbar.Create ( this ) ;
m_wndtoolbar.LoadToolBar ( IDR_MAINFRAME1 ) ;
m_wndtoolbar.SetBarStyle ( m_wndtoolbar.GetBarStyle( ) | CBRS_TOOLTIPS |
CBRS_FLYBY | CBRS_SIZE_DYNAMIC ) ;
return 0 ;
}

Add command handlers for the buttons of the newly created toolbar.

54

How do you prevent an MDI application to open a new document at startup?


Ans: If you run an MDI application you would see a new empty document opened when you
run the application. We can prevent the application to open such empty document by
making a simple change in InitInstance( ) function as shown below:
BOOL CNoemptydocApp::InitInstance( )
{
// AppWizard generated code
CCommandLineInfo cmdInfo ;
cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing ;
ParseCommandLine ( cmdInfo ) ;
// AppWizard generated code
}

How do I write code that allows to create a dynamic splitter at run time, i.e. when
we select an option like split window through a menu?
Ans: To create a dynamic splitter, override OnCreateClient( ) and add code to it as shown
below:
BOOL CMainFrame :: OnCreateClient ( LPCREATESTRUCT lpcs, CCreateContext* pContext )
{
m_dyn.Create ( this , 1 , 2 , CSize( 01 , 01 ) , pContext ) ; // where m_dyn is a member
variable of type CSplitterWnd
return TRUE ;
}
Here, we have simply created a dynamic splitter window of one row two columns. Then, to
the handler of menu item call DoKeyboardSplit( ) method of CSplitterWnd class as
shown below:
void CMainFrame :: OnSplit( )
{
m_dyn.DoKeyboardSplit( ) ;
}

SHFILEINFO...
The structure SHFILEINFO contains information about a file object. The elements of the
SHFILEINFO structure are as shown below.
typedef struct _SHFILEINFO
{
HICON hIcon ;
int iIcon ;
DWORD dwAttributes ;
char szDisplayName[MAX_PATH] ;
char szTypeName[80] ;
} SHFILEINFO ;
The element hIcon contains a handle to an icon that represents the file. The element iIcon
stores an index of the icon image (which is stored) within the system image list.
dwAttributes contains an array of values that indicates the attributes of the file object. The
name and type of the file is stored in szDisplayName and szTypeName respectively.

55

How do you display an hourglass cursor during lengthy operation?


Ans: Many a times our application needs quite a long time to complete a particular task. For
example, we may search for a file or browse the hard disk or sort a large number of items.
At such times we can display an hourglass cursor to show that the application is busy doing
the task. Following function shows how to display the hourglass cursor.
void CChildView::OnDisplay( )
{
BeginWaitCursor( )
// Perform the task
EndWaitCursor( )
}
The second technique to show the hourglass cursor is to create an object of class
CWaitCursor. The constructor calls the BeginWaitCursor( ) function and destructor calls
the EndWaitCursor( ) function respectively.

How do I write code that splits the client window statically into 3 panes (i.e. rows)
and further splits statically the second pane into 1 row 2 columns?
Ans: This shown in following code snippet:
BOOL CMainFrame :: OnCreateClient ( LPCREATESTRUCT lpcs, CCreateContext* pContext )
{
m_stat1.CreateStatic ( this, 3, 1 ) ;
m_stat2.CreateStatic ( &m_stat1, 1, 2, WS_CHILD | WS_VISIBLE , m_stat1.IdFromRowCol
( 1, 0 ) ) ;
m_stat1.CreateView ( 0, 0, RUNTIME_CLASS ( textview ), CSize ( 1, 1 ), pContext ) ;
m_stat1.CreateView ( 2, 0, RUNTIME_CLASS ( newview ), CSize ( 1, 1 ), pContext ) ;
m_stat2.CreateView ( 0, 0, RUNTIME_CLASS ( graphicsview ), CSize ( 1, 1 ), pContext ) ;
m_stat2.CreateView ( 0, 1, RUNTIME_CLASS ( newview ), CSize ( 1, 1 ), pContext ) ;
m_stat1.SetRowInfo ( 0, 100, 1 ) ;
m_stat1.SetRowInfo ( 1, 100, 1 ) ;
m_stat1.SetRowInfo ( 2, 100, 1 ) ;
m_stat2.SetColumnInfo ( 0, 200, 1 ) ;
m_stat2.SetColumnInfo ( 1, 200, 1 ) ;
return TRUE ;
}
Here, first statement creates static splitter window that splits the client window into 3 rows.
The second statement splits the 2 pane of static window into 2 panes. Then we have set the
views for the panes of static splitter windows and also set the row and column size of each
pane. Note that m_stat1, m_stat2 are the member variables of CMainFrame class of
type CSplitterWnd class.

How do I write code to disable top-level menu?

56

Ans: We often enable/disable menu items. But if we have to disable the entire top-level
menu instead of a menu item we can do so using the following statements:
CMenu *m = GetMenu( ) ;
m -> EnableMenuItem ( 0, MF_BYPOSITION | MF_DISABLED | MF_GRAYED ) ;
The GetMenu( ) function returns pointer to the top-level menu. 0 mentioned in the
EnableMenuItem( ) function specifies to disable the zeroth top-level menu.

CRectTracker...
The CRectTracker class provides a user interface between rectangular items in an
application and the user by providing a variety of display styles. These styles include, solid,
hatched, or dashed borders; a hatched pattern that covers the item; and resize handles
that can be located on the outside or inside of a border. Trackers are often used in
conjunction with OLE items, that is, objects derived from COleClientItem.

In a dialog box how can I make sure that the dialog box does not get dismissed if
Esc key is pressed?
Ans: If a dialog box is displayed and Esc key is pressed, OnCancel( ) handler gets called
and the dialog gets dismissed. At times we want to take some other step when Esc key is
pressed. For example, if user has selected an item from a combo box we may want that his
selection should get cancelled if he presses Esc key. In this situation we cannot handle
WM_KEYDOWN message to check whether Esc is pressed since this message is not
generated if Esc key is hit when the dialog is displayed. This situation can be handled in the
following way:
Add a handler for the 'Cancel' button and add code to it as given below:
void CTrickDlg::OnCancel( )
{
short i = ::GetKeyState ( 27 ) ;
if ( i < 0 )
;
else
CDialog::OnCancel( ) ;
}
Here we have checked whether Esc is hit by calling ::GetKeyState( ) function and passing
to it virtual code of Esc key. If OnCancel( ) is called because of pressing Esc key do nothing
(note the ';' after if statement) otherwise call base class's OnCancel( ) to dismiss the
dialog.

How do I write code to change the color of every static text that gets displayed on
a dialog box?
Ans: Add a handler for WM_CTLCOLOR to the dialog class and add code to it as shown
below:
HBRUSH CMyDlg :: OnCtlColor ( CDC* pDC, CWnd* pWnd, UINT nCtlColor )
{
HBRUSH hbr = CDialog :: OnCtlColor ( pDC, pWnd, nCtlColor ) ;
SetTextColor ( pDC->GetSafeHdc( ), RGB ( 255, 255, 0 ) ) ;
return hbr ;
}

57

How MFC objects are related to each other in a Doc/View application?


Ans: In a Doc/View application the information about objects is kept as explained below:
- A document keeps a list of the views of that document and a pointer to the document
template.
- A view keeps a pointer to its document and is a child of its parent frame window.
- A frame window keeps a pointer to its current active view.
- A document template keeps a list of its open documents.
- The application keeps a list of its document templates.
- Windows keeps track of all open windows so it can send messages to them.
From a given object like an object of document class or view class, the information about
other objects is gained by calling some functions.
Document: - Use GetFirstViewPosition( ) and GetNextView( ) functions to
access the document's view list. Call
GetDocTemplate( ) to get the document template.
View: - Call GetDocument( ) function to get the document. Call
GetParentFrame( ) function to get the frame window. Call
GetActiveDocument( ) function to get the document attached to the
current view.
Frame window: - Call GetActiveView( ) function to get the current view.
MDI frame window: - Call MDIGetActive( ) to get the currently active
CMDIChildWnd.

Can we enumerate the various application windows currently running on machine?


Ans: Yes, we can! A tool shipped with Visual Studio called 'Process Viewer' list all the
applications currently running on the machine. We can also do the same using the
GetWindow( ) and GetNextWindow( ) functions. Create an SDI application without
Doc/View support and write following code into the OnCreate( ) handler of the
CMainFrame class.
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
//AppWizard generated code
CWnd *p ;
p = GetWindow ( GW_HWNDFIRST ) ;
CString str ;
while ( p != NULL )
{
p -> GetWindowText ( str ) ;
if ( str != "" )
MessageBox ( str ) ;
p = p -> GetNextWindow ( GW_HWNDNEXT ) ;
}
return 0 ;
}

How do I prevent an application window from moving?


Ans: To prevent an application window from moving write the code given below to the

58

handler for WM_WINDOWPOSCHANGING message. The OnWindowPosChanging( )


function gets called whenever we change the size or position or the Z-order of an application
window.
void CMainFrame :: OnWindowPosChanging ( WINDOWPOS FAR* lpwndpos )
{
if ( IsWindowVisible( ) )
lpwndpos -> flags |= SWP_NOMOVE ;
CFrameWnd :: OnWindowPosChanging ( lpwndpos ) ;
}
Here, for the window which is visible, we are setting bits in the flags parameter of the
WINDOWPOS structure, to SWP_NOMOVE. This will prevent application window from
moving.

Why do AppWizard adds 'stdAfx.h' and 'stdAfx.cpp' files to your project ?


Ans: All header files that are #included in 'StdAfx.h' are precompiled into file name
'<projectname>.pch' and 'stdafx.obj' so that once compiled, they do not have to be
compiled again. AppWizard #includes 'StdAfx.h' in the CPP files that it generates and inside
'StdAfx.h', it adds #includes for MFC header files such as 'AfxWin.h'.

What are the series of actions that take place when I try to close a window?
Ans: When we try to close an application by clicking on the close button, a WM_CLOSE
message is sent to our application. If we do not handle this message then it is passed on to
the default window procedure. The default window procedure destroys the window by calling
the ::DestroyWindow( ) API function. This function places a WM_DESTROY message in the
message queue of our application. If we do not handle this message once again the default
window procedure gets a shot at it. Following WM_DESTROY, is another message called
WM_NCDESTROY. In reaction to this message a handler OnNcDestroy( ) gets called. This
handler calls another functionPostNcDestroy( ). It is in this function that the
::PostQuitMessage( ) function is called. This function places a message WM_QUIT in the
message queue. When this message is retrieved, the message loop is terminated. This
ultimately leads to termination of the application.

Why did the following code failed to draw second rectangle?


void CChildView :: OnPaint( )
{
CPaintDC dc ( this ) ;
dc.Rectangle ( 10, 10, 50, 50 ) ;
CPaintDC dc1 ( this ) ;
dc1.Rectangle ( 10, 70, 50, 120 ) ;
}
Ans: Here, the client area got already validated before we could create second object dc1
of CPaintDC. Using CPaintDC we can draw only in invalid area, hence the second rectangle
would never get drawn. To display second rectangle add following statements before
constructing dc1, to OnPaint( ).
CRect r ( 10, 70, 50, 120 ) ;
InvalidateRect ( &r ) ;

59

How do I write code to provide an auto complete utility for the combo box?
Ans: Follow the steps given below:
1. Create a dialog based application.
2. Add a combo box control to the dialog template and then add a control variable say
m_combo.
3. Add a variable flag of type BOOL.
4. Add a virtual function PreTranslateMessage( ) and write following code to it.
BOOL mydialog :: PreTranslateMessage ( MSG* pMsg )
{
// check if a keyboard key is pressed
if ( pMsg -> message == WM_KEYDOWN )
{
flag = TRUE ;
int v = ( int ) pMsg -> wParam ;
if ( v == VK_DELETE || v == VK_BACK )
flag = FALSE ;
}
return CDialog::PreTranslateMessage ( pMsg ) ;
}
5. Add a handler for CBN_EDITUPDATE event for the combo box. Enter code given
below to this handler.
void mydialog :: OnEditupdateCombo1( )
{
if ( !flag )
return ;
// get the text typed in combo box
CString str ;
m_combo.GetWindowText ( str ) ;
int l = str.GetLength( ) ;
// get the starting & ending character position
DWORD cursel = m_combo.GetEditSel( ) ;
WORD start = LOWORD ( cursel ) ;
WORD end = HIWORD ( cursel ) ;
// If matching string not found
if ( m_combo.SelectString ( -1, str ) == CB_ERR )
{
m_combo.SetWindowText ( str ) ;
if ( cursel != CB_ERR )
m_combo.SetEditSel ( start, end ) ;
}
// place the selected string in combobox
if ( end < l && cursel != CB_ERR )
m_combo.SetEditSel ( start, end ) ;
else
m_combo.SetEditSel ( l, -1 ) ;
}
The PreTranslateMessage( ) function translates the window messages before they are
dispatched to the TranslateMessage( ) and DispatchMessage( ) functions. In this
function we are checking whether or not a keyboard key is pressed. If the key pressed is
other than 'del' or 'backspace' key then we are setting flag to TRUE, otherwise FALSE.

60

Then in the OnEditupdateCombo1( ) function first we have retrieved the text typed in the
edit control of the combo box. Then we have searched for the occurrence of the string that
begins with the same set of characters typed in edit control of combo box. If the matching
string is found then the text gets displayed in the edit control.

Why a base class implementation of OnInitDialog( ) is called in the OnInitDialog( )


of our dialog class?
Ans: The base class OnInitDialog( ) calls UpdateData( ) with parameter FALSE. The
UpdateData( ), in turn creates a CDataExchange object and calls the dialog's
DoDataExchange( ), passing to it the CDataExchange object. The parameter FALSE tells
that the default (initial) values from variables are to be transferred to the controls on the
dialog template. The job of transferring values from variables to controls is done in the
DoDataExchange( ) function. Hence, there is a call to base class's OnInitDialog( ).

How to start a slide show in VC++?


Ans: The API function ShellExecute( ) allows to start a slide show in VC++ using a switch
'/s' as follows.
int OnCreate ( LPCREATESTRUCT l )
{
CFrameWnd::OnCreate ( l ) ;
ShellExecute ( m_hWnd, "open", "C:\\Program Files\\Microsoft
Office\\Office\\powerpoint.exe",
"/s c:\\first.ppt", 0, SW_SHOWMAXIMIZED ) ;
return 0 ;
}
This will start slide show of 'first.ppt' which is in root directory.

If there are two edit controls in a dialog, and the focus is set on one of the edit
controls, then how do I write code so that on pressing enter key the focus gets
set on next edit control?
Ans: When we press enter key the OnOK( ) handler gets called, which in turn calls
EndDialog( ) that dismisses the dialog. To prevent this default behavior we will have to
override OnOK( ) as shown below:
void CEditDlg::OnOK( )
{
short i = ::GetKeyState ( 0x0D ) ; // Where 0x0D is a virtual key code for Enter key
if ( i < 0 )
{
CWnd *w = GetFocus( ) ;
if ( &m_edit1 == w )
// where m_edit1 and m_edit2 are control variables added for two
edit controls respectively
m_edit2.SetFocus( ) ;
else
{
if ( &m_edit2 == w )
m_edit1.SetFocus( ) ;
else

61

CDialog::OnOK( ) ;
}
}
else
CDialog::OnOK( ) ;
}
Here we have called GetKeyState( ) function to which we have passed the virtual key code
of enter key. This function checks if the specified key is down (i.e. pressed) or up. If the key
is pressed then we have extracted the address of control on which the focus is. We have
compared this address with the address of controls we have created and accordingly set
focus on the next control.

How do I access the functions of CChildView class through a button handler of that
dialog, which has been popped up on clicking a menu item?
Ans: Follow the steps given below:
1. Add following data member with access specifier as private to the dialog class.
CWnd *w ;
2. Add the statement given below to the constructor of the dialog class
mydialog :: mydialog ( CWnd* pParent /*=NULL*/)
: CDialog ( mydialog::IDD, pParent )
{
// AppWizard generated code
w = pParent ;
}
3. In the handler for the menu item add code given below:
void CChildView :: OnShowDialog( )
{
mydialog d ( this ) ;
d.DoModal( ) ;
}
Here, we have passed the address of view window (i.e. the address of the object of
CChildView class) to the constructor of the mydialog class. Then #include 'ChildView.h'
file to the '.cpp' file of dialog class. Now, we can access any public member function of view
class through pointer w as shown below:
void mydialog :: OnApply( )
{
( ( CChildView * ) w ) -> myfun( ) ;
}

We can see the following statements in the InitInstance( ) function of the


application class.
CCommandLineInfo cmdInfo ;
ParseCommandLine ( cmdInfo ) ;
If ( !ProcessShellCommand ( cmdInfo ) )
Return FALSE ;
Let us understand the job of these statements:
Ans: The function ParseCommandLine initializes the CCommandLineInfo object
cmdInfo with values that represents the parameters entered on the command line. The
ProcessShellCommand( ) function processes the command line parameters. It also calls

62

OnFileNew( ) to start the application with an empty document. This is the phase when the
framework creates document, frame window, and view objects using the information stored
in the document template.

How would you remove 'Untitled' from caption bar in Doc/View?


Ans: To remove 'Untitled' from caption bar of frame window in Doc/View add following code.
int PreCreateWindow ( CREATESTRUCT cs )
{
cs.style &= ~FWS_ADDTOTITLE ;
return CFrameWnd::PreCreateWindow ( cs ) ;
}

How do I write code to add list of directories/files for given path to the
combobox?
Ans: To add a list of files/directories to a combo box we can use CComboBox::Dir( )
function. This function takes 2 argumentsthe attribute and a string specifying the path of
the directory or combination of wildcard strings. The attribute can be a combination of
values like DDL_READWRITE, DDL_READONLY, DDL_DIRECTORY, DDL_DRIVES, etc. The
following code snippet shows how this function can be used to get a list of directories as well
as files for a specified path.
void CComboDlg::OnGetList( )
{
m_combo.Dir ( DDL_DIRECTORY, "C:\\Windows\\*.*" ) ;
m_combo.SetCurSel ( 1 ) ;
}

While a dialog box is displayed if we hit the Enter key, the dialog box gets dismissed. This is
because, by default, when Enter key is hit, OnOk( ) handler gets called. However, many
times we provide few edit boxes on a dialog for taking input from user and we want that
after entering data if user hits Enter key, input focus should move on to the next edit box
instead of dialog box getting dismissed.
For this, we must override the OnOK( ) handler as shown below:
void mydialog::OnOK( )
{
CWnd *p = GetFocus( ) ;
int id = p -> GetDlgCtrlID( ) ;
switch ( id )
{
case IDC_EDIT1:
( ( CEdit* ) GetDlgItem ( IDC_EDIT2 ) ) -> SetFous( ) ;
break ;
case IDC_EDIT2:
( ( CEdit* ) GetDlgItem ( IDC_EDIT3 ) ) -> SetFous( ) ;
break ;
case IDOK:
CDialog::OnOK( ) ;
}
}
When we press Enter key although OnOK( ) handler gets called, focus remains on the same
control on which it was before calling OnOK( ). Hence, in OnOK( ) we can obtain the

63

pointer to that control and through this pointer we can obtain its ID. We can check this ID
and shift the focus accordingly. If the focus is on the OK button itself, we have called base
class's OnOK( ) to dismiss the dialog.

How to program serial ports?


Ans: We can use the API functions CreateFile( ), ReadFile( ) and WriteFile( ) for serial
ports programming. For example:
HANDLE h = CreateFile ( "COM1:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
0, OPEN_EXISTING, 0, 0 ) ;
DWORD cnt = 0 ;
OVERLAPPED over = { 0 } ;
BYTE buff[256] ;
ReadFile ( h, buff, 10, &cnt, &over ) ;
WriteFile ( h, buff, sizeof ( buff ), &cnt, &over ) ;
Suppose modem is installed on COM1 port then you can detect the incoming and outgoing
call.

Can we create a transparent control?


Ans: Yes, use following code to create transparent control.
HBRUSH OnCtlColor ( CDC *p, CWnd *w, UINT c )
{
brush.CreateStockObject ( NULL_BRUSH ) ;
p -> SetBkMode ( TRANSPARENT ) ;
return ( HBRUSH ) brush.m_hObject ;
}
brush is an object of CBrush. Whenever a control is drawn OnCtlColor( ) gets called. We
have created a NULL brush in it and returned handle to that brush. The control is now drawn
with a NULL brush.

How do I write code that maximizes an MDI child window whenever a new
document is opened/created?
Ans: When we click on maximize button of view window, it gets maximized and the
framework places the child windows Control menu in the frames menu bar so that the user
can restore or close the child window and adds the title of the child window to the framewindow title. To maximize the child window we need to call
CMDIChildWnd::MDIMaximize( ) function. This function must be called by the main
frame window. Add code given below to OnDraw( ) of view class.
#include "MainFrm.h"
void CMDIView :: OnDraw ( CDC* pDC )
{
//AppWizard generated code
if ( flag == 0 ) // where flag is data member of view class, initialized with zero
{

64

CMainFrame *f = ( CMainFrame * ) AfxGetMainWnd( ) ;


f -> fun( ) ;
flag = 1 ;
}
}
Here, we have extracted an address of frame window and called fun( ) a user-defined
function of CMainFrame class. We have used flag variable so that the window gets
maximized once only, when it gets displayed for the first time. There onwards if we click on
restore button the window should get restored. Add code to CMainFrame::fun( ) as shown
below:
void CMainFrame :: fun( )
{
BOOL maximized ;
CMDIChildWnd* child = MDIGetActive ( &maximized ) ;
if ( child && ( !maximized ) )
child -> MDIMaximize( ) ;
}
Here, we have called CMDIFrameWnd::MDIGetActive( ) to get the address of child
window. We have passed a boolean value to this function which stores TRUE if the window is
maximized. If the child window exists and is not maximized then we have called
MDIMaximize( ) function.

How do I add controls like combo box, button control, etc. to a toolbar and make it
dockable?
Ans: To have a toolbar containing controls like combo box, button, etc. we need to add a
dialog bar to our application. Follow the steps given below:
1. Create an SDI application.
2. Add a dialog bar as a new resource. Then add controls on this dialog bar.
3. Add a new class say mybar to manage this dialog bar.
4. Now add a data member say dlgbar of type CDialogBar to the CMainFrame class.
5. Open OnCreate( ) function and add following code to it.
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// AppWizard generated code
dlgbar.Create ( this, IDD_DIALOGBAR, WS_CHILD | WS_VISIBLE | CBRS_TOP |
CBRS_GRIPPER | CBRS_TOOLTIPS |
CBRS_FLYBY | CBRS_SIZE_DYNAMIC, IDD_DIALOGBAR ) ;
dlgbar.EnableDocking ( CBRS_ALIGN_ANY ) ;
EnableDocking ( CBRS_ALIGN_ANY ) ;
DockControlBar ( &dlgbar ) ;
return 0 ;
}
6. Lastly, add functions to handle the events of the corresponding controls of the dialog bar,
to the CMainFrame class.

The AddDocTemplate( ) function...


Ans: When you create an application with a 'Document/View' support, MFC calls a function
AddDocTemplate( ) in InitInstance( ) function of an application class, as shown below.

65

BOOL CMyAppApp::InitInstance( )
{
// AppWizard generated code
// Register the application's document templates.
// Document templates serve as the connection between documents, frame windows and
views.
CSingleDocTemplate* pDocTemplate ;
pDocTemplate = new CSingleDocTemplate ( IDR_MAINFRAME, RUNTIME_CLASS
( CMyAppDoc ),
RUNTIME_CLASS ( CMainFrame ), // main SDI frame window
RUNTIME_CLASS ( CMyAppView ) ) ;
AddDocTemplate ( pDocTemplate ) ;
// AppWizard generated code
return TRUE ;

}
To help an application support different types of documents a document template is created.
After the document template is created it should get added to the list of document
templates maintained by the application object. This job is done by AddDocTemplate( ).
Each template registered in this way defines one document type the application supports.
SDI supports only one document type whereas MDI supports multiple document types.

How do I write code that gives an IP address and the port on which the client
program is running?
Ans: While working with CSocket class many times an IP address or port number on which
the client program is running is required. We can obtain this information by using
CAsyncSocket::GetPeerName( ) function. Override CAsyncSocket::OnReceive( ) in the
class derived from CSocket and call the GetPeerName( ) function in it as shown below:
CString ipadr ;
UINT ip ;
GetPeerName ( ipadr, ip ) ;
CString str ;
str.Format ( "IP Address: %s and Port No.:%u", ipadr, ip ) ;
AfxMessageBox ( str ) ;

How do I avoid resizing of a window?


Ans: To avoid resizing of a window write following code in PrecreateWindow( ) function of
CMainFrame class.
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
// AppWizard generated code
cs.dwExStyle &= ~WS_EX_CLIENTEDGE ;
cs.style &= ~WS_THICKFRAME ;
cs.style &= ~WS_MAXIMIZEBOX ;
cs.lpszClass = AfxRegisterWndClass ( 0 ) ;
return TRUE ;
}
The style WS_THICKFRAME has been set to avoid resizing whereas style
WS_MAXIMIZEBOX is to avoid maximizing of a window.

66

How to play '.avi' files having sound?


Ans: To play '.avi' files programatically we use animate control and CAnimateCtrl class's
member functions. However, this control is not able to play '.avi' files having sound support.
To play these files, we can use MCIWnd (Multimedia Control Interface) functions. MCIWnd is
a window class that is used for multimedia controlling. Following code would display the
'globe.avi' file in a dialog box.
BOOL CAviDlg::OnInitDialog( )
{
HWND havi = MCIWndCreate ( m_hWnd, AfxGetApp( ) -> m_hInstance,
MCIWNDF_NOAUTOSIZEMOVIE, "globe.avi" ) ;
MCIWndPlay ( havi ) ;
}

return TRUE ;

When we use the MCI functions it is necessary to link the file 'vfw32.lib' file to our project.
Also #include 'vfw.h' file to make these functions available.

If our application needs to take some action when the machine is about to shut down we
can do so in OnEndSession( ) handler. All the top-level windows receive WM_ENDSESSION
message when the session is about to close. Handle the WM_ENDSESSION message in
frame class as given below:
void CMainFrame::OnEndSession ( BOOL bEnding )
{
CFrameWnd::OnEndSession ( bEnding ) ;
MessageBox ( "The Windows is shuting down" ) ;
}

How do I enable horizontal scrolling for a list box?


Ans: To implement a horizontal scrolling for a list box, we need to set the style 'Horizontal
Scroll' for the list box. However, even after setting the style, list box does not implement a
default horizontal scrolling. In order to do that, we are required to modify the horizontal
extent for the list box as shown in the following code.
BOOL CTrialDlg::OnInitDialog()
{
//AppWizard generated code
CString str = "Gold is a precious metal that glitters, but all that gliitters is not a gold" ;
m_list.AddString ( str ) ;
CClientDC dc ( &m_list ) ;
CSize size = dc.GetTextExtent ( str, str.GetLength( ) ) ;
if ( size.cx > m_list.GetHorizontalExtent( ) )
m_list.SetHorizontalExtent ( size.cx ) ;
return TRUE ;
}

67

The function GetTextExtent( ) returns the dimension, i.e. width and height of the given
string with respect to the current font selected in the device context. Then we have checked
for the width of the list box by calling GetHorizontalExtent( ) function.
GetHorizontaExtent( ) function returns the width of the list box (in terms of pixels). If it
happens to be smaller than the size returned by GetTextExtent( ), then we are setting the
scrollable width of the list box to the one returned by GetTextExtent( ). Note that the list
box must have the style 'Horizontal Scroll' checked in order to enable the horizontal scroll
bar.

Why don't we use CClientDC class in OnPaint( )?


Ans: If we want to draw something in client area in a handler other than the OnPaint( )
handler, we use CClientDC class's object. However, in OnPaint( ) handler we never use
CClientDC class's object. This is because the constructor of CPaintDC class calls the
BeginPaint( ) function which marks the invalid region as valid. Seeing that there is no
more invalid region in the window the operating system stops posting the WM_PAINT
message. On the other hand, the constructor of CClientDC class only calls the GetDC( )
function which retrieves the device context and returns back. Hence, if we create
CClientDC's object in OnPaint( ) instead of CPaintDC invalid region would never get
validated and so the operating system would post the WM_PAINT message again and again
causing the window to flicker.

How do I write code that hides current dialog and displays a new dialog when a
button is pressed and on pressing a button of the new dialog it dismisses new
dialog and unhide the previous dialog?
Create a dialog based application. Add a button called 'Next' and add a handler for it. Add a
new dialog using Resource Editor. Add a class say Dialog1 to handle the newly added
dialog. Add a button called 'Previous' to new dialog and add a handler for it. Now add code
to OnNext( ) as shown below:
void CMyDlg :: OnNext( )
{
this -> ShowWindow ( SW_HIDE ) ;
Dialog1 dlg ( this ) ; // this is the address of parent dialog
dlg.DoModal( ) ;
}
Add a data member called m_parent of type CWnd* to Dialog1 class. Collect the address
of parent window in m_parent in the constructor as shown below:
Dialog1 :: Dialog1 ( CWnd* pParent /*=NULL*/ )
: CDialog ( Dialog1 :: IDD, pParent )
{
//AppWizard generated code
m_parent = pParent ;
}
Now, add code to OnPrevious( ) handler as shown below:
#include "MyDlg.h"
void Dialog1 :: OnPrevious( )
{
EndDialog ( 1 ) ; // to dismiss current dialog
( ( CMyDlg * ) m_parent ) -> ShowWindow ( SW_SHOW ) ; // to show previous dialog
}

68

How do I change the text of Open/Save button of the common dialog CFileDialog?
Ans: To change the text of button in CFileDialog, follow the steps given below.
1. Add a new class mydlg say for example, derived from CFileDialog to your
application.
2. Add message handler for WM_ONINITDIALOG to this class. Then enter code given
below to OnInitDialog( ) function.
BOOL mydlg :: OnInitDialog( )
{
CFileDialog::OnInitDialog( ) ;
CButton *b = ( CButton * ) GetParent( ) -> GetDlgItem ( IDOK ) ;
if ( b )
b -> SetWindowText ( "mybutton" ) ;
return TRUE ;
}
3. Create an object of mydlg class and pass necessary parameters to the constructor.
Call DoModal( ) to display the CFileDialog with the button 'mybutton' .

How an application recognizes keyboard or mouse messages?


The mouse and keyboard input comes in the form of messages. The device drivers for the
keyboard and mouse process mouse and keyboard interrupts and places the resultant event
notification in a system wide queue called as raw input queue. The raw input queue has the
same WM_message identifiers, but the data in them needs further processing before it is
meaningful to an application. A dedicated thread owned by the operating system monitors
the raw input queue and transfers each message to the appropriate thread message queue.
The message is then retrieved and dispatched.

How would you convert a handle into a pointer?


Ans: Very often we get a handle of an object and we need to convert it to a pointer to that
object. For this FromHandle( ) function can be used. Following code snippets show how to
get a pointer to different classes from a handle.

HBRUSH hb = ( HBRUSH ) GetStockObject ( BLACK_BRUSH ) ;


CBrush *b = CBrush::FromHandle ( hb ) ;

HDC hdc = ::GetDC ( NULL ) ;


CDC* pDC = CDC::FromHandle ( hdc ) ;

CWnd *pWnd = ( CWnd * ) ::FromHandle ( m_hWnd ) ;

How do I write code to display standard Find dialog on clicking a button?


Ans: The CFindReplaceDialog class is used to display standard Find dialog. It can also
display Find/replace dialog. Following code demonstrates how this class can be used to
display dialog.
void CMyDlg :: OnFind_Replace( )
{
CFindReplaceDialog *d = new CFindReplaceDialog ;
d -> Create ( TRUE, "", NULL, FR_DOWN, this ) ;
d -> ShowWindow ( SW_SHOW ) ;
}

69

The standard Find dialog is a modeless dialog. Hence, we are required to allocate space for
object of CFindReplaceDialog on heap. The first parameter passed to Create( ) function,
indicates to display Find dialog. Passing FALSE would display standard Find/Replace dialog.
The next parameter specifies the string to search for. Since we don't want to replace the
found string, we have specified NULL at the place of third parameter. FR_DOWN is the
default value which specifies that the search has to be proceed in downward direction. On
clicking 'Find Next' button a handler should get called. To do so add a user-defined member
function say OnFind( ) to the dialog class. To be able to call the handler, we need to
register a message. Hence, add code shown below to the header file of dialog class.
static UINT WM_FIND = ::RegisterWindowMessage ( FINDMSGSTRING ) ;
Then add following entry in message map.
BEGIN_MESSAGE_MAP ( CMyDlg, CDialog )
//{{AFX_MSG_MAP(CFind_ReplaceDlg)
ON_REGISTERED_MESSAGE( WM_FIND, OnFind )
//}}AFX_MSG_MAP
END_MESSAGE_MAP( )

How do I move a dialog when I drag it by pressing left mouse button at any point?
Ans: When we press a left mouse button on the title-bar area of a window and drag it then
only the window gets moved. In order to get the dialog window moved when the left mouse
button is pressed at any other point in the dialog window, we need to add a message
handler for WM_NCHITTEST. The OnNcHitTest( ) handler gets called every time the mouse
is moved. It gets called for that window which contains the cursor or the window that has
called SetCapture( ) to capture the mouse input. The function takes the screen coordinates
of the cursor as a parameter and returns enumerated values for mouse. Enter code to this
handler as shown below:
UINT mydlgDlg::OnNcHitTest(CPoint point)
{
CRect r ;
GetClientRect ( &r ) ;
ClientToScreen ( &r ) ;
if ( r.PtInRect( point ) )
return HTCAPTION ;
return CDialog::OnNcHitTest ( point ) ;
}
Here we have checked whether the point lies within client area or not. If it is, then we are
returning an enumerated value HTCAPTION which indicates that mouse is hit in the title-bar
area of a window. As a result, the dialog box widow will get moved as we drag it by clicking
left mouse button.

In InitInstance( ) function the CMainFrame object is created dynamically by


calling operator new. Its a rule that using delete we must destroy an object thus
created. We do not have any such statement in application class, then how the
frame object gets destroyed?
Ans: When you click the close button to terminate an application, the last message an
application window receives is WM_NCDESTROY. The CWnd::OnNcDestroy( ) function calls
a virtual function named PostNcDestroy( ). CFameWnd class overrides
PostNcDestroy( ) and executes a statement
delete this ;

70

Thus when a frame window is destroyed, the object associated with that window is
automatically deleted.

You must know that:

m_pMainWnd is a public data member of CWinApp class which contains address


of frame
window.

Function AfxGetApp( ) returns address of application object. So AfxGetApp( ) can


be used
to call member functions of CWinApp class.

AfxGetMainWnd( ) function returns the address stored in m_pMainWnd i.e.


address of
frame window.

Returning 0 from InitInstance( ) function will close down the application.

WS_VISIBLE style can be used in Create( ) function instead of calling


ShowWindow( )
function.

MAKEINTRESOURCE is a macro declared in 'windows.h' file. It converts an integer to


string.

Functions preceded by 'Afx' prefix are global function which can be called anywhere.

If changes are made in resources then during compilation only the resources get
compiled and not the whole
program.

Selecting 'Use MFC in static DLL' from Project | Settings will create a stand alone
exe.

How do I write code that displays the flyby text for an item of a menu created
programmatically ?
Ans: To get the flyby text displayed on a status bar for an item of menu created
programmatically, handle WM_MENUSELECT message in your application as shown below:
void CMainFrame :: OnMenuSelect ( UINT nItemID, UINT nFlags, HMENU hSysMenu )
{
if ( nItemID == 300 ) // where 300 is an ID for an item of menu created programmatically
m_wndStatusBar.SetPaneText ( 0, "Draws a line" ) ;
else
CFrameWnd :: OnMenuSelect ( nItemID, nFlags, hSysMenu ) ;
}

How to create our own mapping mode?


Ans: Mapping mode specifies how logical coordinates should get converted into physical
coordinates. By default, 1 logical unit is converted into 1 physical unit i.e. 1 pixel. There are
few pre-defined mapping modes each of which convert logical coordinates into physical
coordinates in different way. But sometimes, we may want to create our own mapping
modes, so that we can define our own conversion system. We can do so by using
MM_ISOTROPIC and MM_ANISOTROPIC mapping modes. Difference between the two modes
is that in MM_ISOTROPIC, 1 unit along x-axis is equal to 1 unit along y-axis. in
MM_ANISOTROPIC we can define how many units along x-axis should be equal to how many
units along y-axis.

71

Following code shows how to create a coordinate system where origin is at the center of the
client area and the size of one unit in x-direction is twice the size of one unit in y-direction.
CPaintDC d ( this ) ;
CRect r ;
GetClientRect ( &r ) ;
d.SetViewportOrg ( r.right / 2, r.bottom / 2 ) ;
d.SetMapMode ( MM_ANISOTROPIC ) ;
d.SetWindowExt ( 10, 20 ) ;
d.SetViewportExt ( r.right, r.bottom ) ;
d.Rectangle ( 0, 0, 2, 2 ) ;

How to get exit code of a thread?


Ans: If we start a worker thread from our application we may wish to see whether the
thread is still alive or not. If the thread is not alive we may wish to check the exit code of
the thread to determine the success or failure of the thread function. We can perform both
these jobs by calling a function GetExitCodeThread( ). If the thread is active the
GetExitCodeThread( ) function returns STILL_ALIVE value. If the thread is terminated the
GetExitCodeThread( ) function returns the exit code of the thread. This exit code may be
the value returned by the thread function or the code passed to the TerminateThread( )
function.

How do I add a 'cancel' button to the message box dialog that gets displayed when
we call MessageBox( ) function?
Ans: The following code snippet demonstrates this:
void CChildView :: fun( )
{
MessageBox ( "Hello!", "Message", MB_OKCANCEL ) ;
}
The third parameter MB_OKCANCEL passed to the MessageBox( ) function adds two push
buttons OK and Cancel to the message box dialog. In addition to this we can also display
the icon in the message box by setting flag as MB_ICONSTOP, MB_ICONERROR,
MB_ICONHAND etc.

Why do we need a port number in socket programming?


Ans: In socket programming we often provide computer name and the port number to the
sockets. Why isn't computer name enough to establish connection between two computers,
why do we need a port number? Data transfer between two machines take place only
through one network connection. Whereas, there may be number of applications running at
a time that can receive data through network connection. Hence communication happens
through the port number (16 bit number). Each application should communicate through a
different port number. This is the reason why we need computer name as well as the port
number. The machine name ultimately becomes some IP address. No two applications can
be bound to the same port.

72

How do I get the list of logical drives in the system and add it in a combobox?
Ans: The API function GetLogicalDriveStrings( ) fills a buffer with strings that specify
valid logical drives in the system. The buffer is filled with the null terminated strings where
every string is the name of the logical drive. The following code demonstrates how we can
get the logical drives and add them in the combobox.
void CMydlgDlg::OnDrives( )
{
char buff[100] ;
DWORD str = GetLogicalDriveStrings ( sizeof ( buff ) / sizeof ( char ), buff ) ;
char *s = buff ;
while ( *s )
{
LPCTSTR dp = s ;
if ( *dp != '\\' )
m_combo.AddString ( dp ) ;
s += 2 ;
}
m_combo.SetCurSel ( 1 ) ;
}
The GetLogicalDriveStrings( ) function takes two parameters, first, the size or length of
the buffer in which the series of null terminated strings are to be stored and the second is a
pointer to the buffer that receives the strings.

What is a Versionable Schema?


Ans: Suppose an application has a serializable class that serializes end points of the
rectangle. This application uses black pen and white brush as defaults to draw all rectangles.
Suppose, we modify the application and decide to provide a facility to select different colors
for pens and brushes for each new rectangle that is drawn. This needs that the pen color
and the brush color should also be serialized and de-serialized. Hence, we would modify the
serialization and de-serialization code. Thus, our application has now two versions, say 1.0
and 2.0. The new code would work properly while serializing the data onto the disk but
would fail while de-serializing the data from the file that was created with the older version.
This is because the older version had never serialized pen and brush color on to the disk. To
prevent this we need to use 'Versionable Schemas'. To use the Versionable Schema, we
must properly update the IMPELEMENT_SERIAL( ) macro given in the class derived from the
CObject class. The default IMPELEMENT_SERIAL( ) macro as written in old version is as
shown below:
IMPLEMENT_SERIAL ( crect, CObject, 1 )
As against this, in the new version we will have to write the schema number 2 through the
macro shown below:
IMPLEMENT_SERIAL ( crect, CObject, 2 | VERSIONABLE_SCHEMA )
While reading the crect objects we must read the schema number. This we can dovv
through a call to the function GetObjectSchema( ). If it returns a value 1 the object
should be de-serialized the old way and if it returns a value 2 it should be de-serialized in
the new way (alongwith pen and brush color).

73

How do I write a code to select entire row in CListCtrl control?


Ans: Create a dialog based application and add a CListCtrl control to the dialog template.
Change the view style of the control to 'Report'. Add a control variable m_list for the
control. Then add following statement to the OnInitDialog( ).
BOOL mydialog :: OnInitDialog( )
{
//AppWizard generated code
m_list.SendMessage ( LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
LVS_EX_FULLROWSELECT ) ;
// code
}
The parameter LVM_SETEXTENDEDLISTVIEWSTYLE is used to set an extended style in the
list view control and the parameter LVS_EX_FULLROWSELECT ensures that when an item is
selected in a list control, then all its subitems should also get highlighted. Note that
LVS_EX_FULLROWSELECT style can be used only if the view style of list control is set to
LVS_REPORT.

How to hide a button from the taskbar?


Ans: If you want that your application should run but it should not be visible on the taskbar,
you can hide the button from the taskbar and also from the window which shows the
running applications if user presses Alt + Tab. For this, you must add an extended style in
the PreCreateWindow( ) function of the frame class as shown below:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
cs.dwExStyle |= WS_EX_TOOLWINDOW ;
cs.dwExStyle &= ~WS_EX_APPWINDOW ;
return TRUE;
}

How do I write code to create scrolling tabs in a property sheet?


Ans: By default, if a property sheet has more tabs than those that can fit in a single row in
the width of the property sheet, the tabs will stack in multiple rows. To use scrolling tabs
instead of stacking tabs, we can call the EnableStackedTabs( ) function passing to it
FALSE before calling DoModal( ) or Create( ) functions.

If we create a list control dynamically then we cannot add handlers for it through
ClassWizard. If we need to add a handler then we have to add it manually. For example, if
we want to add double-click handler for a list control then we need to add following
declaration in the '.h' file:
void OnDblclkItem ( NMLISTVIEW *p, LRESULT *q ) ;
Also we need to add following entry in the message map.
ON_NOTIFY_REFLECT ( NM_DBLCLK, OnDblclkItem )

74

How do I write code that displays a progress control while copying contents?
Ans: Use SHFileOperation( ) function as shown below:
void MyDlgdlg::OnCopy( )
{
SHFILEOPSTRUCT s ;
::ZeroMemory ( &s, sizeof ( s ) ) ; // Initialize the structure
CString f = "C:\\MyFolder" ;
CString t = "D:\\" ;
char from [ MAX_PATH ], to [ MAX_PATH ] ; // buffer used to copy source and target path
strcpy ( from, f ) ;
int l = f.GetLength( ) ;
from[l+1] = '\0' ;
strcpy ( to, t ) ;
l = t.GetLength( ) ;
to[l+1] = '\0' ;
// Set the values in structure
s.hwnd = this -> m_hWnd ;
s.wFunc = FO_COPY ;
s.pFrom = ( LPCTSTR ) from ;
s.pTo = ( LPCTSTR ) to ;
s.fFlags = FOF_SIMPLEPROGRESS ;
s.lpszProgressTitle = "Copying files..." ;
::SHFileOperation ( &s ) ;
}

How do I check programmatically, whether 'View As Web Page' option is enabled?


Ans: Use shell API function SHGetSettings( ) as shown below:
void CMyDlg::OnGetSettings( )
{
SHELLFLAGSTATE sh ;
SHGetSettings ( &sh, SSF_DESKTOPHTML ) ;
int status = sh.fDesktopHTML ;
if ( status != 0 )
AfxMessageBox ( "View As Web Page option is enabled" ) ;
}
Here, to the SHGetSettings( ) function we have passed address of variable of
SHELLFLAGSTATE structure and a parameter called SSF_DESKTOPHTML to indicate that the
information about fDesktopHTML member of SHELLFLAGSTATE structure is required. We
can also use this function to know whether options like 'Show All Files', 'Show Hidden Files'
are enabled or not.

75

S-ar putea să vă placă și