I am a new comer in MFC programming. I have already wrote a program, and I want to display the program in a graphical interface. So I use MFC dialog to realize it, but it does not work when runs.
Once the OK button is clicked :
void CTest1Dlg::OnBnClickedOk()
{
UpdateData();
FILE *stream;
freopen_s( &stream, "out_file.ps", "w", stdout ); // reopen stream as .ps
if (mode == 1) //main() in my code
{
ActiveAuthoring();
}
else if (mode == 0)
{
XYAuthoring();
}
else
{
ActiveAuthoring();
}
cout<<"showpage"<<endl;
UpdateData(FALSE);
OnOK();
}
My code is in converter.cpp, so first I change converter.cpp to converter.h and include it in Test1Dlg.cpp. And then when the OK button click run the main() in my code.
However, I discover that it seems the parameter does not transfer from the graphical interface to my code, although I relevant the edit control box to every parameter. So the dialog does not work. Could some one help me?
EDIT
The eight edit control boxes are the parameters I used in my coverter.cpp.
My code is aim to use eight parameters to generate some strings, these strings are saved in a file named as out_file which format is .ps.
There are two basic ways you get data from dialog controls to "your code"... if you're using the Visual Studio dialog editor and adding the controls there, it will generate code inside of virtual void DoDataExchange(CDataExchange* pDX) for you to move data to and from your controls when the dialog gets initialized and terminates. You'll have a line like DDX_Text(pDX, IDC_DIGITS, m_Digits); that the IDE adds that does the exchange. You can also just set and get the data directly if you wanted, e.g. GetDlgItem( IDC_DIGITS )->GetWindowText( m_Digits );
Related
I have an application (Manager) used to send commands to another application (Instructor) through sockets. From the first application I will have configure some data which is useful to invoke and run the second application. Same time im getting reports from the second application to first application.
Let me explain my question, I have the set of exercises which has to be run in second application. Either I can invoke it from First app or from the second app by invoking the exercise dialog. Once I invoked, I can get the report. For that I have one button in my first app.
Here whats happening,before the exercise dialog get invoked,when i press this button, it shows error.
So, I just want to know whether that dialog is opened or not.
I use GetSafeHwnd(), but once the object created for that dialog class, these handle get some value even the dialog is not open.
Here I pasted the code, once I get the button press 'GenXL' command from first app.
extern CPerfScore *oPerfScore;
void CMainFrame::ProcessPendingRead(void)
{
int nRead;
CString strBuf;
CString sCmd;
nRead = m_pCltSocket->Receive( &m_pRecPacket, sizeof(Packet));
if(nRead > 0)
{
// read the message
sCmd = m_pRecPacket.sMessage;
AfxMessageBox(sCmd);
if (sCmd.CompareNoCase("CLOSE") == 0)
{
OnClose();
}
if (sCmd.CompareNoCase("GENXL") == 0)
{
if(oPerfScore->GetSafeHwnd() == 0)
{
oPerfScore->SendMessage(WM_COMMAND, IDC_GENERATE_EXCEL);
}
else
{
AfxMessageBox("Exercise dialog not open");
}
}
}
}
A handle will be valid even if the window isn't currently being shown, as long as it has been created. I think you're looking for the API call IsWindowVisible(). I believe MFC wraps this as a member.
I'm working on an application for taking screenshots on Windows, OSX and Linux in C++/Qt. Now I need to set global hotkeys, so the user can take screenshots when the application is running in the background. I tried with Qxt and UGlobalHotkey, which are both Qt libraries, but neither of them seemed to work.
I tried to implement it for OSX with Carbon (tutorial), but I need to call a class member function, which just doesn't work. Could someone provide me with an example? You can find my code here. The function i need to call is new_screenshot().
Or is there any other way to achieve something like this? I really need my application to take a screenshot from the background, otherwise it's pretty useless (yes, I should probably have implemented it at the very beginning to see if it even works). Would it maybe be better to have a separate client for every platform (Cocoa Swift for OSX, GTK for Linux, C# client for Windows)? I have often thought about this the past few days.
Do I understand correctly that you want to call new_screenshot from the hot key event handler? If so, InstallApplicationEventHandler lets you pass a pointer to user data in 4th argument. Pass a pointer to your MainWindow instance (based on code from the tutorial):
MainWindow *mainWindow = ... // get main window somehow
InstallApplicationEventHandler(&MyHotKeyHandler,1,&eventType,mainWindow,NULL);
Then you can use it in the event handler.
OSStatus MyHotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEvent, void *userData)
{
//Do something once the key is pressed
static_cast<MainWindow*>(userData)->new_screenshot();
return noErr;
}
I did something in the past with MFC and WIN32 API....so it only works on Windows...but pressing ALT+F10 was able to hide/show a window...
void CWinHideDlg::OnButtonActive()
{
CString tmp;
GetDlgItemText(IDC_BUTTON_ACTIVE,tmp);
if(0 == strcmp(tmp.GetBuffer(tmp.GetLength()),"Activate"))
{
m_myAtom=GlobalAddAtom("MY_GLOBAL_HOT_HIDE_KEY");
int err=RegisterHotKey(this->GetSafeHwnd(),m_myAtom,MOD_ALT,VK_F10);
SetDlgItemText(IDC_BUTTON_ACTIVE,"Stop");
CButton *pBtn = (CButton *)GetDlgItem(IDC_BUTTON_UNHIDE);
pBtn->EnableWindow(TRUE);
SetDlgItemText(IDC_STATIC_INFO,"Set the mouse over the window \nand press ALT + F10 to hide it...");
}
else
{
UnregisterHotKey(this->GetSafeHwnd(),m_myAtom);
GlobalDeleteAtom(m_myAtom);
CButton *pBtn = (CButton *)GetDlgItem(IDC_BUTTON_UNHIDE);
pBtn->EnableWindow(FALSE);
SetDlgItemText(IDC_BUTTON_ACTIVE,"Activate");
}
}
Basically this code activates/deactivates the hot key ALT+F10, once it activates you can hide/unhide a running window on the system by setting the mouse pointer over the window and press ALT+F10...
This is from the WindowProc function:
if(message == WM_HOTKEY)
{
CString tmp;
POINT pc;
GetCursorPos(&pc);
if(GetAsyncKeyState(VK_F10))
{
HWND hwnd=::WindowFromPoint(pc);
if(hwnd)
{
tmp.Format("%08Xh",hwnd);
m_HideWins.InsertString(m_HideWins.GetCount(),tmp);
::ShowWindow(hwnd,SW_HIDE);
}
}
}
You can use the code to register your own HOT Key and use it to take a screenshot...
Hope it helps...
I have a Modeless dialog which shows a bunch of buttons; some of these are customized to draw stuff with GDI.
Now, when the user clicks on a customized one under certain conditions, a message box appears to alert user of the error and this is fine.
The problem is that after accepting the Message Box (showed as MB_ICON_ERROR), everywhere I click in the dialog, I always get the error message as if the whole dialog send the message to the customized button and the only way to get rid this is to press tab and give the focus to another control.
This is a strange behaviour and knowing why happens wouldn't be bad, but a simple workaround for now should do the job.
Since the moment that is probably a matter of focus, I've tried to set it on another control (in the owner dialog) by doing:GetDlgItem( IDC_BTN_ANOTHER_BUTTON )->SetFocus();
and then, inside the customized control by adding:KillFocus( NULL );but had no results.
How should I use these functions?
Thanks in advance.
PS: if I comment the AfxMessageBox, the control does not show this bizarre behaviour.
EDITI'll show some code as requested.
// This is where Message Box is popping out. It is effectively inside the dialog code.
void CProfiloSuolaDlg::ProcessLBtnDownGraphProfilo(PNT_2D &p2dPunto)
{
// m_lboxProfiles is a customized CListBox
if(m_lboxProfiles.GetCurSel() == 0)
{
// This profile cannot be modified.
/*
CString strMessage;
strMessage.Format( _T("Default Profile cannot be edited.") );
AfxMessageBox( strMessaggio, MB_ICONERROR );
*/
return;
}
// Selecting a node from sole perimeter.
SelectNodo(p2dPoint);
}
Actually, the message is commented to keep the dialog working.
// This is inside the customization of CButton
void CMyGraphicButton::OnLButtonDown(UINT nFlags, CPoint point)
{
PNT_2D p2dPunto;
CProfiloSuolaDlg* pDlg = (CProfiloSuolaDlg*)GetParent();
m_pVD->MapToViewport(point,p2dPunto);
switch(m_uType)
{
case GRF_SEZIONE:
pDlg->ProcessLBtnDownGraphProfilo(p2dPunto);
break;
case GRF_PERIMETRO:
pDlg->ProcessLBtnDownGraphPerimetro(p2dPunto);
break;
}
CButton::OnLButtonDown(nFlags, point);
}
Since you are handling the button down event in the button handler for the custom control, you don't need to call the base class. Just comment out CButton::OnLButtonDown(nFlags, point).
I've created a read-only edit box in an MFC dialog box. I'm trying to have it so a user clicks in the edit box, which is read-only, it opens a file dialog, and then puts this value into the text box using UpdateData. I'm catching the ON_EN_SETFOCUS message but pressing OK on the file dialog respawns it, so I get caught in an infinite loop.
UpdateData(TRUE);
CFileDialog fileDialog(TRUE,NULL, NULL,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST, _T("Text Files(*.txt)|*.txt||"));
if( fileDialog.DoModal() == IDOK )
{
configFile=fileDialog.GetPathName(); //Note to self, this includes filename, getPathName includes filename and path.
}
else
{
return;
}
UpdateData(FALSE);
If you've got any ideas on how this should be done, I would be very grateful.
Alright Mr. Lister I guess I'll add an answer.
First off I would preface this with I would probably simply add a button name "..." to launch the file dialog to the right of the edit box for opening the file dialog as that's the simplest solution and what most windows users will expect.
Another option however is to extend an MFC control. When deciding to extend a control you want to pick one that mostly has the desired behavior and that has a virtual destructor which lends itself to being a subclass. Since you want button like behavior CButton may be a good choice.
Your class interface might look something like this:
class CPathButton : public CButton
{
public:
enum { ID /*= IDC_BUTTON1*/ };
const CString GetPath() const;
const CString GetFileName() const;
const CString GetDirectory() const;
const CString GetExtension() const;
// other useful methods for setting file filters etc
protected:
// add ON_CONTROL(BN_CLICKED, ID, &OnClick) or ON_BN_CLICKED(ID, &OnClick)
DECLARE_MESSAGE_MAP()
// CFileDialog fdlg.DoModal(), m_path = fdlg.GetPathName(), SetWindowText(fdlg.GetFileTitle()), etc
afx_msg void OnClick();
// additional message handlers etc
private:
CString m_path; // save full path for after dialog is closed
};
You can add as much or as little customization as you want depending on if the control will be created dynamically, via the resource file, or whatever. The basic idea being that you display the currently selected file name on the button while storing the full path for other uses as a member so the user doesn't need to see the clutter of a long path with nested directories.
If you don't like the way it looks by default you can override OnPaint and handle WM_PAINT messages and use a custom font, size, or add ellipsis for a long file title. You could also handle re-sizing the button to fit the file title by using text metrics and GetTextExtent to ensure the name fits or simply display a CToolTipCtrl when they hover the mouse over the button so they can see the full name. The CMFCButton from the MFC feature pack in VS2008+ has tool tip functionality built in so if you inherit from that instead of CButton displaying a tool tip would be as simple as calling SetTooltip(m_path)
If you want to get really fancy you could use some of the uxtheme API or new windows animation API.
You can override PreTranslateMessage() in your dialog class, and determine if the edit control was clicked that way:
CEdit m_CEditCtrl;
// ...
BOOL YourDialogClass::PreTranslateMessage(MSG *pMsg)
{
if((pMsg->wParam == VK_LBUTTON) && (m_CEditCtrl.m_hWnd == pMsg->hwnd))
{
// open your file dialog
return TRUE; // Return that the message was translated and doesn't need to be dispatched
}
return CDialog::PreTranslateMessage(pMsg);
}
Update: You can also (and it may be a better idea) to override your CEdit control's CWnd::PreTranslateMessage() function. This would require deriving a class from CEdit.
If you are using VS2008 SP1 or above, the easiest way to ask for a path is with CMFCEditBrowseCtrl. It displays an edit control with a button. The steps to use it are:
Change your edit control's class to CMFCEditBrowseCtrl
Call EnableFileBrowseButton to tell it that you want to browse for files, not folders (you can set a filter and default extension)
When the user clicks the button, a file dialog appears, and when you click OK in it, the selected path is written in the edit control.
Language: C++
Development Environment: Microsoft Visual C++
Libraries Used: MFC
Background: So I've created an application that is basically a large preference dialog where the user can configure a number of pages, each with a bunch of different settings. When the user is finished, he/she has three options for saving the preferences (as XML): Save Current [page], Save These, and Save All.
I'm working with the Save These function right now. When the user chooses this option, a dialog appears with check boxes for each page, allowing them to choose which pages they wish to output. Once they choose the directory into which they wish the files to be saved, the magic happens and the XML files are written.
Problem: I have a function (UpdatePageData) that will detect which page is being displayed and update the current page's data by calling UpdateData. I have put in a break point to watch to make sure the variables are being filled with the user's inputted values, and everything is dandy and working correctly. However, when the program jumps from the checkbox dialog (where I call UpdatePageData) to the classes for the pages I'm saving, suddenly all of the values are wrong.
Below I've included some code that will help you guys understand the program flow.
NOTE: In SaveThese, I am currently just working on saving a single page...I will have it update all pages selected once I figure out the problem I'm having.
Location: Main Dialog
void CSAPrefsDialog::OnSaveThese()
{
int msgboxID = ::MessageBox(
NULL,
(LPCSTR)"Are you sure you want to save?",
(LPCSTR)"Save These",
MB_ICONQUESTION | MB_OKCANCEL
);
switch (msgboxID)
{
case IDCANCEL:
break;
case IDOK:
UpdatePageData();
CSaveThese m_sT;
m_sT.DoModal();
break;
}
}
Location: Main Dialog
void CSAPrefsDialog::UpdatePageData()
{
if ((m_iCurPage >= 0) && (m_iCurPage < m_pages.GetSize()))
{
pageStruct *pPS = (pageStruct *)m_pages.GetAt(m_iCurPage);
if (pPS)
{
ASSERT(pPS->pDlg);
if (pPS->pDlg)
{
if (!pPS->pDlg->UpdateData()) // THIS WORKS. THE DATA IS UPDATED.
{
AfxMessageBox("Did not update data.");
}
}
}
}
}
Location: SaveThese Class
void CSaveThese::OnBnClickedOk()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE); // figures out which boxes are checked for saving
CDirDialog dir;
CSAPrefsDialog prefsDialog;
if(dir.DoBrowse())
{
prefsDialog.m_strDirectorySavePath = dir.m_strPath;
}
// [ other if-statements like the one below to check the check boxes ]
}
if(m_bST_FS)
{
FSC_Main m_FS;
m_FS.Save(prefsDialog.m_strDirectorySavePath);
}
OnOK();
}
Location: FSC_Main Class
void FSC_Main::Save(CString dirPath)
{
if(Validate())
{
dirPath += "\\FS_Config.xml";
FILE *fp = fopen(dirPath, "w+");
WriteXML(fp);
fclose(fp);
}
}
By the time it gets to WriteXML, the values have either reverted back to their initialized values (empty strings and -1 for all combo boxes), or have strange values (empty for strings, and large numbers for combo boxes).
I imagine I just have something in the wrong place. I'm just not sure why this is happening, and it's really the biggest hurdle between me and really getting this project rolling.
Jon, Very hard to understand your code. What i understood is you have a member variable m_pages in CSAPrefsDialog dialog class which you are updating by calling UpdateData. And then you are creating a local variable CSaveThese m_sT and calling DoModal. Do you expect CSaveThese class should hold the values of m_Pages?