Click here to Skip to main content
15,867,594 members
Articles / Desktop Programming / MFC
Article

Reading quota information on an NTFS volume

Rate me:
Please Sign up or sign in to vote.
4.23/5 (6 votes)
23 Jun 200513 min read 43.2K   503   16   3
A class wrapping most of the functionality of the IDiskQuotaControl interface.

Image 1

Introduction

As I was perusing the MSDN for another unrelated reason, I stumbled across the IDiskQuotaControl interface. While it sounded interesting, my lack of COM experience forced me to press on with my original goal. Several months later I decided to explore the IDiskQuotaControl interface again. What I discovered along the way was very helpful, at least to me.

Raw interface pointers

I started out just including the dskquota.h header file. To make use of the interfaces and properties in this file, I used a code similar to:

IDiskQuotaControl   *pDiskQuotaControl;
IEnumDiskQuotaUsers *pEnumDiskQuotaUsers;
HRESULT             hr;
    
hr = CoCreateInstance(CLSID_DiskQuotaControl,
                      NULL,
                      CLSCTX_INPROC_SERVER,
                      IID_IDiskQuotaControl,
                      (PVOID *) &pDiskQuotaControl);
if (SUCCEEDED(hr))
{
    hr = pDiskQuotaControl->Initialize(_bstr_t("c:\\"), TRUE);
    if (SUCCEEDED(hr))
    {
        hr = pDiskQuotaControl->CreateEnumUsers(NULL, 
                      0, DISKQUOTA_USERNAME_RESOLVE_SYNC,
                      &pEnumDiskQuotaUsers);
        if (SUCCEEDED(hr))
        {
            ...
            pEnumDiskQuotaUsers->Release();
        }
    }

    pDiskQuotaControl->Release();
}

Cool, I thought. I wonder if I could make that CoCreateInstance() call a bit cleaner. At this point I remembered reading about smart pointers from a COM project I worked on several years ago. Looking back at that code as a starting point, I put the necessary changes in place.

Smart pointers

First I imported the disk quota type library contained within dskquota.dll:

#import <dskquota.dll> rename("DiskQuotaTypeLibrary", "DQ")

I renamed the namespace simply because it was so long. Now I was ready to change the raw interface pointers to smart pointers. I started out with something simple:

DQ::DIDiskQuotaControlPtr ptrDiskQuotaControl;

HRESULT hr = 
   ptrDiskQuotaControl.CreateInstance(__uuidof(DQ::DiskQuotaControl));
if (SUCCEEDED(hr))
{
    hr = ptrDiskQuotaControl->Initialize(_bstr_t("c:\\"), TRUE);
    if (NOERROR == hr)
    {
        ...
    }
}

Wow, this works too. I went on and tried to use the CreateEnumUsers() method. That's when things went downhill. First, that method did not exist. Second, the fourth parameter was a IEnumDiskQuotaUsers smart pointer which also did not exist. Now I was really stumped, especially since the MSDN documentation indicated otherwise. I poked at it a while longer before asking for help. I was told that it looks like a type library which only has dispatch interfaces, but that I could still use smart pointers if I wanted. The only changes I'd need were to remove the #import statement, and add my own types using the _COM_SMARTPTR_TYPEDEF() macro:

_COM_SMARTPTR_TYPEDEF(IDiskQuotaControl, IID_IDiskQuotaControl);
_COM_SMARTPTR_TYPEDEF(IEnumDiskQuotaUsers, IID_IEnumDiskQuotaUsers);
_COM_SMARTPTR_TYPEDEF(IDiskQuotaUser, IID_IDiskQuotaUser);

Now I was making some progress! I could create an instance of the IDiskQuotaControl interface, initialize it, and call the CreateEnumUsers() method just like I had when using the raw interface pointers:

IEnumDiskQuotaUsersPtr ptrEnumDQUsers;
hr = ptrDiskQuotaControl->CreateEnumUsers(NULL, 
                                          0,
                                          DISKQUOTA_USERNAME_RESOLVE_SYNC,
                                          &ptrEnumDQUsers);
if (NOERROR == hr)
{
    IDiskQuotaUserPtr ptrDQUser;
    
    hr = ptrEnumDQUsers->Next(1, &ptrDQUser, NULL);
    if (NOERROR == hr)
    {
        ...
    }
}

Just to ensure that I was indeed able to enumerate through each of the registered users, I used:

TCHAR szLogonName[128];
      szDisplayname[128];

while (ptrEnumDQUsers->Next(1, &ptrDQUser, NULL) == NOERROR)
{
    hr = ptrDQUser->GetName(NULL, 
                            0, 
                            szLogonName,
                            sizeof(szLogonName), 
                            szDisplayName,
                            sizeof(szDisplayName));

    if (NOERROR == hr)
        TRACE(_T("Logon name = ]%s[\n"), szLogonName);
}

Yep, it worked! My next goal was to somehow wrap all this up into a useful class or two to hide some of the COM-ness from it.

The CDiskQuotaControl class

This class is a wrapper around most of the IDiskQuotaControl and IEnumDiskQuotaUsers interfaces. Most of the text comes straight from the MSDN.

CDiskQuotaControlConstructs a CDiskQuotaControl object.
InitializeInitializes a new CDiskQuotaControl object by opening the NTFS volume in read-only mode. The return value indicates whether the volume supports NTFS disk quotas and whether the caller has sufficient access rights.
EnumFirstUserCreates an enumerator object for enumerating quota users on the volume, and then retrieves the first user in the enumeration sequence. The user's account information is resolved synchronously.
EnumNextUserRetrieves the next user in the enumeration sequence.
GetDefaultQuotaLimitRetrieves the default quota limit for the volume.
GetDefaultQuotaLimitTextRetrieves the default quota limit for the volume. The limit is expressed as a text string, for example "10.5 MB". If the volume has no limit, the string returned is "No Limit." If the buffer is too small, it is truncated to fit the buffer.
GetDefaultQuotaThresholdRetrieves the default quota warning threshold for the volume.
GetDefaultQuotaThresholdTextRetrieves the default warning threshold for the volume. This threshold is expressed as a text string, for example "10.5 MB". If the volume does not have a threshold, the string returned is "No Limit." If the buffer is too small, the string is truncated to fit the buffer.
IsStateDisabledDetermines if quotas are enabled on the volume.
IsStateTrackedDetermines if quotas are tracked (i.e., the limit is not enforced) on the volume.
IsStateEnforcedDetermines if quotas are enforced on the volume.
IsStateIncompleteDetermines if the volume's quota information is out of date.
IsStateRebuildingDetermines if the volume's quota information is being rebuilt.

HRESULT Initialize( PCTSTR pszVolume )

Return value

ValueMeaning
NOERRORSuccess.
ERROR_ACCESS_DENIEDThe caller has insufficient access rights.
ERROR_FILE_NOT_FOUNDThe requested file or object was not found.
ERROR_INITIALIZEDThe controller object has already been initialized. Multiple initialization is not allowed.
ERROR_INVALID_NAMEThe requested file path is invalid.
ERROR_NOTSUPPORTEDThe file system does not support quotas.
ERROR_PATH_NOT_FOUNDThe requested file path was not found.

Parameters

  • pszVolume

    Specifies the path to the volume's root.

HRESULT EnumFirstUser( CDiskQuotaUser *pDiskQuotaUser )

HRESULT EnumNextUser( CDiskQuotaUser *pDiskQuotaUser ) const

Return value

ValueMeaning
NOERRORSuccess.
ERROR_ACCESS_DENIEDThe caller has insufficient access rights.
ERROR_NOT_READYThe CDiskQuotaControl object is not initialized.
E_INVALIDARGThe pDiskQuotaUser parameter is NULL.
E_OUTOFMEMORYInsufficient memory.
E_FAILAn unexpected file system error occurred.
E_UNEXPECTEDAn unexpected exception occurred.
S_FALSEIf the first, or next, user in the enumeration sequence was not successfully retrieved.

Parameters

  • pDiskQuotaUser

    Pointer to a CDiskQuotaUser object.

HRESULT GetDefaultQuotaLimit( PLONGLONG pLimit ) const

Return value

ValueMeaning
NOERRORSuccess.
ERROR_ACCESS_DENIEDThe caller has insufficient access rights.
ERROR_NOT_READYThe CDiskQuotaControl object is not initialized.
E_INVALIDARGThe pLimit parameter is NULL.
E_OUTOFMEMORYInsufficient memory.
E_FAILAn unexpected file system error occurred.
E_UNEXPECTEDAn unexpected exception occurred.

Parameters

  • pLimit

    Pointer to the variable to receive the quota limit. If this value is -1, the user has an unlimited quota.

HRESULT GetDefaultQuotaLimitText( CString &strDefaultQuotaText ) const

HRESULT GetDefaultQuotaLimitText( PTSTR pszDefaultQuotaText, const DWORD dwSize ) const

Return value

ValueMeaning
NOERRORSuccess.
ERROR_ACCESS_DENIEDThe caller has insufficient access rights.
ERROR_NOT_READYThe CDiskQuotaControl object is not initialized.
E_INVALIDARGThe pszDefaultQuotaText parameter is NULL.
E_OUTOFMEMORYInsufficient memory.
E_FAILAn unexpected file system error occurred.
E_UNEXPECTEDAn unexpected exception occurred.

Parameters

  • strDefaultQuotaText

    Reference to a CString object that will receive the text string.

  • pszDefaultQuotaText

    Pointer to the buffer to receive the text string.

  • dwSize

    Size of the buffer, in characters.

HRESULT GetDefaultQuotaThreshold( PLONGLONG pThreshold ) const

Return value

ValueMeaning
NOERRORSuccess.
ERROR_ACCESS_DENIEDThe caller has insufficient access rights.
ERROR_NOT_READYThe CDiskQuotaControl object is not initialized.
E_INVALIDARGThe pThreshold parameter is NULL.
E_OUTOFMEMORYInsufficient memory.
E_FAILAn unexpected file system error occurred.
E_UNEXPECTEDAn unexpected exception occurred.

Parameters

  • pThreshold

    Pointer to the variable to receive the default warning threshold value, in bytes.

HRESULT GetDefaultQuotaThresholdText( CString &strDefaultQuotaText ) const

HRESULT GetDefaultQuotaThresholdText( PTSTR pszDefaultQuotaText, const DWORD dwSize ) const

Return value

ValueMeaning
NOERRORSuccess.
ERROR_ACCESS_DENIEDThe caller has insufficient access rights.
ERROR_NOT_READYThe CDiskQuotaControl object is not initialized.
E_INVALIDARGThe pszDefaultQuotaText parameter is NULL.
E_OUTOFMEMORYInsufficient memory.
E_FAILAn unexpected file system error occurred.
E_UNEXPECTEDAn unexpected exception occurred.

Parameters

  • strDefaultQuotaText

    Reference to a CString object that will receive the text string.

  • pszDefaultQuotaText

    Pointer to the buffer to receive the text string.

  • dwSize

    Size of the buffer, in characters.

bool IsStateDisabled( void ) const;

Return value

true, if quotas are disabled on the volume; false otherwise.

bool IsStateTracked( void ) const;

Return value

true, if quotas are enabled on the volume but the limit is not being enforced; false otherwise.

bool IsStateEnforced( void ) const;

Return value

true, if quotas are enabled on the volume and the limit is being enforced; false otherwise.

bool IsStateIncomplete( void ) const;

Return value

true, if the quota's information is out of date; false otherwise.

bool IsStateRebuilding( void ) const;

