views:

199

answers:

1

I'm trying to write a wrapper for Winamp input plugins and have hit a bit of a snag. I'd like my wrapper to be able to display a plugin's configuration dialog, which is (or should be) achieved by calling the plugin's Config(HWND hwndParent) function.

For most plugins, this works fine and my program is able to display the plugin's configuration dialog. However, 64th Note (a plugin for playing USF files) is giving me problems. Winamp can display its configuration dialog just fine, but whenever I try to display it from my wrapper, the dialog gets destroyed before it ever shows itself. Thankfully, 64th Note is open source, so I took a look at its innards to try and get an idea of what's going wrong. I've trimmed off the irrelevant bits and am left with this:

Config function in the plugin (should show configuration dialog):

void Config(HWND hwndParent) {
    DialogBox(slave, (const char *) IDD_CONFIG_WINDOW, NULL, configDlgProc);
}

(Slave is the plugin DLL's HINSTANCE handle.) The proc for the dialog is as follows (I have stripped out all the functionality, since it doesn't appear to have an influence on this problem):

BOOL CALLBACK configDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 return 0;
}

The template for IDD_CONFIG_WINDOW is as follows:

IDD_CONFIG_WINDOW DIALOGEX 0, 0, 269, 149
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "64th Note configuration"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,212,38,50,14
    CONTROL         "Play Forever",IDC_NOLENGTH,"Button",BS_AUTORADIOBUTTON,7,7,55,8
    CONTROL         "Always Use Default Length",IDC_SETLEN,"Button",BS_AUTORADIOBUTTON,7,17,101,8
    CONTROL         "Default Length",IDC_DEFLEN,"Button",BS_AUTORADIOBUTTON,7,29,63,8
    EDITTEXT        IDC_DEFLENVAL,71,28,38,12,ES_AUTOHSCROLL
    EDITTEXT        IDC_DEFFADEVAL,71,42,38,12,ES_AUTOHSCROLL
    CONTROL         "Detect Silence",IDC_DETSIL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,56,63,8
    EDITTEXT        IDC_DETSILVAL,71,56,38,12,ES_AUTOHSCROLL
    CONTROL         "Slider2",IDC_PRISLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,74,90,108,11
    EDITTEXT        IDC_TITLEFMT,7,127,255,15,ES_AUTOHSCROLL
    CONTROL         "Default to file name on missing field",IDC_FNONMISSINGTAG,
                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,50,114,124,8
    CONTROL         "Use Recompiler CPU",IDC_RECOMPILER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,145,7,83,8
    CONTROL         "Round Frequency",IDC_ROUNDFREQ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,145,16,73,8
    CONTROL         "Seek Backwards",IDC_BACKWARDS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,145,26,70,8
    CONTROL         "Fast Seek",IDC_FASTSEEK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,145,35,48,8
    CONTROL         "RSP Sections",IDC_SECTIONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,145,45,60,8
    CONTROL         "Soft Amplify",IDC_SOFTAMP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,145,54,53,8
    CONTROL         "Audio HLE",IDC_AUDIOHLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,145,63,50,8
    CONTROL         "Auto Audio HLE",IDC_AUTOAUDIOHLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,145,72,64,8
    CONTROL         "Display Errors",IDC_DISPERROR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,145,81,58,8
    EDITTEXT        IDC_RELVOL,211,104,28,12,ES_AUTOHSCROLL
    PUSHBUTTON      "Cancel",IDCANCEL,212,54,50,14
    PUSHBUTTON      "Help",IDHELPBUTTON,212,71,50,14
    LTEXT           "Title format:",IDC_STATIC,7,113,38,8
    LTEXT           "seconds",IDC_STATIC,112,29,28,8
    LTEXT           "Default Fade",IDC_STATIC,19,43,42,8
    LTEXT           "seconds",IDC_STATIC,112,43,28,8
    LTEXT           "seconds",IDC_STATIC,112,57,28,8
    CTEXT           "CPU Thread Priority",IDC_STATIC,7,91,63,8
    CTEXT           "Look ma, I'm data!",IDC_CPUPRI,75,104,108,8
    LTEXT           "Relative Volume",IDC_STATIC,199,94,52,8
    LTEXT           "Fade Type",IDC_STATIC,7,75,35,8
    COMBOBOX        IDC_FADETYPE,45,72,87,74,CBS_DROPDOWNLIST | WS_TABSTOP
END

Naturally, without any substance in the proc function, the dialog doesn't have any functionality, but it still displays in Winamp when the Config function is invoked. However, it does not appear when I invoke it from my wrapper program. When I monitored the messages sent to the dialog in its proc function, I saw that WM_DESTROY and WM_NCDESTROY were sent within the first few messages, though I have no clue as to why.

If I change the Config function so that it displays the plugin's About dialog instead of its configuration dialog, both Winamp and my wrapper will display the About dialog, which suggests that there is something unique to the configuration dialog template that's causing the problem. The modified Config function reads like so:

void Config(HWND hwndParent) {
    DialogBox(slave, (const char *) IDD_ABOUTBOX, NULL, configDlgProc);
}

The template for the About dialog is as follows:

IDD_ABOUTBOX DIALOGEX 0, 0, 152, 151
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About 64th Note"
FONT 8, "MS Sans Serif", 0, 0, 0x1
BEGIN
    LTEXT           "64th Note v1.2 beta 3\nBased on Project 64 1.6 by Zilmar and Jabo\nAudio HLE by Azimer\nPSF concept and tagging by Neill Corlett\nPlayer by hcs, Josh W, dr0\nhttp://hcs64.com/usf",IDC_STATIC,7,94,138,50
    CONTROL         110,IDC_STATIC,"Static",SS_BITMAP,26,7,95,86,WS_EX_DLGMODALFRAME
END

Like I said, my wrapper displays the About dialog just fine, as does Winamp. Why can Winamp display the Config dialog, while my wrapper cannot?

+2  A: 

Perhaps you haven't registered the Trackbar control's WNDCLASS? You have to load the common control DLL before you can instantiate it.

I'm specifically looking at this line:

 CONTROL         "Slider2",IDC_PRISLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,74,90,108,11

EDIT: You'll need to link with comctl32.lib and call InitCommonControlsEx during your program startup.

Ben Voigt
Yay!!! Using Code::Blocks it kept saying InitCommonControlsEx wasn't declared (even when linking with comctl32 and including commctrl.h) but I tried plain old InitCommonControls and it worked! If anyone incidentally knows how to solve that InitCommonControlsEx undeclared problem, then that's great too, but the show-stopper is fixed at least and I can finally proceed with my wrapper!
nonoitall
Is it depending on if "#include <windows.h>" is before or after the "#include <commctrl.h>"?
Default
I just get the one undeclared error if <commctrl.h> comes after <windows.h>. I get like 50+ errors if the <commctrl.h> include comes before <windows.h>. (Things like "DWORD does not name a type" or "HINSTANCE does not name a type".)
nonoitall
I found a solution to my problem here:http://invisionfree.com/forums/CPPlearningcommunity/ar/t2899.htmThe instructions are for Dev-C++ but they worked for Code::Blocks too.
nonoitall
Yeah you need to define WINVER to at least 0x0500, since MSDN says the function was introduced in Win2000. I'd be very wary of using InitCommonControls because MSDN says that starting with Common Controls 6.0, it does nothing and you MUST use InitCommonControlsEx.
Ben Voigt
Actually I managed to get it working just by defining _WIN32_IE 0x0300 before the commctrl.h include. :-)
nonoitall