15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


saving/restoring toolbars

PP mail system -- LAWSONW@sydney.ccur.com
Friday, October 11, 1996

G'day!
Unless you can make use of CDockState View-to-View I reckon
you've got trouble.  See previous threads for mention of
CMiniDockFrameWnd and CDockBar.  As Microsoft has not documented
these Classes, presumably sometime in the future the whole basis
for toolbar-handling could change.  If, however, you're content to risk
that,

      if  (m_pToolBar->GetParentOwner()  == this)

in CMainFrame, then the CDockBar parent is docked, else floating in a
CMiniDockFrameWnd.  You could fight your way back through the hierarchy
to find out where everything is.

It should be no great trick to SW_SHOW/HIDE a particular toolbar.  If
you're docked, m_pToolBar->ShowWindow(...), else use the ParentOwner.

However, given that you are 2 levels removed from the floating-frame
CLOSE message, offhand I can't think of any way of preventing the User
from closing a bar other than by peeking at the message-queue, and
ripping up CLOSEs addressed to the floating frame.

Regards,
Jim LW

                          Forwarded Mail Item.
========================================================================
Subject:dynamically saving/restoring too   Created by: /Gateway ocpt
Message:Message-Id: <9610081900.AA24569@cra11.noname>
        To: mfc-l@netcom.com
        Subject: dynamically saving/restoring toolbar state
        Errors-To: owner-mfc-l@majordomo.netcom.com
        Precedence: bulk
        Reply-To: mfc-l@netcom.com
        Sender: owner-mfc-l@majordomo.netcom.com
        From: pburbano@cra11.cambridge.com (Patricio Burbano)
========================================================================
Send to:  LAWSONW


Dated at:  15:00    on  8 October 96

Environment: VC++ 4.2, NT 4.0

Hi all,

I have an SDI application that has more than one view for a document.
The frame window creates a set of toolbars that are going to be
shared by all the views.
At any time, the user should be able to dock/undock, hide/show the
toolbars.
I would like to be able to save the state of the toolbars for each
view dynamically.  This means for example, that with view1,
toolbar1 is docked, and with view2 toolbar1 is floating.  I would
like the toolbars to return to the state the user left them for
each view, when views change.

I am able to find out most of the information I need from the toolbars
before I change from one view to the next.  However, I can not seem
to find out on which side of the frame window a particular toolbar
was docked to.

I would like not to have to destroy and create the toolbars every
time the user changes views.

Any ideas on how to do this?



Greg Lee ID -- GLee@kollmorgen.com
Tuesday, November 05, 1996

Environment: VC 4.0, Win95

I am attempting to maintain the state of the toolbars in one of my
programs from run to run.  I have attempted to do this by adding a
handler to OnDestroy through the class wizard:

void CMainFrame::OnDestroy() 
{
	m_wndToolBar.GetToolBarCtrl().SaveState( HKEY_CURRENT_USER,
"KMTGeditor", "MainToolbar");
	m_wndWizardToolBar.GetToolBarCtrl().SaveState( HKEY_CURRENT_USER,
"KMTGeditor", "WizardToolbar");
	m_wndDebugToolBar.GetToolBarCtrl().SaveState( HKEY_CURRENT_USER,
"KMTGeditor", "DebugToolbar");
	m_wndModeToolBar.GetToolBarCtrl().SaveState( HKEY_CURRENT_USER,
"KMTGeditor", "ModeToolbar");
	
	CMDIFrameWnd::OnDestroy();
}

