MSI: Radio Buttons
Ulrich Czekalla
ulrich.czekalla at utoronto.ca
Thu Mar 3 07:59:51 CST 2005
On Thu, Mar 03, 2005 at 12:42:53PM +0100, Alexandre Julliard wrote:
> Ulrich Czekalla <ulrich.czekalla at utoronto.ca> writes:
>
> > const static WCHAR szStatic[] = { 'S','t','a','t','i','c',0 };
> > +const static WCHAR szButton[] = { 'B','U','T','T','O','N', 0 };
> > +
> > +const static WCHAR szButtonData = { 0 };
>
> Did you really intend to use an empty string here for the button
> property? That doesn't seem right; though if you really need to
I was just making sure you still review all the patches ;-) New patch
resubmitted.
> redefine the winproc it would be much cleaner IMO to define a proper
> window class.
>
Checking using spy++ MSI does just subclass the button class.
Thanks,
/Ulrich
-------------- next part --------------
Index: dlls/msi/dialog.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/dialog.c,v
retrieving revision 1.6
diff -u -p -r1.6 dialog.c
--- dlls/msi/dialog.c 16 Feb 2005 16:25:36 -0000 1.6
+++ dlls/msi/dialog.c 3 Mar 2005 13:57:23 -0000
@@ -41,6 +41,9 @@ const WCHAR szMsiDialogClass[] = {
'M','s','i','D','i','a','l','o','g','C','l','o','s','e','C','l','a','s','s',0
};
const static WCHAR szStatic[] = { 'S','t','a','t','i','c',0 };
+const static WCHAR szButton[] = { 'B','U','T','T','O','N', 0 };
+
+const static WCHAR szButtonData[] = { 'M','S','I','D','A','T','A',0 };
struct msi_control_tag;
typedef struct msi_control_tag msi_control;
@@ -83,10 +86,19 @@ struct control_handler
msi_dialog_control_func func;
};
+typedef struct
+{
+ msi_dialog* dialog;
+ msi_control *parent;
+ DWORD attributes;
+} radio_button_group_descr;
+
static UINT msi_dialog_checkbox_handler( msi_dialog *, msi_control *, WPARAM );
static void msi_dialog_checkbox_sync_state( msi_dialog *, msi_control * );
static UINT msi_dialog_button_handler( msi_dialog *, msi_control *, WPARAM );
static UINT msi_dialog_edit_handler( msi_dialog *, msi_control *, WPARAM );
+static UINT msi_dialog_radiogroup_handler( msi_dialog *, msi_control *, WPARAM param );
+static LRESULT WINAPI MSIRadioGroup_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
INT msi_dialog_scale_unit( msi_dialog *dialog, INT val )
@@ -275,7 +287,6 @@ static UINT msi_dialog_text_control( msi
static UINT msi_dialog_button_control( msi_dialog *dialog, MSIRECORD *rec )
{
- const static WCHAR szButton[] = { 'B','U','T','T','O','N', 0 };
msi_control *control;
TRACE("%p %p\n", dialog, rec);
@@ -288,7 +299,6 @@ static UINT msi_dialog_button_control( m
static UINT msi_dialog_checkbox_control( msi_dialog *dialog, MSIRECORD *rec )
{
- const static WCHAR szButton[] = { 'B','U','T','T','O','N', 0 };
msi_control *control;
LPCWSTR prop;
@@ -367,17 +377,119 @@ static UINT msi_dialog_pathedit_control(
return msi_dialog_edit_control( dialog, rec );
}
-static UINT msi_dialog_radiogroup_control( msi_dialog *dialog, MSIRECORD *rec )
+static UINT msi_dialog_create_radiobutton( MSIRECORD *rec, LPVOID param )
{
- LPCWSTR name;
+ radio_button_group_descr *group = (radio_button_group_descr *)param;
+ msi_dialog *dialog = group->dialog;
+ msi_control *control;
+ LPCWSTR prop;
+ DWORD x, y, width, height, style;
+ DWORD attributes = group->attributes;
+ LPCWSTR text, name;
+ LPWSTR font = NULL, title = NULL;
+
+ style = WS_CHILD | BS_AUTORADIOBUTTON | BS_MULTILINE;
+ name = MSI_RecordGetString( rec, 3 );
+ control = HeapAlloc( GetProcessHeap(), 0,
+ sizeof *control + strlenW(name)*sizeof(WCHAR) );
+ strcpyW( control->name, name );
+ control->next = dialog->control_list;
+ dialog->control_list = control;
+
+ x = MSI_RecordGetInteger( rec, 4 );
+ y = MSI_RecordGetInteger( rec, 5 );
+ width = MSI_RecordGetInteger( rec, 6 );
+ height = MSI_RecordGetInteger( rec, 7 );
+ text = MSI_RecordGetString( rec, 8 );
+
+ x = msi_dialog_scale_unit( dialog, x );
+ y = msi_dialog_scale_unit( dialog, y );
+ width = msi_dialog_scale_unit( dialog, width );
+ height = msi_dialog_scale_unit( dialog, height );
+
+ if( attributes & 1 )
+ style |= WS_VISIBLE;
+ if( ~attributes & 2 )
+ style |= WS_DISABLED;
+
+ if( text )
+ {
+ font = msi_dialog_get_style( &text );
+ deformat_string( dialog->package, text, &title );
+ }
+
+ control->hwnd = CreateWindowW( szButton, title, style, x, y, width, height,
+ group->parent->hwnd, NULL, NULL, NULL );
+
+ TRACE("Dialog %s control %s hwnd %p\n", debugstr_w(dialog->name), debugstr_w(text), control->hwnd);
+
+ msi_dialog_set_font( dialog, control->hwnd,
+ font ? font : dialog->default_font );
+
+ HeapFree( GetProcessHeap(), 0, font );
+ HeapFree( GetProcessHeap(), 0, title );
+
+ control->handler = msi_dialog_radiogroup_handler;
+
+ prop = MSI_RecordGetString( rec, 1 );
+ if( prop )
+ control->property = dupstrW( prop );
- name = MSI_RecordGetString( rec, 2 );
- FIXME("Radio group %s\n", debugstr_w( name ) );
return ERROR_SUCCESS;
}
+static UINT msi_dialog_radiogroup_control( msi_dialog *dialog, MSIRECORD *rec )
+{
+ static const WCHAR query[] = {
+ 'S','E','L','E','C','T',' ','*',' ',
+ 'F','R','O','M',' ','R','a','d','i','o','B','u','t','t','o','n',' ',
+ 'W','H','E','R','E',' ',
+ '`','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
+ UINT r;
+ LPCWSTR prop;
+ msi_control *control;
+ MSIQUERY *view = NULL;
+ radio_button_group_descr group;
+ MSIPACKAGE *package = dialog->package;
+
+ prop = MSI_RecordGetString( rec, 9 );
+
+ TRACE("%p %p %s\n", dialog, rec, debugstr_w( prop ));
+
+ /* Create parent group box to hold radio buttons */
+ control = msi_dialog_add_control( dialog, rec, szButton, BS_OWNERDRAW );
+
+ if (control->hwnd)
+ {
+ WNDPROC oldproc = (WNDPROC) SetWindowLongW(control->hwnd, GWLP_WNDPROC,
+ (LONG)MSIRadioGroup_WndProc);
+ SetPropW(control->hwnd, szButtonData, oldproc);
+ }
+
+ if( prop )
+ control->property = dupstrW( prop );
+
+ /* query the Radio Button table for all control in this group */
+ r = MSI_OpenQuery( package->db, &view, query, prop );
+ if( r != ERROR_SUCCESS )
+ {
+ ERR("query failed for dialog %s radio group %s\n",
+ debugstr_w(dialog->name), debugstr_w(prop));
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ group.dialog = dialog;
+ group.parent = control;
+ group.attributes = MSI_RecordGetInteger( rec, 8 );
+
+ r = MSI_IterateRecords( view, 0, msi_dialog_create_radiobutton, &group );
+ msiobj_release( &view->hdr );
+
+ return r;
+}
+
static const WCHAR szText[] = { 'T','e','x','t',0 };
-static const WCHAR szButton[] = { 'P','u','s','h','B','u','t','t','o','n',0 };
+static const WCHAR szPushButton[] = { 'P','u','s','h','B','u','t','t','o','n',0 };
static const WCHAR szLine[] = { 'L','i','n','e',0 };
static const WCHAR szBitmap[] = { 'B','i','t','m','a','p',0 };
static const WCHAR szCheckBox[] = { 'C','h','e','c','k','B','o','x',0 };
@@ -393,7 +505,7 @@ static const WCHAR szRadioButtonGroup[]
struct control_handler msi_dialog_handler[] =
{
{ szText, msi_dialog_text_control },
- { szButton, msi_dialog_button_control },
+ { szPushButton, msi_dialog_button_control },
{ szLine, msi_dialog_line_control },
{ szBitmap, msi_dialog_bitmap_control },
{ szCheckBox, msi_dialog_checkbox_control },
@@ -811,6 +923,20 @@ static UINT msi_dialog_edit_handler( msi
return ERROR_SUCCESS;
}
+static UINT msi_dialog_radiogroup_handler( msi_dialog *dialog,
+ msi_control *control, WPARAM param )
+{
+ if( HIWORD(param) != BN_CLICKED )
+ return ERROR_SUCCESS;
+
+ TRACE("clicked radio button %s, set %s\n", debugstr_w(control->name),
+ debugstr_w(control->property));
+
+ MSI_SetPropertyW( dialog->package, control->property, control->name );
+
+ return msi_dialog_button_handler( dialog, control, param );
+}
+
static LRESULT msi_dialog_oncommand( msi_dialog *dialog, WPARAM param, HWND hwnd )
{
msi_control *control;
@@ -836,6 +962,7 @@ static LRESULT WINAPI MSIDialog_WndProc(
{
msi_dialog *dialog = (LPVOID) GetWindowLongPtrW( hwnd, GWLP_USERDATA );
+ TRACE(" 0x%04x\n", msg);
switch (msg)
{
case WM_CREATE:
@@ -990,4 +1117,16 @@ void msi_dialog_register_class( void )
void msi_dialog_unregister_class( void )
{
UnregisterClassW( szMsiDialogClass, NULL );
+}
+
+static LRESULT WINAPI MSIRadioGroup_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ WNDPROC oldproc = (WNDPROC) GetPropW(hWnd, szButtonData);
+
+ TRACE("hWnd %p msg %04x wParam 0x%08x lParam 0x%08lx\n", hWnd, msg, wParam, lParam);
+
+ if (msg == WM_COMMAND) /* Forward notifications to dialog */
+ SendMessageW(GetParent(hWnd), msg, wParam, lParam);
+
+ return CallWindowProcW(oldproc, hWnd, msg, wParam, lParam);
}
More information about the wine-patches
mailing list