Monthly Archives: January 2006

Basics for catching a windows message manually

In the following sample, we catch the WM_RBUTTONDOWN message. This would work for any windows message :

  1. In the AFX_MSG section of your .h file, add the declaration of your message handler function :
     //{{AFX_MSG(CMyCtrl)
    // NOTE – the ClassWizard will add and remove member functions here.
    afx_msg LRESULT OnRBtnDown(WPARAM wParam, LPARAM lParam); // handler function
    //}}AFX_MSG
  2. Add the body of your function in your .cpp file :
    LRESULT CMyCtrl::OnRBtnDown(WPARAM wParam, LPARAM lParam)
    {
    AfxMessageBox(“WM_RBUTTONDOWN caught”);
    return 0;
    } // LRESULT CMyCtrl::OnRBtnDown
  3. In the message map of your .cpp file, add the following :
    BEGIN_MESSAGE_MAP(CMyCtrl, CWnd)
    //{{AFX_MSG_MAP(CFilteredListCtrl)
    // NOTE – the ClassWizard will add and remove mapping macros here.
    ON_MESSAGE(WM_RBUTTONDOWN, OnRBtnDown)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()

However, some shortcuts allows you to take care of standard messages. For example, the WM_RBUTTONDOWN message can be caught with :

  1. //{{AFX_MSG(CMyCtrl)
    // NOTE – the ClassWizard will add and remove member functions here.
    afx_msg void OnRButtonDown( UINT nFlags, CPoint point );
    //}}AFX_MSG
  2. void CMyCtrl::OnRButtonDown( UINT nFlags, CPoint point )
    {
    CWnd::OnRButtonDown( nFlags, point );
    } // void CMyCtrl::OnRButtonDown
  3. BEGIN_MESSAGE_MAP(CMyCtrl, CWnd)
    //{{AFX_MSG_MAP(CMyCtrl)
    // NOTE – the ClassWizard will add and remove mapping macros here.
    ON_WM_RBUTTONDOWN()
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()

You can apply the same approach to many WM_XXX messages.

Troubles displaying a popup menu dynamically

Damian Powell
Oct 18 1999, 2:00 am   show options
Newsgroups: microsoft.public.vc.mfc
From: Damian Powell <damian_pow@my-deja.com> – Find messages by this author
Date: 1999/10/18
Subject: CMenu::TrackPopupMenu – strange behaviour.
Reply to Author | Forward | Print | Individual Message | Show original | Report Abuse

Hello everyone,

I’m using the following code to display a popup-menu from a CDialog
derrived object but it doesn’t seem to work correctly.

When the menu is displayed, it appears as a thin-ish vertical line with
no text. However, the highlight does move as I move the mouse down the
menu and the correct menu items are selected from the various positions.

Can anyone tell me what I am doing wrong?

void CRs232ClientDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
CDialog::OnRButtonDown(nFlags, point);
ClientToScreen(&point);
CMenu menu;
menu.LoadMenu(IDR_MENU1);
menu.TrackPopupMenu (
TPM_LEFTALIGN|TPM_LEFTBUTTON,
point.x,
point.y,
this
);

 

}

Thanks in advance,
Damian.
Sent via Deja.com http://www.deja.com/
Before you buy.

Douglas Peterson
Oct 18 1999, 2:00 am   show options
Newsgroups: microsoft.public.vc.mfc
From: Douglas Peterson <douglas.peter@nospam.telex.com> – Find messages by this author
Date: 1999/10/18
Subject: Re: CMenu::TrackPopupMenu – strange behaviour.
Reply to Author | Forward | Print | Individual Message | Show original | Report Abuse

There may be an “appropriate” solution, I don’t know, but this works:

Create your menu (IDR_MENU1) with a single popup menu item (sub-menu)
and put the “real” popup as items in this sub.  Then get the menu like
this:

menu.LoadMenu(IDR_MENU1);
CMenu* pPopup = menu.GetSubMenu(0);
pPopup->TrackPopupMenu(…)

 

– Show quoted text –

 

 

