diff --git a/dlls/msi/dialog.c b/dlls/msi/dialog.c index 01e9a5491c9..ccd01a43c1c 100644 --- a/dlls/msi/dialog.c +++ b/dlls/msi/dialog.c @@ -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_dialog *dialog, MSIRECORD *rec ) 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( msi_dialog *dialog, MSIRECORD *rec ) 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( msi_dialog *dialog, MSIRECORD *rec ) 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) SetWindowLongPtrW(control->hwnd, GWLP_WNDPROC, + (LONG_PTR)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_dialog *dialog, 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( HWND hwnd, UINT msg, { msi_dialog *dialog = (LPVOID) GetWindowLongPtrW( hwnd, GWLP_USERDATA ); + TRACE(" 0x%04x\n", msg); switch (msg) { case WM_CREATE: @@ -991,3 +1118,15 @@ 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); +}