MFC interface with tabControl - mfc

I have a window with different control and a TabControl which contains some TabPage. Each TabPage is associated with a class. The code for this class must be able to act on controls of the main window.
I tried in a TabPage class to create a pointer to the main window and the associated set method but I can not create element type of the main window.
How should I do?
class CMedialexieDlg : public CDialogEx
{
public:
CTabCtrl m_TabControl; /*!< TabControl de la fenetre */
TabPage1 tabPage1; /*!< Onglet des contacts */
TabPage2 tabPage2; /*!< Onglet des groupes */
TabPage3 tabPage3; /*!< Onglet des ventes */
CTreeCtrl m_TreeControlContact; /*!< TreeControl regroupant les differents contacts */
CTreeCtrl m_TreeControlGroupe; /*!< TreeControl regroupant les differents groupes et contacts */
...
}
and in the class TabPage1
void TabPage1::OnClickedTbp1ButtonAnuler() {
m_TreeControlGroupe.EnableWindows(false); }

First of all, you really should show some code demonstrating what you tried to do, instead of (poorly) describing it to us and leaving us guessing.
With that said, why can't you use AfxGetMainWnd() to get a pointer to your main window?
One thing to note: you should be careful as directly manipulating other windows can cause subtle problems/bugs that are difficult to track down; it can also can cause headaches if you later try to make your application multi-threaded. You should prefer exchanging messages.

Related

Resource ID's < 32768 do not Command Routing

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?

QtT How To Save Data/State When Changing Central Widgets In QMainWindow

I have inherited the QmainWindow class to use as the mainwindow for the application that I am building.
I have set the central widget as a pointer to another class, that I have created.
//main window constructor
postEntryWidget = 0; // null pointer to another class that extends QWidget
dataEntryWidget = new Data_Entry_Widget; //extends QWidget
setCentralWidget(dataEntryWidget); //set the widget in the main window
When the user clicks on an action, this sets the central widget to another pointer to another widget class.
/*
*this is the implementation of the slot that would be connected to the QAction
*connected to the postEntryWidget slot
*/
if(!postEntryWidget)
postEntryWidget = new Post_Entry_Widget;
setCentralWidget(postEntryWidget);
/*
*this is the implementation of the slot that would be connected to the QAction
*connected to the dataEntryWidget slot
*/
if(!dataEntryWidget)
dataEntryWidget = new Post_Entry_Widget;
setCentralWidget(dataEntryWidget);
This breaks when switching back and forth between views. And If I add a null point to the preceding view I lose the data when I go back to that view.
/*
*this is the implementation of the slot that would be connected to the QAction
*connected to the postEntryWidget slot
*/
dataEntryWidget = 0; //set the previous widget to a null pointer but loses data
if(!postEntryWidget)
postEntryWidget = new Post_Entry_Widget;
setCentralWidget(postEntryWidget);
How would I keep the state between the two views without creating a custom data structure or is this bad practice. I am most familiar with php and web dev so I am not sure if this is even the best way to go about this.
Thanks in advance
Not totally sure what your goal is. But if you are trying to permit someone the ability to go back to something they were working on, then perhaps you'd be better off using a tab widget instead of hiding the existence of that work?
QTabWidget documentation
Qt Tabbed Dialog example
So you'd make that your central widget, and plug the Post_Entry_Widget and Data_Entry_Widget instances under that. An advantage of that is that Qt manages the tab switching for you.
If you don't want tabs there is also a QStackedWidget, which just lets you programmatically switch between a set of widgets.
It is more complicated than it seems. The problem is, that when setCentralWidget() is called, current centralWidget() gets deleted. In order to preserve its contents, you need to remove it from the window by reparenting it to NULL or 0. Try to change your code to:
if(!postEntryWidget)
postEntryWidget = new Post_Entry_Widget;
if (centralWidget()) centralWidget()->setParent(0); //reparent if exists
setCentralWidget(postEntryWidget);
/*
...
*/
if(!dataEntryWidget)
dataEntryWidget = new Post_Entry_Widget;
if (centralWidget()) centralWidget()->setParent(0); //reparent if exists
setCentralWidget(dataEntryWidget);

Seeking a replacement for DDX