Bob Moore
Oct 18 1999, 2:00 am   show options
Newsgroups: microsoft.public.vc.mfc
From: Bob Moore <b@mvps.org> – Find messages by this author
Date: 1999/10/18
Subject: Re: CMenu::TrackPopupMenu – strange behaviour.
Reply to Author | Forward | Print | Individual Message | Show original | Report Abuse

 

On Mon, 18 Oct 1999 15:42:39 GMT, Damian Powell wrote:
>When the menu is displayed, it appears as a thin-ish vertical line with
>no text. However, the highlight does move as I move the mouse down the
>menu and the correct menu items are selected from the various positions.

You’ve loaded a bar menu rather than a popup.

CListCtrl::SortItems() a bug in the MSDN sample

Looking at a way to sort elements in a CCtrlList, I had a look at the sample given by the MSDN.

That’s the second time in a week I find a mistake in the MSDN. Must be unlucky… The first one concerned the “__cplusplus” preprocessor variable definition. I copied a sampe in which there was 1 “_” instead of two. Obviously, the sample didn’t work.

This time, it’s the sort items sample which is problematic.

Here is the MSDN sample :

// Sort the item in reverse alphabetical order.
static int CALLBACK
MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
// lParamSort contains a pointer to the list view control.
CListCtrl* pListCtrl = (CListCtrl*) lParamSort;
CString    strItem1 = pListCtrl->GetItemText(lParam1, 0);
CString    strItem2 = pListCtrl->GetItemText(lParam2, 0);

return strcmp(strItem2, strItem1);
}

void snip_CListCtrl_SortItems()
{
// The pointer to my list view control.
extern CListCtrl* pmyListCtrl;

// Sort the list view items using my callback procedure.
pmyListCtrl->SortItems(MyCompareProc, (LPARAM) pmyListCtrl);
}

(see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_mfc_clistctrl.3a3a.sortitems.asp)

This codes implies that lParam1 and lParam2 contains the index of the items to compare, which is not true since they are the item’s data field, which is not initialized to the index of items.

Moreover, even if you initialize the data of items with the corresponding index, the sort function will work only once, since after the first sort the real item index and the one stored in the data field won’t match anymore…

How to determine the operating system at runtime ?

Ever wanted to determine the operating system at runtime ? That’s possible using the GetVersionEx() Microsoft API function.

Microsoft gives an example of how to use this function a t the address : http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getting_the_system_version.asp.

Below is a copy of the sample function :

