Resource ID's < 32768 do not Command Routing - mfc

I use the same ID's in Menus and Dialog.
I create a modeless or modal CMyDialog within my CView class.
Then I handle CMyDialog Buttons Click in my CView derived class.
(No need to write any code in CDialog, it just forward the commands to CMyView).
That works usually.
ON_COMMAND(IDC_HOME, &CMyView::OnHome)
void CMyView::OnHome()
{
..
}
But what I have discovered is:
If the resource ID is e.g
#define IDC_HOME 1060 // Fail
but
#define IDC_HOME 32796 // Works
I have read TN021: Command and Message Routing but I don't find or see a limitation?
Where is this documented?

Related

CWindowImpl - Create() returns error code 1406

I just tried to setup a small win32 project, and was just about to create a window.
I created a dialog in the resource designer and set up this class for my window:
#pragma once
#include "stdafx.h"
class TTTMainDialog : public CWindowImpl<TTTMainDialog>
{
public:
DECLARE_WND_CLASS(_T("TTTDlg"))
enum { IDD = IDD_TTT_DIALOG };
BEGIN_MSG_MAP_EX(MusicPlayerDialog)
MSG_WM_INITDIALOG(OnInitDialog);
MSG_WM_CLOSE(OnClose);
MSG_WM_DESTROY(OnDestroy);
END_MSG_MAP()
TTTMainDialog();
~TTTMainDialog();
private:
const BOOL OnInitDialog(const CWindow wndFocus, const LPARAM lInitParam);
void OnClose();
void OnDestroy();
};
As you can see, I added the window class declaration, I inherited CWindowImpl, I registered the dialog. I don't think I forgot something here.
In the class which is supposed to create the dialog, I tried to create it like this:
TTTMainDialog myDialog;
HWND handle = myDialog.Create(NULL);
myDialog.ShowWindow(nCmdShow);
However, the Create method does return NULL all the time. I checked the error code with GetLastError(), and it turns out i am getting error code 1406, or "ERROR_TLW_WITH_WSCHILD".
The msdn documentation says the following about this error:
"Cannot create a top-level child window."
I tried to google up on this, but there is not much to find.
If I had to take a guess I would say the problem is caused by some window class name details, but i'm really not sure.
Any advice?
You are trying to build a window class from wrong pieces.
The error is pretty descriptive: you are trying to create a parentless window with a WS_CHILD style and this does not work out.
You get the child style from default template parameter: CWindowImpl -> CWindowImplBaseT -> TWinTraits -> CControlWinTraits. CControlWinTraits is supposed for use with child control windows.
If you are going to use a dialog template (IDD_TTT_DIALOG) then the proper base class is CDialogImpl, which is already prepared to use proper window styles. Also, it has what it takes to create both modal and modeless dialogs. The latter act more like windows and are non-blocking but in the same time take dialog template resource with predefined controls.
Small example for CDialogImpl use
Or, another one

Embedded dialog in Tab Control cannot work in second dialog, MFC

I have following code which works in the main dialog, but cannot work in the second (or third) dialog. The thing is that I want each page of the tab control can show a embedded dialog, it's similar to property page.
First I create two dialog, IDD_DIALOG1 and IDD_DIALOG2.Then I change the style of them to child and border to None. After that I add CDialog class to each of them.
In my MainDialog.h, I have the following code:
#include "Dialog1.h"
#include "Dialog2.h"
...
public:
CDialog1 m_para1;
CDialog2 m_para2;
CTabCtrl m_TabCtrl;
In my MainDialog.cpp, I use the following code to embed the dialo in the OnInitDialog:
m_TabCtrl.InsertItem(0, _T("TAB1"));
m_TabCtrl.InsertItem(1, _T("TAB2"));
m_para1.Create(IDD_DIALOG1,GetDlgItem(IDD_MAINDIALOG));
m_para2.Create(IDD_DIALOG2,GetDlgItem(IDD_MAINDIALOG));
CRect rs;
m_TabCtrl.GetClientRect(&rs);
rs.top+=37;
rs.bottom+=8;
rs.left+=13;
rs.right+=7;
m_para1.MoveWindow(&rs);
m_para2.MoveWindow(&rs);
m_para1.ShowWindow(TRUE);
m_para2.ShowWindow(FALSE);
m_TabCtrl.SetCurSel(1);
By using this way, It can work in this case. But if I want to use this method in my SecondDialog, the non-main dialog, it cannot work. Can someone help me out? Thanks in advance.
When you create a modeless dialog box, try this:
m_para1.Create(IDD_DIALOG1,&m_TabCtrl);
m_para2.Create(IDD_DIALOG2,&m_TabCtrl);
The second parameter of the Create function is a point to the parent window object (of type CWnd) to which the dialog object belongs. The return type of the GetDlgItem function is HWND.
See following:
http://msdn.microsoft.com/en-us/library/tc46f3be.aspx
http://msdn.microsoft.com/en-us/library/kc6x1ya0.aspx

Sharing variable among class instances

