Thursday, May 17, 2012

Comodo Prevents Applications to Modify Windows Registry

Modifying Windows registry is a common task for applications. The installed Comodo Internet Security as the anti virus on my computer.  Each time I compile a native application and running it via the Embarcadero C++Builder, Comodo shows me a "Unrecognized Application" message and runs it in the Sand Box. 


I always click on the "Don't isolate it again" link on the Comodo message box. Usually after a few times of clicking on the mentioned link, Comodo will not show the message again. I thought that it remembers my answer and lets the application to run normally. 


When I called the functions which try to modify Windows registry, I noticed that it can not open the registry at all. This problem wastes lots of my time. I found that Comodo runs the application in the Sand Box, so it can not read or modify Windows registry keys values.


If you have such a kind of problem, check you anti virus which may prevent the application to have access to the Windows registry. For me, I disable the Defence+ feature of Comodo to be able to run the application normally when programming.



Sunday, May 6, 2012

Manage and Remove TRibbon pages and groups


When working with Embarcadero TRibbon component, usually we need to make several changes in the ribbon items including removing a ribbon page, making invisible the ribbon groups and items, and repositioning still visible ribbon groups.

Unfortunately, I couldn’t find straightforward methods in the Embarcadero’s TRibbon component to make these tasks easy to do (I am using C++Builder XE2 Update 3). So, I wrote some methods to solve them:

In this article, I supposed that you have an instance of TRibbon (named Ribbon1) on the current form (Form1) and all of the below methods are members of the form.

To remove a ribbon page (tab) from the ribbon, you can simply use the RemoveTab method of TRibbon class; but if you try to remove a page which has one or more ribbon groups, you will get unexpected access violation error messages. So you need to remove all of the groups in the page before removing the page:

void __fastcall TForm1::RemoveRibbonPage(TRibbonPage *Page)
{
    for(int i = Page->GroupCount - 1; i >= 0; i--)
        RemoveGroupItems(Page, (TRibbonGroup *)Page->Groups[i], false, true);

    Ribbon1->RemoveTab(Page->Caption);
}
//---------------------------------------------------------------------------

To remove ribbon group items, use the following method:

void __fastcall TForm1::RemoveGroupItems(TRibbonPage *Page, TRibbonGroup *Group, bool KeepVisible, bool RemoveIfEmpty)
{
    for(int j = Group->Items->Count - 1; j >= 0; j--)
    {
        if(!KeepVisible || !Group->Items->ActionClients[j]->Visible ||
           (Group->Items->ActionClients[j]->Separator && (j == Group->Items->Count - 1 || !j)))
            Group->Items->Delete(j);
    }

    RemoveExtraSeparators(Page, Group);

    if(RemoveIfEmpty && Group->Items->Count == 0)
        Page->RemoveControl(Group);
}
//---------------------------------------------------------------------------

The KeepVisible parameter indicates whether all of the group items should be removed, or just non-visible ones.
The RemoveIfEmpty parameter indicates whether to remove the ribbon group if there is no item available

When you delete only non-visible group items, some separator items may be still available as the first or last items of the group. They will be removed by calling the below method:

void __fastcall TForm1::RemoveExtraSeparators(TRibbonPage *Page, TRibbonGroup *Group)
{
    for(int j = Group->Items->Count - 1; j >= 0; j--)
    {
        if(Group->Items->ActionClients[j]->Separator &&
           (j == Group->Items->Count - 1 || !j))
            Group->Items->Delete(j);
    }
}
//---------------------------------------------------------------------------

When removing ribbon groups from a page, you may noticed that the width of the ribbon groups which have non-visible items will not be decreased, and you will see some empty spaces in the group. You need to permanently delete the group item from the memory. The below method, scans all of the pages, and removes all of the non-visible group items. By calling this method, extra group spaces will be collapsed.

void __fastcall TForm1::RemoveNonVisibleRibbonItems(void)
{
    TRibbonPage *Page;

    for(int i = 0; i < Ribbon1->Tabs->Count; ++i)
    {
        Page = (TRibbonPage *)Ribbon1->Tabs->Items[i]->Page;
        for(int j = Page->GroupCount - 1; j >= 0; j--)
        RemoveGroupItems(Page, (TRibbonGroup *)Page->Groups[j], true, true);
    }
}
//---------------------------------------------------------------------------

When you remove a group from a page, the group will be removed from the memory (I guess), but the basic information of the group will be kept in the page’s Groups list, so you will see empty spaces at the position of the removed ribbon groups. To correct this problem, simply change the index of the removed (non-visible) groups to put them at the end of the Groups items. This way, all of the groups will be arranged completely:

void __fastcall TForm1::MoveNonVisibleRibbonGroups(void)
{
    TRibbonPage *Page;
    int Index;
    int Counter;

    for(int i = 0; i < Ribbon1->Tabs->Count; ++i)
    {
        Page = (TRibbonPage *)Ribbon1->Tabs->Items[i]->Page;
        Index = FindMaxRibbonGroupIndex(Page) + 1;

        for(int j = 0; j < Page->GroupCount; ++j)
        {
            Counter = j;
            while(!Page->Groups[j]->Visible && Counter++ < Page->GroupCount)
            Page->Groups[j]->GroupIndex = ++Index;
        }
    }
}
//---------------------------------------------------------------------------

To set a group as the last item, of the ribbon page’s Groups list, you need to find the last index number used by the groups. Use FindMaxRibbonGroupIndex method to get the last index:

int __fastcall TForm1::FindMaxRibbonGroupIndex(TRibbonPage *Page)
{
    int ReturnValue = -1;

    for(int j = Page->GroupCount - 1; j >= 0; j--)
        ReturnValue = MAX(ReturnValue, Page->Groups[j]->GroupIndex);

    return ReturnValue;
}
//---------------------------------------------------------------------------

As a recommendation, you set the visibility of the group items you want to keep them on the ribbon, and call the below commands to arrange all of the remaining groups and group items completely:

RemoveNonVisibleRibbonItems();
MoveNonVisibleRibbonGroups();

Any comments on this article would be highly welcomed.