#include <windows.h>
#include <stdio.h>
#define BUFSIZE 80
#define SM_SERVERR2            89
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
int main()
{
OSVERSIONINFOEX osvi;
SYSTEM_INFO si;
PGNSI pGNSI;
BOOL bOsVersionInfoEx;
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
// If that fails, try using the OSVERSIONINFO structure.
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
{
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
return FALSE;
}
switch (osvi.dwPlatformId)
{
// Test for the Windows NT product family.
case VER_PLATFORM_WIN32_NT:
// Test for the specific product.
if ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 )
{
if( osvi.wProductType == VER_NT_WORKSTATION )
printf ("Microsoft Windows Vista ");
else printf ("Windows Server \"Longhorn\" " );
}
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
{
// Use GetProcAddress to avoid load issues on Windows 2000
pGNSI = (PGNSI) GetProcAddress(
GetModuleHandle("kernel32.dll"),
"GetNativeSystemInfo");
if(NULL != pGNSI)
pGNSI(&si);
if( GetSystemMetrics(SM_SERVERR2) )
printf( "Microsoft Windows Server 2003 \"R2\" ");
else if( osvi.wProductType == VER_NT_WORKSTATION &&
si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
{
printf( "Microsoft Windows XP Professional x64 Edition ");
}
else printf ("Microsoft Windows Server 2003, ");
}
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
printf ("Microsoft Windows XP ");
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
printf ("Microsoft Windows 2000 ");
if ( osvi.dwMajorVersion <= 4 )
printf ("Microsoft Windows NT ");
// Test for specific product on Windows NT 4.0 SP6 and later.
if( bOsVersionInfoEx )
{
// Test for the workstation type.
if ( osvi.wProductType == VER_NT_WORKSTATION &&
si.wProcessorArchitecture!=PROCESSOR_ARCHITECTURE_AMD64)
{
if( osvi.dwMajorVersion == 4 )
printf ( "Workstation 4.0 " );
else if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
printf ( "Home Edition " );
else printf ( "Professional " );
}
// Test for the server type.
else if ( osvi.wProductType == VER_NT_SERVER ||
osvi.wProductType == VER_NT_DOMAIN_CONTROLLER )
{
if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==2)
{
if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
{
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
printf ( "Datacenter Edition for Itanium-based Systems" );
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
printf ( "Enterprise Edition for Itanium-based Systems" );
}
else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
{
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
printf ( "Datacenter x64 Edition " );
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
printf ( "Enterprise x64 Edition " );
else printf( "Standard x64 Edition " );
}
else
{
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
printf ( "Datacenter Edition " );
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
printf ( "Enterprise Edition " );
else if ( osvi.wSuiteMask == VER_SUITE_BLADE )
printf ( "Web Edition " );
else printf ( "Standard Edition " );
}
}
else if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0)
{
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
printf ( "Datacenter Server " );
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
printf ( "Advanced Server " );
else printf ( "Server " );
}
else  // Windows NT 4.0
{
if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
printf ("Server 4.0, Enterprise Edition " );
else printf ( "Server 4.0 " );
}
}
}
// Test for specific product on Windows NT 4.0 SP5 and earlier
else
{
HKEY hKey;
char szProductType[BUFSIZE];
DWORD dwBufLen=BUFSIZE;
LONG lRet;
lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
0, KEY_QUERY_VALUE, &hKey );
if( lRet != ERROR_SUCCESS )
return FALSE;
lRet = RegQueryValueEx( hKey, "ProductType", NULL, NULL,
(LPBYTE) szProductType, &dwBufLen);
RegCloseKey( hKey );
if( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE) )
return FALSE;
if ( lstrcmpi( "WINNT", szProductType) == 0 )
printf( "Workstation " );
if ( lstrcmpi( "LANMANNT", szProductType) == 0 )
printf( "Server " );
if ( lstrcmpi( "SERVERNT", szProductType) == 0 )
printf( "Advanced Server " );
printf( "%d.%d ", osvi.dwMajorVersion, osvi.dwMinorVersion );
}
// Display service pack (if any) and build number.
if( osvi.dwMajorVersion == 4 &&
lstrcmpi( osvi.szCSDVersion, "Service Pack 6" ) == 0 )
{
HKEY hKey;
LONG lRet;
// Test for SP6 versus SP6a.
lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
0, KEY_QUERY_VALUE, &hKey );
if( lRet == ERROR_SUCCESS )
printf( "Service Pack 6a (Build %d)\n",
osvi.dwBuildNumber & 0xFFFF );
else // Windows NT 4.0 prior to SP6a
{
printf( "%s (Build %d)\n",
osvi.szCSDVersion,
osvi.dwBuildNumber & 0xFFFF);
}
RegCloseKey( hKey );
}
else // not Windows NT 4.0
{
printf( "%s (Build %d)\n",
osvi.szCSDVersion,
osvi.dwBuildNumber & 0xFFFF);
}
break;
// Test for the Windows Me/98/95.
case VER_PLATFORM_WIN32_WINDOWS:
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
{
printf ("Microsoft Windows 95 ");
if (osvi.szCSDVersion[1]=='C' || osvi.szCSDVersion[1]=='B')
printf("OSR2 " );
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
{
printf ("Microsoft Windows 98 ");
if ( osvi.szCSDVersion[1]=='A' || osvi.szCSDVersion[1]=='B')
printf("SE " );
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
{
printf ("Microsoft Windows Millennium Edition\n");
}
break;
case VER_PLATFORM_WIN32s:
printf ("Microsoft Win32s\n");
break;
}
return TRUE;
}