Bonchev Information Technologies and Systems
Software for organizations and people.
One Hundred Lines of Code Hi guest
Sign up - Login
Audio Control Home Tips for Use Download 100 Lines of Code Awards & Reviews  
Audio Control Windows Compatibility Seals
If you ever wondered what a program like Audio Control looks like, or just what may be inside it, then you might want to have a look in the body of a function included bellow. This code is written in a programming language called "C++" and is only one of hundreds of functions that were written when creating Audio Control. These functions rely on other functions and services provided by the operating system. Besides functions, there are also types, objects and other entities used in C++ programming. There are many other programming languages in addition to C++, all of which have certain positive and negative aspects. For us, C++ is the best professional language for development as it possesses the power of raw low level languages and the power of abstraction, which are both required for professional software development.

If you are a software development professional, you might note the use of memory atoms in the body of the function. Although in this function memory is barely used, meaning that it hardly demonstrates the power of the Atomic Memory Model. However, you can still notice how easily the memory is handled. All necessary checks during allocation are strictly and rigorously made, however their presence is hidden, thus it does not obstruct the already complicated code.
void CDestinationLineEntries::SortMixers( const MList< Pair< const MixerSortCriteria, bool > >& caSortOrder, const bool bLogicalOnly ) throw()
{
// Read the Use Data from the storage if necessary.
if( AudioMixerControl::mscUse == caSortOrder.GetHead()->GetLabelRef() )
{
listMixersUseData.Empty();
 
// Retrieve use data from storage and build the appropriate data structure with it.
HKEY hkRoot( NULL );
 
if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER,
((CAudioControlApp*)AfxGetApp())->GetAppRelativePath(),
0,
TEXT(""),
REG_OPTION_NON_VOLATILE,
KEY_QUERY_VALUE, NULL,
&hkRoot,
NULL ) )
{
DWORD dwValueSize( 0 );
 
if( ERROR_SUCCESS != RegQueryValueEx( hkRoot,
AUDIO_DEVICE_FIRST_CONTROL_USE_DATA_STORAGE_NAME,
NULL,
NULL,
NULL,
&dwValueSize ) )
{
dwValueSize = 0;
}
 
MMemoryPH< BYTE, HEAP_ZERO_MEMORY > memUseData( MMemory< BYTE >::MemUnits( (DWORD)dwValueSize ) );
 
if( ERROR_SUCCESS == RegQueryValueEx( hkRoot,
AUDIO_DEVICE_FIRST_CONTROL_USE_DATA_STORAGE_NAME,
NULL,
NULL,
(BYTE*)(memUseData.GetMemory()),
&dwValueSize ) )
{
// Distribute the data.
const BYTE* pb1Data( memUseData );
BYTE const* pb1FirstBefindData( pb1Data + memUseData.GetSizeBytes() );
 
while( pb1Data < pb1FirstBefindData )
{
Pair< DWORD, USHORT >::AddToHashTable( Pair< DWORD, USHORT >( *(DWORD*)pb1Data, *(USHORT*)(pb1Data + sizeof( DWORD )) ),
listMixersUseData,
true );
 
pb1Data += sizeof( DWORD ) + sizeof( USHORT );
}
}
 
RegCloseKey( hkRoot );
}
 
listMixersUseData.Accelerate();
}
 
 
// First separate the mixers in two flows - privileged (always on top) and normal.
MList< Pair< CAdjustMixer*, MList< CAdjustMixer* > > > listFlowPriviliged;
MList< Pair< CAdjustMixer*, MList< CAdjustMixer* > > > listFlowNormal;
 
for( DWORD dwMixer = 0; dwMixer < listMajorDependents.GetMembersCount(); dwMixer++ )
{
if( (DWORD)MList< CAdjustMixer* >::Invalid == listListControlNeighbours.Find_H2T( listMajorDependents[dwMixer]->GetLabelRef() ) )
{
// Add to the flow of normal groups.
MASSERT( AudioMixerControl::Major == listMajorDependents[dwMixer]->GetLabelRef()->GetMixerItem()->GetImportance() );
 
listFlowNormal.AddTail( listMajorDependents[dwMixer] );
}
else
{
// Add to the flow of privileged groups.
MASSERT( AudioMixerControl::Major == listMajorDependents[dwMixer]->GetLabelRef()->GetMixerItem()->GetImportance() );
 
listFlowPriviliged.AddTail( listMajorDependents[dwMixer] );
}
}
 
listMajorDependents.EmptyNoDelete();
 
 
// Sort each flow of groups and the controls within each group and merge the two flows.
 
const CAdjustMixer::Comparator< const CAdjustMixer* > tcComparator( caSortOrder );
 
