Print Page | Close Window

SaveCommandBars creates hidden file?

Printed From: Codejock Forums
Category: Codejock Products
Forum Name: Toolkit Pro
Forum Description: Topics Related to Codejock Toolkit Pro
URL: http://forum.codejock.com/forum_posts.asp?TID=1142
Printed Date: 09 May 2024 at 11:07pm
Software Version: Web Wiz Forums 12.04 - http://www.webwizforums.com


Topic: SaveCommandBars creates hidden file?
Posted By: Ark42
Subject: SaveCommandBars creates hidden file?
Date Posted: 05 September 2004 at 6:23pm

Why does sometimes SaveCommandBars(_T("CommandBars")); creates a hidden file called like MyApp.exe-CommandBars
It also saves to the registry at the same time just fine, so I don't see why it needs this file also?




Replies:
Posted By: Sven
Date Posted: 08 September 2004 at 1:59am

There are some restrictions for the registry (taken from MSDN):

Windows 95/98/Me: The maximum size of a single registry value is 16,300 bytes. This limit includes the size of the data (cbData) and the size of the value name (lpValueName).

Windows 95/98/Me: There is a 64K limit for the total size of all values of a key.

So if your toolbar customization exceeds the limit the customization would not be stored. There is also a bug in NT4/2000 RegEdit, a value greater than 64K can't be exported/imported with RegEdit. So CodeJock decided to save the customization into a file if the size is larger than 16k (see CXTPCommandBars::SaveBarState).



Posted By: Oleg
Date Posted: 10 September 2004 at 2:04am

Right.

Also you can set the file name to be stored:

CXTPCommandBars::SetCustomizationDataFileName

You can check CustomThemes sample (from Toolkit Pro 9.10)

there is code how to store customize information to

\Documents and Settings\use\Local Settings\   folder

 



-------------
Oleg, Support Team
CODEJOCK SOFTWARE SOLUTIONS


Posted By: cpede
Date Posted: 10 September 2004 at 3:17am

Just a comment.

It is properly also a good idea NOT to save the file into the installation folder like "c:\program files\my program" etc, because you run into problems when running as Restricted User under Windows XP.

- cpede



Posted By: Ark42
Date Posted: 10 September 2004 at 11:23pm
Would it not be possible to chunk the data into 16000 byte pieces and store each piece under a different key?



Posted By: Ark42
Date Posted: 11 September 2004 at 12:20am
Well here is some sample code.  I see no point to saving to a hidden file if this works without issue on Win9x:

Everything in XTPDockState.cpp:

add up near the top:
AFX_STATIC_DATA const TCHAR _afxCommandBarSplit[] = _T("Split");

