I have a C++ / MFC app and I trying to save and restore the window placement of my CFrameWnd derived main frame. I have my GetWindowPlacement and SetWindowPlacement calls in the appropriate places, and all seems to be working well.
That is until I 'store' the window when it is maximised. In that case, when I re-open the app and use the debugger to step over my SetWindowPlacement call, I see that it is placed maximised, as I wanted.
But then if I continue execution, something else 'restores' my window to it's non-maximised size. How do I discover what is doing that? (Since I'm not calling ShowWindow anywhere else)
EDIT: It seems to stem from CFrameWnd::InitialUpdateFrame:
int nCmdShow = -1; // default
CWinApp* pApp = AfxGetApp();
if (pApp != NULL && pApp->m_pMainWnd == this)
{
nCmdShow = pApp->m_nCmdShow; // use the parameter from WinMain
pApp->m_nCmdShow = -1; // set to default after first time
}
ActivateFrame(nCmdShow);
If I set my app m_nCmdShow to SW_MAXIMIZED on start up, it shows maxed - but it's always maxed! I have my SetWindowPlacement in my CMainFrame::OnActivate - should it be somewhere else?
So In my App start up I did this:
WINDOWPLACEMENT* lwp;
UINT nl;
if (AfxGetApp()->GetProfileBinary(_T("MainFrame"), _T("WP"), (LPBYTE*)&lwp, &nl))
{
m_nCmdShow = lwp->showCmd;
}
delete [] lwp;
It seems to work
I'm running cocos2d with cocosbuilder 2.1 and I use the cocosbuilder animation delegate (CCBAnimationManagerDelegate::completedAnimationSequenceNamed) to get notified when an animation has completed and take actions like firing another cocosbuilder animation.
It runs fine the first time the foodfactoryshow animation is run from the delegate and after the animation is completed it also runs restoration animation correctly. However, when restoration animation is completed, the parameter name for -(void) completedAnimationSequenceNamed method is NULL!?
-(void) completedAnimationSequenceNamed:(NSString*)name
{
if ([name isEqualToString:#"foodfactoryshow"])
{
[manager runAnimationsForSequenceNamed:#"restoration"];
}
if ([name isEqualToString:#"restoration"])
{
[self colorLayerChanged];
self.gameLayer.isLock = true;
}
}
Is this a bug or am I not supposed to run animations from the CCBAnimationManagerDelegate::completedAnimationSequenceNamed method!?
Thanks in advance for your help.
I believe it is a CCBReader bug. There is an open issue about it in the CocosBuilder github page (https://github.com/cocos2d/CocosBuilder/issues/121). It should be fixed in the latest version of CocosBuilder + CCBReader, however, if you want to use the 2.1 version you can change the "sequenceCompleted" method of CCBAnimationManager to the following:
- (void) sequenceCompleted
{
NSString *completedSequenceName = [runningSequence.name copy];
int nextSeqId = runningSequence.chainedSequenceId;
runningSequence = NULL;
if (nextSeqId != -1)
{
[self runAnimationsForSequenceId:nextSeqId tweenDuration:0];
}
[delegate completedAnimationSequenceNamed:completedSequenceName];
[completedSequenceName release];
}
I'm trying to have animation on a button click event. But somehow the animation is not working. I have referred the Qt reference docs, but could not find the root cause which is causing the issue
Below is sample code :
void MainWindow::AnimationClick()
{
// define toolbar y movement positions for animation
TOOLBAR_Y_SHOWN = 0;
TOOLBAR_Y_HIDDEN = -m_AnimatedWidget->height();
m_AnimatedWidget = new AnimatedWidget(this);
QPropertyAnimation *m_ani = new QPropertyAnimation(m_AnimatedWidget, "pos", this);
m_ani->setDuration(500);
m_ani->setEndValue(QPoint(m_AnimatedWidget->pos().x(), TOOLBAR_Y_HIDDEN));
m_ani->setEasingCurve(QEasingCurve::InBack);
m_ani->start();
}
With the above implementation nothing is happening on the click event.
Any suggestions , Thanks.
This looks wrong:
TOOLBAR_Y_HIDDEN = -m_AnimatedWidget->height();
m_AnimatedWidget = new AnimatedWidget(this);
First you access m_AnimatedWidget then you allocate it?
When you get a crash, such as segmentation fault, always run your program in a debugger. It would have helped you find this error quite easy as it would have stopped on the line of the error.
m_ani->setDuration(500);
setDuration() argument is expressed in milliseconds. You should probably put more than half a second when you are testing.
I got it. I was not allowing the m_AnimatedWidget to show upon the screen.
Below is the edited snippet.
void MainWindow::AnimationClick()
{
// define toolbar y movement positions for animation
TOOLBAR_Y_SHOWN = 0;
m_AnimatedWidget = new AnimatedWidget(this);
TOOLBAR_Y_HIDDEN = -m_AnimatedWidget->height();
QPropertyAnimation *m_ani = new QPropertyAnimation(m_AnimatedWidget, "pos", this);
m_ani->setDuration(5000);
m_ani->setEndValue(QPoint(m_AnimatedWidget->pos().x(), TOOLBAR_Y_HIDDEN));
m_ani->setEasingCurve(QEasingCurve::InBack);
m_ani->start();
m_AnimatedWidget->show();
}
I am developing a custom print dialog and page setup using MFC and VS2008 for my Win32 program. Since the code is legacy, I can't take much advantage from MFC view/doc architecture. As a result, I wrote a printing code completely from scratch.
I setup CPrintInfo, instantiate my custom print dialog box and hook this dialog box to the CPrintInfo I just created. When my custom print dialog is up, I have a radio button to let a user toggles the page orientation. For some reasons, I couldn't modify the current DEVMODE at the run-time. As a result, every page I print will end up as a portrait.
Even if I manually set pDevMode->dmOrientation to DMORIENT_LANDSCAPE from the event handler of the custom print dialog, the printing result is still ended up as portrait. I am really not sure why this is happening and how to modify the DevMode after the print dialog is up.
Thank you in advance for any help.
Here is the code I have:
void PrintSomething(CWnd* currentWnd) {
// Create CPrintInfo
CPrintInfo* pPrintInfo = new CPrintInfo;
SetupPrintInfo(pPrintInfo); // simply setup some member variables of CPrintInfo
// Create a custom print dialog
CustomPrintDlg* pCustomPrtDlg = new CustomPrintDlg(FALSE, PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS
| PD_HIDEPRINTTOFILE | PD_NOSELECTION, pPrintInfo, currentWnd);
SetupPrintDialog(pPrintInfo,pCustomPrtDlg);
if ( AfxGetApp()->DoPrintDialog(pCustomPrtDlg) == IDOK ) {
... // proceed a print loop
}
}
Code for setting up the custom print dialog:
void SetupPrintDialog(CPrintInfo* pPrintInfo,CustomPrintDlg* pCustomPrtDlg) {
delete pInfo->m_pPD;
pInfo->m_pPD = pCustomPrtDlg;
pInfo->m_pPD->m_pd.hInstance = AfxGetInstanceHandle();
pInfo->m_pPD->m_pd.lpPrintTemplateName = MAKEINTRESOURCE(IDD_CUSTOM_PRTDLG);
// Set the Flags of the PRINTDLG structure as shown, else the
// changes will have no effect.
pInfo>m_pPD->m_pd.Flags |= PD_ENABLEPRINTTEMPLATE;
// Set the page range.
pInfo>m_pPD->m_pd.nMinPage = 1; // one based page numbers.
pInfo>m_pPD->m_pd.nMaxPage = 0xffff; // how many pages is unknown.
}
When a user toggles the radio button to Landscape, this function will be invoked:
void CustomPrintDlg::OnLandscapeChecked() {
// set the current Devmode to landscape
LPDEVMODE pDevMode = GetDevMode();
GlobalUnlock(pDevMode);
pDevMode->dmOrientation = DMORIENT_LANDSCAPE;
}
A pseucode for the custom print dialog class:
class CustomPrintDlg: public CPrintDialog {
... // just override some methods from CPrintDialog
};
Thanks again,
Unagi
I figured out the solution:
All I need is to call GlobalLock to obtain a pointer to the Devmode before changing the current DevMode.
void CustomPrintDlg::OnLandscapeChecked()
{
// set the current Devmode to landscape
LPDEVMODE pDevMode = GetDevMode();
GlobalLock(pDevMode);
pDevMode->dmOrientation = DMORIENT_LANDSCAPE;
GlobalUnlock(pDevMode)
}
Thanks again for helping me.
Nowhere in your example code do you show how you're creating the DC for printing. When you call CreateDC, you must pass a pointer to a DEVMODE structure; this defines whether the printing will be portrait or landscape.
Commence V 2.0 of this question.
My VC++ MFC application compiles and runs just fine. That is, until I switch to another window. As soon as my program loses focus, it freezes; I cannot switch back to it and if I move a window that is in front of it, my app window displays white in the space that the other window was covering.
Since I first posted this question I have been able to pinpoint what portion of my program is causing this behavior, but I still don't know what lines of code are wrong or why.
The main dialog of my MFC application contains a CTabCtrl called m_MainTabControl. This main tab control holds onto two tabs labeled "Basic Design" and "Advanced Design", each of which are tied to their own dialogs. Both dialogs contain a CTabCtrl with several tabs. And thus my problem is born.
When I first created this tab-within-tab structure, I was having problems with my program freezing up when I tried to switch between inner tabs. Needless to say I was puzzled by this, until I noticed that if I first clicked on a control on one of the inner tabs I could then switch tabs just fine. So without fully understanding what the problem was, I set the focus to the first inner tab of the first inner tab on program startup. Problem half solved. When I ran the program I could click around on the first set of inner tabs just fine; if I switched to the second outer tab and tried clicking around its inner tabs without first clicking on a dialog control, it would freeze again. So I made a Focus function to focus the currently selected inner tab of the currently selected outer tab and called that in my tab change event (the one that goes off when you click on another tab).
That is how I got to the point I was at when I first asked this question. I thought my program was working just fine, until I played around with it a bit more and noticed it wasn't playing nicely when I flipped back and forth between it and another window or program. More specifically, as soon as my program goes out of focus some process goes haywire and takes up an entire CPU's worth of processing.
And now, the reason I explained my little tab structure and focus problems in such great detail: after much experimentation, I found that if I commented out the second tab on my outer tab structure (i.e. the "Advanced Design" dialog and all of its little children tabs) the remaining bit of my program runs fine, and I can switch to another window and back without a fight. "Great," I thought, "that's only about 90% of my program that I just commented out to get this working. Let's try and pare it down further." I put the "Advanced Design" tabbed dialog back in, but commented out the tabbed dialogs created by the tab control within "Advanced Design" and everything still worked fine. One by one I put back the tabbed dialogs belonging to "Advanced Design"'s tab control and every time I reintroduced The Error regardless of what tab I uncommented. I should also point out that one of the first tabs I tried putting back in (alone, of course) was my "Margins" tab, which is a MarginDlg class that I ALSO USE UNDER MY "Basic Design" TAB WITHOUT TROUBLE. This leads me to believe that there is something specific I have to do when creating tabbed dialogs within tabbed dialogs that I am not doing, or am doing incorrectly, kind of like how I had to mess with focusing to make it work at first.
I would be EXTREMELY grateful for any light that can be shed on the situation. I am including what I think are relevant snippets of code; as always, let me know if more is needed.
variable declarations from main dialog's .h file:
//tab stuff
CTabCtrl m_MainTabControl;
vector<CDialog*> m_tabPages;
SimpDesDlg* simpDesDlg;
AdvDesDlg* advDesDlg;
When my application starts up, it creates my main dialog, and the OnInitDialog() is called:
(everything above the TODO: comment is default VS stuff dealing with the stupid about dialog)
BOOL CspAceDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
///////////////////////////////////////
DrawResultsArea();
DrawTabs();
theApp.Calculate();
Focus();
//simpDesDlg->Focus();
//DrawToolbar();
return FALSE; // return TRUE unless you set the focus to a control
}
DrawTabs() is where I create the tabs for my outer tab control:
void CspAceDlg::DrawTabs()
{
simpDesDlg = new SimpDesDlg;
m_tabPages.push_back(simpDesDlg);
advDesDlg = new AdvDesDlg;
m_tabPages.push_back(advDesDlg);
// create a tcItem to hold the name of each tab during creation
// and then get inserted, and arrays holding the tab names and IDs of
// the dialogs they refer to
TC_ITEM tcItem;
PSTR pszTabNames[] = {"Basic Design", "Advanced Design"};
UINT pszTabItems[] = {IDD_SIMPLEDESIGNTAB, IDD_ADVANCEDDESIGNTAB};
//every member of m_tabPages[] will become a tab
for (int i = 0; i < int(m_tabPages.size()); i++)
{
//set up the tab name
tcItem.mask = TCIF_TEXT;
tcItem.pszText = pszTabNames[i];
tcItem.cchTextMax = int(strlen(pszTabNames[i]));
//insert the new tab into the tab control and create the dialog window
m_MainTabControl.InsertItem(i, &tcItem);
m_tabPages[i]->Create(pszTabItems[i], &m_MainTabControl);
}
//redraw so that the dialogs don't appear in upper left corner and cover the tabs
CRect tabRect, itemRect;
int nX, nY, nXc, nYc;
m_MainTabControl.GetClientRect(&tabRect);
m_MainTabControl.GetItemRect(0, &itemRect);
nX=itemRect.left;
nY=itemRect.bottom+1;
nXc=tabRect.right-itemRect.left-1;
nYc=tabRect.bottom-nY-1;
m_tabPages[0]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_SHOWWINDOW);
for(int nCount=1; nCount < int(m_tabPages.size()); nCount++){
m_tabPages[nCount]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_HIDEWINDOW);
}
}
Main dialog's Focus() method:
void CspAceDlg::Focus()
{
int curSel = m_MainTabControl.GetCurSel();
m_tabPages[curSel]->SetFocus();
//if it's the basic design, we need to focus its first tab
if (curSel == 0)
{
simpDesDlg->Focus();
}
//if it's the advanced design, we need to focus its first tab
else if (curSel == 1)
{
advDesDlg->Focus();
}
}
code for m_MainTabControl's tab selection change event:
void CspAceDlg::OnTcnSelchangeBuildtabs(NMHDR *pNMHDR, LRESULT *pResult)
{
for (int i = 0; i < int(m_tabPages.size()); i++)
{
m_tabPages[i]->ShowWindow(m_MainTabControl.GetCurSel() == i ? SW_SHOW :
SW_HIDE);
}
Focus();
*pResult = 0;
}
SimpDesDlg and AdvDesDlg's tabs use identical code except for tab initialization (just creating different tabs for each) so here's the code for AdvDesDlg:
OnInitDialog():
BOOL AdvDesDlg::OnInitDialog()
{
CDialog::OnInitDialog();
DrawTabs();
return false;
}
adding in the tabbed dialogs:
void AdvDesDlg::DrawTabs()
{
//Make the dialogs for the tabs
antennaDlg = new AntennaDlg;
commSEDlg = new CommSEDlg;
encryptorDlg = new EncryptorDlg;
marginDlg = new MarginDlg;
miscDlg = new MiscDlg;
transRecDlg = new TransRecDlg;
//add them all to the tabPages vector
m_tabPages.push_back(antennaDlg);
m_tabPages.push_back(commSEDlg);
m_tabPages.push_back(encryptorDlg);
m_tabPages.push_back(marginDlg);
m_tabPages.push_back(miscDlg);
m_tabPages.push_back(transRecDlg);
//m_tabPages[0] = new AntennaDlg;
//m_tabPages[1] = new CommSEDlg;
//m_tabPages[2] = new EncryptorDlg;
//m_tabPages[3] = new MarginDlg;
//m_tabPages[4] = new MiscDlg;
//m_tabPages[5] = new TransRecDlg;
//antennaDlg = (AntennaDlg*) m_tabPages[0];
//commSEDlg = (CommSEDlg*) m_tabPages[1];
//encryptorDlg = (EncryptorDlg*) m_tabPages[2];
//marginDlg = (MarginDlg*) m_tabPages[3];
//miscDlg = (MiscDlg*) m_tabPages[4];
//transRecDlg = (TransRecDlg*) m_tabPages[5];
// create a tcItem to hold the name of each tab during creation
// and then get inserted, and arrays holding the tab names and IDs of
// the dialogs they refer to
TC_ITEM tcItem;
PSTR pszTabNames[] = {"Antenna", "Comm Support", "Encryptor", "Margins", "Misc", "Trasmitter/Receiver"};
UINT pszTabItems[] = {IDD_ANTENNATAB, IDD_COMMSETAB, IDD_ENCRYPTORTAB, IDD_MARGINTAB, IDD_MISCTAB, IDD_TRANSRECTAB};
//every member of m_tabPages[] will become a tab
for (int i = 0; i < int(m_tabPages.size())/*(sizeof(m_tabPages)/sizeof(m_tabPages[0]))*/; i++)
{
//set up the tab name
tcItem.mask = TCIF_TEXT;
tcItem.pszText = pszTabNames[i];
tcItem.cchTextMax = int(strlen(pszTabNames[i]));
//insert the new tab into the tab control and create the dialog window
advTab.InsertItem(i, &tcItem);
m_tabPages[i]->Create(pszTabItems[i], &advTab);
}
//redraw so that the dialogs don't appear in upper left corner and cover the tabs
CRect tabRect, itemRect;
int nX, nY, nXc, nYc;
advTab.GetClientRect(&tabRect);
advTab.GetItemRect(0, &itemRect);
nX=itemRect.left;
nY=itemRect.bottom+1;
nXc=tabRect.right-itemRect.left-1;
nYc=tabRect.bottom-nY-1;
//m_tabPages[0]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_SHOWWINDOW);
for(int nCount=/*1*/0; nCount < int(m_tabPages.size())/*(sizeof(m_tabPages)/sizeof(m_tabPages[0]))*/; nCount++){
m_tabPages[nCount]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_HIDEWINDOW);
}
}
And the Focus() and tab changing:
void AdvDesDlg::Focus()
{
this->SetFocus();
for (int i = 0; i < int(m_tabPages.size())/*(sizeof(m_tabPages)/sizeof(m_tabPages[0]))*/; i++)
{
m_tabPages[i]->ShowWindow(advTab.GetCurSel() == i ? SW_SHOW :
SW_HIDE);
}
int curSel = advTab.GetCurSel();
m_tabPages[curSel]->SetFocus();
}
void AdvDesDlg::OnTcnSelchangeAdvDesign(NMHDR *pNMHDR, LRESULT *pResult)
{
for (int i = 0; i < int(m_tabPages.size())/*(sizeof(m_tabPages)/sizeof(m_tabPages[0]))*/; i++)
{
m_tabPages[i]->ShowWindow(advTab.GetCurSel() == i ? SW_SHOW :
SW_HIDE);
}
int curSel = advTab.GetCurSel();
m_tabPages[curSel]->SetFocus();
*pResult = 0;
}
Debug your app, get it into this state, then go Debug / Break All. Find the main thread in the Threads window, then look at the call stack. Somewhere in the call stack will be your code that's causing the hang.
Note that in order to get a sensible call stack you'll need to point Visual Studio at Microsoft's symbol servers; see http://msdn.microsoft.com/en-us/library/b8ttk8zy.aspx
The behavior you describe usually occurs when you are running some process without allowing the message pump to run.
What does your app do? I assume you start it, and then either hit a button or select a menu item to start some process.
If the program behaves normally when you first start it (before you click to start your processing), but then behaves as you describe after starting the process, then that's your problem.
You'll have to move that processing into another thread to allow the MFC GUI to remain responsive.
I just stumbled about a very similar situation. My setup:
A CPropertySheet containing several CPropertyPages
A CTabCtrl inside one CPropertyPage
Several CDialogs as part of the CTabCtrl
Using a control in one specific CDialog and then switching to another application (e.g. Visual Studio via a hit breakpoint) will stall my application (the respective CPU core ends up at 100% load)
Using a control in the same specific CDialog but then switching to another CPropertyPage before switching to another application will not result in any problems
After some research I found this Knowledge Base article which hinted me to a solution. The specific CDialog which triggered the stall had the line EXSTYLE WS_EX_CONTROLPARENT in its resource definition. Removing the line solved the problem.
This prevents being able to tab into the CDialog, but that problem is slightly less serious and I might come back to it another day.
I had a similar issue. I had multiple nested windows, some with the WS_EX_CONTROLPARENT style, some not. The thing is: Either all inner windows have to have this style, or none of them (at least apparently).