Click here to Skip to main content
Click here to Skip to main content
 
Add your own
alternative version

Multidevice ASIO output plugin for WinAMP

, 13 Feb 2009
A tiny WinAMP output DLL that uses a C++ replacement of the official ASIO SDK that supports multiple ASIO devices.
#include "gui.hpp"

#include "debugMacros.hpp"


//************************************
// Method:    OnSheetInitialized
// FullName:  InDialogPropertySheet::OnSheetInitialized
// Access:    public
//************************************

void InDialogPropertySheet::OnSheetInitialized()
{
    // Resize the property sheet not to include the button area.
    WTL::CButton okButton( GetDlgItem( IDOK ) );
    WTL::CRect rectButton; VERIFY( okButton.GetWindowRect( rectButton ) );
    WTL::CRect rectWnd   ; VERIFY( this->   GetWindowRect( rectWnd    ) );
    VERIFY( SetWindowPos( m_psh.hwndParent, 0, 0, rectWnd.Width(), rectButton.top - rectWnd.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER ) );

    // Destroy the OK and Cancel buttons.
    VERIFY( okButton.DestroyWindow() );
    VERIFY( GetDlgItem( IDCANCEL ).DestroyWindow() );
}


//************************************
// Method:    PropSheetCallback
// FullName:  InDialogPropertySheet::PropSheetCallback
// Access:    public static
//************************************

int CALLBACK InDialogPropertySheet::PropSheetCallback( HWND const hPropSheetWnd, UINT const uMsg, LPARAM const lParam )
{
    if( uMsg == PSCB_PRECREATE )
    {
        assert( hPropSheetWnd == NULL );
        assert( lParam        != 0    );

        WTL::DLGTEMPLATEEX & dlgTemplateEx( *reinterpret_cast<WTL::DLGTEMPLATEEX *>( lParam ) );
           ::DLGTEMPLATE   & dlgTemplate  ( *reinterpret_cast<   ::DLGTEMPLATE   *>( lParam ) );
        bool const usesExtendedDialogTemplate( dlgTemplateEx.signature == 0xFFFF );  // lParam points to an extended dialog template structure.

        DWORD & style        ( usesExtendedDialogTemplate ? dlgTemplateEx.style   : dlgTemplate.style           );
        DWORD & extendedStyle( usesExtendedDialogTemplate ? dlgTemplateEx.exStyle : dlgTemplate.dwExtendedStyle );

        DWORD const childStyles ( WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER | DS_CONTROL );
        DWORD const parentStyles( WS_POPUP | WS_SYSMENU | DS_MODALFRAME | DS_SETFOREGROUND | DS_SYSMODAL );

        // Remove 'parent'/'modal' styles.
        style &= ~parentStyles;
        // Add 'child'/'control' styles.
        style |= childStyles;
        // Fix for "Child CPropertySheet Hangs If Focus Is Switched"
        // http://support.microsoft.com/kb/149501
        extendedStyle |= WS_EX_CONTROLPARENT;
    }

    return CPropertySheetImpl::PropSheetCallback( hPropSheetWnd, uMsg, lParam );
}


//************************************
// Method:    GetToolBarData
// FullName:  GetToolBarData
// Access:    global
//************************************

ToolBarData & GetToolBarData( UINT const nResourceID )
{
    ToolBarData * const toolBarData
    (
        reinterpret_cast<ToolBarData *>
        (
            ::LockResource
            (
                ::LoadResource
                (
                    WTL::ModuleHelper::GetResourceInstance(),
                    ::FindResource( WTL::ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE( nResourceID ), RT_TOOLBAR )
                )
            )
        )
    );
    assert( toolBarData != NULL && "Failed to load toolbar resource." );
    assert( toolBarData->wVersion == 1 && "Unknown toolbar data version." );
    return *toolBarData;
}


//************************************
// Method:    CreateEmptyToolbar
// FullName:  CreateEmptyToolbar
// Access:    global
//************************************

WTL::CToolBarCtrl CreateEmptyToolbar( HWND const hWndParent, DWORD const dwStyle, DWORD const dwStyleEx, int const x, int const y, int const width, int const height, UINT const nID )
{
    WTL::CToolBarCtrl toolBar
    (
        ::CreateWindowEx
        (
            0,
            TOOLBARCLASSNAME,
            NULL,
            dwStyle,
            x,
            y,
            width,
            height,
            hWndParent,
            reinterpret_cast<HMENU>( nID ),
            WTL::ModuleHelper::GetModuleInstance(),
            NULL
        )
    );
    assert( toolBar );
    toolBar.SetButtonStructSize();
    assert( toolBar.SendMessage( CCM_GETVERSION ) == 6 );
    assert( toolBar.GetExtendedStyle() == 0 );
    if ( dwStyleEx ) toolBar.SetExtendedStyle( dwStyleEx );
    return toolBar;
}


//************************************
// Method:    CreateBitmapFromIcon
// FullName:  CreateBitmapFromIcon
// Access:    global
//************************************
//  Optimized for speed only to 'force' inlining as these are actually 'two'
// functions merged here to reduce source code duplication. A template or forced
// inlining is not used to avoid header pollution.
//************************************

#pragma optimize ( "t", on )
WTL::CBitmap CreateBitmapFromIcon( unsigned int const iconResourceID, TCHAR const * const moduleName, bool const assumeModuleIsLoaded )
{
    HMODULE const module( assumeModuleIsLoaded ? ::GetModuleHandle( moduleName ) : ::LoadLibrary( moduleName ) );
    assert( module );
    assert( IS_INTRESOURCE( iconResourceID ) );
    WTL::CIcon const icon( static_cast<HICON>( ::LoadImage( module, reinterpret_cast<LPCSTR>( iconResourceID ), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR ) ) );
    if ( !assumeModuleIsLoaded ) VERIFY( ::FreeLibrary( module ) );
    ICONINFO iconInfo;
    VERIFY( icon.GetIconInfo( &iconInfo ) );
    VERIFY( ::DeleteObject( iconInfo.hbmMask ) );
    return iconInfo.hbmColor;
}
#pragma optimize( "", on )  // End optimize for speed.


//************************************
// Method:    AddToolBarButtons
// FullName:  AddToolBarButtons
// Access:    global
//************************************

unsigned int AddToolBarButtons
(
    WTL::CToolBarCtrl       & toolBar              ,
    WORD              const * items                ,
    WORD              const   numberOfItems        ,
    BYTE              const   buttonWrapState      ,
    size_t            const   separatorWidth       ,
    size_t            const   initialSeparatorWidth
)
{
    size_t const arraySize( numberOfItems * sizeof( TBBUTTON ) );
    TBBUTTON * const buttons( reinterpret_cast<TBBUTTON *>( _alloca( arraySize ) ) );
    ::ZeroMemory( buttons, arraySize );

    TBBUTTON * pButton( buttons );
    // set initial separator (half width by default)
    if( initialSeparatorWidth )
    {
        TBBUTTON & leadingSeparator( *pButton++ );
        leadingSeparator.iBitmap = initialSeparatorWidth;
        leadingSeparator.fsState = buttonWrapState;
        leadingSeparator.fsStyle = BTNS_SEP;
    }

    TBBUTTON const * const buttonsEnd( buttons + numberOfItems );
    unsigned int bitmapIndex( 0 );
    while( pButton < buttonsEnd )
    {
        TBBUTTON & currentButton( *pButton++ );
        WORD const item( *items++ );
        if( item != 0 )
        {
            currentButton.iBitmap   = bitmapIndex++;
            currentButton.idCommand = item;
            currentButton.fsState   = TBSTATE_ENABLED | buttonWrapState;
            assert( currentButton.fsStyle == BTNS_BUTTON ); // BTNS_BUTTON == 0
        }
        else
        {
            currentButton.iBitmap = separatorWidth;
            currentButton.fsState = buttonWrapState;
            currentButton.fsStyle = BTNS_SEP;
        }
    }

    VERIFY( toolBar.AddButtons( numberOfItems, buttons ) );

    return bitmapIndex;
}