Return value

true, if the quota's information is being rebuilt; false otherwise.

The CDiskQuotaUser class

This class is a wrapper around most of the IDiskQuotaUser interface. Most of the text comes straight from the MSDN.

CDiskQuotaUserConstructs a CDiskQuotaUser object which represents a single user quota entry in the volume quota information file.
GetNameRetrieves the name strings associated with a disk quota user.
GetQuotaThresholdTextRetrieves the user's warning threshold for the volume. This threshold is expressed as a text string, for example "10.5 MB". If the user's threshold is unlimited, the string returned is "No Limit." If the destination buffer is too small, the string is truncated to fit the buffer.
GetQuotaThresholdRetrieves the user's warning threshold value on the volume. The threshold is an arbitrary value set by the volume's quota administrator. You can use it to identify users who are approaching their hard quota limit.
GetQuotaLimitTextRetrieves the user's quota limit for the volume. This limit is expressed as a text string, for example "10.5 MB". If the user has no quota limit, the string returned is "No Limit." If the destination buffer is too small, the string is truncated to fit the buffer.
GetQuotaLimitRetrieves the user's quota limit value on the volume. The limit is set as the maximum amount of disk space available to the volume user.
GetQuotaUsedTextRetrieves the user's quota used value for the volume. This value is expressed as a text string, for example "10.5 MB". If the destination buffer is too small, the string is truncated to fit the buffer.
GetQuotaUsedRetrieves the user's quota used value on the volume. This is the amount of information stored on the volume by the user. Note that this is the amount of uncompressed information. Therefore, the use of NTFS compression does not affect this value.
GetQuotaInformationRetrieves the values for the user's warning threshold, hard quota limit, and quota used.
IsStatusResolvedDetermines if a user's SID resolved to a user account.
IsStatusUnavailableDetermines if a user's account is available. The network DC may not be available.
IsStatusDeletedDetermines if a user's account was deleted from the domain.
IsStatusInvalidDetermines if a user's account is invalid.
IsStatusUnknownDetermines if a user's account is unknown.
IsStatusUnresolvedDetermines if a user's SID did not resolve to a user account.

HRESULT GetName( CString &strLogonName, CString &strDisplayName ) const;

HRESULT GetName( PTSTR pszLogonName, const DWORD dwSizeLogon, PTSTR pszDisplayName, const DWORD dwSizeDisplay ) const;

Return value

ValueMeaning
NOERRORSuccess.
ERROR_LOCK_FAILEDFailure to obtain an exclusive lock.

Parameters

  • strLogonName

    Reference to a CString object that will receive the name the user specified to log on to the computer. The format of the name returned depends on whether directory service information is available.

  • strDisplayName

    Reference to a CString object that will receive the display name for the quota user. If the information is not available, the string returned is empty.

  • pszLogonName

    Pointer to the buffer to receive the name the user specified to log on to the computer. This value can be NULL. The format of the name returned depends on whether directory service information is available.

  • dwSizeLogon

    Size of the logon name buffer, in characters. Ignored if pszLogonName is NULL.

  • pszDisplayName

    Pointer to the buffer to receive the display name for the quota user. This value can be NULL. If the information is not available, the string returned is of zero length.

  • dwSizeDisplay

    Size of the display-name buffer, in characters. Ignored if pszDisplayName is NULL.

HRESULT GetQuotaThresholdText( CString &strQuotaThresholdText ) const;

HRESULT GetQuotaThresholdText( PTSTR pszQuotaThresholdText, const DWORD dwSize ) const;

Return value

ValueMeaning
NOERRORSuccess.
ERROR_ACCESS_DENIEDThe caller has insufficient access rights.
ERROR_LOCK_FAILEDFailure to obtain an exclusive lock.
E_INVALIDARGThe pszQuotaThresholdText parameter is NULL.
E_OUTOFMEMORYInsufficient memory.
E_FAILAn unexpected file system error occurred.
E_UNEXPECTEDAn unexpected exception occurred.

Parameters

  • strQuotaThresholdText

    Reference to a CString object that will receive the text string.

  • pszQuotaThresholdText

    Pointer to the buffer to receive the text string.

  • dwSize

    Size of the destination buffer, in characters.

HRESULT GetQuotaThreshold( PLONGLONG pLimit ) const;

Return value

ValueMeaning
NOERRORSuccess.
ERROR_ACCESS_DENIEDThe caller has insufficient access rights.
ERROR_LOCK_FAILEDFailure to obtain an exclusive lock.
E_INVALIDARGThe pLimit parameter is NULL.
E_OUTOFMEMORYInsufficient memory.
E_FAILAn unexpected file system error occurred.
E_UNEXPECTEDAn unexpected exception occurred.

Parameters

  • pLimit

    Pointer to a variable to receive the warning threshold value.

HRESULT GetQuotaLimitText( CString &strQuotaLimitText ) const;

HRESULT GetQuotaLimitText( PTSTR pszQuotaLimitText, const DWORD dwSize ) const;

Return value

ValueMeaning
NOERRORSuccess.
ERROR_ACCESS_DENIEDThe caller has insufficient access rights.
ERROR_LOCK_FAILEDFailure to obtain an exclusive lock.
E_INVALIDARGThe pszQuotaLimitText parameter is NULL.
E_OUTOFMEMORYInsufficient memory.
E_FAILAn unexpected file system error occurred.
E_UNEXPECTEDAn unexpected exception occurred.

Parameters

  • strQuotaLimitText

    Reference to a CString object that will receive the text string.

  • pszQuotaLimitText

    Pointer to the buffer to receive the text string.

  • dwSize

    Size of the buffer, in characters.

HRESULT GetQuotaLimit( PLONGLONG pLimit ) const;

Return value

ValueMeaning
NOERRORSuccess.
ERROR_ACCESS_DENIEDThe caller has insufficient access rights.
ERROR_LOCK_FAILEDFailure to obtain an exclusive lock.
E_INVALIDARGThe pLimit parameter is NULL.
E_OUTOFMEMORYInsufficient memory.
E_FAILAn unexpected file system error occurred.
E_UNEXPECTEDAn unexpected exception occurred.

Parameters

  • pLimit

    Pointer to the variable to receive the limit value. If this value is -1, the user has an unlimited quota.

HRESULT GetQuotaUsedText( CString &strQuotaUsedText ) const;

HRESULT GetQuotaUsedText( PTSTR pszQuotaUsedText, const DWORD dwSize ) const;

Return value

ValueMeaning
NOERRORSuccess.
ERROR_ACCESS_DENIEDThe caller has insufficient access rights.
ERROR_LOCK_FAILEDFailure to obtain an exclusive lock.
E_INVALIDARGThe pszQuotaUsedText parameter is NULL.
E_OUTOFMEMORYInsufficient memory.
E_FAILAn unexpected file system error occurred.
E_UNEXPECTEDAn unexpected exception occurred.

Parameters

  • strQuotaUsedText

    Reference to a CString object that will receive the text string.

  • pszQuotaUsedText

    Pointer to the buffer to receive the text string.

  • dwSize

    Size of the buffer, in bytes.

HRESULT GetQuotaUsed( PLONGLONG pUsed ) const;

Return value

ValueMeaning
NOERRORSuccess.
ERROR_ACCESS_DENIEDThe caller has insufficient access rights.
ERROR_LOCK_FAILEDFailure to obtain an exclusive lock.
E_INVALIDARGThe pUsed parameter is NULL.
E_OUTOFMEMORYInsufficient memory.
E_FAILAn unexpected file system error occurred.
E_UNEXPECTEDAn unexpected exception occurred.

Parameters

  • pUsed

    Pointer to the variable to receive the quota used value.

