User ID:
Password:
Remember Me:
Forgot Password?
Not a member?
Click here for more information and to register.

    How to Save and Load a Windows Region with MFC



    This article is a small tip on how to save a Windows region to a file using CRgn::GetRegionData and how to load and re-create this saved region with CRgn::CreateFromData using MFC.

    SaveRegion

    The SaveRegion function (see below for the complete function) first will create a region. For demonstration purposes, it will create an elliptic region as follows:

    // Create some elliptic region as demonstration
    CRect rc;
    GetWindowRect(rc);
    CRgn rgn;
    rgn.CreateEllipticRgn(0, 0, rc.Width(), rc.Height());
    

    Before you can retrieve the region data with CRgn::GetRegionData, you need to figure out how much memory is required to hold the region data. This is done by calling CRgn::GetRegionData with the first parameter set to NULL. The first parameter is normally a pointer to memory where to store the region data. When this is NULL, the function will return the number of required bytes.

    // Get the size in bytes of our created region
    int iSize = rgn.GetRegionData(NULL, sizeof(RGNDATA));
    

    Now that you have the required memory size, you can allocate the right amount of memory and call CRgn::GetRegionData again but this time the first parameter will have a pointer to your allocated memory:

    // Allocate memory to hold the region data
    RGNDATA* pData = (RGNDATA*)calloc(iSize, 1);
    pData->rdh.dwSize = iSize;
    
    // Get the region data
    int iSize2 = rgn.GetRegionData(pData, iSize);
    // Sanity check
    if (iSize != iSize2)
       AfxMessageBox(_T("Something wrong with GetRegionData..."));
    

    In the code above, there is also a small check to make sure you got the right amount of information. Now, you have your region data stored in pData and can save this to a file as follows:

    // Save region data to a file
    CFile f(_T("test_region.rgn"), CFile::modeCreate | CFile::modeWrite);
    f.Write(pData, iSize);
    f.Close();
    
    Important Note: When opening the file, make sure to open it in binary mode. CFile, by default, opens the file in binary mode.
    Note: In production code, you will need to perform error checking on all file-related functions such as CFile::CFile and CFile::Write.

    After this, you can free your allocated memory with:

    // Free allocated memory
    free(pData);
    

    The full code of the SaveRegion function is shown below:

    void SaveRegion()
    {
       // Create some elliptic region as demonstration
       CRect rc;
       GetWindowRect(rc);
       CRgn rgn;
       rgn.CreateEllipticRgn(0, 0, rc.Width(), rc.Height());
    
       // Get the size in bytes of our created region
       int iSize = rgn.GetRegionData(NULL, sizeof(RGNDATA));
    
       // Allocate memory to hold the region data
       RGNDATA* pData = (RGNDATA*)calloc(iSize, 1);
       pData->rdh.dwSize = iSize;
    
       // Get the region data
       int iSize2 = rgn.GetRegionData(pData, iSize);
       // Sanity check
       if (iSize != iSize2)
          AfxMessageBox(_T("Something wrong with GetRegionData..."));
    
       // Save region data to a file
       CFile f(_T("test_region.rgn"), CFile::modeCreate | CFile::modeWrite);
       f.Write(pData, iSize);
       f.Close();
    
       // Free allocated memory
       free(pData);
    }
    

    LoadRegion

    The workflow to load the saved region is to load all the data back from the file in a memory buffer and then use CRgn::CreateFromData to create a region from this data.

    First, the file is opened and the size of the file is retrieved. This size will be used to allocated enough memory to load the entire file into memory.

    // Open file to read region data from
    CFile f(_T("test_region.rgn"), CFile::modeRead);
    
    // Get size of the file
    int iSize = f.GetLength();
    
    Important Note: When opening the file, make sure to open it in binary mode. CFile, by default, opens the file in binary mode.

    Now that you know the size of the data, you allocate your memory and read the entire file into your buffer as follows:

    // Allocate memory to hold the region data
    RGNDATA* pData = (RGNDATA*)calloc(iSize, 1);
    
    // Read region data from file
    f.Read(pData, iSize);
    f.Close();
    
    Note: In production code, you will need to perform error checking on all file-related functions such as CFile::CFile and CFile::Read.

    Now, you use CRgn::CreateFromData to let Windows create a new region based on your loaded region data:

    // Create region from loaded region data
    CRgn rgn;
    rgn.CreateFromData(NULL, iSize, pData);
    

    The first parameter is a transformation that should be applied to your region. If you specify NULL, your region will not be transformed in any way.

    For demonstration purposes, you now assign your recreated region as a region to your window so that you can visually see that the region was properly loaded.

    // As a demonstration, set the loaded region as window region
    // so it is visually clear that it got loaded correctly.
    SetWindowRgn(rgn, TRUE);
    

    Everything is finished now, so you can free your allocated memory.

    // Free allocated memory
    free(pData);
    

    The full code of the LoadRegion function is shown below:

    void LoadRegion()
    {
       // Open file to read region data from
       CFile f(_T("test_region.rgn"), CFile::modeRead);
    
       // Get size of the file
       int iSize = f.GetLength();
    
       // Allocate memory to hold the region data
       RGNDATA* pData = (RGNDATA*)calloc(iSize, 1);
    
       // Read region data from file
       f.Read(pData, iSize);
       f.Close();
    
       // Create region from loaded region data
       CRgn rgn;
       rgn.CreateFromData(NULL, iSize, pData);
    
       // As a demonstration, set the loaded region as window region
       // so it is visually clear that it got loaded correctly.
       SetWindowRgn(rgn,TRUE);
    
       // Free allocated memory
       free(pData);
    }
    

    Attached to this article is a zip file containing a little sample project with the SaveRegion and LoadRegion functions. This sample project is a simple MFC Dialog application showing one window with two buttons, Save and Load. First, click the Save button to save the elliptic region to a file and then use the Load button to load and re-create that saved region.

    About the Author

    Marc graduated from the Catholic University Leuven, Belgium, with a degree in "Burgerlijk ingenieur in de computer wetenschappen" (equivalent to Master of Science in Engineering in Computer Science) in 2003. In 2004 he got the cum laude degree of Master In Artificial Intelligence at the same university. In 2005 he started working for a big software consultancy company. His main expertise is C/C++ and specifically Microsoft VC++ and the MFC framework. Next to C/C++, he also likes C# and uses PHP for creating webpages. Besides his main interest for Windows development, he also has experience in developing C++ programs running 24x7 on Linux platforms and in developing critical 2G,3G software running on Solaris for big telecom operators.

    Downloads

  • SaveLoadRegionMFC_Demo.zip

  • IT Offers


    Top Authors