The DDX technology was created for linking resources with class members (for example). In my solution I need to make the connection between myCCtreeCtrl (instant of CCtreeCtrl) does not living in resources with class member CCtreeCtrl.
Now I have CTreeCtrl in resouces and silmple doDataExchange:
#define IDC_TREE_LAYER0 2000
#define IDC_TREE_LAYER1 2001
#define IDC_TREE_LAYER2 2002
// ============================================================================
void ForcesGUI::doDataExchange( int id0, int id1, int id2, CDataExchange* pDX )
// ============================================================================
{
DDX_Control(pDX, id0, m_tree[0].data);
DDX_Control(pDX, id1, m_tree[1].data);
DDX_Control(pDX, id2, m_tree[2].data);
}
but in future it will be necessary to delete CCtreeCtrl from resources and make instance.
You'll ask me why do you need deleting from resources?
The answer is: In project I have 3 CCtreeCtrls each of them live on his own bar. There is no different betwen them. That is why I want to use 1 bar class with 1 tree on it instead of redundancy. After I'll create 3 instance of bar and here appears problem with DDX wich does not work here.
Have you any ideas how can I replace basic DDX? May be it will be WinAPI or something else. In any case thanks for help.
If the control isn't generated automatically from a dialog resource, you'll have to create it with the Create method. You'll want to do this in OnInitDialog or whatever equivalent is in your parent window. By creating the window with Create it will automatically be connected to the object you created it from - no need for DDX_Control.

Share Data Between One Member Variable and Several Controls w/DoDataExchange /Force Update Controls on All Windows

I have a VS 2005 C++ MFC project that contains several CDialog based windows. The program communicates with a custom piece of hardware and displays different readings on the different windows. The data is read from the hardware using a public static member function named ReadHardWare() of a class named CTools. ReadHardWare() places the data read from the hardware in an array with global scope and each window has the ability to read from this array. On each window I have an indicator that lights up showing that a read from hardware operation is in progress. This indicator is a National Instruments
Measurement Studio CNiButton class control. CTools has a public static member variable of the CNiButton type named m_read_in_progress_status that I use to identify if a read operation is in progress (m_read_in_progress_status.Value == 1) or not (m_read_in_progress_status.Value == 0). My goal is to have all the read indicators on all the opened windows show a read is in or not in progress at the same time. I regularly use DoDataExchange to connect variables with controls but always on a one-to-one basis. In this case I want several controls to connect with a single variable and to automatically update with that variable.
I seem to have two problems:
1) It seems that I am only able to have one control connect with the variable at the same time. Apparently the only control that the variable shares data with is the first one instantiated (i.e. first window opened)
2) If I send a read command from the second window opened, not only does the read indicator on the second window still not show the read status but neither does the read indicator on the first anymore. The only time any of the read indicators work is when I perform a read command from the first window opened. The first window does not seem to want to update its controls when the second window is sending the read command.
So my questions are:
1) How can I allow two controls on two different windows to share the same member variable and update immediately when that member variable's value is changed?
2) How can I make the ReadHardWare() member function (or some other event) force the first window to update its controls even though it is not the window actively calling that function?
In the current case the first window is the parent of the second. However this will not always be the case.
Below is an excerpt of my code.
//Globalvariables.cpp
NI::CNiButton CTools::m_read_in_progress_status;
//Tools.h
class CTools
{
public:
static ReadHardWare();
public:
static NI::CNiButton m_read_in_progress_status;
}
//Tools.cpp
CTools::ReadHardWare()
{
//Declare and initialize variables and other setup code is here
m_read_in_progress_status.Value == 1 //Set read in progress flag high
//Read operations here
m_read_in_progress_status.Value == 0 //Reset read in progress flag low
}
//FirstWindow.cpp
#include "Tools.h"
#include "SecondWindow.h"
void CFirstWindow::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_First_Window_Read_in_Progress_Indicator, CTools::m_read_in_progress_status);
}
//SecondWindow.cpp
#include "Tools.h"
#include "FirstWindow.h"
void CSecondWindow::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_Second_Window_Read_in_Progress_Indicator, CTools::m_read_in_progress_status);
}
DDX_Control establishes an association between control identifier in dialog and particular instance of CWnd based object. I am not sure it's a good idea is to share the same object representing a button for two windows. I suggest to sligthly modify the design. You should create a timer for pooling read operation state. If state is changed you will update the button.
class CTools
{
public:
static void ReadHardWare();
public:
static int m_read_in_progress_status;
}
class CFirstWindow: CDialog
{
public:
void OnTimer(UINT nIDEvent)
{
if(m_read_in_progress_status != CTools::m_read_in_progress_status)
{
m_read_in_progress_status = CTools::m_read_in_progress_status;
m_button.SetCheck(m_read_in_progress_status);
}
}
private:
int m_read_in_progress_status; // Cached status
NI::CNiButton m_button;
};

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.