views:

1170

answers:

1

I am trying to create a custom file save dialog for XP using C++/VS2008. My dialog will have three dropdowns and an edit box. I need the contents of the dropdowns to dynamically update when selections are made on other dropdowns. Hence, my need to catch the CBN_ events.

I've created a class that extends CFileDialog and a class that extends CComboBox. I can get the custom dialog (with the combos) to display but I cannot trap the CBN_ events.

I used the VS 'Create MFC DLL' wizard to get two classes: The app class and the custom file save dialog class. I created a derived CComboBox class so I could add messages/event trapping code. I put in the message maps, DoDataExchange and event trapping code in the dialog class.

The code that follows is an abridged version of what I'm working with. I figure I don't need to post the creation of three dropdowns when I can't get even one dropdown to work. I also didn't put in any code for the edit box, since I'm not having issues with that.

Some code: From the app class - creating an instance of the custom dialog, calling DoModal:

BOOL CSaveAsApp::InitInstance() 
{
CWinApp::InitInstance();
// Parse the command line to get the defaultExtension and the file filter 
CString cmdLineAsString = CString( theApp.m_lpCmdLine );

int curPos = 0 ;
CString fileExtension = cmdLineAsString.Tokenize(" ", curPos ) ;
CString fileFilter = cmdLineAsString.Tokenize(" ", curPos ) ; ;


MyFileDialog dlg( FALSE, fileExtension.GetBuffer(), "Enter File Name Here",
     OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
     fileFilter.GetBuffer(), m_pMainWnd) ;


m_pMainWnd = &dlg;

int nResponse = dlg.DoModal();

if (nResponse == IDOK)
{
   ... 
}
else if (nResponse == IDCANCEL)
       ...

return FALSE;
}

Here is some code from the custom file save dialog:

IMPLEMENT_DYNAMIC(MyFileDialog, CFileDialog ) 
//  LJM Put in last two parms: DWORD dwSize, BOOL bVistaStyle (0, 0 )
//   bVistaStyle = 0 ==> XP-Style dialog

MyFileDialog::MyFileDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, 
            LPCTSTR    lpszFileName, DWORD dwFlags, LPCTSTR lpszFilter, 
            CWnd* pParentWnd) :
 CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags,
            lpszFilter, pParentWnd, 0, 0) 
{ }

MyFileDialog::~MyFileDialog() { }

void MyFileDialog::DoDataExchange(CDataExchange* pDX)
{
   CFileDialog::DoDataExchange(pDX);
   //{{AFX_DATA_MAP(MyFileDialog)
   //DDX_Control(pDX, IDC_CONTEXT_COMBO, m_ComboContext);
   //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(MyFileDialog, CFileDialog)
ON_CBN_SELCHANGE(IDC_CONTEXT_COMBO, &MyFileDialog::OnCbnSelchangeUniqueNumber)
ON_CBN_SELENDOK(IDC_CONTEXT_COMBO, &MyFileDialog::OnCbnSelchangeUniqueNumber)
END_MESSAGE_MAP()

BOOL MyFileDialog::OnInitDialog() 
{
CFileDialog::OnInitDialog();

//AfxEnableControlContainer();

const UINT iExtraSize = 300;
// Get a pointer to the original dialog box.
CWnd *wndDlg = GetParent();
RECT Rect;


wndDlg->GetWindowRect(&Rect);
// Change the size of FileOpen dialog
wndDlg->SetWindowPos(NULL, 0, 0, 
                    Rect.right - Rect.left, 
                    Rect.bottom - Rect.top + iExtraSize,  
     SWP_NOMOVE);

CWnd *wndComboCtrl = wndDlg->GetDlgItem(cmb1);  
wndComboCtrl->GetWindowRect(&Rect);
wndDlg->ScreenToClient(&Rect); // Remember it is child controls

Rect.top += 60;
Rect.bottom += 120;
Rect.left += 50;

m_ComboContext.Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP, Rect, wndDlg, IDC_CONTEXT_COMBO);  


 m_ComboContext.SetFont(wndComboCtrl->GetFont(), TRUE);

        m_ComboContext.AddString(_T("Lou1") );
 m_ComboContext.AddString(_T("L432") );
 m_ComboContext.AddString(_T("Lou2") );
 m_ComboContext.AddString(_T("Lou3") );



return true ;
}

void MyFileDialog::OnCbnSelchangeUniqueNumber()
{
AfxMessageBox( _T("OnCbnSelchangeUniqueNumber"), 0, 0 ) ;
}

And here's the derived class from CComboBox:

   IMPLEMENT_DYNAMIC(LouComboBox, CComboBox)

   LouComboBox::LouComboBox() {  }

   LouComboBox::~LouComboBox() {  }

BEGIN_MESSAGE_MAP(LouComboBox, CComboBox)
ON_CONTROL_REFLECT(CBN_SELCHANGE, &LouComboBox::OnCbnSelchange)
ON_CONTROL_REFLECT(CBN_KILLFOCUS, &LouComboBox::OnCbnKillfocus)
ON_CONTROL_REFLECT(CBN_SELENDCANCEL, &LouComboBox::OnCbnSelendcancel)

ON_CBN_SELCHANGE(IDC_CONTEXT_COMBO, &LouComboBox::OnCbnSelchangeUniqueNumber)
END_MESSAGE_MAP()

void LouComboBox::OnCbnSelchange()
{
// TODO: Add your control notification handler code here
AfxMessageBox( _T("Menu selected"), 0, 0 ) ;
}

void LouComboBox::OnCbnKillfocus()
{
// TODO: Add your control notification handler code here
AfxMessageBox( _T("Lost focus"), 0, 0 ) ;
}

void LouComboBox::OnCbnSelendcancel()
{
AfxMessageBox( _T("OnCbnSelendcancel"), 0, 0 ) ;
}

void LouComboBox::OnCbnSelchangeUniqueNumber()
{
// TODO: Add your control notification handler code here 
AfxMessageBox( _T("OnCbnSelchangeUniqueNumber"), 0, 0 ) ;
}

I have tried versions where the dialog class has the messagemap/DoDataExchange, the ComboBox class has them, both classes have them..

I am able to catch some events - none with the CComboBox, though. I can get the dialog to respond to ON_NOTIFY, ON_WM_DESTROY and the edit box responds to ON_WM_KILLFOCUS.

I have this nagging thought that this is a forehead-slapper, that I'm too close to this and can't see the obvious.

ANy help, assistance, direction would be greatly appreciated.

A: 

It's a long shot, but do the comboboxes have the WS_NOTIFY style?

adzm
I don't know. I created the combos with WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP. When I added WS_NOTIFY VS2008 said it didn't recognize the symbol WS_NOTIFY. I'll see how to code WS_NOTIFY style for combos. THANKS FOR THE SUGGESTION.
Lou