class MyApp : public CWinApp {
afx_msg OnPrefrences();
};
OnPrefrences() get called when user selects tools->Preference from the menubar.
Now in one dialog(Say DlgX) there is one button, on clicking this I need to open the Preference dialog which has in fact many panes, but here I need to open the Preference dialog by selecting one the these pane as active. Also in that particular pane I need to hide some of the controls only when It gets open through this the dialog not through menu.
So I have created one variable(Say m_varX) in MainFrm class.
void DlgX::OnButtonXClick()
{
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
if(pFrame)
{
pFrame->m_varX = TRUE;
((CMyApp*)(AfxGetApp()))->OnPrefrences();
pFrame->m_varX = FALSE;
}
}
And in button handler of DlgX I have made this m_varX TRUE and call the OnPreference() and after closing of this preference dialog I have made m_varX FALSE.
All this is working fine... But the problem is that things gets clutter in mainFrm. Also the project I am working on is legacy one so I cant make much changes.
Is there any patter available for handling such case?
Thanks
You could solve this with a custom dialog (if you don't have it already)
When you show the dialog from the main menu i.e. onPreferences() you fill and show all 'panes'. you would have to do a custom dialog where the ctor takes some arguments.
E.g.
enum { all, part };
void MainFrame::OnPreferences()
{
CMyPreferences dlg( GetDocument(), all );
dlg.DoModal();
}
but when you call it from within a dialog you only fill in the parts you need.
void YourDialog::OnPreferences()
{
CMyPreferences dlg( GetDocument(), part );
dlg.doModal();
}
The argument could be something more sophisticated for more fine tuned configuration of what to show/allow to edit.
I think for that special case, even if sometimes is no more considered a pattern, the singleton pattern would work for you.

Handle CSliderCtl messages placed on a CDialogBar

VS2008, 32 Bit Win XP
In a class derived from CFrameWnd, I have an object of CDialogBar
that needs to have certain controls on it. Among these controls would
be 2 sliders, whose event handling is to be done in CFrameWnd derived
class. How shall I go about this?
class CFrameWndCustom : public CFrameWnd
{
CDialogBar m_wndDialogBar; // the CDialogBar object.
}
In CFrameWnd derived class's OnCreateClient, I have created the
DialogBar using the above object like:
//Create the DialogBar
if (!m_wndDialogBar.Create(this,
IDD_DIALOGBAR_CONTROL,
CBRS_BOTTOM,
IDD_DIALOGBAR_CONTROL))
{
TRACE("Warning: Couldn't create DialogBar Control!\n");
return FALSE;
}
Here, IDD_DIALOGBAR_CONTROL is a dialog resource with Style as Child.
After this, I drag-dropped a CSliderCtrl on the IDD_DIALOGBAR_CONTROL
in Resource View.
Now, how/where should I handle the CSliderCtrl's events? There would
be 2 such slider controls.
I finally need the values of the sliders in CFrameWndCustom class.
best regards,
Divya
Derive your own CDialogBar class. Then handle all the messages in that. You won't even need to make it do anything but handle the message you want. The rest will get passed up the hierarchy.
Failing that you create your custom CDialogBar class and define your own OnWndMsg function and pass all WM_COMMAND or WM_NOTIFY messages on to the parent window.

Disable/Enable Ribbon Buttons for MFC Feature Pack

I am using the MFC Feature Pack and I have some buttons on a ribbon bar, instances of CMFCRibbonButton. The problem is that I would like to enable and disable some of them in certain conditions, but at runtime. How can I do this? because there is no specific method for this...I heard that a solution would be to attach/detach the event handlers at runtime, but I do not know how...
When you create the CMFCRibbonButton object you have to specify the associated command ID (see the documentation for the CMFCRibbonButton constructor here). Enabling and disabling of ribbon buttons is then done using the usual command update mechanism in MFC, using the CCmdUI class.
For example, if you have a ribbon button whose command ID is ID_MYCOMMAND and you want to handle this command in your application's view class, you should add these functions to the class:
// MyView.h
class CMyView : public CView {
// ...
private:
afx_msg void OnMyCommand();
afx_msg void OnUpdateMyCommand(CCmdUI* pCmdUI);
DECLARE_MESSAGE_MAP()
};
and implement them in the .cpp file:
// MyView.cpp
void CMyView::OnMyCommand() {
// add command handler code.
}
void CMyView::OnUpdateMyCommand(CCmdUI* pCmdUI) {
BOOL enable = ...; // set flag to enable or disable the command.
pCmdUI->Enable(enable);
}
You should also add ON_COMMAND and ON_UPDATE_COMMAND_UI entries to the message map for the CMyView class:
// MyView.cpp
BEGIN_MESSAGE_MAP(CMyView, CView)
ON_COMMAND(ID_MYCOMMAND, &CMyView::OnMyCommand)
ON_UPDATE_COMMAND_UI(ID_MYCOMMAND, &CMyView::OnUpdateMyCommand)
END_MESSAGE_MAP()
For more information on message maps in MFC, refer to TN006: Message Maps in MSDN.
I hope this helps!
ChrisN gave a pretty perfect answer. You can see an example of exactly how this is done by downloading the VS2008 Sample Pack from here, and opening the MSOffice2007Demo solution.
When running the sample, look at the "Thumbnails" checkbox in the View tab of the ribbon, it's disabled.
This is controlled by CMSOffice2007DemoView::OnUpdateViewThumb which calls pCmdUI->Enable(FALSE);. You can change this to call TRUE or FALSE at runtime to enable/disable the button respectively.