My CMainFrame::OnCreate() has the following code repeated for each of
the toolbar mentioned above:

	if (!m_wndWizardToolBar.Create(this,
			WS_CHILD | WS_VISIBLE | CBRS_TOP, ID_VIEW_WIZARD_TOOLBAR) ||
		!m_wndWizardToolBar.LoadToolBar(IDR_WIZARD_TOOLBAR))
	{
		TRACE0("Failed to create wizard toolbar\n");
		return -1;      // fail to create
	}

	m_wndWizardToolBar.SetBarStyle(m_wndWizardToolBar.GetBarStyle() |
		CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
	m_wndWizardToolBar.EnableDocking(CBRS_ALIGN_ANY);
// **** here is the call to restore the toolbar state ... probably not
good idea to use "KMTGeditor" as the key, pick a new one ****
	m_wndWizardToolBar.GetToolBarCtrl().RestoreState( HKEY_CURRENT_USER,
"KMTGeditor", "WizardToolbar");
	DockControlBar(&m_wndWizardToolBar);



Problem: My toolbars are micro-scopic.  Obviously my RestoreState call
is not working properly.  Is OnDestroy the proper place to save the
toolbars?  Or do I have something else wrong?  I have experimented with
the CCS_ADJUSTABLE style ORing it in with the rest of the style flags
(in both the Create and the SetBarStyle calls).  I have not been able to
find a place in the documentation that explicitly says you need to use
this style if you want to Save/Restore, although most of the mentions of
RestoreState and SaveState are in toolbar customization sections (to
support TBN_RESET).

Greg Lee
glee@kollmorgen.com




Roger Onslow/Newcastle/Computer Systems Australia/
Thursday, November 07, 1996

[Mini-digest: 5 responses]

>I am attempting to maintain the state of the toolbars in one of my
>programs from run to run.  I have attempted to do this by adding a
>handler to OnDestroy through the class wizard:
>
>void CMainFrame::OnDestroy() 
>{
> m_wndToolBar.GetToolBarCtrl().SaveState( HKEY_CURRENT_USER,
>"KMTGeditor", "MainToolbar");
> m_wndWizardToolBar.GetToolBarCtrl().SaveState( HKEY_CURRENT_USER,
>"KMTGeditor", "WizardToolbar");
> m_wndDebugToolBar.GetToolBarCtrl().SaveState( HKEY_CURRENT_USER,
>"KMTGeditor", "DebugToolbar");
> m_wndModeToolBar.GetToolBarCtrl().SaveState( HKEY_CURRENT_USER,
>"KMTGeditor", "ModeToolbar");
> CMDIFrameWnd::OnDestroy();
>}
>
>My CMainFrame::OnCreate() has the following code repeated for each of
>the toolbar mentioned above:
>
> if (!m_wndWizardToolBar.Create(this,
>   WS_CHILD | WS_VISIBLE | CBRS_TOP, ID_VIEW_WIZARD_TOOLBAR) ||
>  !m_wndWizardToolBar.LoadToolBar(IDR_WIZARD_TOOLBAR))
> {
>  TRACE0("Failed to create wizard toolbar\n");
>  return -1;      // fail to create
> }
>
> m_wndWizardToolBar.SetBarStyle(m_wndWizardToolBar.GetBarStyle() |
>  CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
> m_wndWizardToolBar.EnableDocking(CBRS_ALIGN_ANY);
>// **** here is the call to restore the toolbar state ... probably not
>good idea to use "KMTGeditor" as the key, pick a new one ****
> m_wndWizardToolBar.GetToolBarCtrl().RestoreState( HKEY_CURRENT_USER,
>"KMTGeditor", "WizardToolbar");
> DockControlBar(&m_wndWizardToolBar);
>
>Problem: My toolbars are micro-scopic.  Obviously my RestoreState call
>is not working properly.  Is OnDestroy the proper place to save the
>toolbars?  Or do I have something else wrong?  I have experimented with
>the CCS_ADJUSTABLE style ORing it in with the rest of the style flags
>(in both the Create and the SetBarStyle calls).  I have not been able to
>find a place in the documentation that explicitly says you need to use
>this style if you want to Save/Restore, although most of the mentions of
>RestoreState and SaveState are in toolbar customization sections (to
>support TBN_RESET).
>
>Greg Lee
>glee@kollmorgen.com
========================================
Here's what I do in my main frame class (and I use SetRegistryKey() in my 
Application to make sure that the registry is used rather than .INI files)...  
NOTE: This is hacked from my own classes with irrelevant stuff removed - 
hopefully I haven't also removed any relevant stuff as well :-)

// NOTE: I declare the following routines as virtual
// and override for each application I build.  That way
// I can have a lot of common functionality in my base
// mainframe class and then derive for each app
//
// the code for each one is pretty much taken from
// the standard app-wizard code for OnCreate

BOOL CMyMainFrame::CreateToolbars() {
 // create toolbars here here
}

BOOL CMyMainFrame::CreateStatusbar() {
 // create status bar here
}

void CMyMainFrame::DockToolbars() {
 // do all the initial docking of toolbars here
}

BOOL CMyMainFrame::LoadBarState(LPCTSTR name) {
 CDockState state;
 state.LoadState(name);
 // note: without this if number of toolbars changes
 // the application will assert and die.
 // this way, if something goes wrong
 // it reverts back to default settings
 if (EnsureValidDockState(state)) { // checks for valid so won't ASSERT
  SetDockState(state);
 } else {
  DockToolbars();
 }
 // note: here I check that all toolbars are correctly restored
 // if not, then I return FALSE
 // but I won't include that code here
 return TRUE;
}

BOOL CMyMainFrame::EnsureValidDockState(CDockState& state) {
 for (int i = 0; i < state.m_arrBarInfo.GetSize(); i++) {
  CControlBarInfo* pInfo = (CControlBarInfo*)state.m_arrBarInfo[i];
  if (! pInfo) return FALSE;
  if (! pInfo->m_bFloating) {
   pInfo->m_pBar = GetControlBar(pInfo->m_nBarID);
   if (!pInfo->m_pBar) return FALSE; //toolbar id's probably changed
  }
 }
 return TRUE;
}

// bug fix for control bar state (is it fixed in 4.2 yet???)
// without the the registry fills up
#if _MFC_VER == 0x0400 || _MFC_VER == 0x0410
static void CleanUpControlBarState(CDockState& state) {
    for (int i = 0; i < state.m_arrBarInfo.GetSize(); i++) {
        CControlBarInfo* pInfo1 = (CControlBarInfo*)state.m_arrBarInfo[i];
        for (int j = 0; j < state.m_arrBarInfo.GetSize(); j++) {
            if (i == j) continue;
            CControlBarInfo* pInfo2 = (CControlBarInfo*)state.m_arrBarInfo[j];
            if (pInfo1->m_uMRUDockID == pInfo2->m_nBarID) continue;
            int nSize = pInfo2->m_arrBarID.GetSize();
            for (int k = 0; k < nSize - 1; k++) {
                if ((LONG)pInfo2->m_arrBarID[k] == (LONG)pInfo1->m_nBarID + 
0x10000) {
                    pInfo2->m_arrBarID[k] = NULL;
                }
            }
        }
    }
    for (i = 0; i < state.m_arrBarInfo.GetSize(); i++) {
        CControlBarInfo* pInfo = (CControlBarInfo*)state.m_arrBarInfo[i];
        int nSize = pInfo->m_arrBarID.GetSize();
        for (int j = 0; j < nSize - 1; j++) {
            if (pInfo->m_arrBarID[j]==NULL) continue;
            for (int k = j + 1; k < nSize; k++) {
                if (pInfo->m_arrBarID[k]==NULL) continue;
                if (pInfo->m_arrBarID[k]==pInfo->m_arrBarID[j]) {
                    pInfo->m_arrBarID[k] = NULL;
                }
            }
        }
  
        while ((nSize!=0) && (pInfo->m_arrBarID[nSize-1]==NULL)) {
            nSize--;
            pInfo->m_arrBarID.RemoveAt(nSize);
        }
        if (nSize) pInfo->m_arrBarID.InsertAt(nSize, (void*)NULL);
    }
}
#endif

void ::SaveBarStateForFrame(const CFrameWnd* pFrame, LPCTSTR lpszProfileName) {
 CDockState state;
 pFrame->GetDockState(state);
// not sureabout 4.2 yet !!!, but requied for 4.0,4.1
#if _MFC_VER == 0x0400 || _MFC_VER == 0x0410
 CleanUpControlBarState(state);
#endif
 state.SaveState(lpszProfileName);
}

void CMyMainFrame::OnDestroy() {
 ::SaveBarStateForFrame(this,"Toolbars");
 CFrameWnd::OnDestroy();
}

int CMyMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
 if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;
 if (! CreateStatusbar()) return -1; // create statusbar
 if (! CreateToolbars()) return -1; // create the toolbars
 EnableDocking(CBRS_ALIGN_ANY);
 DockToolbars();
 if (! LoadBarState("Toolbars",TRUE,NumToolbars())) return -1;
 return 0;
}