HRESULT GetQuotaInformation( PDISKQUOTA_USER_INFORMATION pDQUserInfo, const DWORD dwSize ) const;

Return value

ValueMeaning
NOERRORSuccess.
ERROR_ACCESS_DENIEDThe caller has insufficient access rights.
ERROR_LOCK_FAILEDFailure to obtain an exclusive lock.
E_INVALIDARGThe pDQUserInfo parameter is NULL.
E_OUTOFMEMORYInsufficient memory.
E_FAILAn unexpected file system error occurred.
E_UNEXPECTEDAn unexpected exception occurred.

Parameters

  • pDQUserInfo

    Pointer to a DISKQUOTA_USER_INFORMATION structure to receive the quota information.

  • dwSize

    Size of the quota information structure, in bytes.

bool IsStatusResolved( void ) const;

Return value

true if the user's SID was resolved to a user account; false otherwise.

bool IsStatusUnavailable( void ) const;

Return value

true if the user's account is unavailable (e.g., the domain controller may not be available); false otherwise.

bool IsStatusDeleted( void ) const;

Return value

true if the user's account was deleted; false otherwise.

bool IsStatusInvalid( void ) const;

Return value

true if the user's account is invalid; false otherwise.

bool IsStatusUnknown( void ) const;

Return value

true if the user's account is unknown; false otherwise.

bool IsStatusUnresolved( void ) const;

Return value

true if the user's SID does not resolve to a user account; false otherwise.

Example

CDiskQuotaControl DiskQuotaControl;

HRESULT hr = DiskQuotaControl.Initialize(strVolume);    
if (ERROR_NOT_SUPPORTED == hr)
    TRACE(CString((LPCTSTR) IDS_NOT_SUPPORTED));

if (NOERROR == hr)
{
    if (DiskQuotaControl.IsStateDisabled())
        TRACE(CString((LPCTSTR) IDS_NOT_ENABLED));
    else if (DiskQuotaControl.IsStateTracked())
        TRACE(CString((LPCTSTR) IDS_NOT_TRACKED));
    else if (DiskQuotaControl.IsStateEnforced())
        TRACE(CString((LPCTSTR) IDS_NOT_ENFORCED));
    else if (DiskQuotaControl.IsStateIncomplete())
        TRACE(CString((LPCTSTR) IDS_INCOMPLETE));
    else if (DiskQuotaControl.IsStateRebuilding())
        TRACE(CString((LPCTSTR) IDS_REBUILDING));
    else
        TRACE(CString((LPCTSTR) IDS_UNKNOWN));

    
    DISKQUOTA_USER_INFORMATION  DQUserInfo;
    CString                     strLogonName,
                                strDisplayName,
                                strQuotaThresholdText,
                                strQuotaLimitText,
                                strQuotaUsedText;

    // enumerate through each of the users
    hr = DiskQuotaControl.EnumFirstUser(&DiskQuotaUser);
    while (S_OK == hr)
    {
        // get information about the user's numbers
        DiskQuotaUser.GetName(strLogonName, strDisplayName);
        DiskQuotaUser.GetQuotaThresholdText(strQuotaThresholdText);
        DiskQuotaUser.GetQuotaLimitText(strQuotaLimitText);
        DiskQuotaUser.GetQuotaUsedText(strQuotaUsedText);
        DiskQuotaUser.GetQuotaInformation(&DQUserInfo, 
                       sizeof(DISKQUOTA_USER_INFORMATION));

        // determine if the user is above/below their quota
        if (DQUserInfo.QuotaUsed > DQUserInfo.QuotaLimit && 
                                   DQUserInfo.QuotaLimit >= 0)
            TRACE(CString((LPCTSTR) IDS_ABOVE_LIMIT));
        else if (DQUserInfo.QuotaUsed > DQUserInfo.QuotaThreshold && 
                                      DQUserInfo.QuotaThreshold >= 0)
            TRACE(CString((LPCTSTR) IDS_WARNING));
        else
            TRACE(CString((LPCTSTR) IDS_OK));

        TRACE(strLogonName);

        hr = DiskQuotaControl.EnumNextUser(&DiskQuotaUser);
    }
}

Extras

The code in this section isn't within the scope of this article but I wanted to show it anyway as it was useful for me and hopefully for anyone else who might need it.

I've seen several different varieties of adjusting a control's dimensions or location at runtime. Some examples were painfully long while others were not as bad or were just plain hard to follow. I put a simple function together that I feel is small and easy to understand. This function is called from the dialog's OnSize() method.

In the dialog's OnInitDialog() method, we need to get the initial size of the client area. This is so we have a reference point from which to move. This looks like:

GetClientRect(m_rectOrig);
m_nWidth  = m_rectOrig.Width();
m_nHeight = m_rectOrig.Height();

Notice that m_rectOrig is a member variable rather than just a local variable. It is used in the OnGetMinMaxInfo() method to make sure we don't minimize the dialog too much.

The function to do the sizing and moving of the child controls looks like:

void RepositionChildControl( CWnd *pWnd, const int dx, 
                       const int dy, const UINT uAnchor )
{
    // make sure the dialog exists
    if (NULL != pWnd->m_hWnd)
    {
        CRect   rect;

        pWnd->GetWindowRect(rect);
        ScreenToClient(rect);

        if (uAnchor & resizeVERT)        // 0x0020
            rect.bottom += dy;
        else if (uAnchor & anchorBOTTOM) // 0x0004
            rect.OffsetRect(0, dy);
        
        if (uAnchor & resizeHORZ)        // 0x0010
            rect.right += dx;
        else if (uAnchor & anchorRIGHT)  // 0x0002
            rect.OffsetRect(dx, 0);

        pWnd->MoveWindow(rect);
    }
}

Whenever the dialog is being resized, the OnSize() method is called. Here is where we call RepositionChildControl():

void OnSize(UINT nType, int cx, int cy) 
{
    CDialog::OnSize(nType, cx, cy);
    
    // how much did the dialog grow/shrink by?
    int nWidthOffset  = cx - m_nWidth;
    int nHeightOffset = cy - m_nHeight;

    // this control is anchored at the top and right, 
    // and is sized horizontally
    RepositionChildControl(&m_lblStatus, nWidthOffset, 
      nHeightOffset, anchorTOP | anchorRIGHT | resizeHORZ);
    
    // this control is anchored at the top and left, 
    // and is sized horizontally and vertically
    RepositionChildControl(&m_lcDQInfo,  nWidthOffset, 
      nHeightOffset, anchorTOP | anchorLEFT | resizeBOTH);
    
    // this control is anchored at the top and right
    RepositionChildControl(&m_btnCancel, nWidthOffset, 
                 nHeightOffset, anchorTOP | anchorRIGHT);

    // save dialog's new dimensions
    m_nWidth  = cx;
    m_nHeight = cy;
}

Since this type of movement does cause a little bit of flicker, the interested reader could add each of the controls to a CWnd* array. Then in the dialog's OnEraseBkgnd() method, subtract the rect of each of the controls from the dialog's rect using CDC::ExcludeClipRect().

Summary

These two classes are far from complete. They reflect the "read" methods of each of the interfaces, thus they do not update any quota information. However, they could easily be expanded for such functionality.

Enjoy!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior) Pinnacle Business Systems
United States United States

The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.

HTTP 404 - File not found
Internet Information Services

Comments and Discussions

 
GeneralNice one David Pin
Owner drawn26-Jan-06 17:42
Owner drawn26-Jan-06 17:42 
GeneralYeap, Nice Article Pin
ThatsAlok23-Jun-05 19:51
ThatsAlok23-Jun-05 19:51 
GeneralRe: Yeap, Nice Article Pin
David Crow24-Jun-05 3:34
David Crow24-Jun-05 3:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.