// This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product. #include "stdafx.h" #include "afxsettingsstore.h" #include "afxrebar.h" #include "afxrebarstate.h" #define AFX_REBAR_FORMAT_KEY _T("Rebar-%ld") #define AFX_REBAR_KEY _T("RBI") #define AFX_REBAR_ID_KEY _T("IDs") BOOL CMFCReBarState::LoadRebarStateProc(HWND hwnd, LPARAM lParam) { // determine if this is a rebar: CWnd* pWnd = CWnd::FromHandle(hwnd); if (!pWnd->IsKindOf(RUNTIME_CLASS(CMFCReBar))) { return TRUE; } CReBarCtrl& rc = reinterpret_cast(pWnd)->GetReBarCtrl(); const UINT nBandInfoSize = reinterpret_cast(pWnd)->GetReBarBandInfoSize (); // retrieve our registry section: CString strRegSection = reinterpret_cast(lParam); CString strRebar; strRebar.Format(AFX_REBAR_FORMAT_KEY, GetWindowLong(rc.GetSafeHwnd(), GWL_ID)); strRegSection += strRebar; CSettingsStoreSP regSP; CSettingsStore& reg = regSP.Create(FALSE, TRUE); if (!reg.Open(strRegSection)) { return FALSE; } UINT nBands = 0; // attempt to load this rebar: REBARBANDINFO* aBandInfo = NULL; if (!reg.Read(AFX_REBAR_KEY, reinterpret_cast(&aBandInfo), &nBands)) { if (aBandInfo != NULL) { delete [] aBandInfo; } return TRUE; } LONG_PTR* aBandIds = NULL; if (!reg.Read(AFX_REBAR_ID_KEY, reinterpret_cast(&aBandIds), &nBands)) { delete [] aBandInfo; if (aBandIds != NULL) { delete [] aBandIds; } return TRUE; } // band count should be identical nBands /= sizeof(LONG_PTR); if (nBands != rc.GetBandCount()) { delete [] aBandInfo; delete [] aBandIds; return TRUE; } // reorder the bands: REBARBANDINFO rbi; for (int i = 0 ; i < (int)nBands ; i++) { // check all bands(in a release build the assert above won't fire if there's a mixup // and we'll happily do our best) for (int j = i; j < (int) rc.GetBandCount(); j++) { memset(&rbi, 0, nBandInfoSize); rbi.cbSize = nBandInfoSize; rbi.fMask = RBBIM_CHILD; rc.GetBandInfo(j, &rbi); if (aBandIds[i] != GetWindowLong(rbi.hwndChild, GWL_ID)) continue; if (i != j) rc.MoveBand(j, i); // make sure that unpersistable information is not used when setting the band info aBandInfo[i].lpText = NULL; aBandInfo[i].cch = 0; aBandInfo[i].hwndChild = NULL; aBandInfo[i].hbmBack = NULL; aBandInfo[i].lParam = NULL; aBandInfo[i].fMask &= ~(RBBIM_TEXT | RBBIM_CHILD | RBBIM_BACKGROUND | RBBIM_LPARAM); rc.SetBandInfo(i, &aBandInfo[i]); break; } } delete [] aBandInfo; delete [] aBandIds; return TRUE; } BOOL CMFCReBarState::SaveRebarStateProc(HWND hwnd, LPARAM lParam) { // determine if this is a rebar: CWnd* pWnd = CWnd::FromHandle(hwnd); if (!pWnd->IsKindOf(RUNTIME_CLASS(CMFCReBar))) { return TRUE; } CReBarCtrl& rc = reinterpret_cast(pWnd)->GetReBarCtrl(); const UINT nBandInfoSize = reinterpret_cast(pWnd)->GetReBarBandInfoSize (); // retrieve our registry section: CString strRegSection = reinterpret_cast(lParam); CString strRebar; strRebar.Format(AFX_REBAR_FORMAT_KEY, GetWindowLong(rc.GetSafeHwnd(), GWL_ID)); strRegSection += strRebar; CSettingsStoreSP regSP; CSettingsStore& reg = regSP.Create(FALSE, FALSE); if (!reg.CreateKey(strRegSection)) { return FALSE; } UINT nBands = rc.GetBandCount(); if (nBands == 0) { return TRUE; } #pragma warning(disable : 6211) REBARBANDINFO* aBandInfo = new REBARBANDINFO[nBands]; LONG_PTR* aBandIds = new LONG_PTR[nBands]; memset(aBandInfo, 0, nBands * nBandInfoSize); for (UINT i = 0; i < nBands; i++) { REBARBANDINFO& rbi = aBandInfo [i]; rbi.cbSize = nBandInfoSize; rbi.fMask = RBBIM_CHILD | RBBIM_ID | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_SIZE | RBBIM_STYLE | RBBIM_HEADERSIZE; rc.GetBandInfo(i, &aBandInfo[i]); // apparently fixed size bands mis-report their cxMinChildSize: rbi.cxMinChild += rbi.fStyle & RBBS_FIXEDSIZE ? 4 : 0; aBandIds[i] = (LONG_PTR)GetWindowLong(rbi.hwndChild, GWL_ID); rbi.hwndChild = 0; rbi.fMask ^= RBBIM_CHILD; } reg.Write(AFX_REBAR_KEY, reinterpret_cast(aBandInfo), nBands * sizeof(REBARBANDINFO)); reg.Write(AFX_REBAR_ID_KEY, reinterpret_cast(aBandIds), nBands * sizeof(LONG_PTR)); delete [] aBandIds; delete [] aBandInfo; #pragma warning(default : 6211) return TRUE; } void __stdcall CMFCReBarState::LoadState(CString& strRegKey, CFrameWnd* pFrame) { ASSERT_VALID(pFrame); EnumChildWindows(pFrame->GetSafeHwnd(), LoadRebarStateProc, (LPARAM)(LPCTSTR)strRegKey); } void __stdcall CMFCReBarState::SaveState(CString& strRegKey, CFrameWnd* pFrame) { ASSERT_VALID(pFrame); EnumChildWindows(pFrame->GetSafeHwnd(), SaveRebarStateProc, (LPARAM)(LPCTSTR)strRegKey); }