Hope this helps

Roger
-----From: Manolis Papadopoulos 

Hello,

have you seen the example DOCKTOOL on the VC4.0 CD in =
"\msdev\samples\mfc\general"? I had similar problems and it helped a =
lot. You should know however that, as stated in previous messages to =
this list, LoadBarStyle does NOT work properly if the toolbar is a =
resource toolbar, that is, it is not created by the program, as is the =
case in DOCKTOOL. I pretty sure there are other older messages about =
this subject, which you can get if you visit advn.com/pub/mfc/. There is =
an archive of ALL the messages to this list.

Best Regards,

Manolis Papadopoulos

-----From: Carl Gunther 

Greg,

A good place to save things like window placements is
the OnClose() function of your CFrameWnd-derived class.

Carl

-----From: "Robert H. Mowery III" 

Greg, 

If I understand your question correctly you are simply trying to save the
settings of the toolbars when a user exits your program and then next time
through you want to restore those same settings of the toolbar.  There is a
very good exple of this presented in the VC++ samples.  You should look at
the DockTool sample and the code can be found in Mainframe.cpp. I think you
are going through more trouble then you need to with the code you are
trying to implement.

-Robert

-----From: browkl@inel.gov (Kenneth L Brown)

Here's a couple things you can try.

After setting your toolbar positions call AutoSize().  This is a member
of CToolBarCtrl.  You can get to the CToolBarCtrl for your toolbar by
calling GetToolBarCtrl, something like
m_wndToolBar.GetToolBarCtrl().AutoSize();