// Transfer the groups in correct order from the privileged flow to the destination list.
while( !listFlowPriviliged.IsEmpty() )
{
listFlowPriviliged.Accelerate();
 
DWORD dwExtremum( 0 );
 
for( dwMixer = dwExtremum + 1; dwMixer < listFlowPriviliged.GetMembersCount(); dwMixer++ )
{
if( !tcComparator.IsOrdered( listFlowPriviliged[dwExtremum]->GetLabelRef(), listFlowPriviliged[dwMixer]->GetLabelRef() ) )
{
dwExtremum = dwMixer;
}
}
 
// The dwExtremum is the indef of the following group to be added to the sorted list.
listMajorDependents.AddTail( listFlowPriviliged.RemoveMember( dwExtremum ) );
 
// The insignificant group is not sorted, so sort it now.
listMajorDependents.GetTail()->GetValueRef().SortList< CAdjustMixer::Comparator< const CAdjustMixer* > >( tcComparator );
listMajorDependents.GetTail()->GetValueRef().Accelerate();
}
 
 
// Transfer the groups in correct order from the normal flow to the destination list.
while( !listFlowNormal.IsEmpty() )
{
listFlowNormal.Accelerate();
 
DWORD dwExtremum( 0 );
 
for( dwMixer = dwExtremum + 1; dwMixer < listFlowNormal.GetMembersCount(); dwMixer++ )
{
if( !tcComparator.IsOrdered( listFlowNormal[dwExtremum]->GetLabelRef(), listFlowNormal[dwMixer]->GetLabelRef() ) )
{
dwExtremum = dwMixer;
}
}
 
// The dwExtremum is the indef of the following group to be added to the sorted list.
listMajorDependents.AddTail( listFlowNormal.RemoveMember( dwExtremum ) );
 
// The insignificant group is not sorted, so sort it now.
listMajorDependents.GetTail()->GetValueRef().SortList< CAdjustMixer::Comparator< const CAdjustMixer* > >( tcComparator );
listMajorDependents.GetTail()->GetValueRef().Accelerate();
}
 
listMajorDependents.Accelerate();
 
// Finally build the "display" list.
listMixersSortedPtr.Empty();
 
for( dwMixer = 0; dwMixer < listMajorDependents.GetMembersCount(); dwMixer++ )
{
listMixersSortedPtr.AddTail( new CAdjustMixer*( listMajorDependents[dwMixer]->GetLabelRef() ) );
 
MList< CAdjustMixer* >& listGroupMembers( listMajorDependents[dwMixer]->GetValueRef() );
 
for( DWORD dwGroupMember = 0; dwGroupMember < listGroupMembers.GetMembersCount(); dwGroupMember++ )
{
listMixersSortedPtr.AddTail( new CAdjustMixer*( *listGroupMembers[dwGroupMember] ) );
}
}
 
listMixersSortedPtr.Accelerate();
 
 
// Rearrangement of the CAdjustMixer in the system Z order, so the tab order will be
// consistent with the view order.
CWnd* pwndLastZOrder( this );
 
for( DWORD dwMixer = 0; dwMixer < listMixersSortedPtr.GetMembersCount(); dwMixer++ )
{
MASSERT( IsWindow( pwndLastZOrder->m_hWnd ) );
 
(*listMixersSortedPtr[dwMixer])->SetWindowPos( pwndLastZOrder,
0,
0,
0,
0,
SWP_NOACTIVATE |
SWP_NOCOPYBITS |
SWP_NOMOVE |
SWP_NOREDRAW |
SWP_NOSIZE |
SWP_NOOWNERZORDER );
 
pwndLastZOrder = (*listMixersSortedPtr[dwMixer]);
}
 
 
// To use listMixersSortedPtr - it must be sorted first - confirmation.
MASSERT( listMixersSortedPtr.GetMembersCount() == listMixers.GetMembersCount() );
 
if( !bLogicalOnly )
{
// Redispaly the CAdjustMixers in accordance with the new order.
SCROLLINFO si;
ZeroMemory( &si, sizeof( SCROLLINFO ) );
si.cbSize = sizeof( SCROLLINFO );
 
GetScrollInfo( SB_VERT, &si, SIF_POS | SIF_PAGE | SIF_RANGE);
 
MASSERT( int( min( si.nMax - si.nPage + Scroll_Min, (DWORD)max( Scroll_Min, si.nPos ) ) ) == si.nPos );
 
CRect rcMixer;
(*listMixersSortedPtr[0])->GetWindowRect( rcMixer );
ScreenToClient( rcMixer );
 
// si.nPos is correct for the scroll, but the scroll has offset from the display as the display
// always starts from ( 0, 0 ) client coordinates, so it needs to shift si.nPos with scroll_min.
rcMixer.top = - (si.nPos - Scroll_Min);
 
for( DWORD dwMixer = 0; dwMixer < listMixersSortedPtr.GetMembersCount(); dwMixer++ )
{
if( !(*listMixersSortedPtr[dwMixer])->IsWindowVisible() ) { continue; }
 
rcMixer.bottom = rcMixer.top + uiScrollLine;
 
(*listMixersSortedPtr[dwMixer])->MoveWindow( rcMixer, FALSE );
 
rcMixer.top = rcMixer.bottom;
}
 
RedrawWindow();
}
}
Community Content
(To enter your comments you must be signed in. Log in or create FREE account.)
MemberComments
Be the first to comment.
Products
The ELIAS Project
Fine Art App
Information Presenter
Act On File
Audio Control
Photo Window
Information Presenter
Homepage
for Museums and Art galleries
for Schools and Universities
for Resorts, Hotels and Cruises
for Parks of any kind
for Corporations
for any business
Learning
Encryption and Authentication
Safe Online Communication
Website Testimonials
Learn how to store private keys
Make The Most From Your Files
Convenient Volume Control
Photo Window - an Awesome Gift
Support
My Account
FAQ - Forum
 
Community
Blog
Email this page
Newsletter
Bonchev IT
About
Contact
Download
Public Authentication Key
Public Encryption Key

Sitemap
Disclaimer
Privacy
Antispam
© Copyright 2024 Bonchev Information Technologies. All Rights Reserved.
Machine translation:
Search: 


Email this page
To:
use semicolon to separate emails eg: joe@abc.com; lea@abc.com
Subject:
Message:
a link to this page will be automatically added to your message
From:
Please type the anti-bot text below.
Type text:
Thank you for subscribing to the MBBSoftware newsletter.
Enter your email address:
Please type the anti-bot text below.
Type text: