add last backwards-compatible version

This commit is contained in:
2021-12-14 00:33:46 -07:00
parent 68b10d413b
commit b0dd3f07f3
335 changed files with 4746 additions and 19627 deletions

View File

@@ -95,7 +95,7 @@ public:
RangeTotal = RangeMax - RangeMin
};
BEGIN_MSG_MAP_EX(CMyDSPPopup)
BEGIN_MSG_MAP(CMyDSPPopup)
MSG_WM_INITDIALOG(OnInitDialog)
COMMAND_HANDLER_EX(IDOK, BN_CLICKED, OnButton)
COMMAND_HANDLER_EX(IDCANCEL, BN_CLICKED, OnButton)

View File

@@ -112,14 +112,6 @@ BEGIN
LTEXT "Header",IDC_HEADER,8,4,348,8
END
IDD_LISTCONTROL_DEMO DIALOGEX 0, 0, 311, 177
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_LIST1,"SysListView32",LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,12,12,288,156
END
/////////////////////////////////////////////////////////////////////////////
//
@@ -168,14 +160,6 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 225
END
IDD_LISTCONTROL_DEMO, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 304
TOPMARGIN, 7
BOTTOMMARGIN, 170
END
END
#endif // APSTUDIO_INVOKED
@@ -195,21 +179,6 @@ BEGIN
0
END
IDD_LISTCONTROL_DEMO AFX_DIALOG_LAYOUT
BEGIN
0
END
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_SCROLL ICON "..\\..\\libPPUI\\IDI_SCROLL.ico"
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////

View File

@@ -5,6 +5,8 @@ VisualStudioVersion = 15.0.27130.2027
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "foo_sample", "foo_sample.vcxproj", "{85FBFD09-0099-4FE9-9DB6-78DB6F60F817}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "foobar2000_ATL_helpers", "..\ATLHelpers\foobar2000_ATL_helpers.vcxproj", "{622E8B19-8109-4717-BD4D-9657AA78363E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "foobar2000_SDK", "..\SDK\foobar2000_SDK.vcxproj", "{E8091321-D79D-4575-86EF-064EA1A4A20D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pfc", "..\..\pfc\pfc.vcxproj", "{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}"
@@ -13,8 +15,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "foobar2000_sdk_helpers", ".
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "foobar2000_component_client", "..\foobar2000_component_client\foobar2000_component_client.vcxproj", "{71AD2674-065B-48F5-B8B0-E1F9D3892081}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libPPUI", "..\..\libPPUI\libPPUI.vcxproj", "{7729EB82-4069-4414-964B-AD399091A03F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
@@ -25,14 +25,18 @@ Global
{85FBFD09-0099-4FE9-9DB6-78DB6F60F817}.Debug|x86.Build.0 = Debug|Win32
{85FBFD09-0099-4FE9-9DB6-78DB6F60F817}.Release|x86.ActiveCfg = Release|Win32
{85FBFD09-0099-4FE9-9DB6-78DB6F60F817}.Release|x86.Build.0 = Release|Win32
{622E8B19-8109-4717-BD4D-9657AA78363E}.Debug|x86.ActiveCfg = Debug|Win32
{622E8B19-8109-4717-BD4D-9657AA78363E}.Debug|x86.Build.0 = Debug|Win32
{622E8B19-8109-4717-BD4D-9657AA78363E}.Release|x86.ActiveCfg = Release|Win32
{622E8B19-8109-4717-BD4D-9657AA78363E}.Release|x86.Build.0 = Release|Win32
{E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug|x86.ActiveCfg = Debug|Win32
{E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug|x86.Build.0 = Debug|Win32
{E8091321-D79D-4575-86EF-064EA1A4A20D}.Release|x86.ActiveCfg = Release|Win32
{E8091321-D79D-4575-86EF-064EA1A4A20D}.Release|x86.Build.0 = Release|Win32
{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|x86.ActiveCfg = Debug FB2K|Win32
{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|x86.Build.0 = Debug FB2K|Win32
{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|x86.ActiveCfg = Release FB2K|Win32
{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|x86.Build.0 = Release FB2K|Win32
{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|x86.ActiveCfg = Debug|Win32
{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|x86.Build.0 = Debug|Win32
{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|x86.ActiveCfg = Release|Win32
{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|x86.Build.0 = Release|Win32
{EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Debug|x86.ActiveCfg = Debug|Win32
{EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Debug|x86.Build.0 = Debug|Win32
{EE47764E-A202-4F85-A767-ABDAB4AFF35F}.Release|x86.ActiveCfg = Release|Win32
@@ -41,10 +45,6 @@ Global
{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug|x86.Build.0 = Debug|Win32
{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release|x86.ActiveCfg = Release|Win32
{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release|x86.Build.0 = Release|Win32
{7729EB82-4069-4414-964B-AD399091A03F}.Debug|x86.ActiveCfg = Debug|Win32
{7729EB82-4069-4414-964B-AD399091A03F}.Debug|x86.Build.0 = Debug|Win32
{7729EB82-4069-4414-964B-AD399091A03F}.Release|x86.ActiveCfg = Release|Win32
{7729EB82-4069-4414-964B-AD399091A03F}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -14,18 +14,19 @@
<ProjectGuid>{85FBFD09-0099-4FE9-9DB6-78DB6F60F817}</ProjectGuid>
<RootNamespace>foo_input_raw</RootNamespace>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v141_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v141_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -49,6 +50,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;FOO_INPUT_RAW_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>Use</PrecompiledHeader>
@@ -56,6 +58,7 @@
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<TreatSpecificWarningsAsErrors>4715</TreatSpecificWarningsAsErrors>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<AdditionalIncludeDirectories>..;../..</AdditionalIncludeDirectories>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
@@ -71,11 +74,13 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;FOO_INPUT_RAW_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<AdditionalOptions>/d2notypeopt %(AdditionalOptions)</AdditionalOptions>
<TreatSpecificWarningsAsErrors>4715</TreatSpecificWarningsAsErrors>
<BufferSecurityCheck>false</BufferSecurityCheck>
@@ -83,7 +88,6 @@
<OmitFramePointers>true</OmitFramePointers>
<AdditionalIncludeDirectories>..;../..</AdditionalIncludeDirectories>
<FloatingPointModel>Fast</FloatingPointModel>
<PreprocessorDefinitions>NDEBUG;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -103,11 +107,7 @@
<ClCompile Include="dsp.cpp" />
<ClCompile Include="initquit.cpp" />
<ClCompile Include="input_raw.cpp" />
<ClCompile Include="listcontrol-advanced.cpp" />
<ClCompile Include="listcontrol-ownerdata.cpp" />
<ClCompile Include="listcontrol-simple.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="mainmenu-dynamic.cpp" />
<ClCompile Include="mainmenu.cpp" />
<ClCompile Include="IO.cpp" />
<ClCompile Include="PCH.cpp">
@@ -115,7 +115,6 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="playback_state.cpp" />
<ClCompile Include="playback_stream_capture.cpp" />
<ClCompile Include="preferences.cpp" />
<ClCompile Include="rating.cpp" />
<ClCompile Include="ui_and_threads.cpp" />
@@ -123,7 +122,6 @@
<ClCompile Include="ui_element_dialog.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="playback_stream_capture.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="stdafx.h" />
</ItemGroup>
@@ -134,12 +132,12 @@
<None Include="readme.txt" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\libPPUI\libPPUI.vcxproj">
<Project>{7729eb82-4069-4414-964b-ad399091a03f}</Project>
</ProjectReference>
<ProjectReference Include="..\..\pfc\pfc.vcxproj">
<Project>{ebfffb4e-261d-44d3-b89c-957b31a0bf9c}</Project>
</ProjectReference>
<ProjectReference Include="..\ATLHelpers\foobar2000_ATL_helpers.vcxproj">
<Project>{622e8b19-8109-4717-bd4d-9657aa78363e}</Project>
</ProjectReference>
<ProjectReference Include="..\foobar2000_component_client\foobar2000_component_client.vcxproj">
<Project>{71ad2674-065b-48f5-b8b0-e1f9d3892081}</Project>
</ProjectReference>
@@ -150,9 +148,6 @@
<Project>{e8091321-d79d-4575-86ef-064ea1a4a20d}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Image Include="..\..\libPPUI\IDI_SCROLL.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@@ -60,21 +60,6 @@
<ClCompile Include="ui_and_threads.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="listcontrol-advanced.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="listcontrol-simple.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="listcontrol-ownerdata.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mainmenu-dynamic.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="playback_stream_capture.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h">
@@ -83,9 +68,6 @@
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="playback_stream_capture.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="foo_sample.rc">
@@ -95,9 +77,4 @@
<ItemGroup>
<None Include="readme.txt" />
</ItemGroup>
<ItemGroup>
<Image Include="..\..\libPPUI\IDI_SCROLL.ico">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
</Project>

View File

@@ -1,323 +0,0 @@
// Advanced CListControl use demo
// Subclasses a CListControl to use all its features
#include "stdafx.h"
#include "resource.h"
#include <helpers/atl-misc.h>
#include <libPPUI/CListControlComplete.h>
#include <libPPUI/CListControl-Cells.h>
#include <string>
#include <algorithm>
#include <vector>
namespace {
struct listData_t {
std::string m_key, m_value;
bool m_checkState = false;
};
static std::vector<listData_t> makeListData() {
std::vector<listData_t> data;
data.resize( 10 );
for( size_t walk = 0; walk < data.size(); ++ walk ) {
auto & rec = data[walk];
rec.m_key = (PFC_string_formatter() << "Item #" << (walk+1) ).c_str();
rec.m_value = "edit me";
}
return data;
}
// See CListControlComplete.h for base class description
typedef CListControlComplete CListControlDemoParent;
class CListControlDemo : public CListControlDemoParent {
typedef CListControlDemoParent parent_t;
public:
BEGIN_MSG_MAP_EX(CListControlDemo)
CHAIN_MSG_MAP( parent_t );
MSG_WM_CREATE(OnCreate)
MSG_WM_CONTEXTMENU(OnContextMenu)
END_MSG_MAP()
// Context menu handler
void OnContextMenu(CWindow wnd, CPoint point) {
// did we get a (-1,-1) point due to context menu key rather than right click?
// GetContextMenuPoint fixes that, returning a proper point at which the menu should be shown
point = this->GetContextMenuPoint(point);
CMenu menu;
// WIN32_OP_D() : debug build only return value check
// Used to check for obscure errors in debug builds, does nothing (ignores errors) in release build
WIN32_OP_D(menu.CreatePopupMenu());
enum { ID_TEST1 = 1, ID_TEST2, ID_SELECTALL, ID_SELECTNONE, ID_INVERTSEL };
menu.AppendMenu(MF_STRING, ID_TEST1, L"Test 1");
menu.AppendMenu(MF_STRING, ID_TEST2, L"Test 2");
menu.AppendMenu(MF_SEPARATOR);
// Note: Ctrl+A handled automatically by CListControl, no need for us to catch it
menu.AppendMenu(MF_STRING, ID_SELECTALL, L"Select all\tCtrl+A");
menu.AppendMenu(MF_STRING, ID_SELECTNONE, L"Select none");
menu.AppendMenu(MF_STRING, ID_INVERTSEL, L"Invert selection");
int cmd;
{
// Callback object to show menu command descriptions in the status bar.
// it's actually a hidden window, needs a parent HWND, where we feed our control's HWND
CMenuDescriptionMap descriptions(m_hWnd);
// Set descriptions of all our items
descriptions.Set(ID_TEST1, "This is a test item #1");
descriptions.Set(ID_TEST2, "This is a test item #2");
descriptions.Set(ID_SELECTALL, "Selects all items");
descriptions.Set(ID_SELECTNONE, "Deselects all items");
descriptions.Set(ID_INVERTSEL, "Invert selection");
cmd = menu.TrackPopupMenuEx(TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, point.x, point.y, descriptions, nullptr);
}
switch(cmd) {
case ID_TEST1:
{
pfc::string_formatter msg;
msg << "Test command #1 triggered.\r\n";
msg << this->GetSelectedCount() << " items selected.";
// popup_message : non-blocking MessageBox equivalent
popup_message::g_show(msg, "Information");
}
break;
case ID_TEST2:
{
pfc::string_formatter msg;
msg << "Test command #1 triggered.\r\n";
msg << "Selected items:\r\n";
for( size_t walk = 0; walk < GetItemCount(); ++ walk) {
if ( this->IsItemSelected( walk ) ) {
msg << m_data[walk].m_key.c_str() << "\r\n";
}
}
msg << "End selected items.";
// popup_message : non-blocking MessageBox equivalent
popup_message::g_show(msg, "Information");
}
break;
case ID_SELECTALL:
this->SelectAll(); // trivial
break;
case ID_SELECTNONE:
this->SelectNone(); // trivial
break;
case ID_INVERTSEL:
{
auto mask = this->GetSelectionMask();
this->SetSelection(
// Items which we alter - all of them
pfc::bit_array_true(),
// Selection values - NOT'd original selection mask
pfc::bit_array_not(mask)
);
// Exclusion of footer item from selection handled via CanSelectItem()
}
break;
}
}
int OnCreate(LPCREATESTRUCT lpCreateStruct) {
InitHeader(); // set up header control with columns
SetWindowText(L"List Control Demo"); // screen reader will see this
return 0;
}
void InitHeader() {
InitializeHeaderCtrl(HDS_FULLDRAG);
// never hardcode values in pixels, always use screen DPI
auto DPI = m_dpi;
AddColumn( "Check", MulDiv(60, DPI.cx, 96 ) );
AddColumn( "Name", MulDiv(100, DPI.cx, 96 ) );
AddColumn( "Value", MulDiv(100, DPI.cx, 96 ) );
}
bool CanSelectItem( size_t row ) const override {
// can not select footer
return row != footerRow();
}
size_t footerRow() const {
return m_data.size();
}
t_size GetItemCount() const override {
return m_data.size() + 1; // footer
}
void onFooterClicked() {
SelectNone();
listData_t obj = {};
obj.m_key = "New item";
size_t index = m_data.size();
m_data.push_back( std::move(obj) );
OnItemsInserted(index, 1, true);
}
void OnSubItemClicked(t_size item, t_size subItem, CPoint pt) override {
if ( item == footerRow() ) {
onFooterClicked(); return;
}
if ( subItem == 2 ) {
TableEdit_Start(item, subItem); return;
}
__super::OnSubItemClicked( item, subItem, pt );
}
bool AllowScrollbar(bool vertical) const override {
return true;
}
t_size InsertIndexFromPointEx(const CPoint & pt, bool & bInside) const override {
// Drag&drop insertion point hook, for reordering only
auto ret = __super::InsertIndexFromPointEx(pt, bInside);
bInside = false; // never drop *into* an item, only between, as we only allow reorder
if ( ret > m_data.size() ) ret = m_data.size(); // never allow drop beyond footer
return ret;
}
void RequestReorder(size_t const * order, size_t count) override {
// we've been asked to reorder the items, by either drag&drop or cursors+modifiers
// we can either reorder as requested, reorder partially if some of the items aren't moveable, or reject the request
PFC_ASSERT( count == GetItemCount() );
// Footer row cannot be moved
if ( order[footerRow()] != footerRow() ) return;
pfc::reorder_t( m_data, order, count );
this->OnItemsReordered( order, count );
}
void RemoveMask( pfc::bit_array const & mask ) {
if ( mask.get(footerRow() ) ) return; // footer row cannot be removed
auto oldCount = GetItemCount();
pfc::remove_mask_t( m_data, mask );
this->OnItemsRemoved( mask, oldCount );
}
void RequestRemoveSelection() override {
// Delete key etc
RemoveMask(GetSelectionMask());
}
void ExecuteDefaultAction(t_size index) override {
// double click, enter key, etc
if ( index == footerRow() ) onFooterClicked();
}
bool GetSubItemText(t_size item, t_size subItem, pfc::string_base & out) const override {
if ( item == footerRow() ) {
if ( subItem == 0 ) {
out = "+ add new";
return true;
}
return false;
}
auto & rec = m_data[item];
switch(subItem) {
case 0:
// pass blank string or return false to create a checkbox only column
out = "check";
return true;
case 1:
out = rec.m_key.c_str();
return true;
case 2:
out = rec.m_value.c_str();
return true;
default:
return false;
}
}
size_t GetSubItemSpan(size_t row, size_t column) const override {
if ( row == footerRow() && column == 0 ) {
return GetColumnCount();
}
return 1;
}
cellType_t GetCellType(size_t item, size_t subItem) const override {
// cellType_t is a pointer to a cell class object supplying cell behavior specification & rendering methods
// use PFC_SINGLETON to provide static instances of used cells
if ( item == footerRow() ) {
if ( subItem == 0 ) {
return & PFC_SINGLETON( CListCell_Button );
} else {
return nullptr;
}
}
switch(subItem) {
case 0:
return & PFC_SINGLETON( CListCell_Checkbox );
default:
return & PFC_SINGLETON( CListCell_Text );
}
}
bool GetCellTypeSupported() const override {
return true;
}
bool GetCellCheckState(size_t item, size_t subItem) const override {
if ( subItem == 0 ) {
auto & rec = m_data[item];
return rec.m_checkState;
}
return false;
}
void SetCellCheckState(size_t item, size_t subItem, bool value) override {
if ( subItem == 0 ) {
auto & rec = m_data[item];
if (rec.m_checkState != value) {
rec.m_checkState = value;
__super::SetCellCheckState(item, subItem, value);
}
}
}
uint32_t QueryDragDropTypes() const override {return dragDrop_reorder;}
// Inplace edit handlers
// Overrides of CTableEditHelperV2 methods
void TableEdit_SetField(t_size item, t_size subItem, const char * value) override {
if ( subItem == 2 ) {
m_data[item].m_value = value;
ReloadItem( item );
}
}
bool TableEdit_IsColumnEditable(t_size subItem) const override {
return subItem == 2;
}
private:
std::vector< listData_t > m_data = makeListData();
};
// Straightforward WTL dialog code
class CListControlAdvancedDemoDialog : public CDialogImpl<CListControlAdvancedDemoDialog> {
public:
enum { IDD = IDD_LISTCONTROL_DEMO };
BEGIN_MSG_MAP_EX(CListControlAdvancedDemoDialog)
MSG_WM_INITDIALOG(OnInitDialog)
COMMAND_HANDLER_EX(IDCANCEL, BN_CLICKED, OnCancel)
END_MSG_MAP()
private:
void OnCancel(UINT, int, CWindow) {
DestroyWindow();
}
BOOL OnInitDialog(CWindow, LPARAM) {
// Create replacing existing windows list control
// automatically initialize position, font, etc
m_list.CreateInDialog( *this, IDC_LIST1 );
ShowWindow(SW_SHOW);
return TRUE; // system should set focus
}
CListControlDemo m_list;
};
}
// Called from mainmenu.cpp
void RunListControlAdvancedDemo() {
// automatically creates the dialog with object lifetime management and modeless dialog registration
fb2k::newDialog<CListControlAdvancedDemoDialog>();
}

View File

@@ -1,204 +0,0 @@
#include "stdafx.h"
// Owner-data CListControl use demo
// CListControlOwnerData with callbacks
#include "stdafx.h"
#include "resource.h"
#include <helpers/atl-misc.h>
#include <libPPUI/CListControlOwnerData.h>
#include <string>
#include <algorithm>
#include <vector>
namespace {
struct listData_t {
std::string m_key, m_value;
};
static std::vector<listData_t> makeListData() {
std::vector<listData_t> data;
data.resize( 10 );
for( size_t walk = 0; walk < data.size(); ++ walk ) {
auto & rec = data[walk];
rec.m_key = (PFC_string_formatter() << "Item #" << (walk+1) ).c_str();
rec.m_value = "edit me";
}
return data;
}
class CListControlOwnerDataDemoDialog : public CDialogImpl<CListControlOwnerDataDemoDialog>, private IListControlOwnerDataSource {
public:
// CListControlOwnerData constructor requires ptr to IListControlOwnerDataSource object
CListControlOwnerDataDemoDialog() : m_list(this) {}
enum { IDD = IDD_LISTCONTROL_DEMO };
BEGIN_MSG_MAP_EX(CListControlOwnerDataDemoDialog)
MSG_WM_INITDIALOG(OnInitDialog)
COMMAND_HANDLER_EX(IDCANCEL, BN_CLICKED, OnCancel)
MSG_WM_CONTEXTMENU(OnContextMenu)
END_MSG_MAP()
private:
void OnCancel(UINT, int, CWindow) {
DestroyWindow();
}
BOOL OnInitDialog(CWindow, LPARAM) {
// Create replacing existing windows list control
// automatically initialize position, font, etc
m_list.CreateInDialog( *this, IDC_LIST1 );
// never hardcode values in pixels, always use screen DPI
auto DPI = m_list.GetDPI();
m_list.AddColumn( "Name", MulDiv(100, DPI.cx, 96 ) );
m_list.AddColumn( "Value", MulDiv(150, DPI.cx, 96 ) );
ShowWindow(SW_SHOW);
return TRUE; // system should set focus
}
// Context menu handler
void OnContextMenu(CWindow wnd, CPoint point) {
// did we get a (-1,-1) point due to context menu key rather than right click?
// GetContextMenuPoint fixes that, returning a proper point at which the menu should be shown
point = m_list.GetContextMenuPoint(point);
CMenu menu;
// WIN32_OP_D() : debug build only return value check
// Used to check for obscure errors in debug builds, does nothing (ignores errors) in release build
WIN32_OP_D(menu.CreatePopupMenu());
enum { ID_TEST1 = 1, ID_TEST2, ID_SELECTALL, ID_SELECTNONE, ID_INVERTSEL };
menu.AppendMenu(MF_STRING, ID_TEST1, L"Test 1");
menu.AppendMenu(MF_STRING, ID_TEST2, L"Test 2");
menu.AppendMenu(MF_SEPARATOR);
// Note: Ctrl+A handled automatically by CListControl, no need for us to catch it
menu.AppendMenu(MF_STRING, ID_SELECTALL, L"Select all\tCtrl+A");
menu.AppendMenu(MF_STRING, ID_SELECTNONE, L"Select none");
menu.AppendMenu(MF_STRING, ID_INVERTSEL, L"Invert selection");
int cmd;
{
// Callback object to show menu command descriptions in the status bar.
// it's actually a hidden window, needs a parent HWND, where we feed our control's HWND
CMenuDescriptionMap descriptions(m_hWnd);
// Set descriptions of all our items
descriptions.Set(ID_TEST1, "This is a test item #1");
descriptions.Set(ID_TEST2, "This is a test item #2");
descriptions.Set(ID_SELECTALL, "Selects all items");
descriptions.Set(ID_SELECTNONE, "Deselects all items");
descriptions.Set(ID_INVERTSEL, "Invert selection");
cmd = menu.TrackPopupMenuEx(TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, point.x, point.y, descriptions, nullptr);
}
switch(cmd) {
case ID_TEST1:
{
pfc::string_formatter msg;
msg << "Test command #1 triggered.\r\n";
msg << m_list.GetSelectedCount() << " items selected.";
// popup_message : non-blocking MessageBox equivalent
popup_message::g_show(msg, "Information");
}
break;
case ID_TEST2:
{
pfc::string_formatter msg;
msg << "Test command #1 triggered.\r\n";
msg << "Selected items:\r\n";
for( size_t walk = 0; walk < m_list.GetItemCount(); ++ walk) {
if ( m_list.IsItemSelected( walk ) ) {
msg << m_data[walk].m_key.c_str() << "\r\n";
}
}
msg << "End selected items.";
// popup_message : non-blocking MessageBox equivalent
popup_message::g_show(msg, "Information");
}
break;
case ID_SELECTALL:
m_list.SelectAll(); // trivial
break;
case ID_SELECTNONE:
m_list.SelectNone(); // trivial
break;
case ID_INVERTSEL:
{
auto mask = m_list.GetSelectionMask();
m_list.SetSelection(
// Items which we alter - all of them
pfc::bit_array_true(),
// Selection values - NOT'd original selection mask
pfc::bit_array_not(mask)
);
// Exclusion of footer item from selection handled via CanSelectItem()
}
break;
}
}
private:
// IListControlOwnerDataSource methods
size_t listGetItemCount( ctx_t ctx ) override {
PFC_ASSERT( ctx == &m_list ); // ctx is a pointer to the object calling us
return m_data.size();
}
pfc::string8 listGetSubItemText( ctx_t, size_t item, size_t subItem ) override {
auto & rec = m_data[item];
switch(subItem) {
case 0:
return rec.m_key.c_str();
case 1:
return rec.m_value.c_str();
default:
return "";
}
}
bool listCanReorderItems( ctx_t ) override {
return true;
}
bool listReorderItems( ctx_t, const size_t* order, size_t count) override {
PFC_ASSERT( count == m_data.size() );
pfc::reorder_t( m_data, order, count );
return true;
}
bool listRemoveItems( ctx_t, pfc::bit_array const & mask) override {
pfc::remove_mask_t( m_data, mask );
return true;
}
void listItemAction(ctx_t, size_t item) override {
m_list.TableEdit_Start( item, 1 );
}
void listSubItemClicked( ctx_t, size_t item, size_t subItem) override {
if ( subItem == 1 ) {
m_list.TableEdit_Start( item, subItem );
}
}
void listSetEditField(ctx_t ctx, size_t item, size_t subItem, const char * val) override {
if ( subItem == 1 ) {
m_data[item].m_value = val;
}
}
bool listIsColumnEditable( ctx_t, size_t subItem ) override {
return subItem == 1;
}
std::vector< listData_t > m_data = makeListData();
CListControlOwnerData m_list;
};
}
// Called from mainmenu.cpp
void RunListControlOwnerDataDemo() {
// automatically creates the dialog with object lifetime management and modeless dialog registration
fb2k::newDialog<CListControlOwnerDataDemoDialog>();
}

View File

@@ -1,163 +0,0 @@
#include "stdafx.h"
// Simple CListControl use demo
// CListControlSimple
#include "stdafx.h"
#include "resource.h"
#include <helpers/atl-misc.h>
#include <libPPUI/CListControlSimple.h>
#include <string>
#include <algorithm>
#include <vector>
namespace {
struct listData_t {
std::string m_key, m_value;
};
static std::vector<listData_t> makeListData() {
std::vector<listData_t> data;
data.resize( 10 );
for( size_t walk = 0; walk < data.size(); ++ walk ) {
auto & rec = data[walk];
rec.m_key = (PFC_string_formatter() << "Item #" << (walk+1) ).c_str();
rec.m_value = "sample value";
}
return data;
}
class CListControlSimpleDemoDialog : public CDialogImpl<CListControlSimpleDemoDialog> {
public:
enum { IDD = IDD_LISTCONTROL_DEMO };
BEGIN_MSG_MAP_EX(CListControlOwnerDataDemoDialog)
MSG_WM_INITDIALOG(OnInitDialog)
COMMAND_HANDLER_EX(IDCANCEL, BN_CLICKED, OnCancel)
MSG_WM_CONTEXTMENU(OnContextMenu)
END_MSG_MAP()
private:
void OnCancel(UINT, int, CWindow) {
DestroyWindow();
}
BOOL OnInitDialog(CWindow, LPARAM) {
// Create replacing existing windows list control
// automatically initialize position, font, etc
m_list.CreateInDialog( *this, IDC_LIST1 );
// never hardcode values in pixels, always use screen DPI
auto DPI = m_list.GetDPI();
m_list.AddColumn( "Name", MulDiv(100, DPI.cx, 96 ) );
m_list.AddColumn( "Value", MulDiv(150, DPI.cx, 96 ) );
{
auto data = makeListData();
m_list.SetItemCount( data.size( ) );
for( size_t walk = 0; walk < data.size(); ++ walk ) {
auto & rec = data[walk];
m_list.SetItemText( walk, 0, rec.m_key.c_str() );
m_list.SetItemText( walk, 1, rec.m_value.c_str() );
}
}
ShowWindow(SW_SHOW);
return TRUE; // system should set focus
}
// Context menu handler
void OnContextMenu(CWindow wnd, CPoint point) {
// did we get a (-1,-1) point due to context menu key rather than right click?
// GetContextMenuPoint fixes that, returning a proper point at which the menu should be shown
point = m_list.GetContextMenuPoint(point);
CMenu menu;
// WIN32_OP_D() : debug build only return value check
// Used to check for obscure errors in debug builds, does nothing (ignores errors) in release build
WIN32_OP_D(menu.CreatePopupMenu());
enum { ID_TEST1 = 1, ID_TEST2, ID_SELECTALL, ID_SELECTNONE, ID_INVERTSEL };
menu.AppendMenu(MF_STRING, ID_TEST1, L"Test 1");
menu.AppendMenu(MF_STRING, ID_TEST2, L"Test 2");
menu.AppendMenu(MF_SEPARATOR);
// Note: Ctrl+A handled automatically by CListControl, no need for us to catch it
menu.AppendMenu(MF_STRING, ID_SELECTALL, L"Select all\tCtrl+A");
menu.AppendMenu(MF_STRING, ID_SELECTNONE, L"Select none");
menu.AppendMenu(MF_STRING, ID_INVERTSEL, L"Invert selection");
int cmd;
{
// Callback object to show menu command descriptions in the status bar.
// it's actually a hidden window, needs a parent HWND, where we feed our control's HWND
CMenuDescriptionMap descriptions(m_hWnd);
// Set descriptions of all our items
descriptions.Set(ID_TEST1, "This is a test item #1");
descriptions.Set(ID_TEST2, "This is a test item #2");
descriptions.Set(ID_SELECTALL, "Selects all items");
descriptions.Set(ID_SELECTNONE, "Deselects all items");
descriptions.Set(ID_INVERTSEL, "Invert selection");
cmd = menu.TrackPopupMenuEx(TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, point.x, point.y, descriptions, nullptr);
}
switch(cmd) {
case ID_TEST1:
{
pfc::string_formatter msg;
msg << "Test command #1 triggered.\r\n";
msg << m_list.GetSelectedCount() << " items selected.";
// popup_message : non-blocking MessageBox equivalent
popup_message::g_show(msg, "Information");
}
break;
case ID_TEST2:
{
pfc::string_formatter msg;
msg << "Test command #1 triggered.\r\n";
msg << "Selected items:\r\n";
for( size_t walk = 0; walk < m_list.GetItemCount(); ++ walk) {
if ( m_list.IsItemSelected( walk ) ) {
msg << "#" << (walk+1) << "\r\n";
}
}
msg << "End selected items.";
// popup_message : non-blocking MessageBox equivalent
popup_message::g_show(msg, "Information");
}
break;
case ID_SELECTALL:
m_list.SelectAll(); // trivial
break;
case ID_SELECTNONE:
m_list.SelectNone(); // trivial
break;
case ID_INVERTSEL:
{
auto mask = m_list.GetSelectionMask();
m_list.SetSelection(
// Items which we alter - all of them
pfc::bit_array_true(),
// Selection values - NOT'd original selection mask
pfc::bit_array_not(mask)
);
// Exclusion of footer item from selection handled via CanSelectItem()
}
break;
}
}
private:
CListControlSimple m_list;
};
}
// Called from mainmenu.cpp
void RunListControlSimpleDemo() {
fb2k::newDialog<CListControlSimpleDemoDialog>();
}

View File

@@ -1,120 +0,0 @@
#include "stdafx.h"
#include <vector>
namespace { // anon namespace everything, it's not accessible by means other than the service factory
// The command ID.
// Generate a new GUID when reusing code.
static const GUID guid_menucommand = { 0xab754b0b, 0x204, 0x4471, { 0xb5, 0x29, 0xff, 0x73, 0xae, 0x51, 0x5d, 0xe9 } };
// Shared with mainmenu.cpp
static const GUID guid_mainmenu_group_id = { 0x44963e7a, 0x4b2a, 0x4588, { 0xb0, 0x17, 0xa8, 0x69, 0x18, 0xcb, 0x8a, 0xa5 } };
class sample_command : public mainmenu_node_command {
public:
sample_command( size_t index ) : m_index(index) {
}
void get_display(pfc::string_base & text, t_uint32 & flags) override {
flags = 0;
text = PFC_string_formatter() << "Test dynamic item #" << m_index;
}
void execute(service_ptr_t<service_base> callback) override {
popup_message::g_show(PFC_string_formatter() << "Invoked test menu item #" << m_index, "Information");
}
GUID get_guid() override {
// This method returns our subcommand ID.
// Dynamic commands are identified by a pair of GUIDs:
// - command ID ( see: mainmenu_commands interface )
// - subcommand ID ( identifier of one of the dynamic items )
// Subcommand identifiers don't have to be actually globally unique,
// as long as they're unique among the subcommand identifiers for this command ID.
// In our case, we'll just create a makeshift GUID from a hash of the index.
// This is perfectly okay for production code - as long as your command ID is a proper GUID!
// Don't ever hash size_t which varies with CPU architecture
// Integer endianness intentionally disregarded
uint32_t hashme = (uint32_t) m_index;
auto api = hasher_md5::get();
hasher_md5_state state;
api->initialize( state );
api->process( state, &hashme, sizeof(hashme) );
// fb2k hasher_md5 API even provides a convenient method to return MD5 hashes cast to GUIDs for this.
return api->get_result_guid( state );
}
bool get_description(pfc::string_base & out) {
out = PFC_string_formatter() << "This is a test menu item #" << m_index << ".";
return true;
}
private:
const size_t m_index;
};
class sample_group : public mainmenu_node_group {
public:
sample_group() {
m_children.resize(11);
for( size_t walk = 0; walk < m_children.size(); ++ walk ) {
mainmenu_node::ptr node;
// Insert separators for odd items, commands for even
if ( walk % 2 ) {
node = fb2k::service_new<mainmenu_node_separator>();
} else {
auto cmdIndex = walk/2 + 1;
node = fb2k::service_new<sample_command>( cmdIndex );
}
m_children[walk] = std::move(node);
}
}
void get_display(pfc::string_base & text, t_uint32 & flags) override {
flags = 0;
text = "Dynamic menu test group";
}
t_size get_children_count() override {
return m_children.size();
}
mainmenu_node::ptr get_child(t_size index) override {
PFC_ASSERT( index < m_children.size() );
return m_children[index];
}
private:
std::vector<mainmenu_node::ptr> m_children;
};
class mainmenu_sample_dynamic : public mainmenu_commands_v2 {
public:
// mainmenu_commands_v2 methods
t_uint32 get_command_count() override { return 1; }
GUID get_command(t_uint32 p_index) override {return guid_menucommand;}
void get_name(t_uint32 p_index,pfc::string_base & p_out) override {p_out = "Dynamic menu test";}
bool get_description(t_uint32 p_index,pfc::string_base & p_out) override {
// Should not get here much
p_out = "This is a dynamic menu command test.";
return true;
}
GUID get_parent() override {return guid_mainmenu_group_id; }
void execute(t_uint32 p_index,service_ptr_t<service_base> p_callback) override {
// Should not get here, someone not aware of our dynamic status tried to invoke us?
}
bool is_command_dynamic(t_uint32 index) override { return true; }
mainmenu_node::ptr dynamic_instantiate(t_uint32 index) override {
return fb2k::service_new<sample_group>();
}
bool dynamic_execute(t_uint32 index, const GUID & subID, service_ptr_t<service_base> callback) override {
// If your component provides a more efficient way to execute the command,
// than doing full dynamic_instantiate() and walking all the dynamic items to find one with the matching identifier,
// please implement it here.
// ... or just skip implementing this method entirely.
return __super::dynamic_execute( index, subID, callback );
}
};
static service_factory_single_t<mainmenu_sample_dynamic> g_mainmenu_sample_dynamic;
} // namespace

View File

@@ -1,26 +1,16 @@
#include "stdafx.h"
#include "playback_stream_capture.h"
// I am foo_sample and these are *my* GUIDs
// Make your own when reusing code or else
static const GUID guid_mainmenu_group_id = { 0x44963e7a, 0x4b2a, 0x4588, { 0xb0, 0x17, 0xa8, 0x69, 0x18, 0xcb, 0x8a, 0xa5 } };
static const GUID guid_test = { 0x7c4726df, 0x3b2d, 0x4c7c,{ 0xad, 0xe8, 0x43, 0xd8, 0x46, 0xbe, 0xce, 0xa8 } };
static const GUID guid_playbackstate = { 0xbd880c51, 0xf0cc, 0x473f,{ 0x9d, 0x14, 0xa6, 0x6e, 0x8c, 0xed, 0x25, 0xae } };
static const GUID guid_io = { 0xd380c333, 0xa72c, 0x4e1e,{ 0x97, 0xca, 0xed, 0x14, 0xeb, 0x93, 0x76, 0x23 } };
static const GUID guid_listcontrol_advanced = { 0x27e29db0, 0x3079, 0x4ce0, { 0x8b, 0x4a, 0xa0, 0x78, 0xeb, 0x6, 0x56, 0x86 } };
static const GUID guid_listcontrol_simple = { 0x34664996, 0x54cd, 0x48eb, { 0xa8, 0x20, 0x8f, 0x45, 0x7d, 0xcc, 0xff, 0xbb } };
static const GUID guid_listcontrol_ownerdata = { 0xc6d23696, 0x4be5, 0x4daa, { 0xaf, 0xb2, 0x35, 0x14, 0xa, 0x47, 0xd2, 0xf9 } };
static const GUID guid_playback_stream_capture = { 0x3d0f0f1a, 0x6b5f, 0x42e3, { 0xa4, 0x6d, 0x49, 0x1, 0x3, 0xf0, 0x54, 0xb2 } };
static mainmenu_group_popup_factory g_mainmenu_group(guid_mainmenu_group_id, mainmenu_groups::file, mainmenu_commands::sort_priority_dontcare, "Sample component");
void RunPlaybackStateDemo(); //playback_state.cpp
void RunIOTest(); // IO.cpp
void RunListControlSimpleDemo(); // listcontrol-simple.cpp
void RunListControlOwnerDataDemo(); // listcontrol-ownerdata.cpp
void RunListControlAdvancedDemo(); // listcontrol-advanced.cpp
class mainmenu_commands_sample : public mainmenu_commands {
public:
@@ -28,56 +18,40 @@ public:
cmd_test = 0,
cmd_playbackstate,
cmd_io,
cmd_listcontrol_simple,
cmd_listcontrol_ownerdata,
cmd_listcontrol_advanced,
cmd_playback_stream_capture,
cmd_total
};
t_uint32 get_command_count() override {
t_uint32 get_command_count() {
return cmd_total;
}
GUID get_command(t_uint32 p_index) override {
GUID get_command(t_uint32 p_index) {
switch(p_index) {
case cmd_test: return guid_test;
case cmd_playbackstate: return guid_playbackstate;
case cmd_io: return guid_io;
case cmd_listcontrol_simple: return guid_listcontrol_simple;
case cmd_listcontrol_ownerdata: return guid_listcontrol_ownerdata;
case cmd_listcontrol_advanced: return guid_listcontrol_advanced;
case cmd_playback_stream_capture: return guid_playback_stream_capture;
default: uBugCheck(); // should never happen unless somebody called us with invalid parameters - bail
}
}
void get_name(t_uint32 p_index,pfc::string_base & p_out) override {
void get_name(t_uint32 p_index,pfc::string_base & p_out) {
switch(p_index) {
case cmd_test: p_out = "Test command"; break;
case cmd_playbackstate: p_out = "Playback state demo"; break;
case cmd_io: p_out = "I/O test"; break;
case cmd_listcontrol_simple: p_out = "Simple CListControl demo"; break;
case cmd_listcontrol_ownerdata: p_out = "Owner-data CListControl demo"; break;
case cmd_listcontrol_advanced: p_out = "Advanced CListControl demo"; break;
case cmd_playback_stream_capture: p_out = "Playback stream capture demo"; break;
default: uBugCheck(); // should never happen unless somebody called us with invalid parameters - bail
}
}
bool get_description(t_uint32 p_index,pfc::string_base & p_out) override {
bool get_description(t_uint32 p_index,pfc::string_base & p_out) {
switch(p_index) {
case cmd_test: p_out = "This is a sample menu command."; return true;
case cmd_playbackstate: p_out = "Opens the playback state demo dialog."; return true;
case cmd_io: p_out = "Runs I/O test."; return true;
case cmd_listcontrol_simple: p_out = "Runs Simple CListControl demo."; return true;
case cmd_listcontrol_ownerdata: p_out = "Runs Owner Data CListControl demo."; return true;
case cmd_listcontrol_advanced: p_out = "Runs Advanced CListControl demo."; return true;
case cmd_playback_stream_capture: p_out = "Toggles playback stream capture operation."; return true;
default: return false;
default: uBugCheck(); // should never happen unless somebody called us with invalid parameters - bail
}
}
GUID get_parent() override {
GUID get_parent() {
return guid_mainmenu_group_id;
}
void execute(t_uint32 p_index,service_ptr_t<service_base> p_callback) override {
void execute(t_uint32 p_index,service_ptr_t<service_base> p_callback) {
switch(p_index) {
case cmd_test:
popup_message::g_show("This is a sample menu command.", "Blah");
@@ -88,33 +62,10 @@ public:
case cmd_io:
RunIOTest();
break;
case cmd_listcontrol_simple:
RunListControlSimpleDemo();
break;
case cmd_listcontrol_ownerdata:
RunListControlOwnerDataDemo();
break;
case cmd_listcontrol_advanced:
RunListControlAdvancedDemo();
break;
case cmd_playback_stream_capture:
ToggleCapture();
break;
default:
uBugCheck(); // should never happen unless somebody called us with invalid parameters - bail
}
}
bool get_display(t_uint32 p_index,pfc::string_base & p_text,t_uint32 & p_flags) override {
// OPTIONAL method
bool rv = __super::get_display(p_index, p_text, p_flags);
if (rv) switch(p_index) {
case cmd_playback_stream_capture:
// Add checkmark if capture is in progress
if ( IsCaptureRunning() ) p_flags |= flag_checked;
break;
}
return rv;
}
};
static mainmenu_commands_factory_t<mainmenu_commands_sample> g_mainmenu_commands_sample_factory;

View File

@@ -1,13 +1,11 @@
#include "stdafx.h"
#include "resource.h"
#include <helpers/WindowPositionUtils.h>
#include <helpers/atl-misc.h>
class CPlaybackStateDemo : public CDialogImpl<CPlaybackStateDemo>, private play_callback_impl_base {
public:
enum {IDD = IDD_PLAYBACK_STATE};
BEGIN_MSG_MAP_EX(CPlaybackStateDemo)
BEGIN_MSG_MAP(CPlaybackStateDemo)
MSG_WM_INITDIALOG(OnInitDialog)
COMMAND_HANDLER_EX(IDC_PATTERN, EN_CHANGE, OnPatternChange)
COMMAND_HANDLER_EX(IDCANCEL, BN_CLICKED, OnCancel)

View File

@@ -1,121 +0,0 @@
#include "stdafx.h"
#include <helpers/writer_wav.h>
namespace {
// private classes in anon namespace
typedef CWavWriter wav_writer;
typedef wavWriterSetup_t wav_writer_setup;
static pfc::string8 g_outputPath;
static wav_writer g_wav_writer;
class playback_stream_capture_callback_impl : public playback_stream_capture_callback {
public:
void on_chunk(const audio_chunk & chunk) override {
PFC_ASSERT(core_api::is_main_thread());
try {
// writing files in main thread is not pretty, but good enough for our demo
auto & abort = fb2k::noAbort;
if (g_wav_writer.is_open() && g_wav_writer.get_spec() != chunk.get_spec()) {
g_wav_writer.finalize(abort);
}
if (!g_wav_writer.is_open() && ! core_api::is_shutting_down() ) {
wav_writer_setup setup; setup.initialize(chunk, 16, false, false);
GUID g; CoCreateGuid(&g);
pfc::string_formatter fn;
fn << "capture-" << pfc::print_guid(g) << ".wav";
pfc::string_formatter path = g_outputPath;
path.add_filename( fn ); // pretty method to add file path components with auto inserted delimiter
g_wav_writer.open(path, setup, abort);
}
g_wav_writer.write(chunk, abort);
} catch(std::exception const & e) {
FB2K_console_formatter() << "Playback stream capture error: " << e;
// FIX ME handle this in a pretty manner, likely inaccessible output folder or out of disk space
}
}
};
static playback_stream_capture_callback_impl g_callback;
static bool g_active = false;
static void FlushCapture() {
if (g_active) {
g_wav_writer.finalize(fb2k::noAbort);
}
}
static void StopCapture() {
if ( g_active ) {
g_active = false;
playback_stream_capture::get()->remove_callback(&g_callback);
g_wav_writer.finalize(fb2k::noAbort);
}
}
static void StartCapture() {
PFC_ASSERT( g_outputPath.length() > 0 );
if (!g_active && !core_api::is_shutting_down()) {
g_active = true;
playback_stream_capture::get()->add_callback(&g_callback);
}
}
// Forcibly stop capture when fb2k is shutting down
class initquit_psc : public initquit {
public:
void on_quit() override {
PFC_ASSERT( core_api::is_shutting_down() );
StopCapture();
}
};
// Handle playback stop events to split output WAV files
class play_callback_psc : public play_callback_static {
public:
unsigned get_flags() override {
return flag_on_playback_stop;
}
void on_playback_stop(play_control::t_stop_reason p_reason) override {
// Terminate the current stream
FlushCapture();
}
void on_playback_starting(play_control::t_track_command p_command,bool p_paused) override {}
void on_playback_new_track(metadb_handle_ptr p_track) override {}
void on_playback_seek(double p_time) override {}
void on_playback_pause(bool p_state) override {}
void on_playback_edited(metadb_handle_ptr p_track) override {}
void on_playback_dynamic_info(const file_info & p_info) override {}
void on_playback_dynamic_info_track(const file_info & p_info) override {}
void on_playback_time(double p_time) override {}
void on_volume_change(float p_new_val) override {}
};
// pretty modern macro for service_factory_single_t<>
FB2K_SERVICE_FACTORY( initquit_psc );
FB2K_SERVICE_FACTORY( play_callback_psc );
}
void ToggleCapture() {
// Block modal dialog recursions.
// Folder picker below is a modal dialog, don't ever call it if there's another modal dialog in progress.
// Also prevents this function from recursing into itself if someone manages to hit the menu item while already picking folder.
// This will bump whatever modal dialog already exists, so the user has some idea why this was refused.
if ( !ModalDialogPrologue() ) return;
if (g_active) {
StopCapture();
} else {
const HWND wndParent = core_api::get_main_window();
modal_dialog_scope scope(wndParent); // we can't have a handle to the modal dialog, but parent handle is good enough
if (uBrowseForFolder(wndParent, "Choose output folder", g_outputPath)) {
StartCapture();
}
}
}
bool IsCaptureRunning() {
return g_active;
}

View File

@@ -1,4 +0,0 @@
#pragma once
void ToggleCapture();
bool IsCaptureRunning();

View File

@@ -1,6 +1,5 @@
#include "stdafx.h"
#include "resource.h"
#include <helpers/atl-misc.h>
// Sample preferences interface: two meaningless configuration settings accessible through a preferences page and one accessible through advanced preferences.
@@ -43,7 +42,7 @@ public:
void reset();
//WTL message map
BEGIN_MSG_MAP_EX(CMyPreferences)
BEGIN_MSG_MAP(CMyPreferences)
MSG_WM_INITDIALOG(OnInitDialog)
COMMAND_HANDLER_EX(IDC_BOGO1, EN_CHANGE, OnEditChange)
COMMAND_HANDLER_EX(IDC_BOGO2, EN_CHANGE, OnEditChange)

View File

@@ -6,9 +6,6 @@
#define IDD_DSP 102
#define IDD_UI_ELEMENT 103
#define IDD_THREADS 105
#define IDD_LISTCONTROL_DEMO 107
#define IDI_ICON1 109
#define IDI_SCROLL 109
#define IDD_MYPREFERENCES 148
#define IDC_BOGO1 1001
#define IDC_BOGO2 1002
@@ -38,7 +35,7 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 110
#define _APS_NEXT_RESOURCE_VALUE 107
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1021
#define _APS_NEXT_SYMED_VALUE 101

View File

@@ -1,2 +1,2 @@
#include <helpers/foobar2000+atl.h>
#include <ATLHelpers/ATLHelpers.h>

View File

@@ -5,10 +5,6 @@
// Or: how I learned to stop worrying and love the lambdas
#include <memory> // shared_ptr
#include <libPPUI/CDialogResizeHelper.h>
#include <helpers/filetimetools.h>
#include <helpers/duration_counter.h>
#include <helpers/atl-misc.h>
@@ -30,13 +26,6 @@ namespace { // anon namespace local classes for good measure
{IDCANCEL, 1,1,1,1 },
{IDC_HEADER, 0,0,1,0 },
{IDC_LIST, 0,0,1,1 },
// current position of a control is determined by initial_position + factor * (current_dialog_size - initial_dialog_size)
// where factor is the value from the table above
// applied to all four values - left, top, right, bottom
// 0,0,0,0 means that a control doesn't react to dialog resizing (aligned to top+left, no resize)
// 1,1,1,1 means that the control is aligned to bottom+right but doesn't resize
// 0,0,1,0 means that the control disregards vertical resize (aligned to top) and changes its width with the dialog
};
// Minimum/maximum size, in dialog box units; see MSDN MapDialogRect for more info about dialog box units.

View File

@@ -1,7 +1,5 @@
#include "stdafx.h"
#include <libPPUI/win32_op.h>
#include <helpers/BumpableElem.h>
namespace {
@@ -19,7 +17,7 @@ namespace {
void initialize_window(HWND parent) {WIN32_OP(Create(parent) != NULL);}
BEGIN_MSG_MAP_EX(CMyElemWindow)
BEGIN_MSG_MAP(CMyElemWindow)
MESSAGE_HANDLER(WM_LBUTTONDOWN,OnLButtonDown);
MSG_WM_ERASEBKGND(OnEraseBkgnd)
MSG_WM_PAINT(OnPaint)

View File

@@ -2,11 +2,6 @@
#include "resource.h"
#include <libPPUI/win32_utility.h>
#include <libPPUI/win32_op.h> // WIN32_OP()
#include <libPPUI/wtl-pp.h> // CCheckBox
#include <helpers/atl-misc.h> // ui_element_impl
namespace {
// Anonymous namespace : standard practice in fb2k components
// Nothing outside should have any reason to see these symbols, and we don't want funny results if another cpp has similarly named classes.