In CXTPCommandBars::SaveBarState:
remove everything from CString strFileName; to the else and add this before the else instead:
            if (dwCount > 16000)
            {
                int iNumChunks = dwCount / 16000;
                DWORD dwLastSize = dwCount % 16000;
                TCHAR buf[256];

                AfxGetApp()->WriteProfileBinary(szSec tion, _afxCommandBarControls, pControls, 16000);
                AfxGetApp()->WriteProfileInt(szSectio n, _afxCommandBarLoadFromFile, FALSE);
                AfxGetApp()->WriteProfileInt(szSectio n, _afxCommandBarSplit, iNumChunks);
                for (int i = 1; i < iNumChunks; i++)
                {
                    wsprintf(buf, "%s\\%d", szSection, i);
                    AfxGetApp()->WriteProfileBinary(buf, _afxCommandBarContr ols, pControls + (i * 16000), 16000);
                }
                wsprintf(buf, "%s\\%d", szSection, iNumChunks);
                AfxGetApp()->WriteProfileBinary(buf, _afxCommandBarControls, pControls + (iNumChunks * 16000), dwLastSize);

also add:
AfxGetApp()->WriteProfileInt(szSection, _afxCommandBarSplit, 0);
after the two lines in the else block

then in CXTPCommandBars::LoadBarState:
add all of this:
        } else if (AfxGetApp()->GetProfileInt(szSection, _afxCommandBarSplit, 0))
        {
            int iNumChunks = AfxGetApp()->GetProfileInt(szSection, _afxCommandBarSplit, 0);
            TCHAR buf[256];
            BYTE* pControls = NULL;
            BYTE* pTmp = NULL;
            UINT dwCount = 0;
            UINT dwTmp = 0;

            wsprintf(buf, "%s\\%d", szSection, iNumChunks);
            if (AfxGetApp()->GetProfileBinary(buf, _afxCommandBarControls, &pTmp, &dwTmp))
            {
                dwCount = dwTmp + (iNumChunks * 16000);
                pControls = new BYTE[dwCount];
                memcpy(pControls + (iNumChunks * 16000), pTmp, dwTmp);
                delete [] pTmp;

                BOOL bOk = TRUE;
                for (int i = 1; i < iNumChunks; i++)
                {
                    wsprintf(buf, "%s\\%d", szSection, i);
                    if (!AfxGetApp()->GetProfileBinary(buf, _afxCommandBarControls, &pTmp, &dwTmp) )
                    {
                        bOk = FALSE;
                        break;
                    }
                    if( dwTmp != 16000 ) {
                        delete [] pTmp;
                        bOk = FALSE;
                        break;
                    }
                    memcpy(pControls + (i * 16000), pTmp, 16000);
                    delete [] pTmp;
                }
                if (!AfxGetApp()->GetProfileBinary(szSection, _afxCommandBa rControls, &pTmp, &dwTmp) )
                {
                    bOk = FALSE;
                } else if( dwTmp != 16000 )
                {
                    delete [] pTmp;
                    bOk = FALSE;
                } else
                {
                    memcpy(pControls, pTmp, 16000);
                    delete [] pTmp;
                }

                if (bOk)
                {
                    CMemFile memFile(pControls, dwCount);

                    _LoadControlsPart(memFile, bSilent);
                   
                    memFile.Close();
                }
                delete [] pControls;
            }
right before the else block.


This will cause the info to be split into 16000 byte chunks, the first which is in the normal location, and the rest which are in subkeys numbered 1 to whatever the 'Split' value specifies.
Each chunk is in its own key with the value 'Controls' still.




Posted By: Sven
Date Posted: 11 September 2004 at 3:10am

MS doesn not recommend to store large values in registry. See remarks for RegSetValueEx in MSDN:

Value sizes are limited by available memory. Long values (more than 2048 bytes) should be stored as files with the file names stored in the registry. This helps the registry perform efficiently. Application elements such as icons, bitmaps, and executable files should be stored as files and not be placed in the registry.



Posted By: Ark42
Date Posted: 11 September 2004 at 10:44am

They may recommend that, but its not storing bitmaps or executables, just the position and text of the commands for the toolbars.  I don't see that its ever going to take up a large amount of space. Mine take up 18-19K it seems.  I hardly see that as a problem if it needs 2 regkeys because of a 16K limit.  Maybe the problem is the command bar information is not stored efficiently? Could it be changed to take up less space?  Why not at least make it an option to split the info in the registry?  I definately don't want hidden files, in the program files or the local settings directory.  I think I might be tempted to remove the option for the user to customize the toolbars if this would happen.  Does anybody really have toolbar files that take up something near 500K or something that would really make it inefficient?


Posted By: Sven
Date Posted: 11 September 2004 at 2:40pm

I had command bar streams with more than 160k base size, this produced the errors in W2k/W9x. If you change the icon of a command the customized icon is also be stored in this stream.

Imho there are some information which does not have to be stored in the stream (m_strTooltipText, m_strDescriptionText) because they can easily retrieved. But ist seems to be impossible to change the format because of the downward compatibility.

I slightly changed the command bar serialization in my apps, the stream is always stored into a file in the <Application Data\Company Name\Product Name> folder (only NT based systems). In W9x systems I use the folder where the application is installed. Further I added a menu command to export the settings (registry, bar state) into a selected folder.




Print Page | Close Window

Forum Software by Web Wiz Forums® version 12.04 - http://www.webwizforums.com
Copyright ©2001-2021 Web Wiz Ltd. - https://www.webwiz.net