//************************************
// Method:    fontHeight
// FullName:  fontHeight
// Access:    global
//************************************

WORD fontHeight( ATL::CWindow const & window )
{
    WTL::CFontHandle font( window.GetFont() );
    if( font.IsNull() ) 
        font.Attach( WTL::AtlGetDefaultGuiFont() );
    LOGFONT lf;
    VERIFY( font.GetLogFont( lf ) );

    return static_cast<WORD>( abs( lf.lfHeight ) );
}


//************************************
// Method:    GetDlgItemRect
// FullName:  GetDlgItemRect
// Access:    global
//************************************

WTL::CRect GetDlgItemRect( ATL::CWindow const & window, int const itemID )
{
    RECT itemRect;
    VERIFY( window.GetDlgItem( itemID ).GetWindowRect( &itemRect ) );
    VERIFY( window.ScreenToClient( &itemRect ) );
    return itemRect;
}


//************************************
// Method:    CreateSimpleToolBar
// FullName:  CreateSimpleToolBar
// Access:    global
//************************************

WTL::CToolBarCtrl CreateSimpleToolBar
(
    HWND  const hWndParent,
    UINT  const nResourceID,
    bool  const bInitialSeparator,
    WORD  const buttonMargin,
    DWORD const dwStyle,
    UINT  const nID
)
{
    WTL::CToolBarCtrl toolBar( CreateEmptyToolbar( hWndParent, nID, dwStyle ) );

    ToolBarData & toolBarData( GetToolBarData( nResourceID ) );

    // check if font is taller than our bitmaps
    WORD const bitmapHeight( (std::max)( toolBarData.wHeight, fontHeight( toolBar ) ) );

    // MSDN remarks: The size can be set only before adding any bitmaps to the
    // toolbar. If an application does not explicitly set the bitmap size, the
    // size defaults to 16 by 15 pixels.
    VERIFY( toolBar.SetBitmapSize( toolBarData.wWidth, bitmapHeight ) );

    WORD         const nItems         ( toolBarData.wItemCount + ( bInitialSeparator ? 1 : 0 ) );
    BYTE         const buttonWrapState( ( dwStyle & CCS_VERT ) ? TBSTATE_WRAP : 0 );
    size_t       const separatorWidth ( ( buttonWrapState == false ) ? toolBarData.wWidth / 2 : toolBarData.wHeight / 2 );
    unsigned int const numberOfBitmaps( AddToolBarButtons( toolBar, toolBarData.items(), nItems, buttonWrapState, separatorWidth, separatorWidth / 2 ) );

    WORD const bitsPerPixel( WTL::AtlGetBitmapResourceBitsPerPixel( nResourceID ) );
    if( bitsPerPixel > 4 )
    {
        // 32-bit color bitmap with alpha channel (valid for Windows XP and later)
        COLORREF   const crMask( ( bitsPerPixel == 32 ) ? CLR_NONE : CLR_DEFAULT );
        WTL::CImageList const imageList( ImageList_LoadImage( WTL::ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE( nResourceID ), toolBarData.wWidth, 1, crMask, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_DEFAULTSIZE ) );
        toolBar.SetImageList( imageList );
    }
    else
        VERIFY( toolBar.AddBitmap( numberOfBitmaps, nResourceID ) != -1 );

    VERIFY( toolBar.SetButtonSize( toolBarData.wWidth + buttonMargin, bitmapHeight + buttonMargin ) );
    toolBar.AutoSize();
    return toolBar;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

Share

About the Author

Domagoj Šarić
Software Developer Little Endian Ltd.
Croatia Croatia
No Biography provided

| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 13 Feb 2009
Article Copyright 2009 by Domagoj Šarić
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid