What is the entry point of this basic MFC Dialogue Box Application? - c++

Starting out with GUI programming with C++. So, following some tutorials, I 'wrote' the following code to display a dialogue box. To be honest, the Visual Studio 2015 Wizard did most of the job, but here is the code file. It correctly displays the dialogue box pointed by the identifier, but I really cannot figure out how it works. To begin with, what is the entry point, of the code? There is not even a function, so what exactly executes when I build and run it?
#include<afxwin.h>
#include"resource.h"
class CExampleDlg :public CDialog
{
public:
CExampleDlg():CDialog(IDD_EXAMPLE_DLG){}
~CExampleDlg(){}
};
class CExample:public CWinApp
{public:
BOOL InitInstance()
{
CExampleDlg myDlg;
m_pMainWnd = &myDlg;
myDlg.DoModal();
return TRUE;
}
};
CExample MyApp;

Unlike normal c/c++ application where the entry point is main and you have full control over the flow of execution. MFC applications are event driven. The code you write is executed based on the events that occur due to user interaction with the application like, clicking on the button, entering text in the text box etc. When there is no interaction the application sits idle.
1) The best place to is OnInitDialog to place your initialization code. You can initialize all the member variables in OnInitDialog. (Remember winMain is the entry point for windows application. But in MFC this is embedded deep down in the boilerplate code.)
2) Add message handlers to handle the user actions to execute your core logic later. For e.g.: If you have a button on the dialog then you need to add the message handler function for the button which will get invoked when the user clicks on that button. This can be done easily using the class wizard (https://msdn.microsoft.com/en-us/library/ee748520.aspx).

Related

MFC dialog-based app with tab control - Visual Studio bugs/restrictions make recommended path impossible?

Create a dialog-based application in Visual Studio 2019. Insert a new dialog in the resources. Place a control (or two) on that dialog that you will later (try to) hook up to a variable (e.g. an edit box to enter your name).
Prepare to add that control variable by creating a class for this second dialog. If you inherit from CDialogEx (or perhaps other classes too - not tested), you can go on to add a variable for the control you added - easy, normal.
But if you had the "tab control" context from the title above in your mind, and chose to inherit from CMFCPropertyPage instead, can you add a variable subsequently? No you cannot - the class added makes no reference to the ID of the dialog resource, and so the Add Variable process has no basis to find a class to add the variable to.
I think this is a bug in Visual Studio... but I'm not 100% sure because I have always found the documentation around property sheets and property pages somewhat confusing. Specifically:
Do the classes implementing the tabs contents on a tab control "contain" the controls "on" the tab... or is the tab control really just a way to provide visual cues to show/hide sets of controls, and all of those controls and associated variables reside in one class?
I believe it's intended to be the former, but I can imagine that one uses a tab control because there are strong similarities between tab contents, and therefore potential benefits in implementing all the control variables in one place so as to avoid duplication. I just wish it was stated explicitly somewhere what the intention was.
Wider context: I'm trying to implement a dialog-based app with a tab control dominating that dialog. MS documentation says to implement a tab control using CPropertySheet and CPropertyPage to implement the tabbed dialog and tab contents. However, there is no (direct) way to create a dialog-based application whose main dialog inherits from CPropertySheet. When you look for examples of tab controls at the application level, you readily find things that deviate from the documented path considerably - using neither CPropertySheet nor CPropertyPage and using the WM_LBUTTONDOWN event instead of TCN_SELCHANGE, both without obvious reasons.
Any tips on (a) how to repair the apparent Visual Studio bug and/or (b) how to inherit from CPropertySheet for my application dialog and/or (c) where to find a clearer and more conventional example of tab control use at the top level would be greatly appreciated.
Given that there appears to be no clear and consistent way of approaching this, if (like me) you think "how hard can it be?", you might naively set out to see if you can create a new dialog-based application based on CDialog and manually convert it to CPropertyPage. You might fare better; I quickly hit a weird problem with the app compiling but not running - it could not load the window caption from the resource ID, despite the caption literally being there in black and white. Due to the weirdness, this was a red flag, and so to my mind problem (b) seems to be not worth the effort.
Without a CPropertySheet at the top level, there is no point having any kind of CPropertyPage or CMFCPropertyPage involved, making problem (a) pointless. That said, if you manually convert from (default) CDialogEx to CPropertyPage for your tab classes, it seems to have no problem compiling and running - the tabs just don't have any functionality that integrates with the main dialog.
Instead, I can now recommend working through the details of the video example even though it does strange things at first glance. You can achieve the desired result in more or less the same way as follows:
Use plain CDialogEx throughout, and so provide all the tab switching/showing/hiding/control work yourself (which the example demonstrates).
Create your main dialog and all tabs in the resource editor, adding the CDialog-based classes from there.
If you create your tab dialog resources via Insert Dialog (generic) instead of Add Resource (uses specific templates) then you will have to manually set certain dialog properties for each tab:
Border: Thin (or I preferred None)
Style: Child
System Menu: false
Title Bar: false
You can simplify the repositioning of the tabs (see below; it barely justifies the separate SetRectangle() function)
You should (probably) drive the tab changing from the TCN_SELCHANGE event instead of WM_LBUTTONDOWN
As noted, repositioning the tabs can be simplified to something like:
CRect tabRect;
m_tabControl.GetWindowRect( &tabRect );
for ( int i = 0; i < m_totalTabs; i++ )
{
m_pTabPage[ i ]->SetWindowPos( &wndTop, tabRect.left, tabRect.top, 0, 0,
i == m_currentTab? SWP_NOSIZE|SWP_SHOWWINDOW : SWP_NOSIZE|SWP_HIDEWINDOW );
}
Additional calls to ShowWindow() for each tab shown in the example are redundant.
One time, I had made on application as such. I don't remember if I used the Visual Studio new project wizard. Most probably, I did. But I will assist you on how to do it if you can not reach how to do it via the assistant.
The essential things:
Define the main dialog in the resources and the respective class in its H and CPP files.
In the YourAppClass::InitInstance you will need to have something like:
YourMainDlgClass dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
else if (nResponse == -1)
{
TRACE(traceAppMsg, 0, "Warning: dialog creation failed, so application is terminating unexpectedly.\n");
TRACE(traceAppMsg, 0, "Warning: if you are using MFC controls on the dialog, you cannot #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS.\n");
}
Insert a CMFCTabCtrl element in your dialog for tabs, instead of using a CPropertySheet.

Running Code during Dialog initialization, after GUI is drawn

I'm writing an application that communicates and initializes instruments (via COM ports) during the initialization phase of a Dialog (using MFC, on Windows 10).
The instrument initialization is presently taking between 4 seconds and 10 seconds. So the GUI won't appear until the initialization is finished.
I want to know how to perform the drawing of the GUI, then call the instrument initialization function.
Here's a code fragment:
BOOL MyDialog::OnInitDialog()
{
//...
// code to initialize dialog widgets
//...
Initialize_Intruments();
return false;
}
From the Microsoft Documentation of the CDialog::OnInitDialog method:
Remarks
Windows sends the WM_INITDIALOG message to the dialog box during the Create, CreateIndirect, or DoModal calls, which occur immediately before the dialog box is displayed. {emphasis mine}
I want to perform functionality, after the dialog box is displayed, during initialization of the dialog.
How to do this using C++, MFC, Visual Studio (2017) and Windows 10?
Notes:
The application is a single dialog that runs test procedures.
A splash screen is another technique under consideration.

how to disable message box "Fail to create Empty Document " Message box in MFC SDI application

I am using VS2010 for my MFC SDI application.
In MainFrame Class in OnCreate(LPCREATESTRUCT lpCreateStruct) function I am opening one dialog box and on IDCANCLE replay from the Dialog box I want to close my application.
I am using following code for the same in onCreate Function.
CTermsConditionDlg objTNCDlg;
if(!objTNCDlg.DoModal() == IDCANCLE){
return -1;
}
Now my Question is after return Statement the application is Showing message box as shown in Image.
I want to disable this message box and close my application.
Can any one help how can I do That.
Thank You in Advance.
Why do you place this dialog so late into you initialization?
The problem is the SDI framework that relay on some initial things that are expected to run always. In this case it is always expected that the mainframe can be created. See code in CSingleDocTemplate::OpenDocumentFile
Just place this code into InitInistance before LoadFrame or ProcessShellCommand is called. In this case you can easily terminate without disturbing problems.
Another Idea is to allow the creation of the window, but simply using a PostMessage(WM_CLOSE); In this case the initialization is done, everything is created and the application terminates again.

Adding accelerators(shortcuts) in MFC - HOW?

I found this link: http://support.microsoft.com/kb/222829
But I can't understand that much.
Ok, I understood I need to add this to my header file:
HACCEL m_hAccelTable;
and then this:
m_hAccelTable = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR1));
to my main .cpp
But where does this go?
BOOL CAboutDlg::PreTranslateMessage(MSG* pMsg) {
if (m_hAccelTable) {
if (::TranslateAccelerator(m_hWnd, m_hAccelTable, pMsg)) {
return(TRUE);
}
}
return CDialog::PreTranslateMessage(pMsg);
}
I need around 6 shortcuts (CTRL + U to load something, CTRL + O to load smth else), I can't understand how this works, need a little bit of help
Now, MSDN article is misleading. It shows how to add accelerators to About box and only About box will be able to handle accelerator that is in this case equivalent of pressing the button with IDC_BUTTON1 ID.
You need to do something very different allowing all objects in your application to get a chance to handle this message. This is done for you in MDI/SDI apps.
Once you create accelerator table in the resource, you have to add accelerators: Key combination paired Accelerator key combination, when used generates command message with appropriate ID. Once you are done adding, you have to create command message handlers for each of the ID.
When accelerator is used the handler is invoked and you can add the code you need.
Now do this:
Declare HACCEL type variable to your app class. In the InitInstance call LoadAccelerators.
Use wizard to insert PreTranslateMessage override in your application class. Add following:
if (m_hAccelTable)
{
if (::TranslateAccelerator(*m_pMainWnd, m_hAccelTable, pMsg))
{
return(TRUE);
}
}
This will allow the main dialog to handle accelerators. Note *m_pMainWnd. It is your dialog handle (automatically casted).
Now you can add handlers for any accelerator to the dialog or to the application class. You can also route command messages to any window in your application using OnCmdMsg.
My advice for the future.
When you decide to make your app a dialog based, consider creating SDI application with CFormView derived class.
You can change frame style to not allow resizing and it will look like dialog based but. . .
You will have ability to use a toolbar a menu for free and most importantly you will have all accelerator and command routing for free.
The page you referenced describes adding an accelerator table to a dialog based applicaion.
Are you creating a dialog based application or just a normal MFC frame based application with a menu bar?
If you are doing the former then as the page you referenced suggest you need to override the PreTranslateMessage dialog box method.
If you are doing the later then you only need to call the CFrameWnd::LoadAccelTable function.

How to create and add a custom made component to a Dialog based app (MFC)?

I want to make a custom made component (a line chart), that would be used in other applications.
I don't know 2 things:
Where should I use (within component class!) the methods for drawing, like FillRect
or PolyLine? In OnPaint handler that I should define and map it in MESSAGE MAP? Will
it (OnPaint handler) be called from OnPaint handler of the dialog of the application
or where from?
How to connect the component, once it is made, to the test application, which will
for example be dialog based? Where should I instantiate that component? From an
OnCreate method of the MyAppDialog.cpp?
I started coding in MFC few days ago and I'm so confused about it.
Thanks in advance,
Cheers.
Painting the control is handled exactly like it would be if it wasn't a control. Given that you're using MFC, that (at least normally) means you do the drawing in the View class' OnDraw (MFC normally handles OnPaint internally, so you rarely touch it).
Inserting the resulting ActiveX control in the host application will be done like inserting any other ActiveX control. Assuming you're doing your development in Visual Studio, you'll normally do that by opening the dialog, right clicking inside the dialog box, and clicking "Insert ActiveX Control..." in the menu that pops up. Pick your control from the list, and it'll generate a wrapper class for the control and code to create an object of that class as needed. From the viewpoint of the dialog code, it's just there, and you can use it about like any other control.
For create new component in MFC, you must create a class from the window class (CWND),
after that you can have your MessageMap for the component and your methods and also can override CWND::OnDraw method to draw the thing you want.
Before that I suggest you to take a look to device context
http://msdn.microsoft.com/en-us/library/azz5wt61(VS.80).aspx
Good Luck friend.