|
Summary:
m_hWnd is NULL in a CDialog derived class and this leads to an assertion failure.
Details:
I am writing an SDI application. I've subclassed a CDialog class that will popup and gather info from the user. In response to the user clicking some button the Document class handles the message and creates a new CDialog object and calls DoModal(). The basic idea is something like this:
<br />
void CMyDoc::OnButtonClick()<br />
{<br />
CMyDialog md;<br />
md.DoModal();<br />
}
Now, the CMyDialog class has a CTabCtrl named "m_tabSettings" with two tabs. I need to initialize these tabs and have tried to do so with code similar to this:
<br />
m_tabSettings.InsertItem(0,"Tab One");<br />
m_tabSettings.InsertItem(1,"Tab Two");<br />
This causes an assertion failure in AFXCMN.INL on the following line:
<br />
_AFXCMN_INLINE BOOL CTabCtrl::InsertItem(int nItem, LPCTSTR lpszItem)<br />
{ ASSERT(::IsWindow(m_hWnd)); return CTabCtrl::InsertItem(TCIF_TEXT, nItem, lpszItem, 0, 0); }<br />
The key part from above is: ASSERT(::IsWindow(m_hWnd));
I stepped through this code in the debugger and sure enough m_hWnd is 0x00 when I try to insert tabs into my CTabCtrl. I'v tried the following:
1. moving this 'insert item' code to the CMyDialog constructor (actually this is where I had it to begin with)
2. moving the 'insert item' code to a separate function which I call between the dialog declaration and DoModal()
3. changing the CMyDialog variable to a pointer and creating a 'new CMyDialog' on the heap
4. calling CMyDialog::Create() before the call to DoModal() ... and I played with creating a CMyDialog object from the CMyView class as well.
5. getting rid of the tab control initialization code altogether and inserting a CListCtrl in report form as a variable instead. I then tried to call CListCtrl::InsertColumn(0,"col one") ... etc.
All of these cause the same or similar assertion errors. I know, most of the stuff I've tried is some type of 'magic chicken coding' but I have no idea why code that I've pretty much copied from stuff I saw on the MSDN is breaking like this (i.e. I'm out of ideas) .
Is there some order of method calls that I'm missing or some flag for the CMyDialog?
If anyone has had a similar problem please let me know if and how they've fixed it.
|
|
|
|
|
You need to move the initialization to CMyDialog::OnInitDialog(), after calling CDialog::OnInitDialog(). Until that, the dialog controls aren't yet created.
You need to distinguish between the CWnd-derived C++ object that wraps the Windows control (e.g.: m_tabSettings) from the Windows control itself (e.g.: m_tabSettings.m_hWnd);
The dialog constructor constructs the control wrappers, DoModal first creates the Windows controls and then calls [1] OnInitDialog. CDialog::OnInitDialog associates each control wrapper with its corresponding window control.
[1] Actually, during the dialog creation, Windows sends a WM_INITDIALOG message, which is handled in the dialog by OnInitDialog.
--
jlr
http://jlamas.blogspot.com/[^]
|
|
|
|
|
For those interested, I will now answer, at least in part, my own question.:
Solution:
Override CMyDialog::OnInitDialog() and initialize the CTabCtrl there.
As far as I've traced it, CMyDialog::DoModal() calls CDialog::DoModal() (i.e. the base class fn.). This I knew. What I didn't know is that CDialog::DoModal() calls my OnInitDialog() (or some funtion up(down,whatever) on the call stack before DoModal returns does). I just assumed that CMyDialog's constructor was calling OnInitDialog() . So, CDialog::DoModal() apparently initializes some stuff behind the scenes before it calls OnInitDialog() which allows me to init my controls safely.
It is late and I am too tired to dig further.
If anyone out there understands the sequence of behind the scenes initializations or whatnot that happens between the call to CDialog::DoModal() and the call to OnInitDialog() please explain.
|
|
|
|
|
Bah! Thats what I get for reading my post too many times before I click 'submit'. Thank you for your reply Jose!!
|
|
|
|
|
Hi There,
What's the best solution to use and implement an Array with maxixmum size of elements?
Thanks
|
|
|
|
|
SHORT ANSWER:
Use the standard template vector<> (#include <vector>).
If you know the (aproximate) number of elements needed for storage, before coping, then call the member function reserve(), in order to reduce the number of reallocations required when adding new elements to the array.
LONG ANSWER:
The best solution depends on how it is going to be used (implimentation dependent). If you need a dynamic array (increases/decreases size as needed) then use the vector<> template (which is a one dimensional dynamic array). The maximum size of an array of elements, depends on the size of the elements and amount of memory available.
If you use a vector, you can call the max_size() member to determine what is, theoretically, the maximum number of elements that can be stored in a vector. I say theorectically because it, again, depends on the size of the element being stored, the amount of available memory and the amount of contiguous memory that can be allocated (on a given system).
THAT'S ENOUGH:
In C++ just use vector<>, unless you have a good reason not to.
NOTES:
1) Never use type* pArray = new type[size] when type Array[size] will solve the problem.
2) Prefer:
vector<type> myarray;
myarray.reserve(size);
TO
type* pArray = new type[size];
Good Luck!
INTP
"The more help VB provides VB programmers, the more miserable your life as a C++ programmer becomes."
Andrew W. Troelsen
|
|
|
|
|
hi,
have an SDI application where the view class has been derived from the CFormView class. i added a list control to the dialog. but when i tried to add some sample text to it i got and exception. in some earlier posts someone had suggested to define the virtual function DefWindowProc. and in the handler for the WM_INITDIALOG message call UpdateData(FALSE). i tried that but i am still getting the exception. can anyone help
thanks
aditya
|
|
|
|
|
I assume you have a member variable that has been subclassed to the control in question. This might have been done for you. Use the debugger to make sure that m_hWnd is not NULL prior to adding the sample text to the list box. If it is NULL, make sure that the resource ids haven't changed and that the control id is correct for the control. This often causes problems.
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
|
I'm looking for a "multi-slider" control that contains n (>= 1) knobs to allow for the definition of contiguous ranges. An example of one with 6 knobs would look like this:
(min)...|.......|..|....|.......|...|..(max)
1 2 3 4 5 6
A pointer to existing code would be much appreciated. Thanks!
/ravi
My new year's resolution: 2048 x 1536
Home | Music | Articles | Freeware | Trips
ravib(at)ravib(dot)com
|
|
|
|
|
|
it took awhile to figure out what the correct image link was, but here it is [^]
seems there are tons of broken links on CodeGuru...
Steve
|
|
|
|
|
Steve Mayfield wrote:
seems there are tons of broken links on CodeGuru...
No surprise.
/ravi
My new year's resolution: 2048 x 1536
Home | Music | Articles | Freeware | Trips
ravib(at)ravib(dot)com
|
|
|
|
|
|
Strange occurance ?
In one dialog, i call this
myDlg = new CmyDlg;
myDlg ->Create(IDD_DIALOG, GetDesktopWindow());
myDlg ->ShowWindow(1);
Now I have a thread running, if it receives a message, it'll sometimes popup a MessageBox window, but the MessageBox will be under everything. I want the message to popup ontop of everything.
If I call from the thread, with MessageBox(GetForegroundWindow(),...); It'll popup the message box, but then the application will lock.
Not sure what's causing it, and if I do MessageBox(NULL,...) it'll run fine except the MessageBox is under everything ..
?
|
|
|
|
|
I got it, just tagging MB_SYSTEMMODAL to the function.
Btw, why does it do that ?
|
|
|
|
|
Well not realy: MB_SYSTEMMODAL suspends all applications (equivalent to locking up all applications), until the dialog is close.
If you are using MFC, try: AfxMessageBox(...).
I have only used it few times my self, but it should set the hWnd parameter to your main application window or the currently active window in your application (or possibly NULL). If it works then single step into it and find out why.
MessageBox(NULL,...): Should popup the modal messagebox in front of all the windows, it has no parent (actualy that's not true, but the docs say it is) (It has always worked for me).
Search previously asked questions: Some one was having this same problem last week (my be some one knew what the problem was).
The (probable) reason no one has attempted to answer this question is that it does not happen. The only time I've seen this, is when a messagebox popups and the user does not close it, but clicks on the window that the messagebox is in front of (sending the messagbox to the background).
INTP
"The more help VB provides VB programmers, the more miserable your life as a C++ programmer becomes."
Andrew W. Troelsen
|
|
|
|
|
Yea it is quite strange, but got it working. Just plugged in system modal.
|
|
|
|
|
I have an application that was originally developed with Windows 98 ( yes, just recently bought new laptop with XP Pro). I have also occationally built the app. on my work PC which runs Windows 2000. No difference there. But when I now try to build with XP all dialogs and CFormViews come out wrong with static texts in shifted positions relative to edit boxes, etc. The environment is VC6.0 service pack 3.
Regards, Haakon S.
A sure cure for seasickness is to sit under a tree.
Spike Milligan
|
|
|
|
|
No need to be . Win98 (?) and Win2000 (great stystem) have a lot in common, but that is where you should have seen problems (if any).
Each system may use a different default character set, which will affect any windows layout that resembles a dialog (that applies to internationalization as well). That means the static text bounding rectangle should be larger than the default size, which is based on the default font size at design time. (You might need to throw in some calculations as well.)
I recommend making a copy of your application and modifing it on XP so that it looks right. Then compare it to the original program (visualy), to see what the difference is. (That may be enough for you to figure out the problem.)
INTP
"The more help VB provides VB programmers, the more miserable your life as a C++ programmer becomes."
Andrew W. Troelsen
|
|
|
|
|
Thanks for the reply!
I found the cause of the problem. It is as simple as DPI (pixels, or dots, per inch). In my program I have used SepMapMode(MM_TEXT). In the dialogs and CFormViews there will be a mix of this mode and DLU (dialog logical units). The former is dependent on the device, the latter is calculated from the font size, which is device independent. Now, that is something to be about. I should of course have used SetMapMode(HI_METRIC), or some such thing.
My new PC has default DPI=120. By changing this to 96 (designated Normal by Windows) my program works fine.
Regards, Haakon S.
A sure cure for seasickness is to sit under a tree.
Spike Milligan
|
|
|
|
|
Check your desktop display "DPI" settings. On some of the machines, you may be set for "small fonts", and on the other, for "large fonts".
Software Zen: delete this;
|
|
|
|
|
Hello Experts!
I am able to retrieve all the profile properties for a user except the PR_MANAGER_NAME property. All of the other fields fetch fine. All the name, address, custom attributes.. you name it, they retrieve fine. The only one that fails is PR_MANAGER_NAME. This fails on all machines tested.
Below is my code (in abbreviated form, that retrieves a single property). You can plug this code into a simple Win32 project (that supports MFC) and it will build and run for you. You will notice about 1/2 way down where I set the property to be read:
//aSenderProps.aulPropTag[0] = 0x3001001E; // PR_DISPLAY_NAME <==== THIS WORKS
aSenderProps.aulPropTag[0] = 0x3A4E001E; // PR_MANAGER_NAME <==== THIS FAILS
Can anyone shed any light on why this is failing? Many thanks in advance!
//======== Code below ====================
// MapiTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "MapiTest.h"
#include <mapix.h>
#include <atlconv.h>
#include <atlbase.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
USES_CONVERSION;
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
#define MAPI_INIT_VERSION 0
MAPIINIT_0 mapiInit;
mapiInit.ulVersion = MAPI_INIT_VERSION;
mapiInit.ulFlags = MAPI_MULTITHREAD_NOTIFICATIONS;
CComPtr<imapisession> spMapiSession;
// initialize MAPI
HRESULT hr = ::MAPIInitialize(&mapiInit);
if (!SUCCEEDED(hr))
{
AfxMessageBox("MAPIInitialize error");
}
// logon to the profile
hr = ::MAPILogonEx(0, _T("MS Exchange Settings"), NULL, MAPI_EXTENDED|MAPI_NO_MAIL|MAPI_NEW_SESSION|MAPI_TIMEOUT_SHORT, &spMapiSession);
if (FAILED(hr))
{
AfxMessageBox("Unable to logon");
return 0;
}
CComPtr<imapiprop> spSender;
ULONG uObjectType, uCount, cbSenderEntryIDSize;
LPENTRYID pSenderEntryID=NULL;
LPSPropValue pSenderProps=NULL;
// struct used to hold array of properties to read
struct _SPropTagArray_
{
ULONG cValues;
ULONG aulPropTag[1];
} aSenderProps;
// set the properties to read (in this case, 1 property)
aSenderProps.cValues = 1;
//aSenderProps.aulPropTag[0] = 0x3001001E; // PR_DISPLAY_NAME <= = = = = = = = = = = = == THIS WORKS
aSenderProps.aulPropTag[0] = 0x3A4E001E; // PR_MANAGER_NAME <= = = = = = = = = = = = = THIS FAILS
// Get the Entry Identifier used to read the primary identity
hr = spMapiSession->QueryIdentity(&cbSenderEntryIDSize,&pSenderEntryID);
if (FAILED(hr))
{
AfxMessageBox("Unable to QueryIdentity");
return 0;
}
if (hr == MAPI_W_NO_SERVICE)
{
AfxMessageBox("MAPI_W_NO_SERVICE");
return 0;
}
// OpenEntry
hr = spMapiSession->OpenEntry( cbSenderEntryIDSize,
pSenderEntryID,
NULL,
MAPI_BEST_ACCESS | MAPI_DEFERRED_ERRORS,
&uObjectType,
(LPUNKNOWN FAR *)&spSender);
if (FAILED(hr))
{
AfxMessageBox("Unable to OpenEntry");
return 0;
}
// get the properties
hr = spSender->GetProps( (LPSPropTagArray)&aSenderProps,
0,
&uCount,
&pSenderProps);
if(FAILED(hr))
{
// report, but not fatal
}
CComBSTR bstrTemp;
// display each property found
for (UINT i = 0 ; i < aSenderProps.cValues; i++)
{
if (PROP_TYPE(pSenderProps[i].ulPropTag) != PT_ERROR)
{
// successful read
bstrTemp = pSenderProps[i].Value.lpszA;
AfxMessageBox(CString(bstrTemp));
}
else
{
// unable to read property
bstrTemp = "";
AfxMessageBox("Error: Unable to read property");
}
}
// cleanup
spMapiSession->Logoff(0,0,0);
if (pSenderEntryID)
::MAPIFreeBuffer(pSenderEntryID);
if (pSenderProps)
::MAPIFreeBuffer(pSenderProps);
//MAPIUninitialize();
return nRetCode;
}
// ======== END OF CODE ========================
Mark
|
|
|
|
|
How exactly is failing? Does it return an empty string, is the type set to PT_ERROR, is the return different than S_OK?
--
jlr
http://jlamas.blogspot.com/[^]
|
|
|
|
|
It turns out that I need to read the PR_EMS_AB_MANAGER object. Here is the quote I got from another forum:
You will need to open the PR_EMS_AB_MANAGER property as IMAPITable
(IMailUser::OpenEntry(PR_EMS_AB_MANAGER, &IID_IMAPITable, ...)).
You will get back a table with a single row (or no rows at all).
Read PR_DISPLAY_NAME from that table or grab PR_ENTRYID and call
IAddrBook::OpenEntry to get back IMailUser representing the manager, you can
then read PR_DISPLAY_NAME from that object.
.. now all I need to do is figure out how to do what is described above
|
|
|
|
|
Mark Findlay wrote:
.. now all I need to do is figure out how to do what is described above
I'm sure you will
--
jlr
http://jlamas.blogspot.com/[^]
|
|
|
|
|