I have a Dialog-based MFC app, and it has two Dialog Boxes:
IDD_FITNESSAPP_LOGIN_DLG
IDD_FITNESSAPP_MAIN_DLG
On IDD_FITNESSAPP_LOGIN_DLG, I have a button, btnLogin, that runs through some credentials (working so far, and reports failures too).
How do I make it so that when I click btnLogin on IDD_FITNESSAPP_LOGIN_DLG, it leads to IDD_FITNESSAPP_MAIN_DLG?
I read a little on Dlg.DoModal() but I don't understand that if its needed.
Here's the code for the "on button clicked btnLogin":
void CFitnessAppMFC2Dlg::OnBnClickedbtnlogin()
{
// TODO: Add your control notification handler code here
UpdateData();
char UsernameFromFile[20], PasswordFromFile[20];
FILE* fleCredentials;
bool ValidLogin = false;
if (m_Username == "")
{
AfxMessageBox(_T("You must provide a username and a password or click Cancel"));
return;
}
if (m_Password == "")
{
AfxMessageBox(_T("Invalid Login"));
return;
}
try {
// Open the file for reading
fleCredentials = fopen("credentials.txt", "r");
// Scan the file from beginning to end
while (!feof(fleCredentials))
{
// Read a username
fscanf(fleCredentials, "%s", UsernameFromFile);
// Compare the typed username with the username from the file
CT2A ascii(m_Username);
if (strcmp(ascii, UsernameFromFile) == 0)
{
// With the current username, retrieve the corresponding password
fscanf(fleCredentials, "%s", PasswordFromFile);
// Compare the typed password with the one on file
CT2A ascii2(m_Password);
if (strcmp(ascii2, PasswordFromFile) == 0)
{
ValidLogin = true;
}
else
ValidLogin = false;
}
}
if (ValidLogin == true)
OnOK();
else
{
AfxMessageBox(_T("Invalid Credentials. Please try again"));
this->m_EditUsername.SetFocus();
}
fclose(fleCredentials);
}
catch (...)
{
AfxMessageBox(_T("Could not validate the credentials"));
}
UpdateData(FALSE);
}
1.Resourse View-> Dialog->Right click->Add Resource->Dlg, Then add class for the new Dlg.
2.There are two types of Dlgs.
Modal Dialogue Box
When the user wants to operate on applications other than the dialog box, the dialog box must first be responded to.
#include "CXXXDlg.h "
void CXXXDlg::OnBnClickedOk()
{
CMyNewDlg Dlg;
Dlg.DoModal();
}
Modeless Dialogue Box
When the user opens a non-modal dialog box, other windows can still be operated.
#include "CXXXDlg.h"
void CXXXDlg::OnBnClickedOk()
{
CMyNewDlg *pDlg=new CMyNewDlg ;
pDlg->Create(IDD_DIALOG2,this);
pDlg->ShowWindow(SW_SHOW);
}
Related
I am working in a Program in QT where I have a LOGIN Dialog, if the person is logged successfully then the program shows a MainWindow object. There's a Menu Bar in that object. One of the options of the Menu Bar is LOGOUT, then what can I do to make the MainWindow object close or hide and the LOGIN Dialog show again?
Here's what I tried:
In the main.cpp
Dialog login;
if (login.exec() == QDialog::Rejected)
{
return -1;
}
MainWindow mainWindow;
mainWindow.show();
In the LOGOUT function from the Menu Bar:
void MainWindow::on_actionLogOut_triggered()
{
close();
//What else can I do here to make the LOGIN Dialog appear again?
}
I also tried to create a new LOGIN object in the on_actionLogOut_triggered() method but it goes out of the scope and the new Dialog object disappear immediately.
Here you would need a finite state machine...
Depending on which state your application is in and which functions are called will determine the behavior of the overall system. You will want to have your own functions to show a login window, to show the main window, to log in, to log out, etc... then you need to build your structure with the appropriate logic.
Pseudo Example:
enum class AppState {
LOGGED_IN,
LOGGED_OUT,
};
class Application {
AppState state_;
public:
Application() : state_{AppState::LOGGED_OUT} {
run();
}
~Application() {
exitApp();
}
void exitApp() {
// clean up resources
closeMainWindow(true);
}
void run() {
do {
presentLoginScreen();
} while(state_ != AppState::LOGGED_IN);
if (state_ == AppState::LOGGED_IN) {
while (state_ != AppState::LOGGED_OUT)
// do stuff
}
}
void logIn(/*user input*/) {
// test input
}
void logOut() {
if(state_ == AppState::LOGGED_IN) {
closeMainWindow();
state_ = AppState::LOGGED_OUT;
presentLogginScreen();
}
}
void presentLogginScreen() {
// display the login screen
// get user input
logIn(/*user input*/);
// if user input matches credentials sign them in and show the main window
if( credentials == valid_credentials ) {
showMainWindow();
state_ = AppState::LOGGED_IN;
}
}
void closeMainWindow(bool exitApp) {
if(exitApp) // cleanup memory and shutdown
else // otherwise just close window and present login screen
}
};
I have QMessageBox as member to a widget class
If the messagebox is kept open and through program if we close widget messagebox is not getting closed. I did setParent also for message box
// Code local to a function
reply = m_warningMsg.question(this,"Warning","Do you really want to close the connection",QMessageBox::Yes | QMessageBox::No);
if(reply == QMessageBox::No)
{
return;
}
//Function to close the widget
void Window::closeConnection()
{
m_warningMsg.setParent(this);
m_warningMsg.setVisible(true);
// Code inside if executed but not hiding messagebox
if(m_warningMsg.isVisible())
{
m_warningMsg.close();
m_warningMsg.hide();
}
close();
}
QMessageBox::question() is a static method so m_warningMsg is not the QMessageBox that is displayed, as you have passed as a parameter to this as a parent then we can find that QMessageBox (note that it is not necessary to use m_warningMsg) using findchild():
QMessageBox::StandardButton reply = QMessageBox::question(this,"Warning","Do you really want to close the connection",QMessageBox::Yes | QMessageBox::No);
if(reply == QMessageBox::No)
{
return;
}
void Window::closeConnection()
{
QMessageBox *mbox = findChild<QMessageBox*>();
if(mbox)
mbox->close();
close();
}
Sorry for the newbie question, but can anyone point me at sample code that illustrates the use of the CMFCMenuButton? The Microsoft help refers to "New Controls samples", but these samples seem to be in the Visual Studio 2008 "Feature Pack", and this refuses to install on my system since I'm running VS 2013 and don't have VS 2008. I haven't been able to find the samples as stand-alone code.
To be specific, I have a dialog bar in which I want a button labelled Save with drop-down options of Save All and Save Visible (with Save All the default). But any working code would at least get me started.
Declare data members:
CMFCMenuButton m_button_menu;
CMenu m_menu;
Also add the button's id to message map and data exchange:
BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx)
ON_BN_CLICKED(IDC_MFCMENUBUTTON1, OnButtonMenu)
...
END_MESSAGE_MAP
void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_MFCMENUBUTTON1, m_button_menu);
}
Define:
BOOL CMyDialog::OnInitDialog()
{
CDialogEx::OnInitDialog();
//...
m_menu.LoadMenu(IDR_MENU1);
m_button_menu.m_hMenu = m_menu.GetSubMenu(0)->GetSafeHmenu();
return TRUE;
}
Where IDR_MENU1 is a regular menu bar and we get its first submenu. For example:
IDR_MENU1 MENU
BEGIN
POPUP "Dummy"
BEGIN
MENUITEM "&Item1", ID_FILE_ITEM1
MENUITEM "&Item2", ID_FILE_ITEM2
END
END
If button's drop-down arrow is clicked, a popup menu appears, menu result is passed to OnButtonMenu. If left side of button is clicked, then OnButtonMenu is called directly, without showing a popup menu.
void CMyDialog::OnButtonMenu()
{
CString str;
switch (m_button_menu.m_nMenuResult)
{
case ID_FILE_ITEM1:
str = L"first menu item clicked";
break;
case ID_FILE_ITEM2:
str = L"second menu item clicked";
break;
default:
str = L"Button click (popup menu did not appear, or menu ID is not handled)";
break;
}
MessageBox(str);
}
** When working with docking controls, dialog bars, etc. MFC may run its own subclass, I don't think DoDataExchange gets called. m_button_menu could be invalid. GetDlgItem can be used to find the correct pointer:
CMFCMenuButton* CMyDlgBar::GetButtonMenu()
{
CMFCMenuButton* pButton = &m_button_menu;
if (!IsWindow(pButton->m_hWnd))
pButton = (CMFCMenuButton*)GetDlgItem(IDC_MFCMENUBUTTON1);
return pButton;
}
Everywhere else we use GetButtonMenu() instead of m_button_menu. For example:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
//...
m_dlgbar.Create(...);
m_dlgbar.m_menu.LoadMenu(IDR_MENU1);
m_dlgbar.GetButtonMenu()->m_hMenu = m_dlgbar.m_menu.GetSubMenu(0)->GetSafeHmenu();
return 0;
}
void CMainFrame::OnButtonMenu()
{
CString str;
switch (GetButtonMenu()->m_nMenuResult)
...
}
What if the Drop-Down Arrow does not show?
Then read the answer here that explains the changes needed to your RC file.
I have QtInputDialog and I dont like it that, when i press enter it closes.
I would like to type value and confirm it by pressing enter on keyboard. After that line edit resets and i can type another value.
Dialog initialization:
void MainWindow::on_button1_clicked() {
dialog = new QInputDialog();
dialog->installEventFilter(this);
dialog->show();
}
Event filter:
bool MainWindow::eventFilter(QObject *o, QEvent *e) {
if (e->type() == QEvent::KeyPress) {
if (static_cast<QKeyEvent*>(e)->matches(QKeySequence::InsertParagraphSeparator)) {
qDebug() << dialog->textValue(); //use this value as you wish
dialog->setTextValue(QString());
return true; //block this event
}
}
return false;
}
Note that the dialog still can be closed using mouse click on "OK".
I'm in trouble. I have a QDialog as a login form. When I log in, the form closes and my mainwindow will appear. My login is fine but when it closes it returns QDialog::Rejected.
What can I do to prevent the return of QDialog::Rejected? And when will it even return QDialog::Rejected?
Code when I log in :
void Login::on_cmdLogin_clicked()
{
if( ui->txtUsernameLogin->text().isEmpty() || ui->txtPassLogin->text().isEmpty() )
{
QMessageBox::critical(this, "Vocabulary Trainer", "Please fill in both textboxes.", QMessageBox::Ok);
return;
}
User user(filepath + "/users.txt");
if ( user.checkPassword( ui->txtUsernameLogin->text(), ui->txtPassLogin->text() ))
{
username = ui->txtUsernameLogin->text();
close();
}
else
QMessageBox::warning(this, "Vocabulary Trainer", "Sorry, your password is incorrect.\nPlease type in the correct password.", QMessageBox::Ok);
}
main() :
MainWindow w; //Real Window
Login lg(0); //Login Window
lg.set_path(workspace_path);
lg.setModal(true);
if(lg.exec() == QDialog::Rejected)
QMessageBox::critical(0, "rr", "", QMessageBox::Ok);
else
w.show(); //Shows the real window
It'll always rejected.
Try to call done(QDialog::Accepted); instead close(); in Login::on_cmdLogin_clicked()