|
yah,thought on similar lines but isnt tehre any built in methods to accomplish this?
|
|
|
|
|
There are serialization frameworks that do that automatically, but they are rather intrusive (esentially they require that you replace all your pointers with their own smart pointers that take care of the looping references), so I don't think it'd be a good idea to try to use them if you're in the middle of a project. The solution proposed is local (all the code is inside a function) and it is not that hard to implement.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Yes, if you use the serialization support provided in MFC, it will properly handle nested and even cross-linked objects. You need to use CObject as the base class, and add the appropriate DECLARE_SERIAL and IMPLEMENT_SERIAL macros. You also need a Serialize routine for each class.
Best regards,
John
|
|
|
|
|
I don't think MFC automatically supports serialization of linked objects. Basically it provides the barebones framework, all the work is left to the programmer. Please correct me if I'm wrong.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
MFC has complete support for serialization of linked items. I have used it for years with no problems. Internally it keeps track of which objects have already been serialized by using a map.
As long as you setup your macros correctly (DECLARE_SERIAL / IMPLEMENT_SERIAL), it handles all the details of loading and saving complicated data structures which are interlinked, even with loops of objects.
Best regards,
John
|
|
|
|
|
Oh... You were right, I've read some stuff on the subject and the mechanism actually does what you say (and in a pretty clever way.) I used to think ;FC serialization was dumber than it is.
Regards,
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
jbarton,
You seem to have used MFC serialization for a while. Maybe you can help me out with this. I have a class derived from CArray, with not other variables in the class. I'm trying to serialize it to a TXT file. Here's my class definition:
class AFX_EXT_CLASS CFormList : public CArray<CString,CString&> <br />
{<br />
DECLARE_SERIAL(CFormList);<br />
public:<br />
CForm Item(CARSConnection &arsConnection, int iIndex);
void GetForms(CARSConnection &arsConnection, long lType);<br />
CFormList();<br />
virtual ~CFormList();<br />
};<br />
And then my implementation code:
IMPLEMENT_SERIAL(CFormList, CArray, 1);
When I compile it, it's giving me this error:
error C2955: 'CArray' : use of class template requires template argument list
Any idea what I'm doing wrong?
Thanks much for any help
Mike Ellertson
|
|
|
|
|
Hi Mike,
You shouldn't derive from a CArray - it is not designed to be a base class (it does not have a virtual destructor).
Instead, you can make the CArray into a member of your CFormList class
<br />
class AFX_EXT_CLASS CFormList : public CObject<br />
{<br />
DECLARE_SERIAL(CFormList);<br />
<br />
public:<br />
void Serialize( CArchive& ar )<br />
{<br />
CObject::Serialize( ar );<br />
m_Array.Serialize( ar );<br />
}<br />
<br />
private:<br />
CArray<CString,CString&> m_Array;<br />
};<br />
<br />
IMPLEMENT_SERIAL( CFormList, CObject, 1 );<br />
Best regards,
John
|
|
|
|
|
Thanks for the input on this. I did just go ahead and derive from CStringList instead. Just for your info, I read an article on MSDN describing the right way to derive from CArray. So it is meant to be derived from.
I'm pretty sure the issue I was having was due to a bug in the way the Visuall C++ preprocessor interprets comma's in macro's. Another codeproject member let me know that and I found a bug report on Microsoft Website. But your solution worked, so I'm off and running.
Thanks!
Mike Ellertson
|
|
|
|
|
Hi Mike,
One thing that you should be aware of when serializing CArray (or other MFC collection classes):
Normally, when you need to serialize a CArray of some type, you have to check if the type is a POD. The default serialization support in CArray will do a binary copy of the contents of the CArray to the archive. This works for simple data types, but not for class objects. The correct way to fix this is to override the SerializeElements() function for the specific class that you are serializing. You didn't need to do this for a CArray containing CString objects, because Microsoft already provides an override for SerializeElements specifically for CString. If you change what is in the array to some more complicated object (rather than just a CString), you will need to override the SerializeElements() routine for this object.
Best regards,
John
|
|
|
|
|
John's answer is the way to go (I guess you already were using MFC serialization, so this is very good news to you.) The DDJ's article Inside MFC Serialization I've just read could be of some help for you (it was for me.)
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
hi,
are-
* Subclassing
* Owner/Custom Draw
* Custom Controls
complementory,some what same,almost same or totally different?
i am confused
|
|
|
|
|
subclassing (when talking about controls) is where you take an existing windows control (like an edit box) and create a new version that does something differently than the original. it's not the same as C++ subclassing (creating derived classes), but the effect is similar. and with MFC it does work out to the same thing in most cases.
owner draw is where the control allows you to handle the rendering while it handles the back-end data work as usual. a common example is an owner-drawn button where you control the rendering of the button, but all the message handling is handled as usual.
a custom control is something you've built from the ground up.
-c
Garbage collection, making life better - for weenies!
|
|
|
|
|
It's probably good to mention one you omitted: superclassing.
A window is created by the OS as a thing with a callback procedure
and some data. The template for creation of this object is called the
windows class. (not related to c++ class. a window class is just
a spec sheet basically.)
Here's the jist:
SUBCLASSING: Have OS create a window from class X. Replace its callback
with your own. Take care of business in your callback and then pass
off to the replaced callback. (You won't be able to intercept creation
messages since that happens before you subclass.)
~ CREATE, REPLACE CALLBACK, HANDLE MSG, RELAY TO OLD
SUPERCLASSING: Register a new window class Y derived from X. This new
class extends an old class. Your callback gets called first even for
creation messages. You can still pass off to the old callback.
~ REGISTER CLASS, CREATE, HANDLE MSG, RELAY TO OLD
OWNER DRAW: Have OS create a window from class X. Set some data in the
window that lets its callback know that you want to handle some drawing.
The windows callback will route a message allowing you do drawing in
you message handling.
~ CREATE, HANDLE OWNER DRAW MSG
CUSTOM CONTROLS: Just an original window class and callback.
~ REGISTER CLASS, CREATE, HANDLE MSG
I'm probably missing some details.
|
|
|
|
|
I have been doing a bit of detective work on this problem, and have found 2 things that puzzle me ( a bit of an understatement).
First of all, the value of hwnd returned to EnumChildProc() always seems to be the value of lparam supplied to EnumChildWindows(). As if that wasn't bizarre enough, I have found that whilst in EnumChildProc() the value reported for 'this' in the variables window of the debugger changes on the four calls !!
As I have just discovered Spy++, I used the WindowFinder tool to establish the handles for all windows within my application. Would you believe that the four values (Caption and Client area for each of the two documents) corresponds to the 4 values of 'this'. (Yes, yes - I KNOW that one is a handle and the other is a constant pointer to the Document - that's what's so bewildering. More than a coincidence, don't you think ??) I believe this a BIG clue to someone who has more more experience than me.
H E L P !!!!!! (This problem is driving me NUTS !!!!)
My current code is as follows :-
(Incidently, I tried moving these 2 routines from the Document into the View, but it gives exactly the same sort of results)
void CIRCDoc::OnTapeMove()
{
// TODO: Add your command handler code here
CMDIFrameWnd *pFrame = (CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;
// HWND hWndParent = pFrame->GetSafeHwnd();
// pFrame->SetWindowText("Hello Mum !!"); // DOES set mainframe title
// BOOL bResult = FALSE;
// LPARAM lParam = (LPARAM)(&bResult);
// BOOL rc = EnumChildWindows(hWndParent, EnumChildProc, lParam);
DWORD param = 0;
LPARAM lParam = 0; //(LPARAM)(¶m);
BOOL rc = EnumChildWindows(pFrame->m_hWndMDIClient, EnumChildProc, lParam);
}
BOOL CALLBACK CIRCDoc::EnumChildProc(HWND hwnd, LPARAM lparam)
{ TCHAR* pSaveText = new TCHAR[20+1];
BOOL rc = GetWindowText(hwnd,pSaveText,20);
DWORD wErrorResult = 0;
if(!rc)
wErrorResult = GetLastError();
delete pSaveText;
return TRUE; // keeps enumeration going
//SendMessage(hwnd,WM_SETTEXT,0,(LPARAM)"Test");
}
Doug
|
|
|
|
|
Apologies !! I accidently posted this as a new thread rather than an addition to my previous thread entitled "Problem with EnumChildWindows" of 25th June (I think ??)
Doug
|
|
|
|
|
Hello there,
I hope someone has a clue how to solve this problem. I want to 'stop' a PCMCIA card (IDE flash card) so that the user can remove it without a message popping up. You can 'stop' the device with the little icon in the taskbar but I want to provide this functionality in my software. Someone must have had this problem before...
An extensive search on MSDN found nothing, maybe it is a Plug-and-Play problem, maybe it is a 'configuration manager' problem, but I found no sample or code.
Thanks for you help in advance.
Josef
Josef Schroettle
|
|
|
|
|
Hi All,
Can anybody help me out in creating a toolbar in a regular DLL. I have two
modules, first the main exe file, and the second is the DLL.
the Main app loads the DLL, and then invokes CreateToolBar(HWND hWnd), and
passed AfxGetApp()->m_pMainWnd->m_hWnd as the handle of the mainframe window...
But the code to create toolbar asserts... so i tried to comment code which
does the docking part. Now the code does not assert but toolbar is not shown.
I even tried to use ShowWindow(SW_SHOW) on it, but no result...
Please any help in this regard would be great...
Thanks in advance,
Mohit
|
|
|
|
|
I take it that the toolbar resource is in the DLL? If it is, make sure that before creating the toolbar that you have switched to the DLL's resources.
Take a look at the AFX_MANAGE_STATE() macro in the MSDN.
Roger Allen
Sonork 100.10016
If I had a quote, it would be a very good one.
|
|
|
|
|
Hi Allen,
Lemme explain a bit more... The CreateToolBar() method is a member of CPlug_In_App class within the DLL... and this method is responsible for creating the toolbar... not the EXE... I had put AFX_MANAGE_STATE(.....) macro in this function.. but in vain... still the code does not asert but toolbar is not shown... i have comented the code for docking the toolbar... is it not possible to dock the toolbar from within the DLL??? i don't think so.. something must be wrong.. here is the code... the OnCmdMsg() calls
createtoolbar() method... is something wrong????
// I am passing AfxGetApp()->m_pMainWnd->m_hWnd... to the DLL which is then casted to (CMainFrame *) ---->>> m_pFrame
// m_pFrame is CMainFrame *
BOOL CPlug_In_1App::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
#ifdef DEBUG
TRACE("Called CPlug_In_1App::OnCmdMsg() method\n");
#endif
if (!CreatePlugInToolBar())
{
AfxMessageBox("Could not create PlugIn_1's toolbar");
}
// TODO: Add your specialized code here and/or call the base class
return CWinApp::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
bool CPlug_In_1App::CreatePlugInToolBar()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (!m_bIsToolBarCreated)
{
if (!m_wndPlugInToolBar.CreateEx(m_pFrame, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_SIZE_DYNAMIC) ||
!m_wndPlugInToolBar.LoadToolBar(IDR_PLUGIN_1))
{
#ifdef DEBUG
TRACE0("Failed to create toolbar\n");
#endif
return false; // fail to create
}
// TODO: Delete these three lines if you don't want the toolbar to be dockable
m_wndPlugInToolBar.SetOwner(m_pFrame);
// m_wndPlugInToolBar.EnableDocking(CBRS_ALIGN_ANY);
// EnableDocking(CBRS_ALIGN_ANY);
// m_pFrame->DockControlBar(&m_wndPlugInToolBar);
m_wndPlugInToolBar.ShowWindow(SW_SHOW);
m_bIsToolBarCreated = TRUE;
}
return true;
}
Thanks in advance...
-Mohit
|
|
|
|
|
I tackled this problem in one of my own apps. Here is the code I had to load the toolbars from the main program and dock them. Note that you may need to call ShowControlBar() to cause the toolbar(s) to be displayed the first time you run your code.
CToolBar **m_pTB ;
int m_ToolbarCount ;
void CMainFrame::LoadDLLToolbars()
{
CToolBar *last = &m_wndMainToolBar ;
int count = 0 ;
for (int DLL_index = 0 ; DLL_index < refineDLLs ; DLL_index++)
{
if (refineDLL[DLL_index].DLLGetToolbarCount != 0 && refineDLL[DLL_index].DLLGetToolbar != NULL)
{
count += refineDLL[DLL_index].DLLGetToolbarCount() ;
}
}
if (count > 0)
{
m_pTB = new CToolBar*[count] ;
m_DLLIndexes = new int[count] ;
}
int index = 0 ;
for (DLL_index = 0 ; DLL_index < refineDLLs ; DLL_index++)
{
if (refineDLL[DLL_index].DLLGetToolbarCount != 0 && refineDLL[DLL_index].DLLGetToolbar != NULL)
{
for (int i = 0 ; i < refineDLL[DLL_index].DLLGetToolbarCount() ; i++)
{
m_pTB[index] = refineDLL[DLL_index].DLLGetToolbar(i, this) ;
DockControlBar(m_pTB[index]) ;
last = m_pTB[index] ;
m_DLLIndexes[index] = DLL_index ;
index++ ;
}
}
}
m_ToolbarCount = count ;
}
CMainFrame::~CMainFrame()
{
for (int i = 0 ; i < m_ToolbarCount ; i++)
delete m_pTB[i] ;
delete []m_pTB ;
delete []m_DLLIndexes ;
}
int DLLGetToolbarCount()
{
return 1 ;
}
CToolBar* DLLGetToolbar(int index, CWnd *pMP)
{
if (index != 0)
return NULL ;
HINSTANCE hInstance = AfxGetResourceHandle();
AfxSetResourceHandle(theApp.m_hInstance);
CToolBar *pTB = new CToolBar ;
if (!pTB->CreateEx(pMP, TBSTYLE_FLAT, WS_CHILD | CBRS_ALIGN_TOP, CRect(0, 0, 0, 0), IDR_TRAYTOOLBAR) ||
!pTB->LoadToolBar(IDR_TRAYTOOLBAR))
{
TRACE0("Failed to create toolbar\n");
AfxSetResourceHandle(hInstance);
return NULL ;
}
pTB->SetBarStyle(pTB->GetBarStyle() | CBRS_BORDER_3D) ;
pTB->EnableDocking(CBRS_ALIGN_ANY);
pTB->SetWindowText("TraySetup & Communication");
pTB->EnableToolTips(TRUE) ;
g_pTraySetupToolbar = pTB ;
AfxSetResourceHandle(hInstance);
return pTB ;
}
Hope it helps.
Roger Allen
Sonork 100.10016
If I had a quote, it would be a very good one.
|
|
|
|
|
Hi Allen,
I tried it, but now it asserts at CDockContext::CDockContext()...
ASSERT(pBar->m_pDockSite != NULL);
The docksite for my toolbar is NULL....
This code is called by the EnableDocking Method()....
There is really something wrong... Is it valid to pass AfxGetApp()->m_pMainWnd->m_hWnd to DLL's fucntion... and then convert it into (CWnd *) and then use it as the mainframe???
Please help in this...
Now my code is...
bool CPlug_In_1App::CreatePlugInToolBar()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HINSTANCE hInstance = AfxGetResourceHandle();
// set resource handle to ourselves (the DLL)
AfxSetResourceHandle(theApp.m_hInstance);
if (!m_wndPlugInToolBar.CreateEx(m_pFrame, TBSTYLE_FLAT, WS_CHILD|CBRS_ALIGN_TOP, CRect(0, 0, 0, 0), IDR_PLUGIN_1)
|| !m_wndPlugInToolBar.LoadToolBar(IDR_PLUGIN_1))
{
TRACE0("Failed to create toolbar\n");
// reset resource handle
AfxSetResourceHandle(hInstance);
return NULL;
// fail to create
}
//lose garnage pixels
m_wndPlugInToolBar.SetBarStyle(m_wndPlugInToolBar.GetBarStyle()|CBRS_BORDER_3D);
m_wndPlugInToolBar.EnableDocking(CBRS_ALIGN_ANY);
m_wndPlugInToolBar.SetWindowText("TraySetup & Communication");
m_wndPlugInToolBar.EnableToolTips(TRUE);
// reset resource handle
AfxSetResourceHandle(hInstance);
retrun true
}
-Mohit
|
|
|
|
|
3 possible things:
1. Check out your registry entries for LoadBarState()/SaveBarState(). You can have problems if your trying to load a state that is invalid for the new configuration of toolbars. Just delete all the toolbar position registry entries.
2. Are you using MFC in a DLL for both the DLL and EXE projects?
3. In my code I new the CToolbar object and return a pointer to it. In yours its part of the DLL app object. Their could be a problem accessing this memory from the exe file. Create the object on the heap and return a pointer to it.
HTH
Roger Allen
Sonork 100.10016
If I had a quote, it would be a very good one.
|
|
|
|
|
Hi Roger,
I am not saving Barstate in the registry...
Yes, i am using MFC for both DLL and EXE... is this creating probs???
and the third point you mentioned... might be the problem.. is it possible that this would create probs.... Since one thing i want to know...
In one other method.. i had created a button (appened a button) to the default toolbar) from the DLL... here also i did from DLL.. the button shows and works without probs...
But stillif this prob is not solved this way, then ithink i would be changing the code referring your code... creating a pointer and return it...
One more thing... so if your method works out, then do I assume that all of the Plug-Ins written for various apps like MS Office, Winamp, VS 7.0, etc do it this way... (i mean, that their main app takes care of calling CreateToolBar() method???)
I would be now trying your way, and would let you know of any probs...
Thanks a lot for your valuable time,
Regards,
Mohit
|
|
|
|
|
I want to access remote database(SQL Server) on a different Lan.I am working on ATL.How do I do it??
|
|
|
|
|