Link to home
Start Free TrialLog in
Avatar of rickatseasoft
rickatseasoft

asked on

CComboBox Fails to Create

I have a CComboBox, which is restricted to a ListBox via its property sheet.  It is part of a much larger and complex dialog, which is part of a much more complex multi-page tab control.  In other words, there is a lot going on.

The dialogs are created by stepping through a loop that creates and attached each dialog to the tab control.  After the creation step, I load a few CComboBoxes with static data such as states in the union, etc.

Everything works fine on the development machines, but fails when the program is loaded on a 98 Home Edition machine.  

The failure seems to be on a call to ResetAll() on one of the combo boxes.  I KNOW, a ResetAll isn't required if the combobox has just been created---somebody got too diligent.  However, it did raise an interesting question of how to avoid the problem.  On a lark, I placed something that resembled

while(!IsWindow(mydialog->mycombobox.m_hWnd));  //I'll clean this up later

Again this works perfectly, or at least reports no failures on any of the development machines.  However when moved to a non-development XP Hmoe Edition machine, it fails with an assertion, a file name and a line number.  When I examine the file in question it indicates that the problem is that m_hWnd is not a Window.

Does anyone have any idea why this is happening.  I'm still working on a work-around, but for the sake of my sanity, I'd like to know the answer.

Thanks in advance, Rick
Avatar of Alkali_Guy
Alkali_Guy

The probable cause is that the combo box doesn't exist yet when you call ResetAll.  Where do you call ResetAll?  Try moving the routine to somewhere after DoDataExchange or your loading code runs.  Alternately, you can work around it by making a boolean member of the dialog class, initialising it to false, and setting it to true when you load the controls, then swaddling all early initalisation code in an if statement testing this flag.
Avatar of rickatseasoft

ASKER

I am certain that the CComboBox doesn't exist when ResetAll is run.  I hope that you can answer a couple of questions so that I can better understand the issue.  Incidentally, I removed the ResetAll() as it was unnecessary, and now the failure occurs on AddString().

1.  Why on XP Home Edition and not on other machines?
2.  Is the loop while(!IsWindow(...)) preemptive?  In other words does that stop the creation of the Dialog and its controls while it is running.  If so, is there a way to make the loop non-preemptive?
3.  Do you think that the problem is realted to the OS, or to the fact that the machine is without the development system installed?

I know that definitive answers are hard in cases like this, but your best guess will be greatly appreciated.

Rick
Which version of the program are you running on the non-development machine?  Debug or release?

I am actually surprised it seems to work at all on the development machine.  The loop is synchronous; nothing else will happen as long as it runs (I think).  Can you just do?:

if (!IsWindow(mydialog->mycombobox.m_hWnd)) AfxMessageBox("Combo box does not exist.");
Avatar of AndyAinscow
Are you setting anything going by posting messages ?
eg
PDlg1->PostMessage(_START_PROCESSING, x, y);

If you are it could well be a timing problem.  By chance on your development machine the message is late enough in the queue that the combo has been created but on the test machine it is appearing before the combo is created.
Oh - any multi-threading going on? (similar thoughts about timing problem)
Keep in mind that on the development machine, the combobox has been created by this point evidenced by the fact that the code executes properly.  It is only when I get to the non-development machine that the ccombobox seems to have not been created, and therefore fails.  The loop is in response to that failure.

I am running the debug version.

Rick
We need to know from what message handler ResetAll/AddString is called, or if it's in the creation loop.
DEBUG also on test machine?  (RELEASE will run a lot faster - see my earlier comments)
The pseudocode is something like

OnInitDialog()

if(!m_TabPage[0]){
   Call the Create Function for the appropriate dialog and set it to m_TabPage[0];
   Set the masks for some of the controls, etc.

   Call the Create Function for the appropriate dialog and set it to m_TabPage[1];
   Set the masks for some of the controls, etc.
   Set the text limit for some CEdits
   
   Call the Create Function for the appropriate dialog and set it to m_TabPage[2];
   Set the masks for some of the controls, etc.
   Set the text limit for some CEdits
   
   ...

   Call the Create Function for the appropriate dialog and set it to m_TabPage[8];
   Populate the CComboBox with some relatively static data
   Set the text limit for some CEdits
   Set the masks for some of the controls, etc.
}


Rick
ASKER CERTIFIED SOLUTION
Avatar of Alkali_Guy
Alkali_Guy

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Let Me add to the above pseudocode.  After the last Create, I do a loop that moves and sizes the windows to fit on the CTabControl.

It goes like this

            for(ii=0;ii<TAB_PAGE_COUNT_11;ii++){
                  m_CtrlTab1.InsertItem(ii,Captions[ii]);
                  if(m_TabPages[ii])m_TabPages[ii]->MoveWindow(l_Rect,TRUE);
            }
Removing ALL of the code that initializes controls, sets textlength, sets mask, etc. then the code runs right to here, and on the last dialog, it fails because the CDialog isself is not a Window in Winocc.cpp.  The line is

void CWnd::MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint)
{
      ASSERT(::IsWindow(m_hWnd));


Rick
I guess that I can pass the appropriate size to the Create Method for each CDialog, and then within the dialog, set the size, etc. appropriately.

Would it be better to do this in OnInitDialog, or should I use PreSubclassWindow()?

Thanks, Rick
Placed all of the control initialization code in OnInitDialog of the child dialog.  Then when I go through the pass for ShowWindow() depending on which Tab is selected---initially the 1st is auto selected, and therefore on page[0] it will do a SW_SHOW and for all others it will do a SW_HIDE.  All of the rest work fine, but when it gets to the last page, it blows up again since it thinks that the dialog attached to page[7] has no m_hWnd.

Just for testing purposes, I took the code to a Windows 2000 machine without the DevSys.  It produces a different failure:

All of the dialogs are declared something like

CRun11Dates m_Run11Dates;

Then created during the OnInitDialog of the parent with something like m_CRun11Dates.Create(this, &m_CtrlTab) so that the dialog will know not only its parent dialog, but the tab to which it is attached.  The create code is

BOOL CRun11Dates::CreatePage(CWnd *pParent, CWnd *pTabParent)
{
      m_pTabCtrlParent=pTabParent;
      m_pParent=pParent;
      return CreateDlg(MAKEINTRESOURCE(IDD), pTabParent);
}

On the windows 2000 computer, this returns a false.  On the XP Home this returns a TRUE, but, of course, still fails.  I am uncertain how to proceed since I can't debug on a computer with no devsys.

Any ideas, suggestions, or solutions will be greatly appreciated.

One other thought: could this be some sort of buffer overflow, random pointer, etc. that just happens to aligh correctly/incorrectly when the dev sys is attached and when it is not?

I am thinking that we run on and test on at least two other machines without the devsys, but they are at the office, and I don't know which flavor of Windows.

Rick
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Andy:

Never get to that point as there is a failure before I can provide any user input at all.

Rick
Andy:

I did start the program with the task manager open, and watched the number of handles grow, and the number did not increase dramatically at all, about a hundred.

Rick
Andy and Alkali Guy:

Thanks for all of your help.

I started down a different path this morning; what is different about the dialog in question?  It stood out like a sore thumb---this dialog contains the only instance, at this time, of a FlexGrid control.  Sure enough, I removed the control, and all works as specified.

I'll go ahead and award the points, and open a new quesiton since the topic of this one is not actually germaine at all.

Thanks again, Rick  
Guess - Check if you have initialised OLE.  (CoInitialize or similar)