If this does not solve your problem you may need to override the
RecalcLayout member function of your frame window.  I used the
undocumented function GetBarInfo to have more control of the toolbar
positioning.  It takes a reference to CControlBarInfo as the only
argument.  These definitions are found in \msdev\mfc\src\dockstat.cpp
and \msdev\mfc\include\Afxpriv.h respectively.  My guess is they are
undocumented because they are used by the docking serialization but I
had problems getting that to work in my case.

CControlBarInfo has member variables m_rectMRUDockPos that gives you the
most recently used docking positon and m_ptMRUFloatPos that gives you
the most recently used floating position.  These are valid only after
the bar has been positioned obviously.

GetBarStyle will give you the current docking state.  These functions
should allow you to roll your own docking procedure.

You could save the positioning to the registry in your RecalcLayout
function which will happen anytime the user moves a toolbar or makes a
change to the frame window, or you could save the data to member
variables and commit those variables to the registry in the frame
destructor which is what I did.  Seemed to work fine.

You will still need to call AutoSize() after positioning your toolbars.  

Hope this wasn't too long winded but it took me a while to figure this
stuff out.




alan ismail -- alan.ismail@imagin1.com
Tuesday, November 12, 1996



Greg,

I had similar problems. I wasted a call to MS only to have the guy build a 
sample (CTRLBARS?) and see that it was indeed broken. MS confirmed that there 
was a hairy bug in the MFC code: "Yep, it's not working."  A little while later,
VC++ 4.1 came out and guess what?  It just so happened to have a new class 
called CDockState that takes care of the problems. 8^}  

BTW: there is no mention of this problem in any 4.0 documentation that I can 
find.  The closest thing is for VC 2.x (Q138722).  

So, if you can get the latest VC you should be set. Or you can always roll your 
own.

Later,
Alan
alan.ismail@imagin1.com
http://www.inngames.com



______________________________ Reply Separator _________________________________
Subject: Saving/Restoring ToolBars
Author:  mfc-l@netcom.netcom.com at Internet
Date:    11/6/96 8:00 PM


Environment: VC 4.0, Win95

I am attempting to maintain the state of the toolbars in one of my 
programs from run to run.  I have attempted to do this by adding a 
handler to OnDestroy through the class wizard:

void CMainFrame::OnDestroy() 
{
 m_wndToolBar.GetToolBarCtrl().SaveState( HKEY_CURRENT_USER,
"KMTGeditor", "MainToolbar");
 m_wndWizardToolBar.GetToolBarCtrl().SaveState( HKEY_CURRENT_USER,
"KMTGeditor", "WizardToolbar");
 m_wndDebugToolBar.GetToolBarCtrl().SaveState( HKEY_CURRENT_USER,
"KMTGeditor", "DebugToolbar");
 m_wndModeToolBar.GetToolBarCtrl().SaveState( HKEY_CURRENT_USER,
"KMTGeditor", "ModeToolbar");

 CMDIFrameWnd::OnDestroy();
}

My CMainFrame::OnCreate() has the following code repeated for each of 
the toolbar mentioned above:

 if (!m_wndWizardToolBar.Create(this,
   WS_CHILD | WS_VISIBLE | CBRS_TOP, ID_VIEW_WIZARD_TOOLBAR) ||
  !m_wndWizardToolBar.LoadToolBar(IDR_WIZARD_TOOLBAR))
 {
  TRACE0("Failed to create wizard toolbar\n"); 
  return -1;      // fail to create
 }

 m_wndWizardToolBar.SetBarStyle(m_wndWizardToolBar.GetBarStyle() |
  CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
 m_wndWizardToolBar.EnableDocking(CBRS_ALIGN_ANY);
// **** here is the call to restore the toolbar state ... probably not 
good idea to use "KMTGeditor" as the key, pick a new one ****
 m_wndWizardToolBar.GetToolBarCtrl().RestoreState( HKEY_CURRENT_USER,
"KMTGeditor", "WizardToolbar");
 DockControlBar(&m_wndWizardToolBar);



Problem: My toolbars are micro-scopic.  Obviously my RestoreState call 
is not working properly.  Is OnDestroy the proper place to save the 
toolbars?  Or do I have something else wrong?  I have experimented with 
the CCS_ADJUSTABLE style ORing it in with the rest of the style flags 
(in both the Create and the SetBarStyle calls).  I have not been able to 
find a place in the documentation that explicitly says you need to use 
this style if you want to Save/Restore, although most of the mentions of 
RestoreState and SaveState are in toolbar customization sections (to 
support TBN_RESET).

Greg Lee
glee@kollmorgen.com




Roger Onslow/Newcastle/Computer Systems Australia/
Thursday, November 14, 1996

>I had similar problems. I wasted a call to MS only to have the guy build a 
>sample (CTRLBARS?) and see that it was indeed broken. MS confirmed that there 
>was a hairy bug in the MFC code: "Yep, it's not working."  A little while 
later,
>VC++ 4.1 came out and guess what?  It just so happened to have a new class 
>called CDockState that takes care of the problems. 8^}  
>
>BTW: there is no mention of this problem in any 4.0 documentation that I can 
>find.  The closest thing is for VC 2.x (Q138722).  
>
>So, if you can get the latest VC you should be set. Or you can always roll 
your 
>own.

BTW: CBockState was waround earlier, but was not a documented MFC class

I found this in KB, along with a solution which I have included below (massaged 
from the original by me and cut from my working code).

(Also see my earlier response to this topic -- assuming it made it thru to the 
list)

// bug fix for control bar state (is it fixed in 4.2 yet???)
// without the the registry fills up
#if _MFC_VER == 0x0400 || _MFC_VER == 0x0410
static void CleanUpControlBarState(CDockState& state) {
    for (int i = 0; i < state.m_arrBarInfo.GetSize(); i++) {
        CControlBarInfo* pInfo1 = (CControlBarInfo*)state.m_arrBarInfo[i];
        for (int j = 0; j < state.m_arrBarInfo.GetSize(); j++) {
            if (i == j) continue;
            CControlBarInfo* pInfo2 = (CControlBarInfo*)state.m_arrBarInfo[j];
            if (pInfo1->m_uMRUDockID == pInfo2->m_nBarID) continue;
            int nSize = pInfo2->m_arrBarID.GetSize();
            for (int k = 0; k < nSize - 1; k++) {
                if ((LONG)pInfo2->m_arrBarID[k] == (LONG)pInfo1->m_nBarID + 
0x10000) {
                    pInfo2->m_arrBarID[k] = NULL;
                }
            }
        }
    }
    for (i = 0; i < state.m_arrBarInfo.GetSize(); i++) {
        CControlBarInfo* pInfo = (CControlBarInfo*)state.m_arrBarInfo[i];
        int nSize = pInfo->m_arrBarID.GetSize();
        for (int j = 0; j < nSize - 1; j++) {
            if (pInfo->m_arrBarID[j]==NULL) continue;
            for (int k = j + 1; k < nSize; k++) {
                if (pInfo->m_arrBarID[k]==NULL) continue;
                if (pInfo->m_arrBarID[k]==pInfo->m_arrBarID[j]) {
                    pInfo->m_arrBarID[k] = NULL;
                }
            }
        }
  
        while ((nSize!=0) && (pInfo->m_arrBarID[nSize-1]==NULL)) {
            nSize--;
            pInfo->m_arrBarID.RemoveAt(nSize);
        }
        if (nSize) pInfo->m_arrBarID.InsertAt(nSize, (void*)NULL);
    }
}
#endif

static void SaveBarStateForFrame(const CFrameWnd* pFrame, LPCTSTR 
lpszProfileName) {
 CDockState state;
 pFrame->GetDockState(state);
// not sureabout 4.2 yet !!!, but requied for 4.0,4.1
#if _MFC_VER == 0x0400 || _MFC_VER == 0x0410
 CleanUpControlBarState(state);
#endif
 state.SaveState(lpszProfileName);
}

NOTE1: call SaveBarStateForFrame (make it external if required) to save you bar 
state.

NOTE2: the bug this fixes was that the registry/ini file section for toolbars 
would grow every time you saved toolbar state.

NOTE3: as noted in comments, I don't know if this patch is rquired under 4.2 -- 
hopefully they have fixed it.

Roger




| Вернуться в корень Архива |